From 22caa5e502f50bd399643df28ea127783f0374eb Mon Sep 17 00:00:00 2001 From: Pietro Gagliardi Date: Tue, 25 Oct 2016 00:34:12 -0400 Subject: [PATCH] Implemented the window drag stuff on GTK+. It works! --- test/page15.c | 2 +- ui.h | 3 ++ unix/area.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/test/page15.c b/test/page15.c index 99e402e3..2c9728bf 100644 --- a/test/page15.c +++ b/test/page15.c @@ -107,7 +107,7 @@ static void handlerMouseEvent(uiAreaHandler *a, uiArea *area, uiAreaMouseEvent * #define resize(cond, edge) if (cond) { uiAreaBeginUserWindowResize(area, edge); return; } resize(ta.leftresize.in, uiWindowResizeEdgeLeft) resize(ta.topresize.in, uiWindowResizeEdgeTop) - resize((ta.rightresize.in, uiWindowResizeEdgeRight) + resize(ta.rightresize.in, uiWindowResizeEdgeRight) resize(ta.bottomresize.in, uiWindowResizeEdgeBottom) resize(ta.topleftresize.in, uiWindowResizeEdgeTopLeft) resize(ta.toprightresize.in, uiWindowResizeEdgeTopRight) diff --git a/ui.h b/ui.h index 9dbc32b6..518d366a 100644 --- a/ui.h +++ b/ui.h @@ -301,6 +301,8 @@ _UI_ENUM(uiWindowResizeEdge) { uiWindowResizeEdgeBottomLeft, uiWindowResizeEdgeBottomRight, // TODO have one for keyboard resizes? + // TODO GDK doesn't seem to have any others, including for keyboards... + // TODO way to bring up the system menu instead? }; #define uiArea(this) ((uiArea *) (this)) @@ -312,6 +314,7 @@ _UI_EXTERN void uiAreaQueueRedrawAll(uiArea *a); _UI_EXTERN void uiAreaScrollTo(uiArea *a, double x, double y, double width, double height); // TODO document these can only be called within Mouse() handlers // TODO should these be allowed on scrolling areas? +// TODO decide which mouse events should be accepted; Down is the only one guaranteed to work right now _UI_EXTERN void uiAreaBeginUserWindowMove(uiArea *a); _UI_EXTERN void uiAreaBeginUserWindowResize(uiArea *a, uiWindowResizeEdge edge); _UI_EXTERN uiArea *uiNewArea(uiAreaHandler *ah); diff --git a/unix/area.c b/unix/area.c index c5b490d6..c46447cc 100644 --- a/unix/area.c +++ b/unix/area.c @@ -46,6 +46,9 @@ struct uiArea { // note that this is a pointer; see above clickCounter *cc; + + // for user window drags + GdkEventButton *dragevent; }; G_DEFINE_TYPE(areaWidget, areaWidget, GTK_TYPE_DRAWING_AREA) @@ -261,7 +264,11 @@ static gboolean areaWidget_button_press_event(GtkWidget *w, GdkEventButton *e) me.Down = e->button; me.Up = 0; + + // and set things up for window drags + a->dragevent = e; finishMouseEvent(a, &me, e->button, e->x, e->y, e->state, e->window); + a->dragevent = NULL; return GDK_EVENT_PROPAGATE; } @@ -505,6 +512,76 @@ void uiAreaScrollTo(uiArea *a, double x, double y, double width, double height) // TODO adjust adjustments and find source for that } +void uiAreaBeginUserWindowMove(uiArea *a) +{ + GtkWidget *toplevel; + + if (a->dragevent == NULL) + userbug("cannot call uiAreaBeginUserWindowMove() outside of a Mouse() with Down != 0"); + // TODO don't we have a libui function for this? did I scrap it? + // TODO widget or areaWidget? + toplevel = gtk_widget_get_toplevel(a->widget); + if (toplevel == NULL) { + // TODO + return; + } + // the docs say to do this + if (!gtk_widget_is_toplevel(toplevel)) { + // TODO + return; + } + if (!GTK_IS_WINDOW(toplevel)) { + // TODO + return; + } + gtk_window_begin_move_drag(GTK_WINDOW(toplevel), + a->dragevent->button, + a->dragevent->x_root, // TODO are these correct? + a->dragevent->y_root, + a->dragevent->time); +} + +static const GdkWindowEdge edges[] = { + [uiWindowResizeEdgeLeft] = GDK_WINDOW_EDGE_WEST, + [uiWindowResizeEdgeTop] = GDK_WINDOW_EDGE_NORTH, + [uiWindowResizeEdgeRight] = GDK_WINDOW_EDGE_EAST, + [uiWindowResizeEdgeBottom] = GDK_WINDOW_EDGE_SOUTH, + [uiWindowResizeEdgeTopLeft] = GDK_WINDOW_EDGE_NORTH_WEST, + [uiWindowResizeEdgeTopRight] = GDK_WINDOW_EDGE_NORTH_EAST, + [uiWindowResizeEdgeBottomLeft] = GDK_WINDOW_EDGE_SOUTH_WEST, + [uiWindowResizeEdgeBottomRight] = GDK_WINDOW_EDGE_SOUTH_EAST, +}; + +void uiAreaBeginUserWindowResize(uiArea *a, uiWindowResizeEdge edge) +{ + GtkWidget *toplevel; + + if (a->dragevent == NULL) + userbug("cannot call uiAreaBeginUserWindowResize() outside of a Mouse() with Down != 0"); + // TODO don't we have a libui function for this? did I scrap it? + // TODO widget or areaWidget? + toplevel = gtk_widget_get_toplevel(a->widget); + if (toplevel == NULL) { + // TODO + return; + } + // the docs say to do this + if (!gtk_widget_is_toplevel(toplevel)) { + // TODO + return; + } + if (!GTK_IS_WINDOW(toplevel)) { + // TODO + return; + } + gtk_window_begin_resize_drag(GTK_WINDOW(toplevel), + edges[edge], + a->dragevent->button, + a->dragevent->x_root, // TODO are these correct? + a->dragevent->y_root, + a->dragevent->time); +} + uiArea *uiNewArea(uiAreaHandler *ah) { uiArea *a;