From 5fee6341216809b2ac761f95826642cfb43b1985 Mon Sep 17 00:00:00 2001 From: rhp Date: Wed, 20 Jun 2001 04:29:28 +0000 Subject: [PATCH] ... --- src/core.c | 37 ++++++ src/core.h | 14 +++ src/frames.c | 350 ++++++++++++++++++++++++++++++++++++++++++--------- src/frames.h | 17 +++ 4 files changed, 361 insertions(+), 57 deletions(-) diff --git a/src/core.c b/src/core.c index 89ea0e9f3..1d6e9527f 100644 --- a/src/core.c +++ b/src/core.c @@ -75,3 +75,40 @@ meta_core_queue_frame_resize (Display *xdisplay, meta_window_queue_move_resize (window); } +void +meta_core_user_move (Display *xdisplay, + Window frame_xwindow, + int x, + int y) +{ + MetaDisplay *display; + MetaWindow *window; + + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, frame_xwindow); + + if (window == NULL || window->frame == NULL) + meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); + + window->user_has_moved = TRUE; + meta_window_move (window, x, y); +} + +void +meta_core_get_position (Display *xdisplay, + Window frame_xwindow, + int *x, + int *y) +{ + MetaDisplay *display; + MetaWindow *window; + + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, frame_xwindow); + + if (window == NULL || window->frame == NULL) + meta_bug ("No such frame window 0x%lx!\n", frame_xwindow); + + meta_window_get_position (window, x, y); +} + diff --git a/src/core.h b/src/core.h index 58545a6a3..2a27fc4d7 100644 --- a/src/core.h +++ b/src/core.h @@ -39,4 +39,18 @@ MetaFrameFlags meta_core_get_frame_flags (Display *xdisplay, void meta_core_queue_frame_resize (Display *xdisplay, Window frame_xwindow); +/* Move as a result of user operation */ +void meta_core_user_move (Display *xdisplay, + Window frame_xwindow, + int x, + int y); +/* get position of client, same coord space expected by move */ +void meta_core_get_position (Display *xdisplay, + Window frame_xwindow, + int *x, + int *y); + + #endif + + diff --git a/src/frames.c b/src/frames.c index 9b05b13ff..2078dd367 100644 --- a/src/frames.c +++ b/src/frames.c @@ -89,6 +89,9 @@ struct _MetaFrameGeometry int top_height; int bottom_height; + int width; + int height; + GdkRectangle close_rect; GdkRectangle max_rect; GdkRectangle min_rect; @@ -97,53 +100,6 @@ struct _MetaFrameGeometry GdkRectangle title_rect; }; -static GdkRectangle* -control_rect (MetaFrameControl control, - MetaFrameGeometry *fgeom) -{ - GdkRectangle *rect; - - rect = NULL; - switch (control) - { - case META_FRAME_CONTROL_TITLE: - rect = &fgeom->title_rect; - break; - case META_FRAME_CONTROL_DELETE: - rect = &fgeom->close_rect; - break; - case META_FRAME_CONTROL_MENU: - rect = &fgeom->menu_rect; - break; - case META_FRAME_CONTROL_MINIMIZE: - rect = &fgeom->min_rect; - break; - case META_FRAME_CONTROL_MAXIMIZE: - rect = &fgeom->max_rect; - break; - case META_FRAME_CONTROL_RESIZE_SE: - break; - case META_FRAME_CONTROL_RESIZE_S: - break; - case META_FRAME_CONTROL_RESIZE_SW: - break; - case META_FRAME_CONTROL_RESIZE_N: - break; - case META_FRAME_CONTROL_RESIZE_NE: - break; - case META_FRAME_CONTROL_RESIZE_NW: - break; - case META_FRAME_CONTROL_RESIZE_W: - break; - case META_FRAME_CONTROL_RESIZE_E: - break; - case META_FRAME_CONTROL_NONE: - break; - } - - return rect; -} - static void meta_frames_class_init (MetaFramesClass *klass); static void meta_frames_init (MetaFrames *frames); static void meta_frames_destroy (GtkObject *object); @@ -194,6 +150,26 @@ static void meta_frames_calc_geometry (MetaFrames *frames, static MetaUIFrame* meta_frames_lookup_window (MetaFrames *frames, Window xwindow); +static void meta_frames_begin_grab (MetaFrames *frames, + MetaUIFrame *frame, + MetaFrameStatus status, + int start_button, + int start_root_x, + int start_root_y, + int start_window_x, + int start_window_y, + guint32 timestamp); +static void meta_frames_end_grab (MetaFrames *frames, + guint32 timestamp); + + +static GdkRectangle* control_rect (MetaFrameControl control, + MetaFrameGeometry *fgeom); +static MetaFrameControl get_control (MetaFrames *frames, + MetaUIFrame *frame, + int x, + int y); + enum { LAST_SIGNAL @@ -264,6 +240,11 @@ meta_frames_class_init (MetaFramesClass *class) widget_class->style_set = meta_frames_style_set; widget_class->expose_event = meta_frames_expose_event; + widget_class->unmap_event = meta_frames_unmap_event; + widget_class->destroy_event = meta_frames_destroy_event; + widget_class->button_press_event = meta_frames_button_press_event; + widget_class->button_release_event = meta_frames_button_release_event; + widget_class->motion_notify_event = meta_frames_motion_notify_event; INT_PROPERTY ("left_width", 6, _("Left edge"), _("Left window edge width")); INT_PROPERTY ("right_width", 6, _("Right edge"), _("Right window edge width")); @@ -315,6 +296,8 @@ meta_frames_init (MetaFrames *frames) frames->props = g_new0 (MetaFrameProperties, 1); frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal); + + frames->grab_status = META_FRAME_STATUS_NORMAL; } static void @@ -508,8 +491,11 @@ meta_frames_calc_geometry (MetaFrames *frames, meta_core_get_frame_size (gdk_display, frame->xwindow, &width, &height); - + flags = meta_core_get_frame_flags (gdk_display, frame->xwindow); + + fgeom->width = width; + fgeom->height = height; buttons_height = props.button_height + props.button_border.top + props.button_border.bottom; @@ -693,7 +679,6 @@ meta_frames_manage_window (MetaFrames *frames, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK); -#endif /* This shouldn't be required if we don't select for button * press in frame.c? @@ -706,6 +691,7 @@ meta_frames_manage_window (MetaFrames *frames, False, None); XFlush (gdk_display); +#endif frame->xwindow = xwindow; frame->layout = NULL; @@ -723,6 +709,9 @@ meta_frames_unmanage_window (MetaFrames *frames, if (frame) { + if (frames->grab_frame == frame) + meta_frames_end_grab (frames, GDK_CURRENT_TIME); + g_hash_table_remove (frames->frames, &frame->xwindow); g_object_unref (G_OBJECT (frame->window)); @@ -823,19 +812,131 @@ meta_frames_set_title (MetaFrames *frames, gdk_window_invalidate_rect (frame->window, NULL, FALSE); } +static void +meta_frames_begin_grab (MetaFrames *frames, + MetaUIFrame *frame, + MetaFrameStatus status, + int start_button, + int start_root_x, + int start_root_y, + int start_window_x, + int start_window_y, + guint32 timestamp) +{ + g_return_if_fail (frames->grab_frame == NULL); + + /* This grab isn't needed I don't think */ + if (gdk_pointer_grab (frame->window, + FALSE, + GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | + GDK_POINTER_MOTION_HINT_MASK | GDK_POINTER_MOTION_MASK, + NULL, + NULL, + timestamp) == GDK_GRAB_SUCCESS) + { + frames->grab_frame = frame; + frames->grab_status = status; + frames->start_button = start_button; + frames->start_root_x = start_root_x; + frames->start_root_y = start_root_y; + frames->start_window_x = start_window_x; + frames->start_window_y = start_window_y; + } +} + +static void +meta_frames_end_grab (MetaFrames *frames, + guint32 timestamp) +{ + if (frames->grab_frame) + { + frames->grab_frame = NULL; + frames->grab_status = META_FRAME_STATUS_NORMAL; + gdk_pointer_ungrab (timestamp); + } +} + +static void +frame_query_root_pointer (MetaUIFrame *frame, + int *x, int *y) +{ + Window root_return, child_return; + int root_x_return, root_y_return; + int win_x_return, win_y_return; + unsigned int mask_return; + + XQueryPointer (gdk_display, + frame->xwindow, + &root_return, + &child_return, + &root_x_return, + &root_y_return, + &win_x_return, + &win_y_return, + &mask_return); + + if (x) + *x = root_x_return; + if (y) + *y = root_y_return; +} + +static void +update_move (MetaFrames *frames, + MetaUIFrame *frame, + int x, + int y) +{ + int dx, dy; + + dx = x - frames->start_root_x; + dy = y - frames->start_root_y; + + meta_core_user_move (gdk_display, + frame->xwindow, + frames->start_window_x + dx, + frames->start_window_y + dy); +} + gboolean meta_frames_button_press_event (GtkWidget *widget, GdkEventButton *event) { MetaUIFrame *frame; MetaFrames *frames; - + MetaFrameControl control; + frames = META_FRAMES (widget); + if (frames->grab_frame != NULL) + return FALSE; /* already up to something */ + frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); if (frame == NULL) return FALSE; + + control = get_control (frames, frame, event->x, event->y); + + if (((control == META_FRAME_CONTROL_TITLE || + control == META_FRAME_CONTROL_NONE) && + event->button == 1) || + event->button == 2) + { + int x, y; + meta_core_get_position (gdk_display, + frame->xwindow, + &x, &y); + + meta_frames_begin_grab (frames, frame, + META_FRAME_STATUS_MOVING, + event->button, + event->x_root, + event->y_root, + x, y, + event->time); + } + return TRUE; } @@ -847,11 +948,27 @@ meta_frames_button_release_event (GtkWidget *widget, MetaFrames *frames; frames = META_FRAMES (widget); - + frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); if (frame == NULL) return FALSE; + if (frames->grab_frame == frame && + frames->start_button == event->button) + { + meta_frames_end_grab (frames, event->time); + + switch (frames->grab_status) + { + case META_FRAME_STATUS_MOVING: + update_move (frames, frame, event->x_root, event->y_root); + break; + + case META_FRAME_STATUS_NORMAL: + break; + } + } + return TRUE; } @@ -861,13 +978,20 @@ meta_frames_motion_notify_event (GtkWidget *widget, { MetaUIFrame *frame; MetaFrames *frames; - + frames = META_FRAMES (widget); frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); if (frame == NULL) return FALSE; + if (frames->grab_status == META_FRAME_STATUS_MOVING) + { + int x, y; + frame_query_root_pointer (frame, &x, &y); + update_move (frames, frame, x, y); + } + return TRUE; } @@ -884,6 +1008,9 @@ meta_frames_destroy_event (GtkWidget *widget, if (frame == NULL) return FALSE; + if (frames->grab_frame == frame) + meta_frames_end_grab (frames, GDK_CURRENT_TIME); + return TRUE; } @@ -1048,6 +1175,7 @@ meta_frames_expose_event (GtkWidget *widget, fgeom.close_rect.y + inner.top); } +#define THICK_LINE_WIDTH 3 if (fgeom.max_rect.width > 0 && fgeom.max_rect.height > 0) { gdk_draw_rectangle (frame->window, @@ -1058,7 +1186,7 @@ meta_frames_expose_event (GtkWidget *widget, fgeom.max_rect.width - inner.left - inner.right, fgeom.max_rect.height - inner.top - inner.bottom); - vals.line_width = 3; + vals.line_width = THICK_LINE_WIDTH; gdk_gc_set_values (widget->style->fg_gc[GTK_STATE_NORMAL], &vals, GDK_GC_LINE_WIDTH); @@ -1068,7 +1196,7 @@ meta_frames_expose_event (GtkWidget *widget, fgeom.max_rect.x + inner.left, fgeom.max_rect.y + inner.top, fgeom.max_rect.x + fgeom.max_rect.width - inner.right, - fgeom.max_rect.y + fgeom.max_rect.height - inner.bottom); + fgeom.max_rect.y + inner.top); vals.line_width = 0; gdk_gc_set_values (widget->style->fg_gc[GTK_STATE_NORMAL], @@ -1079,7 +1207,7 @@ meta_frames_expose_event (GtkWidget *widget, if (fgeom.min_rect.width > 0 && fgeom.min_rect.height > 0) { - vals.line_width = 3; + vals.line_width = THICK_LINE_WIDTH; gdk_gc_set_values (widget->style->fg_gc[GTK_STATE_NORMAL], &vals, GDK_GC_LINE_WIDTH); @@ -1087,15 +1215,16 @@ meta_frames_expose_event (GtkWidget *widget, gdk_draw_line (frame->window, widget->style->fg_gc[GTK_STATE_NORMAL], fgeom.min_rect.x + inner.left, - fgeom.min_rect.y + inner.top, + fgeom.min_rect.y + fgeom.min_rect.height - inner.bottom - THICK_LINE_WIDTH, fgeom.min_rect.x + fgeom.min_rect.width - inner.right, - fgeom.min_rect.y + fgeom.min_rect.height - inner.bottom); + fgeom.min_rect.y + fgeom.min_rect.height - inner.bottom - THICK_LINE_WIDTH); vals.line_width = 0; gdk_gc_set_values (widget->style->fg_gc[GTK_STATE_NORMAL], &vals, GDK_GC_LINE_WIDTH); } +#undef THICK_LINE_WIDTH if (fgeom.spacer_rect.width > 0 && fgeom.spacer_rect.height > 0) { @@ -1274,6 +1403,9 @@ meta_frames_unmap_event (GtkWidget *widget, if (frame == NULL) return FALSE; + if (frames->grab_frame == frame) + meta_frames_end_grab (frames, GDK_CURRENT_TIME); + return TRUE; } @@ -1326,6 +1458,110 @@ meta_frames_window_state_event (GtkWidget *widget, } + + +static GdkRectangle* +control_rect (MetaFrameControl control, + MetaFrameGeometry *fgeom) +{ + GdkRectangle *rect; + + rect = NULL; + switch (control) + { + case META_FRAME_CONTROL_TITLE: + rect = &fgeom->title_rect; + break; + case META_FRAME_CONTROL_DELETE: + rect = &fgeom->close_rect; + break; + case META_FRAME_CONTROL_MENU: + rect = &fgeom->menu_rect; + break; + case META_FRAME_CONTROL_MINIMIZE: + rect = &fgeom->min_rect; + break; + case META_FRAME_CONTROL_MAXIMIZE: + rect = &fgeom->max_rect; + break; + case META_FRAME_CONTROL_RESIZE_SE: + break; + case META_FRAME_CONTROL_RESIZE_S: + break; + case META_FRAME_CONTROL_RESIZE_SW: + break; + case META_FRAME_CONTROL_RESIZE_N: + break; + case META_FRAME_CONTROL_RESIZE_NE: + break; + case META_FRAME_CONTROL_RESIZE_NW: + break; + case META_FRAME_CONTROL_RESIZE_W: + break; + case META_FRAME_CONTROL_RESIZE_E: + break; + case META_FRAME_CONTROL_NONE: + break; + } + + return rect; +} + +#define POINT_IN_RECT(xcoord, ycoord, rect) \ + ((xcoord) >= (rect).x && \ + (xcoord) < ((rect).x + (rect).width) && \ + (ycoord) >= (rect).y && \ + (ycoord) < ((rect).y + (rect).height)) + +#define RESIZE_EXTENDS 10 +static MetaFrameControl +get_control (MetaFrames *frames, + MetaUIFrame *frame, + int x, int y) +{ + MetaFrameGeometry fgeom; + + meta_frames_calc_geometry (frames, frame, &fgeom); + + if (POINT_IN_RECT (x, y, fgeom.close_rect)) + return META_FRAME_CONTROL_DELETE; + + if (POINT_IN_RECT (x, y, fgeom.min_rect)) + return META_FRAME_CONTROL_MINIMIZE; + + if (POINT_IN_RECT (x, y, fgeom.max_rect)) + return META_FRAME_CONTROL_MAXIMIZE; + + if (POINT_IN_RECT (x, y, fgeom.menu_rect)) + return META_FRAME_CONTROL_MENU; + + if (POINT_IN_RECT (x, y, fgeom.title_rect)) + return META_FRAME_CONTROL_TITLE; + + if (y > (fgeom.height - fgeom.bottom_height - RESIZE_EXTENDS) && + x > (fgeom.width - fgeom.right_width - RESIZE_EXTENDS)) + return META_FRAME_CONTROL_RESIZE_SE; + + return META_FRAME_CONTROL_NONE; +} + + + + + + + + + + + + + + + + + + #if 0 static void diff --git a/src/frames.h b/src/frames.h index e7d8f3cd2..a608ad808 100644 --- a/src/frames.h +++ b/src/frames.h @@ -44,6 +44,13 @@ typedef enum META_FRAME_CONTROL_RESIZE_E } MetaFrameControl; +typedef enum +{ + META_FRAME_STATUS_NORMAL, + META_FRAME_STATUS_MOVING + +} MetaFrameStatus; + /* This is one widget that manages all the window frames * as subwindows. */ @@ -71,6 +78,16 @@ struct _MetaFrames int text_height; GHashTable *frames; + + /* The below is all for grabs */ + MetaFrameStatus grab_status; + MetaUIFrame *grab_frame; + /* initial mouse position for drags */ + int start_root_x, start_root_y; + /* initial window size or initial window position for drags */ + int start_window_x, start_window_y; + /* button doing the dragging */ + int start_button; }; struct _MetaFramesClass