diff options
Diffstat (limited to 'src/ui/frames.c')
-rw-r--r-- | src/ui/frames.c | 859 |
1 files changed, 446 insertions, 413 deletions
diff --git a/src/ui/frames.c b/src/ui/frames.c index e639abbb..7c25b2cc 100644 --- a/src/ui/frames.c +++ b/src/ui/frames.c @@ -48,9 +48,6 @@ static void meta_frames_destroy (GtkWidget *widget); static void meta_frames_finalize (GObject *object); static void meta_frames_style_updated (GtkWidget *widget); -static void meta_frames_update_prelit_control (MetaFrames *frames, - MetaUIFrame *frame, - MetaFrameControl control); static gboolean meta_frames_button_press_event (GtkWidget *widget, GdkEventButton *event); static gboolean meta_frames_button_release_event (GtkWidget *widget, @@ -81,13 +78,6 @@ static MetaUIFrame* meta_frames_lookup_window (MetaFrames *frames, static void meta_frames_font_changed (MetaFrames *frames); static void meta_frames_button_layout_changed (MetaFrames *frames); - -static GdkRectangle* control_rect (MetaFrameControl control, - MetaFrameGeometry *fgeom); -static MetaFrameControl get_control (MetaFrames *frames, - MetaUIFrame *frame, - int x, - int y); static void clear_tip (MetaFrames *frames); static void invalidate_all_caches (MetaFrames *frames); static void invalidate_whole_window (MetaFrames *frames, @@ -114,6 +104,277 @@ struct _MetaFrames G_DEFINE_TYPE (MetaFrames, meta_frames, GTK_TYPE_WINDOW) static void +get_client_rect (MetaFrameGeometry *fgeom, + GdkRectangle *rect) +{ + rect->x = fgeom->borders.total.left; + rect->y = fgeom->borders.total.top; + rect->width = fgeom->width - fgeom->borders.total.right - rect->x; + rect->height = fgeom->height - fgeom->borders.total.bottom - rect->y; +} + +#define RESIZE_EXTENDS 15 +#define TOP_RESIZE_HEIGHT 4 +static MetaFrameControl +get_control (MetaFrames *frames, + MetaUIFrame *frame, + gint x, + gint y) +{ + MetaFrameGeometry fgeom; + MetaFrameFlags flags; + MetaFrameType type; + gboolean has_vert, has_horiz; + gboolean has_north_resize; + GdkRectangle client; + MetaFrameBorders borders; + MetaTheme *theme; + MetaButton button; + + meta_frames_calc_geometry (frames, frame, &fgeom); + get_client_rect (&fgeom, &client); + + borders = fgeom.borders; + theme = meta_ui_get_theme (); + + if (x < borders.invisible.left - borders.resize.left || + y < borders.invisible.top - borders.resize.top || + x > fgeom.width - borders.invisible.right + borders.resize.right || + y > fgeom.height - borders.invisible.bottom + borders.resize.bottom) + return META_FRAME_CONTROL_NONE; + + if (POINT_IN_RECT (x, y, client)) + return META_FRAME_CONTROL_CLIENT_AREA; + + meta_core_get (frames->xdisplay, frame->xwindow, + META_CORE_GET_FRAME_FLAGS, &flags, + META_CORE_GET_FRAME_TYPE, &type, + META_CORE_GET_END); + + if (meta_theme_get_button (theme, x, y, &button)) + { + switch (button.type) + { + case META_BUTTON_TYPE_CLOSE: + return META_FRAME_CONTROL_DELETE; + + case META_BUTTON_TYPE_MINIMIZE: + return META_FRAME_CONTROL_MINIMIZE; + + case META_BUTTON_TYPE_MENU: + return META_FRAME_CONTROL_MENU; + + case META_BUTTON_TYPE_APPMENU: + return META_FRAME_CONTROL_APPMENU; + + case META_BUTTON_TYPE_MAXIMIZE: + if (flags & META_FRAME_MAXIMIZED) + return META_FRAME_CONTROL_UNMAXIMIZE; + else + return META_FRAME_CONTROL_MAXIMIZE; + + case META_BUTTON_TYPE_SHADE: + return META_FRAME_CONTROL_SHADE; + + case META_BUTTON_TYPE_UNSHADE: + return META_FRAME_CONTROL_UNSHADE; + + case META_BUTTON_TYPE_ABOVE: + return META_FRAME_CONTROL_ABOVE; + + case META_BUTTON_TYPE_UNABOVE: + return META_FRAME_CONTROL_UNABOVE; + + case META_BUTTON_TYPE_STICK: + return META_FRAME_CONTROL_STICK; + + case META_BUTTON_TYPE_UNSTICK: + return META_FRAME_CONTROL_UNSTICK; + + case META_BUTTON_TYPE_SPACER: + case META_BUTTON_TYPE_LAST: + default: + break; + } + } + + has_north_resize = (type != META_FRAME_TYPE_ATTACHED); + has_vert = (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) != 0; + has_horiz = (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) != 0; + + if (POINT_IN_RECT (x, y, fgeom.title_rect)) + { + if (has_vert && y <= (fgeom.borders.invisible.top + TOP_RESIZE_HEIGHT) && has_north_resize) + return META_FRAME_CONTROL_RESIZE_N; + else + return META_FRAME_CONTROL_TITLE; + } + + /* South resize always has priority over north resize, + * in case of overlap. + */ + + if (y >= (fgeom.height - fgeom.borders.total.bottom - RESIZE_EXTENDS) && + x >= (fgeom.width - fgeom.borders.total.right - RESIZE_EXTENDS)) + { + if (has_vert && has_horiz) + return META_FRAME_CONTROL_RESIZE_SE; + else if (has_vert) + return META_FRAME_CONTROL_RESIZE_S; + else if (has_horiz) + return META_FRAME_CONTROL_RESIZE_E; + } + else if (y >= (fgeom.height - fgeom.borders.total.bottom - RESIZE_EXTENDS) && + x <= (fgeom.borders.total.left + RESIZE_EXTENDS)) + { + if (has_vert && has_horiz) + return META_FRAME_CONTROL_RESIZE_SW; + else if (has_vert) + return META_FRAME_CONTROL_RESIZE_S; + else if (has_horiz) + return META_FRAME_CONTROL_RESIZE_W; + } + else if (y < (fgeom.borders.invisible.top + RESIZE_EXTENDS) && + x <= (fgeom.borders.total.left + RESIZE_EXTENDS) && has_north_resize) + { + if (has_vert && has_horiz) + return META_FRAME_CONTROL_RESIZE_NW; + else if (has_vert) + return META_FRAME_CONTROL_RESIZE_N; + else if (has_horiz) + return META_FRAME_CONTROL_RESIZE_W; + } + else if (y < (fgeom.borders.invisible.top + RESIZE_EXTENDS) && + x >= (fgeom.width - fgeom.borders.total.right - RESIZE_EXTENDS) && has_north_resize) + { + if (has_vert && has_horiz) + return META_FRAME_CONTROL_RESIZE_NE; + else if (has_vert) + return META_FRAME_CONTROL_RESIZE_N; + else if (has_horiz) + return META_FRAME_CONTROL_RESIZE_E; + } + else if (y < (fgeom.borders.invisible.top + TOP_RESIZE_HEIGHT)) + { + if (has_vert && has_north_resize) + return META_FRAME_CONTROL_RESIZE_N; + } + else if (y >= (fgeom.height - fgeom.borders.total.bottom - RESIZE_EXTENDS)) + { + if (has_vert) + return META_FRAME_CONTROL_RESIZE_S; + } + else if (x <= fgeom.borders.total.left + RESIZE_EXTENDS) + { + if (has_horiz) + return META_FRAME_CONTROL_RESIZE_W; + } + else if (x >= (fgeom.width - fgeom.borders.total.right - RESIZE_EXTENDS)) + { + if (has_horiz) + return META_FRAME_CONTROL_RESIZE_E; + } + + if (y >= fgeom.borders.total.top) + return META_FRAME_CONTROL_NONE; + else + return META_FRAME_CONTROL_TITLE; +} + +static gboolean +get_control_rect (MetaFrameControl control, + MetaFrameGeometry *fgeom, + gint x, + gint y, + GdkRectangle *rect) +{ + MetaButtonType type; + MetaTheme *theme; + MetaButton button; + + type = META_BUTTON_TYPE_LAST; + + switch (control) + { + case META_FRAME_CONTROL_TITLE: + *rect = fgeom->title_rect; + return TRUE; + + case META_FRAME_CONTROL_DELETE: + type = META_BUTTON_TYPE_CLOSE; + break; + + case META_FRAME_CONTROL_MENU: + type = META_BUTTON_TYPE_MENU; + break; + + case META_FRAME_CONTROL_APPMENU: + type = META_BUTTON_TYPE_APPMENU; + break; + + case META_FRAME_CONTROL_MINIMIZE: + type = META_BUTTON_TYPE_MINIMIZE; + break; + + case META_FRAME_CONTROL_MAXIMIZE: + case META_FRAME_CONTROL_UNMAXIMIZE: + type = META_BUTTON_TYPE_MAXIMIZE; + break; + + case META_FRAME_CONTROL_SHADE: + type = META_BUTTON_TYPE_SHADE; + break; + + case META_FRAME_CONTROL_UNSHADE: + type = META_BUTTON_TYPE_UNSHADE; + break; + + case META_FRAME_CONTROL_ABOVE: + type = META_BUTTON_TYPE_ABOVE; + break; + + case META_FRAME_CONTROL_UNABOVE: + type = META_BUTTON_TYPE_UNABOVE; + break; + + case META_FRAME_CONTROL_STICK: + type = META_BUTTON_TYPE_STICK; + break; + + case META_FRAME_CONTROL_UNSTICK: + type = META_BUTTON_TYPE_UNSTICK; + break; + + case META_FRAME_CONTROL_CLIENT_AREA: + case META_FRAME_CONTROL_RESIZE_SE: + case META_FRAME_CONTROL_RESIZE_S: + case META_FRAME_CONTROL_RESIZE_SW: + case META_FRAME_CONTROL_RESIZE_N: + case META_FRAME_CONTROL_RESIZE_NE: + case META_FRAME_CONTROL_RESIZE_NW: + case META_FRAME_CONTROL_RESIZE_W: + case META_FRAME_CONTROL_RESIZE_E: + case META_FRAME_CONTROL_NONE: + default: + break; + } + + theme = meta_ui_get_theme (); + + if (type != META_BUTTON_TYPE_LAST && + meta_theme_get_button (theme, x, y, &button)) + { + if (type == button.type) + { + *rect = button.rect.clickable; + return TRUE; + } + } + + return FALSE; +} + +static void meta_frames_class_init (MetaFramesClass *frames_class) { GObjectClass *object_class; @@ -514,6 +775,8 @@ meta_frames_manage_window (MetaFrames *frames, frame->expose_delayed = FALSE; frame->shape_applied = FALSE; frame->prelit_control = META_FRAME_CONTROL_NONE; + frame->prelit_x = 0; + frame->prelit_y = 0; meta_core_grab_buttons (frames->xdisplay, frame->xwindow); @@ -642,21 +905,6 @@ apply_cairo_region_to_window (Display *display, g_free (rects); } -/* The client rectangle surrounds client window; it subtracts both - * the visible and invisible borders from the frame window's size. - */ -static void -get_client_rect (MetaFrameGeometry *fgeom, - int window_width, - int window_height, - cairo_rectangle_int_t *rect) -{ - rect->x = fgeom->borders.total.left; - rect->y = fgeom->borders.total.top; - rect->width = window_width - fgeom->borders.total.right - rect->x; - rect->height = window_height - fgeom->borders.total.bottom - rect->y; -} - /* The visible frame rectangle surrounds the visible portion of the * frame window; it subtracts only the invisible borders from the frame * window's size. @@ -1120,12 +1368,13 @@ show_tip_now (MetaFrames *frames) if (tiptext) { MetaFrameGeometry fgeom; - GdkRectangle *rect; + GdkRectangle rect; int dx, dy; meta_frames_calc_geometry (frames, frame, &fgeom); - rect = control_rect (control, &fgeom); + if (!get_control_rect (control, &fgeom, x, y, &rect)) + return; /* get conversion delta for root-to-frame coords */ dx = root_x - x; @@ -1133,10 +1382,10 @@ show_tip_now (MetaFrames *frames) /* Align the tooltip to the button right end if RTL */ if (meta_ui_get_direction() == META_UI_DIRECTION_RTL) - dx += rect->width; + dx += rect.width; - meta_fixed_tip_show (rect->x + dx, - rect->y + rect->height + 2 + dy, + meta_fixed_tip_show (rect.x + dx, + rect.y + rect.height + 2 + dy, tiptext); } } @@ -1178,21 +1427,146 @@ clear_tip (MetaFrames *frames) } static void -redraw_control (MetaFrames *frames, - MetaUIFrame *frame, - MetaFrameControl control) +redraw_control (MetaFrames *frames, + MetaUIFrame *frame, + MetaFrameControl control, + gint x, + gint y) { MetaFrameGeometry fgeom; - GdkRectangle *rect; + GdkRectangle rect; meta_frames_calc_geometry (frames, frame, &fgeom); - rect = control_rect (control, &fgeom); + if (!get_control_rect (control, &fgeom, x, y, &rect)) + return; - gdk_window_invalidate_rect (frame->window, rect, FALSE); + gdk_window_invalidate_rect (frame->window, &rect, FALSE); invalidate_cache (frames, frame); } +static void +update_prelit_control (MetaFrames *frames, + MetaUIFrame *frame, + MetaFrameControl control, + gint x, + gint y) +{ + MetaCursor cursor; + MetaFrameControl old_control; + gint old_x; + gint old_y; + + meta_verbose ("Updating prelit control from %u to %u\n", + frame->prelit_control, control); + + switch (control) + { + case META_FRAME_CONTROL_RESIZE_SE: + cursor = META_CURSOR_SE_RESIZE; + break; + + case META_FRAME_CONTROL_RESIZE_S: + cursor = META_CURSOR_SOUTH_RESIZE; + break; + + case META_FRAME_CONTROL_RESIZE_SW: + cursor = META_CURSOR_SW_RESIZE; + break; + + case META_FRAME_CONTROL_RESIZE_N: + cursor = META_CURSOR_NORTH_RESIZE; + break; + + case META_FRAME_CONTROL_RESIZE_NE: + cursor = META_CURSOR_NE_RESIZE; + break; + + case META_FRAME_CONTROL_RESIZE_NW: + cursor = META_CURSOR_NW_RESIZE; + break; + + case META_FRAME_CONTROL_RESIZE_W: + cursor = META_CURSOR_WEST_RESIZE; + break; + + case META_FRAME_CONTROL_RESIZE_E: + cursor = META_CURSOR_EAST_RESIZE; + break; + + case META_FRAME_CONTROL_CLIENT_AREA: + case META_FRAME_CONTROL_NONE: + case META_FRAME_CONTROL_TITLE: + case META_FRAME_CONTROL_DELETE: + case META_FRAME_CONTROL_MENU: + case META_FRAME_CONTROL_APPMENU: + case META_FRAME_CONTROL_MINIMIZE: + case META_FRAME_CONTROL_MAXIMIZE: + case META_FRAME_CONTROL_UNMAXIMIZE: + case META_FRAME_CONTROL_SHADE: + case META_FRAME_CONTROL_UNSHADE: + case META_FRAME_CONTROL_ABOVE: + case META_FRAME_CONTROL_UNABOVE: + case META_FRAME_CONTROL_STICK: + case META_FRAME_CONTROL_UNSTICK: + default: + cursor = META_CURSOR_DEFAULT; + break; + } + + /* set/unset the prelight cursor */ + meta_core_set_screen_cursor (frames->xdisplay, frame->xwindow, cursor); + + switch (control) + { + case META_FRAME_CONTROL_MENU: + case META_FRAME_CONTROL_APPMENU: + case META_FRAME_CONTROL_MINIMIZE: + case META_FRAME_CONTROL_MAXIMIZE: + case META_FRAME_CONTROL_DELETE: + case META_FRAME_CONTROL_SHADE: + case META_FRAME_CONTROL_UNSHADE: + case META_FRAME_CONTROL_ABOVE: + case META_FRAME_CONTROL_UNABOVE: + case META_FRAME_CONTROL_STICK: + case META_FRAME_CONTROL_UNSTICK: + case META_FRAME_CONTROL_UNMAXIMIZE: + /* leave control set */ + break; + + case META_FRAME_CONTROL_NONE: + case META_FRAME_CONTROL_TITLE: + case META_FRAME_CONTROL_RESIZE_SE: + case META_FRAME_CONTROL_RESIZE_S: + case META_FRAME_CONTROL_RESIZE_SW: + case META_FRAME_CONTROL_RESIZE_N: + case META_FRAME_CONTROL_RESIZE_NE: + case META_FRAME_CONTROL_RESIZE_NW: + case META_FRAME_CONTROL_RESIZE_W: + case META_FRAME_CONTROL_RESIZE_E: + case META_FRAME_CONTROL_CLIENT_AREA: + default: + /* Only prelight buttons */ + control = META_FRAME_CONTROL_NONE; + break; + } + + if (control == frame->prelit_control) + return; + + /* Save the old control so we can unprelight it */ + old_control = frame->prelit_control; + old_x = frame->prelit_x; + old_y = frame->prelit_y; + + frame->prelit_control = control; + frame->prelit_x = x; + frame->prelit_y = y; + + redraw_control (frames, frame, old_control, old_x, old_y); + redraw_control (frames, frame, control, x, y); +} + static gboolean meta_frame_titlebar_event (MetaFrames *frames, MetaUIFrame *frame, @@ -1428,17 +1802,24 @@ meta_frames_button_press_event (GtkWidget *widget, event->y_root); frame->prelit_control = control; - redraw_control (frames, frame, control); + frame->prelit_x = event->x; + frame->prelit_y = event->y; + + redraw_control (frames, frame, control, event->x, event->y); if (op == META_GRAB_OP_CLICKING_MENU) { MetaFrameGeometry fgeom; - GdkRectangle *rect; + GdkRectangle rect; int dx, dy; meta_frames_calc_geometry (frames, frame, &fgeom); - rect = control_rect (META_FRAME_CONTROL_MENU, &fgeom); + if (!get_control_rect (META_FRAME_CONTROL_MENU, &fgeom, + event->x, event->y, &rect)) + { + return FALSE; + } /* get delta to convert to root coords */ dx = event->x_root - event->x; @@ -1446,12 +1827,12 @@ meta_frames_button_press_event (GtkWidget *widget, /* Align to the right end of the menu rectangle if RTL */ if (meta_ui_get_direction() == META_UI_DIRECTION_RTL) - dx += rect->width; + dx += rect.width; meta_core_show_window_menu (frames->xdisplay, frame->xwindow, - rect->x + dx, - rect->y + rect->height + dy, + rect.x + dx, + rect.y + rect.height + dy, event->button, event->time); } @@ -1552,7 +1933,9 @@ meta_frames_notify_menu_hide (MetaFrames *frames) if (frame) { - redraw_control (frames, frame, META_FRAME_CONTROL_MENU); + redraw_control (frames, frame, META_FRAME_CONTROL_MENU, + frame->prelit_x, frame->prelit_y); + meta_core_end_grab_op (frames->xdisplay, CurrentTime); } } @@ -1709,137 +2092,12 @@ meta_frames_button_release_event (GtkWidget *widget, * prelit so to let the user know that it can now be pressed. * :) */ - meta_frames_update_prelit_control (frames, frame, control); + update_prelit_control (frames, frame, control, event->x, event->y); } return TRUE; } -static void -meta_frames_update_prelit_control (MetaFrames *frames, - MetaUIFrame *frame, - MetaFrameControl control) -{ - MetaFrameControl old_control; - MetaCursor cursor; - - - meta_verbose ("Updating prelit control from %u to %u\n", - frame->prelit_control, control); - - cursor = META_CURSOR_DEFAULT; - - switch (control) - { - case META_FRAME_CONTROL_CLIENT_AREA: - break; - case META_FRAME_CONTROL_NONE: - break; - case META_FRAME_CONTROL_TITLE: - break; - case META_FRAME_CONTROL_DELETE: - break; - case META_FRAME_CONTROL_MENU: - break; - case META_FRAME_CONTROL_APPMENU: - break; - case META_FRAME_CONTROL_MINIMIZE: - break; - case META_FRAME_CONTROL_MAXIMIZE: - break; - case META_FRAME_CONTROL_UNMAXIMIZE: - break; - case META_FRAME_CONTROL_SHADE: - break; - case META_FRAME_CONTROL_UNSHADE: - break; - case META_FRAME_CONTROL_ABOVE: - break; - case META_FRAME_CONTROL_UNABOVE: - break; - case META_FRAME_CONTROL_STICK: - break; - case META_FRAME_CONTROL_UNSTICK: - break; - case META_FRAME_CONTROL_RESIZE_SE: - cursor = META_CURSOR_SE_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_S: - cursor = META_CURSOR_SOUTH_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_SW: - cursor = META_CURSOR_SW_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_N: - cursor = META_CURSOR_NORTH_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_NE: - cursor = META_CURSOR_NE_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_NW: - cursor = META_CURSOR_NW_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_W: - cursor = META_CURSOR_WEST_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_E: - cursor = META_CURSOR_EAST_RESIZE; - break; - default: - break; - } - - /* set/unset the prelight cursor */ - meta_core_set_screen_cursor (frames->xdisplay, frame->xwindow, cursor); - - switch (control) - { - case META_FRAME_CONTROL_MENU: - case META_FRAME_CONTROL_APPMENU: - case META_FRAME_CONTROL_MINIMIZE: - case META_FRAME_CONTROL_MAXIMIZE: - case META_FRAME_CONTROL_DELETE: - case META_FRAME_CONTROL_SHADE: - case META_FRAME_CONTROL_UNSHADE: - case META_FRAME_CONTROL_ABOVE: - case META_FRAME_CONTROL_UNABOVE: - case META_FRAME_CONTROL_STICK: - case META_FRAME_CONTROL_UNSTICK: - case META_FRAME_CONTROL_UNMAXIMIZE: - /* leave control set */ - break; - case META_FRAME_CONTROL_NONE: - case META_FRAME_CONTROL_TITLE: - case META_FRAME_CONTROL_RESIZE_SE: - case META_FRAME_CONTROL_RESIZE_S: - case META_FRAME_CONTROL_RESIZE_SW: - case META_FRAME_CONTROL_RESIZE_N: - case META_FRAME_CONTROL_RESIZE_NE: - case META_FRAME_CONTROL_RESIZE_NW: - case META_FRAME_CONTROL_RESIZE_W: - case META_FRAME_CONTROL_RESIZE_E: - case META_FRAME_CONTROL_CLIENT_AREA: - /* Only prelight buttons */ - control = META_FRAME_CONTROL_NONE; - break; - default: - /* Only prelight buttons */ - control = META_FRAME_CONTROL_NONE; - break; - } - - if (control == frame->prelit_control) - return; - - /* Save the old control so we can unprelight it */ - old_control = frame->prelit_control; - - frame->prelit_control = control; - - redraw_control (frames, frame, old_control); - redraw_control (frames, frame, control); -} - static gboolean meta_frames_motion_notify_event (GtkWidget *widget, GdkEventMotion *event) @@ -1912,7 +2170,7 @@ meta_frames_motion_notify_event (GtkWidget *widget, control = META_FRAME_CONTROL_NONE; /* Update prelit control and cursor */ - meta_frames_update_prelit_control (frames, frame, control); + update_prelit_control (frames, frame, control, x, y); /* No tooltip while in the process of clicking */ } @@ -1928,7 +2186,7 @@ meta_frames_motion_notify_event (GtkWidget *widget, control = get_control (frames, frame, x, y); /* Update prelit control and cursor */ - meta_frames_update_prelit_control (frames, frame, control); + update_prelit_control (frames, frame, control, x, y); queue_tip (frames); } @@ -2284,6 +2542,11 @@ update_button_state (MetaButtonType type, Window grab_frame; MetaGrabOp grab_op; MetaFrameControl control; + GdkDisplay *display; + GdkSeat *seat; + GdkDevice *device; + gint x; + gint y; data = (ButtonStateData *) user_data; @@ -2296,6 +2559,15 @@ update_button_state (MetaButtonType type, control = data->frame->prelit_control; + display = gdk_display_get_default (); + seat = gdk_display_get_default_seat (display); + device = gdk_seat_get_pointer (seat); + + gdk_window_get_device_position (data->frame->window, device, &x, &y, NULL); + + if (!POINT_IN_RECT (x, y, rect)) + return state; + /* Set prelight state */ if (control == META_FRAME_CONTROL_MENU && type == META_BUTTON_TYPE_MENU) @@ -2441,7 +2713,7 @@ meta_frames_enter_notify_event (GtkWidget *widget, return FALSE; control = get_control (frames, frame, event->x, event->y); - meta_frames_update_prelit_control (frames, frame, control); + update_prelit_control (frames, frame, control, event->x, event->y); return TRUE; } @@ -2459,253 +2731,14 @@ meta_frames_leave_notify_event (GtkWidget *widget, if (frame == NULL) return FALSE; - meta_frames_update_prelit_control (frames, frame, META_FRAME_CONTROL_NONE); + update_prelit_control (frames, frame, META_FRAME_CONTROL_NONE, + event->x, event->y); clear_tip (frames); return TRUE; } -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.visible; - break; - case META_FRAME_CONTROL_MENU: - rect = &fgeom->menu_rect.visible; - break; - case META_FRAME_CONTROL_APPMENU: - rect = &fgeom->appmenu_rect.visible; - break; - case META_FRAME_CONTROL_MINIMIZE: - rect = &fgeom->min_rect.visible; - break; - case META_FRAME_CONTROL_MAXIMIZE: - case META_FRAME_CONTROL_UNMAXIMIZE: - rect = &fgeom->max_rect.visible; - break; - case META_FRAME_CONTROL_SHADE: - rect = &fgeom->shade_rect.visible; - break; - case META_FRAME_CONTROL_UNSHADE: - rect = &fgeom->unshade_rect.visible; - break; - case META_FRAME_CONTROL_ABOVE: - rect = &fgeom->above_rect.visible; - break; - case META_FRAME_CONTROL_UNABOVE: - rect = &fgeom->unabove_rect.visible; - break; - case META_FRAME_CONTROL_STICK: - rect = &fgeom->stick_rect.visible; - break; - case META_FRAME_CONTROL_UNSTICK: - rect = &fgeom->unstick_rect.visible; - 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; - case META_FRAME_CONTROL_CLIENT_AREA: - break; - default: - break; - } - - return rect; -} - -#define RESIZE_EXTENDS 15 -#define TOP_RESIZE_HEIGHT 4 -static MetaFrameControl -get_control (MetaFrames *frames, - MetaUIFrame *frame, - int x, int y) -{ - MetaFrameGeometry fgeom; - MetaFrameFlags flags; - MetaFrameType type; - gboolean has_vert, has_horiz; - gboolean has_north_resize; - GdkRectangle client; - MetaFrameBorders borders; - - meta_frames_calc_geometry (frames, frame, &fgeom); - get_client_rect (&fgeom, fgeom.width, fgeom.height, &client); - - borders = fgeom.borders; - - if (x < borders.invisible.left - borders.resize.left || - y < borders.invisible.top - borders.resize.top || - x > fgeom.width - borders.invisible.right + borders.resize.right || - y > fgeom.height - borders.invisible.bottom + borders.resize.bottom) - return META_FRAME_CONTROL_NONE; - - if (POINT_IN_RECT (x, y, client)) - return META_FRAME_CONTROL_CLIENT_AREA; - - if (POINT_IN_RECT (x, y, fgeom.close_rect.clickable)) - return META_FRAME_CONTROL_DELETE; - - if (POINT_IN_RECT (x, y, fgeom.min_rect.clickable)) - return META_FRAME_CONTROL_MINIMIZE; - - if (POINT_IN_RECT (x, y, fgeom.menu_rect.clickable)) - return META_FRAME_CONTROL_MENU; - - if (POINT_IN_RECT (x, y, fgeom.appmenu_rect.clickable)) - return META_FRAME_CONTROL_APPMENU; - - meta_core_get (frames->xdisplay, frame->xwindow, - META_CORE_GET_FRAME_FLAGS, &flags, - META_CORE_GET_FRAME_TYPE, &type, - META_CORE_GET_END); - - has_north_resize = (type != META_FRAME_TYPE_ATTACHED); - has_vert = (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) != 0; - has_horiz = (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) != 0; - - if (POINT_IN_RECT (x, y, fgeom.title_rect)) - { - if (has_vert && y <= (fgeom.borders.invisible.top + TOP_RESIZE_HEIGHT) && has_north_resize) - return META_FRAME_CONTROL_RESIZE_N; - else - return META_FRAME_CONTROL_TITLE; - } - - if (POINT_IN_RECT (x, y, fgeom.max_rect.clickable)) - { - if (flags & META_FRAME_MAXIMIZED) - return META_FRAME_CONTROL_UNMAXIMIZE; - else - return META_FRAME_CONTROL_MAXIMIZE; - } - - if (POINT_IN_RECT (x, y, fgeom.shade_rect.clickable)) - { - return META_FRAME_CONTROL_SHADE; - } - - if (POINT_IN_RECT (x, y, fgeom.unshade_rect.clickable)) - { - return META_FRAME_CONTROL_UNSHADE; - } - - if (POINT_IN_RECT (x, y, fgeom.above_rect.clickable)) - { - return META_FRAME_CONTROL_ABOVE; - } - - if (POINT_IN_RECT (x, y, fgeom.unabove_rect.clickable)) - { - return META_FRAME_CONTROL_UNABOVE; - } - - if (POINT_IN_RECT (x, y, fgeom.stick_rect.clickable)) - { - return META_FRAME_CONTROL_STICK; - } - - if (POINT_IN_RECT (x, y, fgeom.unstick_rect.clickable)) - { - return META_FRAME_CONTROL_UNSTICK; - } - - /* South resize always has priority over north resize, - * in case of overlap. - */ - - if (y >= (fgeom.height - fgeom.borders.total.bottom - RESIZE_EXTENDS) && - x >= (fgeom.width - fgeom.borders.total.right - RESIZE_EXTENDS)) - { - if (has_vert && has_horiz) - return META_FRAME_CONTROL_RESIZE_SE; - else if (has_vert) - return META_FRAME_CONTROL_RESIZE_S; - else if (has_horiz) - return META_FRAME_CONTROL_RESIZE_E; - } - else if (y >= (fgeom.height - fgeom.borders.total.bottom - RESIZE_EXTENDS) && - x <= (fgeom.borders.total.left + RESIZE_EXTENDS)) - { - if (has_vert && has_horiz) - return META_FRAME_CONTROL_RESIZE_SW; - else if (has_vert) - return META_FRAME_CONTROL_RESIZE_S; - else if (has_horiz) - return META_FRAME_CONTROL_RESIZE_W; - } - else if (y < (fgeom.borders.invisible.top + RESIZE_EXTENDS) && - x <= (fgeom.borders.total.left + RESIZE_EXTENDS) && has_north_resize) - { - if (has_vert && has_horiz) - return META_FRAME_CONTROL_RESIZE_NW; - else if (has_vert) - return META_FRAME_CONTROL_RESIZE_N; - else if (has_horiz) - return META_FRAME_CONTROL_RESIZE_W; - } - else if (y < (fgeom.borders.invisible.top + RESIZE_EXTENDS) && - x >= (fgeom.width - fgeom.borders.total.right - RESIZE_EXTENDS) && has_north_resize) - { - if (has_vert && has_horiz) - return META_FRAME_CONTROL_RESIZE_NE; - else if (has_vert) - return META_FRAME_CONTROL_RESIZE_N; - else if (has_horiz) - return META_FRAME_CONTROL_RESIZE_E; - } - else if (y < (fgeom.borders.invisible.top + TOP_RESIZE_HEIGHT)) - { - if (has_vert && has_north_resize) - return META_FRAME_CONTROL_RESIZE_N; - } - else if (y >= (fgeom.height - fgeom.borders.total.bottom - RESIZE_EXTENDS)) - { - if (has_vert) - return META_FRAME_CONTROL_RESIZE_S; - } - else if (x <= fgeom.borders.total.left + RESIZE_EXTENDS) - { - if (has_horiz) - return META_FRAME_CONTROL_RESIZE_W; - } - else if (x >= (fgeom.width - fgeom.borders.total.right - RESIZE_EXTENDS)) - { - if (has_horiz) - return META_FRAME_CONTROL_RESIZE_E; - } - - if (y >= fgeom.borders.total.top) - return META_FRAME_CONTROL_NONE; - else - return META_FRAME_CONTROL_TITLE; -} - void meta_frames_push_delay_exposes (MetaFrames *frames) { |