From c352e1078ec201ca8bd5fe79974df2473fe17054 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Sun, 19 Jun 2011 00:55:10 +0200 Subject: [PATCH] core: Keep track of per pointer/keyboard grabs There is now a MetaGrabInfo struct, holding all information about an ongoing grab, there were unfortunately no means of making this commit smaller, as things are too intertwined to separate it, On places where it was most obvious, the correct device has been used (in reaction to events, for example), in other parts, the private API has been extended to include the MetaDevice (or device ID for core.h functions), in other places, the virtual core pointer/keyboard are used out of cluelessness. --- src/compositor/compositor.c | 35 ++- src/core/constraints.c | 5 +- src/core/core.c | 86 +++--- src/core/core.h | 12 +- src/core/device-map-private.h | 6 + src/core/devices-core.c | 1 + src/core/devices-core.h | 5 - src/core/display-private.h | 92 +++--- src/core/display.c | 520 +++++++++++++++++++++------------- src/core/edge-resistance.c | 177 +++++++----- src/core/edge-resistance.h | 39 +-- src/core/frame.c | 3 +- src/core/keybindings.c | 181 ++++++++---- src/core/screen.c | 12 +- src/core/window-private.h | 10 +- src/core/window.c | 449 +++++++++++++++++++---------- src/core/workspace.c | 28 +- src/meta/display.h | 5 + src/ui/frames.c | 109 +++---- src/ui/frames.h | 3 +- src/ui/menu.c | 4 +- src/ui/tile-preview.c | 2 + src/ui/tile-preview.h | 2 + 23 files changed, 1122 insertions(+), 664 deletions(-) diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index 261ece209..702448a23 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -364,8 +364,17 @@ meta_begin_modal_for_plugin (MetaScreen *screen, gboolean pointer_grabbed = FALSE; gboolean keyboard_grabbed = FALSE; int result; + MetaDevice *device; + MetaGrabInfo *grab_info; - if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE) + /* FIXME: need a real device here, and probably + * some exclusion mode for other devices */ + device = meta_device_map_lookup (display->device_map, + META_CORE_POINTER_ID); + + grab_info = meta_display_get_grab_info (display, device); + + if (compositor->modal_plugin != NULL || grab_info != NULL) return FALSE; if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0) @@ -397,11 +406,13 @@ meta_begin_modal_for_plugin (MetaScreen *screen, keyboard_grabbed = TRUE; } - display->grab_op = META_GRAB_OP_COMPOSITOR; - display->grab_window = NULL; - display->grab_screen = screen; - display->grab_have_pointer = TRUE; - display->grab_have_keyboard = TRUE; + grab_info = meta_display_create_grab_info (display, device); + + grab_info->grab_op = META_GRAB_OP_COMPOSITOR; + grab_info->grab_window = NULL; + grab_info->grab_screen = screen; + grab_info->grab_have_pointer = TRUE; + grab_info->grab_have_keyboard = TRUE; compositor->modal_plugin = plugin; @@ -424,18 +435,18 @@ meta_end_modal_for_plugin (MetaScreen *screen, MetaDisplay *display = meta_screen_get_display (screen); Display *xdpy = meta_display_get_xdisplay (display); MetaCompositor *compositor = display->compositor; + MetaDevice *device; g_return_if_fail (compositor->modal_plugin == plugin); + /* FIXME: need a real device here */ + device = meta_device_map_lookup (display->device_map, + META_CORE_POINTER_ID); + XUngrabPointer (xdpy, timestamp); XUngrabKeyboard (xdpy, timestamp); - display->grab_op = META_GRAB_OP_NONE; - display->grab_window = NULL; - display->grab_screen = NULL; - display->grab_have_pointer = FALSE; - display->grab_have_keyboard = FALSE; - + meta_display_remove_grab_info (display, device); compositor->modal_plugin = NULL; } diff --git a/src/core/constraints.c b/src/core/constraints.c index 67078a009..b6014613d 100644 --- a/src/core/constraints.c +++ b/src/core/constraints.c @@ -1362,15 +1362,18 @@ constrain_titlebar_visible (MetaWindow *window, int bottom_amount; int horiz_amount_offscreen, vert_amount_offscreen; int horiz_amount_onscreen, vert_amount_onscreen; + MetaGrabInfo *grab_info; if (priority > PRIORITY_TITLEBAR_VISIBLE) return TRUE; + grab_info = window->cur_grab; + /* Allow the titlebar beyond the top of the screen only if the user wasn't * clicking on the frame to start the move. */ unconstrained_user_action = - info->is_user_action && !window->display->grab_frame_action; + info->is_user_action && (!grab_info || !grab_info->grab_frame_action); /* Exit early if we know the constraint won't apply--note that this constraint * is only meant for normal windows (e.g. we don't want docks to be shoved diff --git a/src/core/core.c b/src/core/core.c index 002e6eab4..0607525c8 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -268,16 +268,21 @@ meta_core_user_lower_and_unfocus (Display *xdisplay, void meta_core_lower_beneath_grab_window (Display *xdisplay, Window xwindow, + int device_id, guint32 timestamp) { XWindowChanges changes; MetaDisplay *display; MetaScreen *screen; MetaWindow *grab_window; + MetaDevice *pointer; + MetaGrabInfo *grab_info; display = meta_display_for_x_display (xdisplay); screen = meta_display_screen_for_xwindow (display, xwindow); - grab_window = display->grab_window; + pointer = meta_device_map_lookup (display->device_map, device_id); + grab_info = meta_display_get_grab_info (display, pointer); + grab_window = grab_info->grab_window; if (grab_window == NULL) return; @@ -643,6 +648,7 @@ meta_core_get_workspace_name_with_index (Display *xdisplay, gboolean meta_core_begin_grab_op (Display *xdisplay, Window frame_xwindow, + int device_id, MetaGrabOp op, gboolean pointer_already_grabbed, gboolean frame_action, @@ -655,13 +661,16 @@ meta_core_begin_grab_op (Display *xdisplay, MetaWindow *window = get_window (xdisplay, frame_xwindow); MetaDisplay *display; MetaScreen *screen; - + MetaDevice *device; + display = meta_display_for_x_display (xdisplay); screen = meta_display_screen_for_xwindow (display, frame_xwindow); g_assert (screen != NULL); - - return meta_display_begin_grab_op (display, screen, window, + + device = meta_device_map_lookup (display->device_map, device_id); + + return meta_display_begin_grab_op (display, screen, window, device, op, pointer_already_grabbed, frame_action, button, modmask, @@ -670,57 +679,58 @@ meta_core_begin_grab_op (Display *xdisplay, void meta_core_end_grab_op (Display *xdisplay, + int device_id, guint32 timestamp) { MetaDisplay *display; - - display = meta_display_for_x_display (xdisplay); + MetaDevice *device; - meta_display_end_grab_op (display, timestamp); + display = meta_display_for_x_display (xdisplay); + device = meta_device_map_lookup (display->device_map, device_id); + + meta_display_end_grab_op (display, device, timestamp); } MetaGrabOp -meta_core_get_grab_op (Display *xdisplay) +meta_core_frame_has_grab (Display *xdisplay, + Window frame_xwindow, + gint *device_id, + gint *button_ret) { - MetaDisplay *display; - - display = meta_display_for_x_display (xdisplay); + MetaWindow *window; - return display->grab_op; + window = get_window (xdisplay, frame_xwindow); + + if (window != NULL && + window->cur_grab != NULL) + { + if (button_ret) + *button_ret = window->cur_grab->grab_button; + + if (device_id) + *device_id = meta_device_get_id (window->cur_grab->grab_pointer); + + return window->cur_grab->grab_op; + } + + return META_GRAB_OP_NONE; } Window -meta_core_get_grab_frame (Display *xdisplay) +meta_core_get_frame (Display *xdisplay, + Window client_xwindow) { MetaDisplay *display; - + MetaWindow *window; + display = meta_display_for_x_display (xdisplay); + window = meta_display_lookup_x_window (display, client_xwindow); - g_assert (display != NULL); - g_assert (display->grab_op == META_GRAB_OP_NONE || - display->grab_screen != NULL); - g_assert (display->grab_op == META_GRAB_OP_NONE || - display->grab_screen->display->xdisplay == xdisplay); - - if (display->grab_op != META_GRAB_OP_NONE && - display->grab_window && - display->grab_window->frame) - return display->grab_window->frame->xwindow; - else - return None; -} + if (window && + window->frame) + return window->frame->xwindow; -int -meta_core_get_grab_button (Display *xdisplay) -{ - MetaDisplay *display; - - display = meta_display_for_x_display (xdisplay); - - if (display->grab_op == META_GRAB_OP_NONE) - return -1; - - return display->grab_button; + return None; } void diff --git a/src/core/core.h b/src/core/core.h index 95f8f466d..ba269672a 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -118,6 +118,7 @@ void meta_core_user_focus (Display *xdisplay, void meta_core_lower_beneath_grab_window (Display *xdisplay, Window xwindow, + int device_id, guint32 timestamp); void meta_core_minimize (Display *xdisplay, @@ -175,6 +176,7 @@ void meta_core_get_menu_accelerator (MetaMenuOp menu_op, gboolean meta_core_begin_grab_op (Display *xdisplay, Window frame_xwindow, + int device_id, MetaGrabOp op, gboolean pointer_already_grabbed, gboolean frame_action, @@ -184,11 +186,15 @@ gboolean meta_core_begin_grab_op (Display *xdisplay, int root_x, int root_y); void meta_core_end_grab_op (Display *xdisplay, + int device_id, guint32 timestamp); -MetaGrabOp meta_core_get_grab_op (Display *xdisplay); -Window meta_core_get_grab_frame (Display *xdisplay); -int meta_core_get_grab_button (Display *xdisplay); +MetaGrabOp meta_core_frame_has_grab (Display *xdisplay, + Window frame_xwindow, + gint *device_id, + gint *button_ret); +Window meta_core_get_frame (Display *xdisplay, + Window client_xwindow); void meta_core_grab_buttons (Display *xdisplay, Window frame_xwindow); diff --git a/src/core/device-map-private.h b/src/core/device-map-private.h index 28e75f2fa..00a2fcbf8 100644 --- a/src/core/device-map-private.h +++ b/src/core/device-map-private.h @@ -35,6 +35,12 @@ #include "display-private.h" #include "device-private.h" +/* Device IDs for Virtual Core Pointer/Keyboard, + * use only in case of emergency. + */ +#define META_CORE_POINTER_ID 2 +#define META_CORE_KEYBOARD_ID 3 + struct _MetaDeviceMap { GObject parent_instance; diff --git a/src/core/devices-core.c b/src/core/devices-core.c index 755d40cf5..d4ad7cf4b 100644 --- a/src/core/devices-core.c +++ b/src/core/devices-core.c @@ -24,6 +24,7 @@ #include #include "screen-private.h" #include "devices-core.h" +#include "device-map-private.h" /* Common functions */ static void diff --git a/src/core/devices-core.h b/src/core/devices-core.h index bdb938f08..7b7e89fd2 100644 --- a/src/core/devices-core.h +++ b/src/core/devices-core.h @@ -32,11 +32,6 @@ #include "device-pointer.h" #include "device-keyboard.h" -/* These IDs are the same than those of the - * VCP/VCK in XInput2, to keep consistency */ -#define META_CORE_POINTER_ID 2 -#define META_CORE_KEYBOARD_ID 3 - /* Pointer */ #define META_TYPE_DEVICE_POINTER_CORE (meta_device_pointer_core_get_type ()) #define META_DEVICE_POINTER_CORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_POINTER_CORE, MetaDevicePointerCore)) diff --git a/src/core/display-private.h b/src/core/display-private.h index 7e428ff45..b0cea08da 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -57,6 +57,8 @@ typedef struct _MetaWindowPropHooks MetaWindowPropHooks; typedef struct MetaEdgeResistanceData MetaEdgeResistanceData; +typedef struct _MetaGrabInfo MetaGrabInfo; + typedef void (* MetaWindowPingFunc) (MetaDisplay *display, Window xwindow, guint32 timestamp, @@ -85,6 +87,45 @@ typedef enum { META_TILE_MAXIMIZED } MetaTileMode; +struct _MetaGrabInfo +{ + MetaDevice *grab_pointer; + MetaDevice *grab_keyboard; + + MetaGrabOp grab_op; + MetaScreen *grab_screen; + MetaWindow *grab_window; + Window grab_xwindow; + int grab_button; + int grab_anchor_root_x; + int grab_anchor_root_y; + MetaRectangle grab_anchor_window_pos; + MetaTileMode grab_tile_mode; + int grab_latest_motion_x; + int grab_latest_motion_y; + gulong grab_mask; + guint grab_have_pointer : 1; + guint grab_have_keyboard : 1; + guint grab_frame_action : 1; + /* During a resize operation, the directions in which we've broken + * out of the initial maximization state */ + guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */ + MetaRectangle grab_initial_window_pos; + int grab_initial_x, grab_initial_y; /* These are only relevant for */ + gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */ + MetaResizePopup *grab_resize_popup; + GTimeVal grab_last_moveresize_time; + guint32 grab_motion_notify_time; + GList* grab_old_window_stacking; + unsigned int grab_last_user_action_was_snap; + +#ifdef HAVE_XSYNC + /* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */ + XSyncAlarm grab_sync_request_alarm; +#endif + int grab_resize_timeout_id; +}; + struct _MetaDisplay { GObject parent_instance; @@ -178,34 +219,11 @@ struct _MetaDisplay /* Alt+click button grabs */ unsigned int window_grab_modifiers; - /* current window operation */ - MetaGrabOp grab_op; - MetaScreen *grab_screen; - MetaWindow *grab_window; - Window grab_xwindow; - int grab_button; - int grab_anchor_root_x; - int grab_anchor_root_y; - MetaRectangle grab_anchor_window_pos; - MetaTileMode grab_tile_mode; - int grab_latest_motion_x; - int grab_latest_motion_y; - gulong grab_mask; - guint grab_have_pointer : 1; - guint grab_have_keyboard : 1; - guint grab_frame_action : 1; - /* During a resize operation, the directions in which we've broken - * out of the initial maximization state */ - guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */ - MetaRectangle grab_initial_window_pos; - int grab_initial_x, grab_initial_y; /* These are only relevant for */ - gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */ - MetaResizePopup *grab_resize_popup; - GTimeVal grab_last_moveresize_time; - guint32 grab_motion_notify_time; - GList* grab_old_window_stacking; - MetaEdgeResistanceData *grab_edge_resistance_data; - unsigned int grab_last_user_action_was_snap; + /* per-device current window operation */ + GHashTable *current_grabs; + + /* per-screen edge resistance cache */ + GHashTable *edge_resistance_info; /* we use property updates as sentinels for certain window focus events * to avoid some race conditions on EnterNotify events @@ -216,11 +234,6 @@ struct _MetaDisplay int xkb_base_event_type; guint32 last_bell_time; #endif -#ifdef HAVE_XSYNC - /* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */ - XSyncAlarm grab_sync_request_alarm; -#endif - int grab_resize_timeout_id; /* Keybindings stuff */ MetaKeyBinding *key_bindings; @@ -388,12 +401,14 @@ Cursor meta_display_create_x_cursor (MetaDisplay *display, void meta_display_set_grab_op_cursor (MetaDisplay *display, MetaScreen *screen, + MetaDevice *device, MetaGrabOp op, gboolean change_pointer, Window grab_xwindow, guint32 timestamp); void meta_display_check_threshold_reached (MetaDisplay *display, + MetaDevice *device, int x, int y); void meta_display_grab_window_buttons (MetaDisplay *display, @@ -407,7 +422,8 @@ void meta_display_ungrab_focus_window_button (MetaDisplay *display, MetaWindow *window); /* Next function is defined in edge-resistance.c */ -void meta_display_cleanup_edges (MetaDisplay *display); +void meta_display_cleanup_edges (MetaDisplay *display, + MetaScreen *screen); /* make a request to ensure the event serial has changed */ void meta_display_increment_event_serial (MetaDisplay *display); @@ -455,4 +471,12 @@ void meta_display_overlay_key_activate (MetaDisplay *display); /* In above-tab-keycode.c */ guint meta_display_get_above_tab_keycode (MetaDisplay *display); +MetaGrabInfo * meta_display_create_grab_info (MetaDisplay *display, + MetaDevice *device); +void meta_display_remove_grab_info (MetaDisplay *display, + MetaDevice *device); + +MetaGrabInfo * meta_display_get_grab_info (MetaDisplay *display, + MetaDevice *device); + #endif diff --git a/src/core/display.c b/src/core/display.c index 812f760f2..25fa5731d 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -48,6 +48,7 @@ #include "xprops.h" #include "workspace-private.h" #include "bell.h" +#include "device-keyboard.h" #include "device-private.h" #include "input-events.h" #include @@ -469,16 +470,11 @@ meta_display_open (void) the_display->autoraise_window = NULL; the_display->focus_window = NULL; the_display->expected_focus_window = NULL; - the_display->grab_old_window_stacking = NULL; the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */ the_display->allow_terminal_deactivation = TRUE; /* Only relevant for when a terminal has the focus */ -#ifdef HAVE_XSYNC - the_display->grab_sync_request_alarm = None; -#endif - /* FIXME copy the checks from GDK probably */ the_display->static_gravity_works = g_getenv ("MUTTER_USE_STATIC_GRAVITY") != NULL; @@ -549,20 +545,13 @@ meta_display_open (void) the_display->current_time = CurrentTime; the_display->sentinel_counter = 0; - the_display->grab_resize_timeout_id = 0; - the_display->grab_have_keyboard = FALSE; - #ifdef HAVE_XKB the_display->last_bell_time = 0; #endif - the_display->grab_op = META_GRAB_OP_NONE; - the_display->grab_window = NULL; - the_display->grab_screen = NULL; - the_display->grab_resize_popup = NULL; - the_display->grab_tile_mode = META_TILE_NONE; - - the_display->grab_edge_resistance_data = NULL; + the_display->current_grabs = g_hash_table_new_full (NULL, NULL, NULL, + (GDestroyNotify) g_free); + the_display->edge_resistance_info = g_hash_table_new (NULL, NULL); #ifdef HAVE_XSYNC { @@ -994,9 +983,6 @@ meta_display_close (MetaDisplay *display, meta_display_remove_autoraise_callback (display); - if (display->grab_old_window_stacking) - g_list_free (display->grab_old_window_stacking); - /* Stop caring about events */ meta_ui_remove_event_func (display->xdisplay, event_callback, @@ -1582,6 +1568,7 @@ event_callback (XEvent *event, MetaWindow *window; MetaWindow *property_for_window; MetaDisplay *display; + MetaGrabInfo *grab_info; Window modified; gboolean frame_was_receiver; gboolean bypass_compositor; @@ -1666,15 +1653,30 @@ event_callback (XEvent *event, #ifdef HAVE_XSYNC if (META_DISPLAY_HAS_XSYNC (display) && - event->type == (display->xsync_event_base + XSyncAlarmNotify) && - ((XSyncAlarmNotifyEvent*)event)->alarm == display->grab_sync_request_alarm) + event->type == (display->xsync_event_base + XSyncAlarmNotify)) { - filter_out_event = TRUE; /* GTK doesn't want to see this really */ - - if (display->grab_op != META_GRAB_OP_NONE && - display->grab_window != NULL && - grab_op_is_mouse (display->grab_op)) - meta_window_handle_mouse_grab_op_event (display->grab_window, event); + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, display->current_grabs); + + /* Each ongoing grab has its own sync alarm */ + while (g_hash_table_iter_next (&iter, &key, &value)) + { + grab_info = value; + + if (((XSyncAlarmNotifyEvent*)event)->alarm != grab_info->grab_sync_request_alarm) + continue; + + filter_out_event = TRUE; /* GTK doesn't want to see this really */ + + if (grab_info->grab_op != META_GRAB_OP_NONE && + grab_info->grab_window != NULL && + grab_op_is_mouse (grab_info->grab_op)) + meta_window_handle_mouse_grab_op_event (grab_info->grab_window, + event); + break; + } } #endif /* HAVE_XSYNC */ @@ -1769,12 +1771,13 @@ event_callback (XEvent *event, } device = meta_input_event_get_device (display, event); + grab_info = meta_display_get_grab_info (display, device); switch (evtype) { case KeyPress: case KeyRelease: - if (display->grab_op == META_GRAB_OP_COMPOSITOR) + if (grab_info && grab_info->grab_op == META_GRAB_OP_COMPOSITOR) break; /* For key events, it's important to enforce single-handling, or @@ -1794,26 +1797,27 @@ event_callback (XEvent *event, &ev_root_x, &ev_root_y); - if (display->grab_op == META_GRAB_OP_COMPOSITOR) + if (grab_info && grab_info->grab_op == META_GRAB_OP_COMPOSITOR) break; if (n_button == 4 || n_button == 5) /* Scrollwheel event, do nothing and deliver event to compositor below */ break; - if ((window && - grab_op_is_mouse (display->grab_op) && - display->grab_button != (int) n_button && - display->grab_window == window) || - grab_op_is_keyboard (display->grab_op)) + if (grab_info && + ((window && + grab_op_is_mouse (grab_info->grab_op) && + grab_info->grab_button != (int) n_button && + grab_info->grab_window == window) || + grab_op_is_keyboard (grab_info->grab_op))) { meta_topic (META_DEBUG_WINDOW_OPS, "Ending grab op %u on window %s due to button press\n", - display->grab_op, - (display->grab_window ? - display->grab_window->desc : + grab_info->grab_op, + (grab_info->grab_window ? + grab_info->grab_window->desc : "none")); - if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op)) + if (GRAB_OP_IS_WINDOW_SWITCH (grab_info->grab_op)) { MetaScreen *screen; meta_topic (META_DEBUG_WINDOW_OPS, @@ -1821,13 +1825,16 @@ event_callback (XEvent *event, screen = meta_display_screen_for_root (display, xwindow); + /* FIXME: won't work well with multiple + * devices messing with stacking + */ if (screen!=NULL) meta_stack_set_positions (screen->stack, - display->grab_old_window_stacking); + grab_info->grab_old_window_stacking); } - meta_display_end_grab_op (display, evtime); + meta_display_end_grab_op (display, device, evtime); } - else if (window && display->grab_op == META_GRAB_OP_NONE) + else if (window && !grab_info) { gboolean begin_move = FALSE; unsigned int grab_mask; @@ -1920,6 +1927,7 @@ event_callback (XEvent *event, meta_display_begin_grab_op (display, window->screen, window, + device, op, TRUE, FALSE, @@ -1976,6 +1984,7 @@ event_callback (XEvent *event, meta_display_begin_grab_op (display, window->screen, window, + device, META_GRAB_OP_MOVING, TRUE, FALSE, @@ -1988,27 +1997,30 @@ event_callback (XEvent *event, } break; case ButtonRelease: - if (display->grab_op == META_GRAB_OP_COMPOSITOR) + if (grab_info && grab_info->grab_op == META_GRAB_OP_COMPOSITOR) break; - if (display->grab_window == window && - grab_op_is_mouse (display->grab_op)) + if (grab_info && + grab_info->grab_window == window && + grab_op_is_mouse (grab_info->grab_op)) meta_window_handle_mouse_grab_op_event (window, event); break; case MotionNotify: - if (display->grab_op == META_GRAB_OP_COMPOSITOR) + if (grab_info && grab_info->grab_op == META_GRAB_OP_COMPOSITOR) break; - if (display->grab_window == window && - grab_op_is_mouse (display->grab_op)) + if (grab_info && + grab_info->grab_window == window && + grab_op_is_mouse (grab_info->grab_op)) meta_window_handle_mouse_grab_op_event (window, event); break; case EnterNotify: - if (display->grab_op == META_GRAB_OP_COMPOSITOR) + if (grab_info && grab_info->grab_op == META_GRAB_OP_COMPOSITOR) break; - if (display->grab_window == window && - grab_op_is_mouse (display->grab_op)) + if (grab_info && + grab_info->grab_window == window && + grab_op_is_mouse (grab_info->grab_op)) { meta_window_handle_mouse_grab_op_event (window, event); break; @@ -2101,11 +2113,12 @@ event_callback (XEvent *event, } break; case LeaveNotify: - if (display->grab_op == META_GRAB_OP_COMPOSITOR) + if (grab_info && grab_info->grab_op == META_GRAB_OP_COMPOSITOR) break; - if (display->grab_window == window && - grab_op_is_mouse (display->grab_op)) + if (grab_info && + grab_info->grab_window == window && + grab_op_is_mouse (grab_info->grab_op)) meta_window_handle_mouse_grab_op_event (window, event); else if (window != NULL) { @@ -2226,11 +2239,15 @@ event_callback (XEvent *event, * will change one day? */ guint32 timestamp; - timestamp = meta_display_get_current_time_roundtrip (display); - if (display->grab_op != META_GRAB_OP_NONE && - display->grab_window == window) - meta_display_end_grab_op (display, timestamp); + timestamp = meta_display_get_current_time_roundtrip (display); + grab_info = window->cur_grab; + + if (grab_info && + grab_info->grab_op != META_GRAB_OP_NONE) + meta_display_end_grab_op (display, + grab_info->grab_pointer, + timestamp); if (frame_was_receiver) { @@ -2256,12 +2273,16 @@ event_callback (XEvent *event, * will change one day? */ guint32 timestamp; - timestamp = meta_display_get_current_time_roundtrip (display); - if (display->grab_op != META_GRAB_OP_NONE && - display->grab_window == window && + timestamp = meta_display_get_current_time_roundtrip (display); + grab_info = window->cur_grab; + + if (grab_info && + grab_info->grab_op != META_GRAB_OP_NONE && ((window->frame == NULL) || !window->frame->mapped)) - meta_display_end_grab_op (display, timestamp); + meta_display_end_grab_op (display, + grab_info->grab_pointer, + timestamp); if (!frame_was_receiver) { @@ -3445,14 +3466,17 @@ xcursor_for_op (MetaDisplay *display, void meta_display_set_grab_op_cursor (MetaDisplay *display, MetaScreen *screen, + MetaDevice *device, MetaGrabOp op, gboolean change_pointer, Window grab_xwindow, guint32 timestamp) { + MetaGrabInfo *grab_info; Cursor cursor; cursor = xcursor_for_op (display, op); + grab_info = meta_display_get_grab_info (display, device); #define GRAB_MASK (PointerMotionMask | \ ButtonPressMask | ButtonReleaseMask | \ @@ -3473,8 +3497,8 @@ meta_display_set_grab_op_cursor (MetaDisplay *display, { meta_topic (META_DEBUG_WINDOW_OPS, "Error trapped from XChangeActivePointerGrab()\n"); - if (display->grab_have_pointer) - display->grab_have_pointer = FALSE; + if (grab_info->grab_have_pointer) + grab_info->grab_have_pointer = FALSE; } } else @@ -3491,7 +3515,7 @@ meta_display_set_grab_op_cursor (MetaDisplay *display, cursor, timestamp) == GrabSuccess) { - display->grab_have_pointer = TRUE; + grab_info->grab_have_pointer = TRUE; meta_topic (META_DEBUG_WINDOW_OPS, "XGrabPointer() returned GrabSuccess time %u\n", timestamp); @@ -3515,6 +3539,7 @@ gboolean meta_display_begin_grab_op (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, + MetaDevice *device, MetaGrabOp op, gboolean pointer_already_grabbed, gboolean frame_action, @@ -3525,22 +3550,29 @@ meta_display_begin_grab_op (MetaDisplay *display, int root_y) { MetaWindow *grab_window = NULL; + MetaGrabInfo *grab_info; Window grab_xwindow; meta_topic (META_DEBUG_WINDOW_OPS, "Doing grab op %u on window %s button %d pointer already grabbed: %d pointer pos %d,%d\n", op, window ? window->desc : "none", button, pointer_already_grabbed, root_x, root_y); + + grab_info = meta_display_get_grab_info (display, device); - if (display->grab_op != META_GRAB_OP_NONE) + if (grab_info != NULL && + grab_info->grab_op != META_GRAB_OP_NONE) { if (window) meta_warning ("Attempt to perform window operation %u on window %s when operation %u on %s already in effect\n", - op, window->desc, display->grab_op, - display->grab_window ? display->grab_window->desc : "none"); + op, window->desc, grab_info->grab_op, + grab_info->grab_window ? grab_info->grab_window->desc : "none"); return FALSE; } + if (grab_info == NULL) + grab_info = meta_display_create_grab_info (display, device); + if (window && (meta_grab_op_is_moving (op) || meta_grab_op_is_resizing (op))) { @@ -3548,9 +3580,9 @@ meta_display_begin_grab_op (MetaDisplay *display, meta_window_raise (window); else { - display->grab_initial_x = root_x; - display->grab_initial_y = root_y; - display->grab_threshold_movement_reached = FALSE; + grab_info->grab_initial_x = root_x; + grab_info->grab_initial_y = root_y; + grab_info->grab_threshold_movement_reached = FALSE; } } @@ -3576,15 +3608,15 @@ meta_display_begin_grab_op (MetaDisplay *display, else grab_xwindow = screen->xroot; - display->grab_have_pointer = FALSE; - - if (pointer_already_grabbed) - display->grab_have_pointer = TRUE; - - meta_display_set_grab_op_cursor (display, screen, op, FALSE, grab_xwindow, - timestamp); + grab_info->grab_have_pointer = FALSE; - if (!display->grab_have_pointer) + if (pointer_already_grabbed) + grab_info->grab_have_pointer = TRUE; + + meta_display_set_grab_op_cursor (display, screen, device, op, FALSE, + grab_xwindow, timestamp); + + if (!grab_info->grab_have_pointer) { meta_topic (META_DEBUG_WINDOW_OPS, "XGrabPointer() failed\n"); @@ -3595,63 +3627,64 @@ meta_display_begin_grab_op (MetaDisplay *display, if (grab_op_is_keyboard (op) || grab_op_is_mouse_only (op)) { if (grab_window) - display->grab_have_keyboard = + grab_info->grab_have_keyboard = meta_window_grab_all_keys (grab_window, timestamp); else - display->grab_have_keyboard = + grab_info->grab_have_keyboard = meta_screen_grab_all_keys (screen, timestamp); - if (!display->grab_have_keyboard) + if (!grab_info->grab_have_keyboard) { meta_topic (META_DEBUG_WINDOW_OPS, "grabbing all keys failed, ungrabbing pointer\n"); XUngrabPointer (display->xdisplay, timestamp); - display->grab_have_pointer = FALSE; + grab_info->grab_have_pointer = FALSE; return FALSE; } } - display->grab_op = op; - display->grab_window = grab_window; - display->grab_screen = screen; - display->grab_xwindow = grab_xwindow; - display->grab_button = button; - display->grab_mask = modmask; + grab_info->grab_op = op; + grab_info->grab_window = grab_window; + grab_info->grab_screen = screen; + grab_info->grab_xwindow = grab_xwindow; + grab_info->grab_button = button; + grab_info->grab_mask = modmask; if (window) - display->grab_tile_mode = window->tile_mode; + grab_info->grab_tile_mode = window->tile_mode; else - display->grab_tile_mode = META_TILE_NONE; - display->grab_anchor_root_x = root_x; - display->grab_anchor_root_y = root_y; - display->grab_latest_motion_x = root_x; - display->grab_latest_motion_y = root_y; - display->grab_last_moveresize_time.tv_sec = 0; - display->grab_last_moveresize_time.tv_usec = 0; - display->grab_motion_notify_time = 0; - display->grab_old_window_stacking = NULL; + grab_info->grab_tile_mode = META_TILE_NONE; + grab_info->grab_anchor_root_x = root_x; + grab_info->grab_anchor_root_y = root_y; + grab_info->grab_latest_motion_x = root_x; + grab_info->grab_latest_motion_y = root_y; + grab_info->grab_last_moveresize_time.tv_sec = 0; + grab_info->grab_last_moveresize_time.tv_usec = 0; + grab_info->grab_motion_notify_time = 0; + grab_info->grab_old_window_stacking = NULL; #ifdef HAVE_XSYNC - display->grab_sync_request_alarm = None; - display->grab_last_user_action_was_snap = FALSE; + grab_info->grab_sync_request_alarm = None; + grab_info->grab_last_user_action_was_snap = FALSE; #endif - display->grab_frame_action = frame_action; - display->grab_resize_unmaximize = 0; + grab_info->grab_frame_action = frame_action; + grab_info->grab_resize_unmaximize = 0; - if (display->grab_resize_timeout_id) + if (grab_info->grab_resize_timeout_id) { - g_source_remove (display->grab_resize_timeout_id); - display->grab_resize_timeout_id = 0; + g_source_remove (grab_info->grab_resize_timeout_id); + grab_info->grab_resize_timeout_id = 0; } - if (display->grab_window) + if (grab_info->grab_window) { - meta_window_get_client_root_coords (display->grab_window, - &display->grab_initial_window_pos); - display->grab_anchor_window_pos = display->grab_initial_window_pos; + grab_info->grab_window->cur_grab = grab_info; + meta_window_get_client_root_coords (grab_info->grab_window, + &grab_info->grab_initial_window_pos); + grab_info->grab_anchor_window_pos = grab_info->grab_initial_window_pos; #ifdef HAVE_XSYNC - if ( meta_grab_op_is_resizing (display->grab_op) && - display->grab_window->sync_request_counter != None) + if (meta_grab_op_is_resizing (grab_info->grab_op) && + grab_info->grab_window->sync_request_counter != None) { XSyncAlarmAttributes values; XSyncValue init; @@ -3662,90 +3695,103 @@ meta_display_begin_grab_op (MetaDisplay *display, * responses to the client messages will always trigger * a PositiveTransition */ - + XSyncIntToValue (&init, 0); XSyncSetCounter (display->xdisplay, - display->grab_window->sync_request_counter, init); - - display->grab_window->sync_request_serial = 0; - display->grab_window->sync_request_time.tv_sec = 0; - display->grab_window->sync_request_time.tv_usec = 0; - - values.trigger.counter = display->grab_window->sync_request_counter; + grab_info->grab_window->sync_request_counter, init); + + grab_info->grab_window->sync_request_serial = 0; + grab_info->grab_window->sync_request_time.tv_sec = 0; + grab_info->grab_window->sync_request_time.tv_usec = 0; + + values.trigger.counter = grab_info->grab_window->sync_request_counter; values.trigger.value_type = XSyncAbsolute; values.trigger.test_type = XSyncPositiveTransition; XSyncIntToValue (&values.trigger.wait_value, - display->grab_window->sync_request_serial + 1); - + grab_info->grab_window->sync_request_serial + 1); + /* After triggering, increment test_value by this. * (NOT wait_value above) */ XSyncIntToValue (&values.delta, 1); - + /* we want events (on by default anyway) */ values.events = True; - - display->grab_sync_request_alarm = XSyncCreateAlarm (display->xdisplay, - XSyncCACounter | - XSyncCAValueType | - XSyncCAValue | - XSyncCATestType | - XSyncCADelta | - XSyncCAEvents, - &values); + + grab_info->grab_sync_request_alarm = XSyncCreateAlarm (display->xdisplay, + XSyncCACounter | + XSyncCAValueType | + XSyncCAValue | + XSyncCATestType | + XSyncCADelta | + XSyncCAEvents, + &values); if (meta_error_trap_pop_with_return (display) != Success) - display->grab_sync_request_alarm = None; + grab_info->grab_sync_request_alarm = None; meta_topic (META_DEBUG_RESIZING, "Created update alarm 0x%lx\n", - display->grab_sync_request_alarm); + grab_info->grab_sync_request_alarm); } #endif } - + meta_topic (META_DEBUG_WINDOW_OPS, "Grab op %u on window %s successful\n", - display->grab_op, window ? window->desc : "(null)"); + grab_info->grab_op, window ? window->desc : "(null)"); - g_assert (display->grab_window != NULL || display->grab_screen != NULL); - g_assert (display->grab_op != META_GRAB_OP_NONE); + g_assert (grab_info->grab_window != NULL || grab_info->grab_screen != NULL); + g_assert (grab_info->grab_op != META_GRAB_OP_NONE); /* Save the old stacking */ - if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op)) + if (GRAB_OP_IS_WINDOW_SWITCH (grab_info->grab_op)) { meta_topic (META_DEBUG_WINDOW_OPS, "Saving old stack positions; old pointer was %p.\n", - display->grab_old_window_stacking); - display->grab_old_window_stacking = + grab_info->grab_old_window_stacking); + grab_info->grab_old_window_stacking = meta_stack_get_positions (screen->stack); } - if (display->grab_window) + if (grab_info->grab_window) { - meta_window_refresh_resize_popup (display->grab_window); + meta_window_refresh_resize_popup (grab_info->grab_window); } - + return TRUE; } void meta_display_end_grab_op (MetaDisplay *display, + MetaDevice *device, guint32 timestamp) { + MetaGrabInfo *grab_info; + + grab_info = meta_display_get_grab_info (display, device); + + if (!grab_info) + { + meta_topic (META_DEBUG_WINDOW_OPS, + "Ending non-existent grab op at time %u\n", + timestamp); + return; + } + meta_topic (META_DEBUG_WINDOW_OPS, - "Ending grab op %u at time %u\n", display->grab_op, timestamp); - - if (display->grab_op == META_GRAB_OP_NONE) + "Ending grab op %u at time %u\n", grab_info->grab_op, timestamp); + + if (grab_info->grab_op == META_GRAB_OP_NONE) return; - if (display->grab_window != NULL) - display->grab_window->shaken_loose = FALSE; - - if (display->grab_window != NULL && + if (grab_info->grab_window != NULL) + grab_info->grab_window->shaken_loose = FALSE; + + if (grab_info->grab_window != NULL && !meta_prefs_get_raise_on_click () && - (meta_grab_op_is_moving (display->grab_op) || - meta_grab_op_is_resizing (display->grab_op))) + (meta_grab_op_is_moving (grab_info->grab_op) || + meta_grab_op_is_resizing (grab_info->grab_op))) { /* Only raise the window in orthogonal raise * ('do-not-raise-on-click') mode if the user didn't try to move @@ -3753,85 +3799,95 @@ meta_display_end_grab_op (MetaDisplay *display, * For raise on click mode, the window was raised at the * beginning of the grab_op. */ - if (!display->grab_threshold_movement_reached) - meta_window_raise (display->grab_window); + if (!grab_info->grab_threshold_movement_reached) + meta_window_raise (grab_info->grab_window); } - if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op) || - display->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING) + if (GRAB_OP_IS_WINDOW_SWITCH (grab_info->grab_op) || + grab_info->grab_op == META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING) { - if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op)) - meta_screen_tab_popup_destroy (display->grab_screen); + if (GRAB_OP_IS_WINDOW_SWITCH (grab_info->grab_op)) + meta_screen_tab_popup_destroy (grab_info->grab_screen); else - meta_screen_workspace_popup_destroy (display->grab_screen); + meta_screen_workspace_popup_destroy (grab_info->grab_screen); /* If the ungrab here causes an EnterNotify, ignore it for * sloppy focus */ - display->ungrab_should_not_cause_focus_window = display->grab_xwindow; + display->ungrab_should_not_cause_focus_window = grab_info->grab_xwindow; } - + /* If this was a move or resize clear out the edge cache */ - if (meta_grab_op_is_resizing (display->grab_op) || - meta_grab_op_is_moving (display->grab_op)) + if (meta_grab_op_is_resizing (grab_info->grab_op) || + meta_grab_op_is_moving (grab_info->grab_op)) { meta_topic (META_DEBUG_WINDOW_OPS, "Clearing out the edges for resistance/snapping"); - meta_display_cleanup_edges (display); + meta_display_cleanup_edges (display, grab_info->grab_screen); } - if (display->grab_old_window_stacking != NULL) + if (grab_info->grab_old_window_stacking != NULL) { meta_topic (META_DEBUG_WINDOW_OPS, "Clearing out the old stack position, which was %p.\n", - display->grab_old_window_stacking); - g_list_free (display->grab_old_window_stacking); - display->grab_old_window_stacking = NULL; + grab_info->grab_old_window_stacking); + g_list_free (grab_info->grab_old_window_stacking); + grab_info->grab_old_window_stacking = NULL; } - if (display->grab_have_pointer) + if (grab_info->grab_have_pointer) { meta_topic (META_DEBUG_WINDOW_OPS, "Ungrabbing pointer with timestamp %u\n", timestamp); XUngrabPointer (display->xdisplay, timestamp); } - if (display->grab_have_keyboard) + if (grab_info->grab_have_keyboard) { meta_topic (META_DEBUG_WINDOW_OPS, "Ungrabbing all keys timestamp %u\n", timestamp); - if (display->grab_window) - meta_window_ungrab_all_keys (display->grab_window, timestamp); + if (grab_info->grab_window) + meta_window_ungrab_all_keys (grab_info->grab_window, timestamp); else - meta_screen_ungrab_all_keys (display->grab_screen, timestamp); + meta_screen_ungrab_all_keys (grab_info->grab_screen, timestamp); } #ifdef HAVE_XSYNC - if (display->grab_sync_request_alarm != None) + if (grab_info->grab_sync_request_alarm != None) { XSyncDestroyAlarm (display->xdisplay, - display->grab_sync_request_alarm); - display->grab_sync_request_alarm = None; + grab_info->grab_sync_request_alarm); + grab_info->grab_sync_request_alarm = None; } #endif /* HAVE_XSYNC */ - - display->grab_window = NULL; - display->grab_screen = NULL; - display->grab_xwindow = None; - display->grab_tile_mode = META_TILE_NONE; - display->grab_op = META_GRAB_OP_NONE; - if (display->grab_resize_popup) + if (grab_info->grab_resize_popup) + meta_ui_resize_popup_free (grab_info->grab_resize_popup); + + if (grab_info->grab_resize_timeout_id) { - meta_ui_resize_popup_free (display->grab_resize_popup); - display->grab_resize_popup = NULL; + g_source_remove (grab_info->grab_resize_timeout_id); + grab_info->grab_resize_timeout_id = 0; } - if (display->grab_resize_timeout_id) - { - g_source_remove (display->grab_resize_timeout_id); - display->grab_resize_timeout_id = 0; - } + if (grab_info->grab_window != NULL) + grab_info->grab_window->cur_grab = NULL; + + meta_display_remove_grab_info (display, device); +} + +MetaGrabOp +meta_display_get_device_grab_op (MetaDisplay *display, + MetaDevice *device) +{ + MetaGrabInfo *info; + + info = meta_display_get_grab_info (display, device); + + if (info) + return info->grab_op; + + return META_GRAB_OP_NONE; } /** @@ -3846,22 +3902,34 @@ meta_display_end_grab_op (MetaDisplay *display, MetaGrabOp meta_display_get_grab_op (MetaDisplay *display) { - return display->grab_op; + MetaDevice *device; + + device = meta_device_map_lookup (display->device_map, + META_CORE_POINTER_ID); + return meta_display_get_device_grab_op (display, device); } void meta_display_check_threshold_reached (MetaDisplay *display, + MetaDevice *device, int x, int y) { - /* Don't bother doing the check again if we've already reached the threshold */ - if (meta_prefs_get_raise_on_click () || - display->grab_threshold_movement_reached) + MetaGrabInfo *grab_info; + + grab_info = meta_display_get_grab_info (display, device); + + if (!grab_info) return; - if (ABS (display->grab_initial_x - x) >= 8 || - ABS (display->grab_initial_y - y) >= 8) - display->grab_threshold_movement_reached = TRUE; + /* Don't bother doing the check again if we've already reached the threshold */ + if (meta_prefs_get_raise_on_click () || + grab_info->grab_threshold_movement_reached) + return; + + if (ABS (grab_info->grab_initial_x - x) >= 8 || + ABS (grab_info->grab_initial_y - y) >= 8) + grab_info->grab_threshold_movement_reached = TRUE; } static void @@ -5553,3 +5621,63 @@ meta_display_get_device_map (MetaDisplay *display) return display->device_map; } + +MetaGrabInfo * +meta_display_create_grab_info (MetaDisplay *display, + MetaDevice *device) +{ + MetaGrabInfo *grab_info; + gpointer key; + + g_assert (meta_display_get_grab_info (display, device) == NULL); + + grab_info = g_new0 (MetaGrabInfo, 1); + + if (META_IS_DEVICE_KEYBOARD (device)) + { + grab_info->grab_keyboard = device; + grab_info->grab_pointer = meta_device_get_paired_device (device); + } + else + { + grab_info->grab_pointer = device; + grab_info->grab_keyboard = meta_device_get_paired_device (device); + } + + key = GINT_TO_POINTER (meta_device_get_id (grab_info->grab_pointer)); + g_hash_table_insert (display->current_grabs, key, grab_info); + + return grab_info; +} + +void +meta_display_remove_grab_info (MetaDisplay *display, + MetaDevice *device) +{ + g_hash_table_remove (display->current_grabs, + GINT_TO_POINTER (meta_device_get_id (device))); + + device = meta_device_get_paired_device (device); + g_hash_table_remove (display->current_grabs, + GINT_TO_POINTER (meta_device_get_id (device))); +} + +MetaGrabInfo * +meta_display_get_grab_info (MetaDisplay *display, + MetaDevice *device) +{ + MetaGrabInfo *info; + + info = g_hash_table_lookup (display->current_grabs, + GINT_TO_POINTER (meta_device_get_id (device))); + + if (!info) + { + /* Try with the paired device */ + device = meta_device_get_paired_device (device); + info = g_hash_table_lookup (display->current_grabs, + GINT_TO_POINTER (meta_device_get_id (device))); + } + + return info; +} diff --git a/src/core/edge-resistance.c b/src/core/edge-resistance.c index 597200216..18fbb26ff 100644 --- a/src/core/edge-resistance.c +++ b/src/core/edge-resistance.c @@ -30,12 +30,12 @@ /* A simple macro for whether a given window's edges are potentially * relevant for resistance/snapping during a move/resize operation */ -#define WINDOW_EDGES_RELEVANT(window, display) \ - meta_window_should_be_showing (window) && \ - window->screen == display->grab_screen && \ - window != display->grab_window && \ - window->type != META_WINDOW_DESKTOP && \ - window->type != META_WINDOW_MENU && \ +#define WINDOW_EDGES_RELEVANT(window, display, screen) \ + meta_window_should_be_showing (window) && \ + window->screen == screen && \ + window->cur_grab == NULL && \ + window->type != META_WINDOW_DESKTOP && \ + window->type != META_WINDOW_MENU && \ window->type != META_WINDOW_SPLASHSCREEN struct ResistanceDataForAnEdge @@ -44,8 +44,9 @@ struct ResistanceDataForAnEdge guint timeout_id; int timeout_edge_pos; gboolean timeout_over; - GSourceFunc timeout_func; + MetaEdgeResistanceFunc timeout_func; MetaWindow *window; + MetaDevice *device; int keyboard_buildup; }; typedef struct ResistanceDataForAnEdge ResistanceDataForAnEdge; @@ -63,7 +64,9 @@ struct MetaEdgeResistanceData ResistanceDataForAnEdge bottom_data; }; -static void compute_resistance_and_snapping_edges (MetaDisplay *display); +static MetaEdgeResistanceData * + compute_resistance_and_snapping_edges (MetaDisplay *display, + MetaScreen *screen); /* !WARNING!: this function can return invalid indices (namely, either -1 or * edges->len); this is by design, but you need to remember this. @@ -318,20 +321,22 @@ edge_resistance_timeout (gpointer data) resistance_data->timeout_over = TRUE; resistance_data->timeout_id = 0; - (*resistance_data->timeout_func)(resistance_data->window); + (*resistance_data->timeout_func) (resistance_data->window, + resistance_data->device); return FALSE; } static int apply_edge_resistance (MetaWindow *window, + MetaDevice *device, int old_pos, int new_pos, const MetaRectangle *old_rect, const MetaRectangle *new_rect, GArray *edges, ResistanceDataForAnEdge *resistance_data, - GSourceFunc timeout_func, + MetaEdgeResistanceFunc timeout_func, gboolean xdir, gboolean keyboard_op) { @@ -445,6 +450,7 @@ apply_edge_resistance (MetaWindow *window, resistance_data->timeout_over = FALSE; resistance_data->timeout_func = timeout_func; resistance_data->window = window; + resistance_data->device = device; } if (!resistance_data->timeout_over && timeout_length_ms != 0) @@ -533,29 +539,28 @@ apply_edge_snapping (int old_pos, * a proposed new position (ignoring edge resistance/snapping), and then * applies edge resistance to EACH edge (separately) updating new_outer. * It returns true if new_outer is modified, false otherwise. - * - * display->grab_edge_resistance_data MUST already be setup or calling this - * function will cause a crash. */ static gboolean -apply_edge_resistance_to_each_side (MetaDisplay *display, - MetaWindow *window, - const MetaRectangle *old_outer, - MetaRectangle *new_outer, - GSourceFunc timeout_func, - gboolean auto_snap, - gboolean keyboard_op, - gboolean is_resize) +apply_edge_resistance_to_each_side (MetaDisplay *display, + MetaWindow *window, + MetaDevice *device, + const MetaRectangle *old_outer, + MetaRectangle *new_outer, + MetaEdgeResistanceFunc timeout_func, + gboolean auto_snap, + gboolean keyboard_op, + gboolean is_resize) { MetaEdgeResistanceData *edge_data; MetaRectangle modified_rect; gboolean modified; int new_left, new_right, new_top, new_bottom; - if (display->grab_edge_resistance_data == NULL) - compute_resistance_and_snapping_edges (display); + edge_data = g_hash_table_lookup (display->edge_resistance_info, + window->screen); - edge_data = display->grab_edge_resistance_data; + if (!edge_data) + edge_data = compute_resistance_and_snapping_edges (display, window->screen); if (auto_snap) { @@ -601,7 +606,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display, if (!is_resize || window->size_hints.width_inc == 1) { /* Now, apply the normal horizontal edge resistance */ - new_left = apply_edge_resistance (window, + new_left = apply_edge_resistance (window, device, BOX_LEFT (*old_outer), BOX_LEFT (*new_outer), old_outer, @@ -611,7 +616,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display, timeout_func, TRUE, keyboard_op); - new_right = apply_edge_resistance (window, + new_right = apply_edge_resistance (window, device, BOX_RIGHT (*old_outer), BOX_RIGHT (*new_outer), old_outer, @@ -630,7 +635,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display, /* Same for vertical resizes... */ if (!is_resize || window->size_hints.height_inc == 1) { - new_top = apply_edge_resistance (window, + new_top = apply_edge_resistance (window, device, BOX_TOP (*old_outer), BOX_TOP (*new_outer), old_outer, @@ -640,7 +645,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display, timeout_func, FALSE, keyboard_op); - new_bottom = apply_edge_resistance (window, + new_bottom = apply_edge_resistance (window, device, BOX_BOTTOM (*old_outer), BOX_BOTTOM (*new_outer), old_outer, @@ -669,15 +674,20 @@ apply_edge_resistance_to_each_side (MetaDisplay *display, } void -meta_display_cleanup_edges (MetaDisplay *display) +meta_display_cleanup_edges (MetaDisplay *display, + MetaScreen *screen) { guint i,j; - MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data; + MetaEdgeResistanceData *edge_data; GHashTable *edges_to_be_freed; + edge_data = g_hash_table_lookup (display->edge_resistance_info, screen); + if (edge_data == NULL) /* Not currently cached */ return; + g_hash_table_steal (display->edge_resistance_info, screen); + /* We first need to clean out any window edges */ edges_to_be_freed = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_free, NULL); @@ -750,8 +760,7 @@ meta_display_cleanup_edges (MetaDisplay *display) edge_data->bottom_data.timeout_id != 0) g_source_remove (edge_data->bottom_data.timeout_id); - g_free (display->grab_edge_resistance_data); - display->grab_edge_resistance_data = NULL; + g_free (edge_data); } static int @@ -763,8 +772,9 @@ stupid_sort_requiring_extra_pointer_dereference (gconstpointer a, return meta_rectangle_edge_cmp_ignore_type (*a_edge, *b_edge); } -static void +static MetaEdgeResistanceData * cache_edges (MetaDisplay *display, + MetaScreen *screen, GList *window_edges, GList *monitor_edges, GList *screen_edges) @@ -848,9 +858,8 @@ cache_edges (MetaDisplay *display, /* * 2nd: Allocate the edges */ - g_assert (display->grab_edge_resistance_data == NULL); - display->grab_edge_resistance_data = g_new0 (MetaEdgeResistanceData, 1); - edge_data = display->grab_edge_resistance_data; + edge_data = g_new0 (MetaEdgeResistanceData, 1); + edge_data->left_edges = g_array_sized_new (FALSE, FALSE, sizeof(MetaEdge*), @@ -917,21 +926,21 @@ cache_edges (MetaDisplay *display, * avoided this sort by sticking them into the array with some simple * merging of the lists). */ - g_array_sort (display->grab_edge_resistance_data->left_edges, + g_array_sort (edge_data->left_edges, stupid_sort_requiring_extra_pointer_dereference); - g_array_sort (display->grab_edge_resistance_data->right_edges, + g_array_sort (edge_data->right_edges, stupid_sort_requiring_extra_pointer_dereference); - g_array_sort (display->grab_edge_resistance_data->top_edges, + g_array_sort (edge_data->top_edges, stupid_sort_requiring_extra_pointer_dereference); - g_array_sort (display->grab_edge_resistance_data->bottom_edges, + g_array_sort (edge_data->bottom_edges, stupid_sort_requiring_extra_pointer_dereference); + + return edge_data; } static void -initialize_grab_edge_resistance_data (MetaDisplay *display) +initialize_grab_edge_resistance_data (MetaEdgeResistanceData *edge_data) { - MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data; - edge_data->left_data.timeout_setup = FALSE; edge_data->right_data.timeout_setup = FALSE; edge_data->top_data.timeout_setup = FALSE; @@ -943,8 +952,9 @@ initialize_grab_edge_resistance_data (MetaDisplay *display) edge_data->bottom_data.keyboard_buildup = 0; } -static void -compute_resistance_and_snapping_edges (MetaDisplay *display) +static MetaEdgeResistanceData * +compute_resistance_and_snapping_edges (MetaDisplay *display, + MetaScreen *screen) { GList *stacked_windows; GList *cur_window_iter; @@ -956,18 +966,17 @@ compute_resistance_and_snapping_edges (MetaDisplay *display) * in the layer that we are working on */ GSList *rem_windows, *rem_win_stacking; + MetaEdgeResistanceData *edge_data; - g_assert (display->grab_window != NULL); meta_topic (META_DEBUG_WINDOW_OPS, - "Computing edges to resist-movement or snap-to for %s.\n", - display->grab_window->desc); + "Computing edges to resist-movement or snap-to for screen %s.\n", + screen->screen_name); /* * 1st: Get the list of relevant windows, from bottom to top */ stacked_windows = - meta_stack_list_windows (display->grab_screen->stack, - display->grab_screen->active_workspace); + meta_stack_list_windows (screen->stack, screen->active_workspace); /* * 2nd: we need to separate that stacked list into a list of windows that @@ -981,7 +990,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display) while (cur_window_iter != NULL) { MetaWindow *cur_window = cur_window_iter->data; - if (WINDOW_EDGES_RELEVANT (cur_window, display)) + if (WINDOW_EDGES_RELEVANT (cur_window, display, screen)) { MetaRectangle *new_rect; new_rect = g_new (MetaRectangle, 1); @@ -1016,7 +1025,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display) * resistance (note that dock edges are considered screen edges * which are handled separately */ - if (WINDOW_EDGES_RELEVANT (cur_window, display) && + if (WINDOW_EDGES_RELEVANT (cur_window, display, screen) && cur_window->type != META_WINDOW_DOCK) { GList *new_edges; @@ -1028,7 +1037,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display) * by other windows or DOCKS, but that's handled below). */ meta_rectangle_intersect (&cur_rect, - &display->grab_screen->rect, + &screen->rect, &reduced); new_edges = NULL; @@ -1123,32 +1132,36 @@ compute_resistance_and_snapping_edges (MetaDisplay *display) * monitor edges in an array for quick access. Free the edges since * they've been cached elsewhere. */ - cache_edges (display, - edges, - display->grab_screen->active_workspace->monitor_edges, - display->grab_screen->active_workspace->screen_edges); + edge_data = cache_edges (display, screen, + edges, + screen->active_workspace->monitor_edges, + screen->active_workspace->screen_edges); g_list_free (edges); /* * 6th: Initialize the resistance timeouts and buildups */ - initialize_grab_edge_resistance_data (display); + initialize_grab_edge_resistance_data (edge_data); + + return edge_data; } /* Note that old_[xy] and new_[xy] are with respect to inner positions of * the window. */ void -meta_window_edge_resistance_for_move (MetaWindow *window, - int old_x, - int old_y, - int *new_x, - int *new_y, - GSourceFunc timeout_func, - gboolean snap, - gboolean is_keyboard_op) +meta_window_edge_resistance_for_move (MetaWindow *window, + MetaDevice *device, + int old_x, + int old_y, + int *new_x, + int *new_y, + MetaEdgeResistanceFunc timeout_func, + gboolean snap, + gboolean is_keyboard_op) { MetaRectangle old_outer, proposed_outer, new_outer; + MetaGrabInfo *grab_info; gboolean is_resize; meta_window_get_outer_rect (window, &old_outer); @@ -1158,10 +1171,14 @@ meta_window_edge_resistance_for_move (MetaWindow *window, proposed_outer.y += (*new_y - old_y); new_outer = proposed_outer; - window->display->grab_last_user_action_was_snap = snap; + grab_info = meta_display_get_grab_info (window->display, device); + g_assert (grab_info != NULL); + + grab_info->grab_last_user_action_was_snap = snap; is_resize = FALSE; if (apply_edge_resistance_to_each_side (window->display, window, + device, &old_outer, &new_outer, timeout_func, @@ -1223,18 +1240,20 @@ meta_window_edge_resistance_for_move (MetaWindow *window, * sizes of the inner window. */ void -meta_window_edge_resistance_for_resize (MetaWindow *window, - int old_width, - int old_height, - int *new_width, - int *new_height, - int gravity, - GSourceFunc timeout_func, - gboolean snap, - gboolean is_keyboard_op) +meta_window_edge_resistance_for_resize (MetaWindow *window, + MetaDevice *device, + int old_width, + int old_height, + int *new_width, + int *new_height, + int gravity, + MetaEdgeResistanceFunc timeout_func, + gboolean snap, + gboolean is_keyboard_op) { MetaRectangle old_outer, new_outer; int proposed_outer_width, proposed_outer_height; + MetaGrabInfo *grab_info; gboolean is_resize; meta_window_get_outer_rect (window, &old_outer); @@ -1246,10 +1265,14 @@ meta_window_edge_resistance_for_resize (MetaWindow *window, proposed_outer_width, proposed_outer_height); - window->display->grab_last_user_action_was_snap = snap; + grab_info = meta_display_get_grab_info (window->display, device); + g_assert (grab_info != NULL); + + grab_info->grab_last_user_action_was_snap = snap; is_resize = TRUE; if (apply_edge_resistance_to_each_side (window->display, window, + device, &old_outer, &new_outer, timeout_func, diff --git a/src/core/edge-resistance.h b/src/core/edge-resistance.h index 14ba17a09..06fba01aa 100644 --- a/src/core/edge-resistance.h +++ b/src/core/edge-resistance.h @@ -26,23 +26,28 @@ #include "window-private.h" -void meta_window_edge_resistance_for_move (MetaWindow *window, - int old_x, - int old_y, - int *new_x, - int *new_y, - GSourceFunc timeout_func, - gboolean snap, - gboolean is_keyboard_op); -void meta_window_edge_resistance_for_resize (MetaWindow *window, - int old_width, - int old_height, - int *new_width, - int *new_height, - int gravity, - GSourceFunc timeout_func, - gboolean snap, - gboolean is_keyboard_op); +typedef gboolean (* MetaEdgeResistanceFunc) (MetaWindow *window, + MetaDevice *device); + +void meta_window_edge_resistance_for_move (MetaWindow *window, + MetaDevice *device, + int old_x, + int old_y, + int *new_x, + int *new_y, + MetaEdgeResistanceFunc func, + gboolean snap, + gboolean is_keyboard_op); +void meta_window_edge_resistance_for_resize (MetaWindow *window, + MetaDevice *device, + int old_width, + int old_height, + int *new_width, + int *new_height, + int gravity, + MetaEdgeResistanceFunc func, + gboolean snap, + gboolean is_keyboard_op); #endif /* META_EDGE_RESISTANCE_H */ diff --git a/src/core/frame.c b/src/core/frame.c index 6c38ae521..74015fd38 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -400,8 +400,7 @@ meta_frame_sync_to_window (MetaFrame *frame, /* If we're interactively resizing the frame, repaint * it immediately so we don't start to lag. */ - if (frame->window->display->grab_window == - frame->window) + if (frame->window->cur_grab != NULL) meta_ui_repaint_frame (frame->window->screen->ui, frame->xwindow); } diff --git a/src/core/keybindings.c b/src/core/keybindings.c index c789d3213..9f2c6c5d5 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -1470,16 +1470,20 @@ meta_display_process_key_event (MetaDisplay *display, all_keys_grabbed = window ? window->all_keys_grabbed : screen->all_keys_grabbed; if (all_keys_grabbed) { - if (display->grab_op == META_GRAB_OP_NONE) + MetaGrabInfo *grab_info; + + grab_info = meta_display_get_grab_info (display, keyboard); + + if (!grab_info) return TRUE; /* If we get here we have a global grab, because * we're in some special keyboard mode such as window move * mode. */ - if (window ? (window == display->grab_window) : - (screen == display->grab_screen)) + if (window ? (window == grab_info->grab_window) : + (screen == grab_info->grab_screen)) { - switch (display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_MOVING: case META_GRAB_OP_RESIZING_SE: @@ -1546,8 +1550,8 @@ meta_display_process_key_event (MetaDisplay *display, { meta_topic (META_DEBUG_KEYBINDINGS, "Ending grab op %u on key event sym %s\n", - display->grab_op, XKeysymToString (keysym)); - meta_display_end_grab_op (display, + grab_info->grab_op, XKeysymToString (keysym)); + meta_display_end_grab_op (display, keyboard, meta_input_event_get_time (display, event)); } @@ -1578,12 +1582,19 @@ process_mouse_move_resize_grab (MetaDisplay *display, if (keysym == XK_Escape) { + MetaGrabInfo *grab_info; + MetaDevice *device; + + device = meta_input_event_get_device (display, event); + grab_info = meta_display_get_grab_info (display, device); + g_assert (grab_info != NULL); + /* Hide the tiling preview if necessary */ if (window->tile_mode != META_TILE_NONE) meta_screen_tile_preview_hide (screen); /* Restore the original tile mode */ - window->tile_mode = display->grab_tile_mode; + window->tile_mode = grab_info->grab_tile_mode; /* End move or resize and restore to original state. If the * window was a maximized window that had been "shaken loose" we @@ -1597,12 +1608,12 @@ process_mouse_move_resize_grab (MetaDisplay *display, else if (window->tile_mode != META_TILE_NONE) meta_window_tile (window); else - meta_window_move_resize (display->grab_window, + meta_window_move_resize (grab_info->grab_window, TRUE, - display->grab_initial_window_pos.x, - display->grab_initial_window_pos.y, - display->grab_initial_window_pos.width, - display->grab_initial_window_pos.height); + grab_info->grab_initial_window_pos.x, + grab_info->grab_initial_window_pos.y, + grab_info->grab_initial_window_pos.width, + grab_info->grab_initial_window_pos.height); /* End grab */ return FALSE; @@ -1653,6 +1664,13 @@ process_keyboard_move_grab (MetaDisplay *display, if (keysym == XK_Escape) { + MetaGrabInfo *grab_info; + MetaDevice *device; + + device = meta_input_event_get_device (display, event); + grab_info = meta_display_get_grab_info (display, device); + g_assert (grab_info != NULL); + /* End move and restore to original state. If the window was a * maximized window that had been "shaken loose" we need to * remaximize it. In normal cases, we need to do a moveresize @@ -1663,12 +1681,12 @@ process_keyboard_move_grab (MetaDisplay *display, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); else - meta_window_move_resize (display->grab_window, + meta_window_move_resize (grab_info->grab_window, TRUE, - display->grab_initial_window_pos.x, - display->grab_initial_window_pos.y, - display->grab_initial_window_pos.width, - display->grab_initial_window_pos.height); + grab_info->grab_initial_window_pos.x, + grab_info->grab_initial_window_pos.y, + grab_info->grab_initial_window_pos.width, + grab_info->grab_initial_window_pos.height); } /* When moving by increments, we still snap to edges if the move @@ -1715,13 +1733,16 @@ process_keyboard_move_grab (MetaDisplay *display, if (handled) { MetaRectangle old_rect; + MetaDevice *device; + meta_topic (META_DEBUG_KEYBINDINGS, "Computed new window location %d,%d due to keypress\n", x, y); + device = meta_input_event_get_device (window->display, event); meta_window_get_client_root_coords (window, &old_rect); - meta_window_edge_resistance_for_move (window, + meta_window_edge_resistance_for_move (window, device, old_rect.x, old_rect.y, &x, @@ -1731,7 +1752,7 @@ process_keyboard_move_grab (MetaDisplay *display, TRUE); meta_window_move (window, TRUE, x, y); - meta_window_update_keyboard_move (window); + meta_window_update_keyboard_move (window, device); } return handled; @@ -1744,32 +1765,37 @@ process_keyboard_resize_grab_op_change (MetaDisplay *display, XEvent *event, KeySym keysym) { + MetaGrabInfo *grab_info; + MetaDevice *device; gboolean handled; + device = meta_input_event_get_device (display, event); + grab_info = meta_display_get_grab_info (display, device); + handled = FALSE; - switch (display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: switch (keysym) { case XK_Up: case XK_KP_Up: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; handled = TRUE; break; case XK_Down: case XK_KP_Down: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; handled = TRUE; break; case XK_Left: case XK_KP_Left: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; handled = TRUE; break; case XK_Right: case XK_KP_Right: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; handled = TRUE; break; } @@ -1780,12 +1806,12 @@ process_keyboard_resize_grab_op_change (MetaDisplay *display, { case XK_Left: case XK_KP_Left: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; handled = TRUE; break; case XK_Right: case XK_KP_Right: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; handled = TRUE; break; } @@ -1796,12 +1822,12 @@ process_keyboard_resize_grab_op_change (MetaDisplay *display, { case XK_Left: case XK_KP_Left: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; handled = TRUE; break; case XK_Right: case XK_KP_Right: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; handled = TRUE; break; } @@ -1812,12 +1838,12 @@ process_keyboard_resize_grab_op_change (MetaDisplay *display, { case XK_Up: case XK_KP_Up: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; handled = TRUE; break; case XK_Down: case XK_KP_Down: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; handled = TRUE; break; } @@ -1828,12 +1854,12 @@ process_keyboard_resize_grab_op_change (MetaDisplay *display, { case XK_Up: case XK_KP_Up: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; handled = TRUE; break; case XK_Down: case XK_KP_Down: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; handled = TRUE; break; } @@ -1852,7 +1878,7 @@ process_keyboard_resize_grab_op_change (MetaDisplay *display, if (handled) { - meta_window_update_keyboard_resize (window, TRUE); + meta_window_update_keyboard_resize (window, device, TRUE); return TRUE; } @@ -1873,6 +1899,8 @@ process_keyboard_resize_grab (MetaDisplay *display, gboolean smart_snap; int gravity; guint keycode, state; + MetaDevice *device; + MetaGrabInfo *grab_info; handled = FALSE; @@ -1887,15 +1915,18 @@ process_keyboard_resize_grab (MetaDisplay *display, if (is_modifier (display, keycode)) return TRUE; + device = meta_input_event_get_device (display, event); + grab_info = meta_display_get_grab_info (display, device); + if (keysym == XK_Escape) { /* End resize and restore to original state. */ - meta_window_move_resize (display->grab_window, + meta_window_move_resize (grab_info->grab_window, TRUE, - display->grab_initial_window_pos.x, - display->grab_initial_window_pos.y, - display->grab_initial_window_pos.width, - display->grab_initial_window_pos.height); + grab_info->grab_initial_window_pos.x, + grab_info->grab_initial_window_pos.y, + grab_info->grab_initial_window_pos.width, + grab_info->grab_initial_window_pos.height); return FALSE; } @@ -1907,7 +1938,7 @@ process_keyboard_resize_grab (MetaDisplay *display, width = window->rect.width; height = window->rect.height; - gravity = meta_resize_gravity_from_grab_op (display->grab_op); + gravity = meta_resize_gravity_from_grab_op (grab_info->grab_op); smart_snap = (state & ShiftMask) != 0; @@ -2073,7 +2104,7 @@ process_keyboard_resize_grab (MetaDisplay *display, old_rect = window->rect; /* Don't actually care about x,y */ /* Do any edge resistance/snapping */ - meta_window_edge_resistance_for_resize (window, + meta_window_edge_resistance_for_resize (window, device, old_rect.width, old_rect.height, &width, @@ -2093,23 +2124,28 @@ process_keyboard_resize_grab (MetaDisplay *display, height, gravity); - meta_window_update_keyboard_resize (window, FALSE); + meta_window_update_keyboard_resize (window, device, FALSE); } return handled; } static gboolean -end_keyboard_grab (MetaDisplay *display, - unsigned int keycode) +end_keyboard_grab (MetaDisplay *display, + MetaDevice *device, + unsigned int keycode) { + MetaGrabInfo *grab_info; + + grab_info = meta_display_get_grab_info (display, device); + #ifdef HAVE_XKB if (display->xkb_base_event_type > 0) { unsigned int primary_modifier; XkbStateRec state; - primary_modifier = get_primary_modifier (display, display->grab_mask); + primary_modifier = get_primary_modifier (display, grab_info->grab_mask); XkbGetState (display->xdisplay, XkbUseCoreKbd, &state); @@ -2119,7 +2155,7 @@ end_keyboard_grab (MetaDisplay *display, else #endif { - if (keycode_is_primary_modifier (display, keycode, display->grab_mask)) + if (keycode_is_primary_modifier (display, keycode, grab_info->grab_mask)) return TRUE; } @@ -2139,8 +2175,16 @@ process_tab_grab (MetaDisplay *display, gboolean key_used; MetaWindow *prev_window; guint evtype, keycode; + MetaDevice *device; + MetaGrabInfo *grab_info; - if (screen != display->grab_screen) + device = meta_input_event_get_device (display, event); + grab_info = meta_display_get_grab_info (display, device); + + if (!grab_info) + return FALSE; + + if (screen != grab_info->grab_screen) return FALSE; if (!meta_input_event_get_type (display, event, &evtype) || @@ -2150,7 +2194,7 @@ process_tab_grab (MetaDisplay *display, binding = display_get_keybinding (display, keysym, keycode, - display->grab_mask); + grab_info->grab_mask); if (binding) action = meta_prefs_get_keybinding_action (binding->name); else @@ -2165,7 +2209,7 @@ process_tab_grab (MetaDisplay *display, { if (evtype == KeyRelease) { - if (end_keyboard_grab (display, keycode)) + if (end_keyboard_grab (display, device, keycode)) { invoke_handler_by_name (display, screen, "tab_popup_select", NULL, event); @@ -2228,7 +2272,7 @@ process_tab_grab (MetaDisplay *display, } if (evtype == KeyRelease && - end_keyboard_grab (display, keycode)) + end_keyboard_grab (display, device, keycode)) { /* We're done, move to the new window. */ MetaWindow *target_window; @@ -2256,7 +2300,7 @@ process_tab_grab (MetaDisplay *display, meta_topic (META_DEBUG_KEYBINDINGS, "Ending grab early so we can focus the target window\n"); - meta_display_end_grab_op (display, evtime); + meta_display_end_grab_op (display, device, evtime); return TRUE; /* we already ended the grab */ } @@ -2286,7 +2330,7 @@ process_tab_grab (MetaDisplay *display, /* CYCLE_* are traditionally Escape-based actions, * and should cancel traditionally Tab-based ones. */ - switch (display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL: case META_GRAB_OP_KEYBOARD_ESCAPING_DOCK: @@ -2303,7 +2347,7 @@ process_tab_grab (MetaDisplay *display, /* SWITCH_* are traditionally Tab-based actions, * and should cancel traditionally Escape-based ones. */ - switch (display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_KEYBOARD_TABBING_NORMAL: case META_GRAB_OP_KEYBOARD_TABBING_DOCK: @@ -2314,7 +2358,7 @@ process_tab_grab (MetaDisplay *display, * we'd previously raised and unminimized. */ meta_stack_set_positions (screen->stack, - screen->display->grab_old_window_stacking); + grab_info->grab_old_window_stacking); if (prev_window && prev_window->tab_unminimized) { meta_window_minimize (prev_window); @@ -2327,7 +2371,7 @@ process_tab_grab (MetaDisplay *display, case META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD: case META_KEYBINDING_ACTION_SWITCH_GROUP: case META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD: - switch (display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_KEYBOARD_ESCAPING_GROUP: case META_GRAB_OP_KEYBOARD_TABBING_GROUP: @@ -2408,7 +2452,7 @@ process_tab_grab (MetaDisplay *display, MetaWindow *target_window; meta_stack_set_positions (screen->stack, - display->grab_old_window_stacking); + grab_info->grab_old_window_stacking); target_window = meta_screen_tab_popup_get_selected (screen); @@ -2435,7 +2479,7 @@ process_tab_grab (MetaDisplay *display, meta_topic (META_DEBUG_KEYBINDINGS, "Syncing to old stack positions.\n"); meta_stack_set_positions (screen->stack, - screen->display->grab_old_window_stacking); + grab_info->grab_old_window_stacking); if (prev_window && prev_window->tab_unminimized) { @@ -2834,9 +2878,14 @@ process_workspace_switch_grab (MetaDisplay *display, { MetaWorkspace *workspace; guint evtype, keycode; + MetaDevice *device; + MetaGrabInfo *grab_info; Time evtime; - if (screen != display->grab_screen || !screen->ws_popup) + device = meta_input_event_get_device (display, event); + grab_info = meta_display_get_grab_info (display, device); + + if (screen != grab_info->grab_screen || !screen->ws_popup) return FALSE; if (!meta_input_event_get_type (display, event, &evtype) || @@ -2846,7 +2895,7 @@ process_workspace_switch_grab (MetaDisplay *display, evtime = meta_input_event_get_time (display, event); if (evtype == KeyRelease && - end_keyboard_grab (display, keycode)) + end_keyboard_grab (display, device, keycode)) { /* We're done, move to the new workspace. */ MetaWorkspace *target_workspace; @@ -2860,7 +2909,7 @@ process_workspace_switch_grab (MetaDisplay *display, { meta_topic (META_DEBUG_KEYBINDINGS, "Ending grab so we can focus on the target workspace\n"); - meta_display_end_grab_op (display, evtime); + meta_display_end_grab_op (display, device, evtime); meta_topic (META_DEBUG_KEYBINDINGS, "Focusing default window on target workspace\n"); @@ -2896,7 +2945,7 @@ process_workspace_switch_grab (MetaDisplay *display, action = meta_display_get_keybinding_action (display, keycode, - display->grab_mask); + grab_info->grab_mask); switch (action) { @@ -3111,6 +3160,7 @@ do_choose_window (MetaDisplay *display, { MetaTabList type = binding->handler->data; MetaWindow *initial_selection; + MetaDevice *device; guint state; Time evtime; @@ -3125,6 +3175,7 @@ do_choose_window (MetaDisplay *display, backward = !backward; evtime = meta_input_event_get_time (display, event); + device = meta_input_event_get_device (display, event); initial_selection = meta_display_get_tab_next (display, type, @@ -3169,6 +3220,7 @@ do_choose_window (MetaDisplay *display, if (!meta_display_begin_grab_op (display, screen, NULL, + device, show_popup ? tab_op_from_tab_type (type) : cycle_op_from_tab_type (type), @@ -3192,7 +3244,7 @@ do_choose_window (MetaDisplay *display, "modifier was released prior to grab\n", initial_selection->desc); - meta_display_end_grab_op (display, evtime); + meta_display_end_grab_op (display, device, evtime); display->mouse_mode = FALSE; meta_window_activate (initial_selection, evtime); return; @@ -3391,6 +3443,7 @@ handle_begin_move (MetaDisplay *display, if (window->has_move_func) { meta_window_begin_grab_op (window, + meta_input_event_get_device (display, event), META_GRAB_OP_KEYBOARD_MOVING, FALSE, meta_input_event_get_time (display, event)); @@ -3408,6 +3461,7 @@ handle_begin_resize (MetaDisplay *display, if (window->has_resize_func) { meta_window_begin_grab_op (window, + meta_input_event_get_device (display, event), META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN, FALSE, meta_input_event_get_time (display, event)); @@ -3564,6 +3618,7 @@ handle_workspace_switch (MetaDisplay *display, unsigned int grab_mask; MetaWorkspace *next; gboolean grabbed_before_release; + MetaDevice *device; guint state; Time evtime; @@ -3578,10 +3633,12 @@ handle_workspace_switch (MetaDisplay *display, /* FIXME should we use binding->mask ? */ grab_mask = state & ~(display->ignored_modifier_mask); evtime = meta_input_event_get_time (display, event); + device = meta_input_event_get_device (display, event); if (!meta_display_begin_grab_op (display, screen, NULL, + device, META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING, FALSE, FALSE, @@ -3605,7 +3662,7 @@ handle_workspace_switch (MetaDisplay *display, * release event. Must end grab before we can switch * spaces. */ - meta_display_end_grab_op (display, evtime); + meta_display_end_grab_op (display, device, evtime); } meta_workspace_activate (next, evtime); diff --git a/src/core/screen.c b/src/core/screen.c index abf5dc62a..c46b101a3 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -1859,9 +1859,17 @@ static gboolean meta_screen_tile_preview_update_timeout (gpointer data) { MetaScreen *screen = data; - MetaWindow *window = screen->display->grab_window; + MetaWindow *window = NULL; gboolean composited = screen->display->compositor != NULL; gboolean needs_preview = FALSE; + MetaGrabInfo *grab_info; + GHashTableIter iter; + + /* FIXME: we're just handling the first grab we find */ + g_hash_table_iter_init (&iter, screen->display->current_grabs); + + if (g_hash_table_iter_next (&iter, NULL, (gpointer *) &grab_info)) + window = grab_info->grab_window; screen->tile_preview_timeout_id = 0; @@ -1905,7 +1913,7 @@ meta_screen_tile_preview_update_timeout (gpointer data) MetaRectangle tile_rect; meta_window_get_current_tile_area (window, &tile_rect); - meta_tile_preview_show (screen->tile_preview, &tile_rect); + meta_tile_preview_show (screen->tile_preview, pointer, &tile_rect); } else meta_tile_preview_hide (screen->tile_preview); diff --git a/src/core/window-private.h b/src/core/window-private.h index 3f7d8827d..fe15abd5d 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -395,6 +395,9 @@ struct _MetaWindow /* Focused window that is (directly or indirectly) attached to this one */ MetaWindow *attached_focus_window; + + /* Current grab op for this window, or NULL */ + MetaGrabInfo *cur_grab; }; struct _MetaWindowClass @@ -613,13 +616,16 @@ void meta_window_free_delete_dialog (MetaWindow *window); void meta_window_begin_grab_op (MetaWindow *window, + MetaDevice *device, MetaGrabOp op, gboolean frame_action, guint32 timestamp); void meta_window_update_keyboard_resize (MetaWindow *window, + MetaDevice *device, gboolean update_cursor); -void meta_window_update_keyboard_move (MetaWindow *window); +void meta_window_update_keyboard_move (MetaWindow *window, + MetaDevice *device); void meta_window_update_layer (MetaWindow *window); @@ -643,4 +649,6 @@ void meta_window_update_on_all_workspaces (MetaWindow *window); void meta_window_propagate_focus_appearance (MetaWindow *window, gboolean focused); +MetaDevice * meta_window_guess_grab_pointer (MetaWindow *window); + #endif diff --git a/src/core/window.c b/src/core/window.c index 32a23789f..76571f4c8 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -110,16 +110,20 @@ static void meta_window_move_resize_now (MetaWindow *window); static void meta_window_unqueue (MetaWindow *window, guint queuebits); static void update_move (MetaWindow *window, + MetaDevice *device, gboolean snap, int x, int y); -static gboolean update_move_timeout (gpointer data); +static gboolean update_move_timeout (MetaWindow *window, + MetaDevice *device); static void update_resize (MetaWindow *window, + MetaDevice *device, gboolean snap, int x, int y, gboolean force); -static gboolean update_resize_timeout (gpointer data); +static gboolean update_resize_timeout (MetaWindow *window, + MetaDevice *device); static gboolean should_be_on_all_workspaces (MetaWindow *window); static void meta_window_flush_calc_showing (MetaWindow *window); @@ -1567,10 +1571,12 @@ meta_window_unmanage (MetaWindow *window, invalidate_work_areas (window); } - if (window->display->grab_window == window) - meta_display_end_grab_op (window->display, timestamp); + if (window->cur_grab != NULL) + meta_display_end_grab_op (window->display, + window->cur_grab->grab_pointer, + timestamp); - g_assert (window->display->grab_window != window); + g_assert (window->cur_grab == NULL); if (window->display->focus_window == window) { @@ -3586,6 +3592,7 @@ meta_window_unmaximize_internal (MetaWindow *window, (unmaximize_vertically && window->maximized_vertically)) { MetaRectangle target_rect; + MetaGrabInfo *grab_info; meta_topic (META_DEBUG_WINDOW_OPS, "Unmaximizing %s%s\n", @@ -3599,6 +3606,8 @@ meta_window_unmaximize_internal (MetaWindow *window, window->maximized_vertically = window->maximized_vertically && !unmaximize_vertically; + grab_info = window->cur_grab; + /* Reset the tile mode for maximized tiled windows for consistency * with "normal" maximized windows, but keep other tile modes, * as side-by-side tiled windows may snap back. @@ -3668,10 +3677,11 @@ meta_window_unmaximize_internal (MetaWindow *window, * it after the actual operation, as the window may have been moved * by constraints. */ - if (meta_grab_op_is_moving (window->display->grab_op) && - window->display->grab_window == window) + if (grab_info && + meta_grab_op_is_moving (grab_info->grab_op) && + grab_info->grab_window == window) { - window->display->grab_anchor_window_pos = window->user_rect; + grab_info->grab_anchor_window_pos = window->user_rect; } recalc_window_features (window); @@ -4657,6 +4667,8 @@ meta_window_move_resize_internal (MetaWindow *window, if (mask != 0) { + MetaGrabInfo *grab_info; + { int newx, newy; meta_window_get_position (window, &newx, &newy); @@ -4670,10 +4682,11 @@ meta_window_move_resize_internal (MetaWindow *window, } meta_error_trap_push (window->display); + grab_info = window->cur_grab; #ifdef HAVE_XSYNC if (window->sync_request_counter != None && - window->display->grab_sync_request_alarm != None && + grab_info && grab_info->grab_sync_request_alarm != None && window->sync_request_time.tv_usec == 0 && window->sync_request_time.tv_sec == 0) { @@ -5214,6 +5227,8 @@ meta_window_focus (MetaWindow *window, guint32 timestamp) { MetaWindow *modal_transient; + MetaGrabInfo *grab_info; + MetaDevice *device; g_return_if_fail (!window->override_redirect); @@ -5221,12 +5236,19 @@ meta_window_focus (MetaWindow *window, "Setting input focus to window %s, input: %d take_focus: %d\n", window->desc, window->input, window->take_focus); - if (window->display->grab_window && - window->display->grab_window->all_keys_grabbed) + device = meta_window_guess_grab_pointer (window); + grab_info = meta_display_get_grab_info (window->display, device); + + if (grab_info && + grab_info->grab_window && + grab_info->grab_window->all_keys_grabbed) { meta_topic (META_DEBUG_FOCUS, - "Current focus window %s has global keygrab, not focusing window %s after all\n", - window->display->grab_window->desc, window->desc); + "Current focus window %s for device %d has global " + "keygrab, not focusing window %s after all\n", + grab_info->grab_window->desc, + meta_device_get_id (device), + window->desc); return; } @@ -5643,6 +5665,7 @@ meta_window_move_resize_request (MetaWindow *window, gboolean allow_position_change; gboolean in_grab_op; MetaMoveResizeFlags flags; + MetaGrabInfo *grab_info; /* We ignore configure requests while the user is moving/resizing * the window, since these represent the app sucking and fighting @@ -5653,10 +5676,11 @@ meta_window_move_resize_request (MetaWindow *window, * app asked for the current size/position instead of the new one. */ in_grab_op = FALSE; - if (window->display->grab_op != META_GRAB_OP_NONE && - window == window->display->grab_window) + grab_info = window->cur_grab; + + if (grab_info != NULL) { - switch (window->display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_MOVING: case META_GRAB_OP_RESIZING_SE: @@ -6223,6 +6247,7 @@ meta_window_client_message (MetaWindow *window, MetaGrabOp op; int button; guint32 timestamp; + MetaDevice *device; /* _NET_WM_MOVERESIZE messages are almost certainly going to come from * clients when users click on the fake "frame" that the client has, @@ -6289,15 +6314,26 @@ meta_window_client_message (MetaWindow *window, break; } + if (window->cur_grab != NULL) + device = window->cur_grab->grab_pointer; + else + { + /* No current device grab, find out + * the best device to operate on + */ + device = meta_window_guess_grab_pointer (window); + } + + if (action == _NET_WM_MOVERESIZE_CANCEL) { - meta_display_end_grab_op (window->display, timestamp); + meta_display_end_grab_op (window->display, device, timestamp); } else if (op != META_GRAB_OP_NONE && ((window->has_move_func && op == META_GRAB_OP_KEYBOARD_MOVING) || (window->has_resize_func && op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN))) { - meta_window_begin_grab_op (window, op, frame_action, timestamp); + meta_window_begin_grab_op (window, device, op, frame_action, timestamp); } else if (op != META_GRAB_OP_NONE && ((window->has_move_func && op == META_GRAB_OP_MOVING) || @@ -6344,6 +6380,7 @@ meta_window_client_message (MetaWindow *window, meta_display_begin_grab_op (window->display, window->screen, window, + device, op, FALSE, frame_action, @@ -7782,6 +7819,13 @@ menu_callback (MetaWindowMenu *menu, if (window != NULL) /* window can be NULL */ { + MetaDevice *device; + + if (window->cur_grab != NULL) + device = window->cur_grab->grab_pointer; + else + device = meta_window_guess_grab_pointer (window); + meta_verbose ("Menu op %u on %s\n", op, window->desc); switch (op) @@ -7860,14 +7904,14 @@ menu_callback (MetaWindowMenu *menu, break; case META_MENU_OP_MOVE: - meta_window_begin_grab_op (window, + meta_window_begin_grab_op (window, device, META_GRAB_OP_KEYBOARD_MOVING, TRUE, timestamp); break; case META_MENU_OP_RESIZE: - meta_window_begin_grab_op (window, + meta_window_begin_grab_op (window, device, META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN, TRUE, timestamp); @@ -8150,16 +8194,17 @@ time_diff (const GTimeVal *first, } static gboolean -check_moveresize_frequency (MetaWindow *window, - gdouble *remaining) +check_moveresize_frequency (MetaWindow *window, + MetaGrabInfo *grab_info, + gdouble *remaining) { GTimeVal current_time; g_get_current_time (¤t_time); #ifdef HAVE_XSYNC - if (!window->disable_sync && - window->display->grab_sync_request_alarm != None) + if (!window->disable_sync && grab_info && + grab_info->grab_sync_request_alarm != None) { if (window->sync_request_time.tv_sec != 0 || window->sync_request_time.tv_usec != 0) @@ -8201,7 +8246,7 @@ check_moveresize_frequency (MetaWindow *window, const double ms_between_resizes = 1000.0 / max_resizes_per_second; double elapsed; - elapsed = time_diff (¤t_time, &window->display->grab_last_moveresize_time); + elapsed = time_diff (¤t_time, &grab_info->grab_last_moveresize_time); if (elapsed >= 0.0 && elapsed < ms_between_resizes) { @@ -8224,20 +8269,25 @@ check_moveresize_frequency (MetaWindow *window, } static gboolean -update_move_timeout (gpointer data) +update_move_timeout (MetaWindow *window, + MetaDevice *device) { - MetaWindow *window = data; + MetaGrabInfo *grab_info; - update_move (window, - window->display->grab_last_user_action_was_snap, - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y); + grab_info = meta_display_get_grab_info (window->display, device); + g_assert (grab_info != NULL); + + update_move (window, device, + grab_info->grab_last_user_action_was_snap, + grab_info->grab_latest_motion_x, + grab_info->grab_latest_motion_y); return FALSE; } static void update_move (MetaWindow *window, + MetaDevice *device, gboolean snap, int x, int y) @@ -8247,22 +8297,25 @@ update_move (MetaWindow *window, MetaRectangle old; int shake_threshold; MetaDisplay *display = window->display; + MetaGrabInfo *grab_info; - display->grab_latest_motion_x = x; - display->grab_latest_motion_y = y; + grab_info = meta_display_get_grab_info (display, device); - dx = x - display->grab_anchor_root_x; - dy = y - display->grab_anchor_root_y; + grab_info->grab_latest_motion_x = x; + grab_info->grab_latest_motion_y = y; - new_x = display->grab_anchor_window_pos.x + dx; - new_y = display->grab_anchor_window_pos.y + dy; + dx = x - grab_info->grab_anchor_root_x; + dy = y - grab_info->grab_anchor_root_y; + + new_x = grab_info->grab_anchor_window_pos.x + dx; + new_y = grab_info->grab_anchor_window_pos.y + dy; meta_verbose ("x,y = %d,%d anchor ptr %d,%d anchor pos %d,%d dx,dy %d,%d\n", x, y, - display->grab_anchor_root_x, - display->grab_anchor_root_y, - display->grab_anchor_window_pos.x, - display->grab_anchor_window_pos.y, + grab_info->grab_anchor_root_x, + grab_info->grab_anchor_root_y, + grab_info->grab_anchor_window_pos.x, + grab_info->grab_anchor_window_pos.y, dx, dy); /* Don't bother doing anything if no move has been specified. (This @@ -8337,22 +8390,22 @@ update_move (MetaWindow *window, /* move the unmaximized window to the cursor */ prop = - ((double)(x - display->grab_initial_window_pos.x)) / - ((double)display->grab_initial_window_pos.width); + ((double)(x - grab_info->grab_initial_window_pos.x)) / + ((double)grab_info->grab_initial_window_pos.width); - display->grab_initial_window_pos.x = + grab_info->grab_initial_window_pos.x = x - window->saved_rect.width * prop; - display->grab_initial_window_pos.y = y; + grab_info->grab_initial_window_pos.y = y; if (window->frame) { - display->grab_initial_window_pos.y += window->frame->child_y / 2; + grab_info->grab_initial_window_pos.y += window->frame->child_y / 2; } - window->saved_rect.x = display->grab_initial_window_pos.x; - window->saved_rect.y = display->grab_initial_window_pos.y; - display->grab_anchor_root_x = x; - display->grab_anchor_root_y = y; + window->saved_rect.x = grab_info->grab_initial_window_pos.x; + window->saved_rect.y = grab_info->grab_initial_window_pos.y; + grab_info->grab_anchor_root_x = x; + grab_info->grab_anchor_root_y = y; meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL | @@ -8406,9 +8459,9 @@ update_move (MetaWindow *window, META_MAXIMIZE_VERTICAL); } - display->grab_initial_window_pos = work_area; - display->grab_anchor_root_x = x; - display->grab_anchor_root_y = y; + grab_info->grab_initial_window_pos = work_area; + grab_info->grab_anchor_root_x = x; + grab_info->grab_anchor_root_y = y; window->shaken_loose = FALSE; meta_window_maximize (window, @@ -8437,6 +8490,7 @@ update_move (MetaWindow *window, /* Do any edge resistance/snapping */ meta_window_edge_resistance_for_move (window, + device, old.x, old.y, &new_x, @@ -8457,11 +8511,13 @@ update_move (MetaWindow *window, */ static MetaMaximizeFlags check_resize_unmaximize(MetaWindow *window, + MetaDevice *device, int dx, int dy) { int threshold; MetaMaximizeFlags new_unmaximize; + MetaGrabInfo *grab_info; #define DRAG_THRESHOLD_TO_RESIZE_THRESHOLD_FACTOR 3 @@ -8469,9 +8525,12 @@ check_resize_unmaximize(MetaWindow *window, DRAG_THRESHOLD_TO_RESIZE_THRESHOLD_FACTOR; new_unmaximize = 0; + grab_info = meta_display_get_grab_info (window->display, device); + g_assert (grab_info != NULL); + if (window->maximized_horizontally || window->tile_mode != META_TILE_NONE || - (window->display->grab_resize_unmaximize & META_MAXIMIZE_HORIZONTAL) != 0) + (grab_info->grab_resize_unmaximize & META_MAXIMIZE_HORIZONTAL) != 0) { int x_amount; @@ -8480,7 +8539,7 @@ check_resize_unmaximize(MetaWindow *window, * monitor. If we wanted to only allow resizing smaller than the * monitor, we'd use - dx for NE/E/SE and dx for SW/W/NW. */ - switch (window->display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_RESIZING_NE: case META_GRAB_OP_KEYBOARD_RESIZING_NE: @@ -8506,11 +8565,11 @@ check_resize_unmaximize(MetaWindow *window, } if (window->maximized_vertically || - (window->display->grab_resize_unmaximize & META_MAXIMIZE_VERTICAL) != 0) + (grab_info->grab_resize_unmaximize & META_MAXIMIZE_VERTICAL) != 0) { int y_amount; - switch (window->display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_RESIZING_N: case META_GRAB_OP_KEYBOARD_RESIZING_N: @@ -8545,10 +8604,10 @@ check_resize_unmaximize(MetaWindow *window, new_unmaximize = 0; if (window->maximized_horizontally || - (window->display->grab_resize_unmaximize & META_MAXIMIZE_HORIZONTAL) != 0) + (grab_info->grab_resize_unmaximize & META_MAXIMIZE_HORIZONTAL) != 0) new_unmaximize |= META_MAXIMIZE_HORIZONTAL; if (window->maximized_vertically || - (window->display->grab_resize_unmaximize & META_MAXIMIZE_VERTICAL) != 0) + (grab_info->grab_resize_unmaximize & META_MAXIMIZE_VERTICAL) != 0) new_unmaximize |= META_MAXIMIZE_VERTICAL; } @@ -8556,20 +8615,39 @@ check_resize_unmaximize(MetaWindow *window, } static gboolean -update_resize_timeout (gpointer data) +update_resize_timeout (MetaWindow *window, + MetaDevice *device) { - MetaWindow *window = data; + MetaGrabInfo *grab_info; - update_resize (window, - window->display->grab_last_user_action_was_snap, - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y, + grab_info = meta_display_get_grab_info (window->display, device); + g_assert (grab_info != NULL); + + update_resize (window, device, + grab_info->grab_last_user_action_was_snap, + grab_info->grab_latest_motion_x, + grab_info->grab_latest_motion_y, TRUE); return FALSE; } +typedef struct +{ + MetaWindow *window; + MetaDevice *device; +} ResizeTimeoutData; + +static gboolean +update_resize_timeout_cb (gpointer user_data) +{ + ResizeTimeoutData *data = user_data; + + return update_resize_timeout (data->window, data->device); +} + static void update_resize (MetaWindow *window, + MetaDevice *device, gboolean snap, int x, int y, gboolean force) @@ -8580,12 +8658,16 @@ update_resize (MetaWindow *window, MetaRectangle old; double remaining; MetaMaximizeFlags new_unmaximize; + MetaGrabInfo *grab_info; - window->display->grab_latest_motion_x = x; - window->display->grab_latest_motion_y = y; + grab_info = meta_display_get_grab_info (window->display, + device); - dx = x - window->display->grab_anchor_root_x; - dy = y - window->display->grab_anchor_root_y; + grab_info->grab_latest_motion_x = x; + grab_info->grab_latest_motion_y = y; + + dx = x - grab_info->grab_anchor_root_x; + dy = y - grab_info->grab_anchor_root_y; /* Attached modal dialogs are special in that horizontal * size changes apply to both sides, so that the dialog @@ -8596,8 +8678,8 @@ update_resize (MetaWindow *window, meta_window_get_transient_for (window) != NULL) dx *= 2; - new_w = window->display->grab_anchor_window_pos.width; - new_h = window->display->grab_anchor_window_pos.height; + new_w = grab_info->grab_anchor_window_pos.width; + new_h = grab_info->grab_anchor_window_pos.height; /* Don't bother doing anything if no move has been specified. (This * happens often, even in keyboard resizing, due to the warping of the @@ -8606,53 +8688,53 @@ update_resize (MetaWindow *window, if (dx == 0 && dy == 0) return; - if (window->display->grab_op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN) + if (grab_info->grab_op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN) { if ((dx > 0) && (dy > 0)) { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SE; - meta_window_update_keyboard_resize (window, TRUE); + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SE; + meta_window_update_keyboard_resize (window, device, TRUE); } else if ((dx < 0) && (dy > 0)) { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SW; - meta_window_update_keyboard_resize (window, TRUE); + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SW; + meta_window_update_keyboard_resize (window, device, TRUE); } else if ((dx > 0) && (dy < 0)) { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NE; - meta_window_update_keyboard_resize (window, TRUE); + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NE; + meta_window_update_keyboard_resize (window, device, TRUE); } else if ((dx < 0) && (dy < 0)) { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NW; - meta_window_update_keyboard_resize (window, TRUE); + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NW; + meta_window_update_keyboard_resize (window, device, TRUE); } else if (dx < 0) { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; - meta_window_update_keyboard_resize (window, TRUE); + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; + meta_window_update_keyboard_resize (window, device, TRUE); } else if (dx > 0) { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; - meta_window_update_keyboard_resize (window, TRUE); + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; + meta_window_update_keyboard_resize (window, device, TRUE); } else if (dy > 0) { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; - meta_window_update_keyboard_resize (window, TRUE); + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; + meta_window_update_keyboard_resize (window, device, TRUE); } else if (dy < 0) { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; - meta_window_update_keyboard_resize (window, TRUE); + grab_info->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + meta_window_update_keyboard_resize (window, device, TRUE); } } - new_unmaximize = check_resize_unmaximize (window, dx, dy); + new_unmaximize = check_resize_unmaximize (window, device, dx, dy); - switch (window->display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_RESIZING_SE: case META_GRAB_OP_RESIZING_NE: @@ -8675,7 +8757,7 @@ update_resize (MetaWindow *window, break; } - switch (window->display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_RESIZING_SE: case META_GRAB_OP_RESIZING_S: @@ -8698,17 +8780,25 @@ update_resize (MetaWindow *window, break; } - if (!check_moveresize_frequency (window, &remaining) && !force) + if (!check_moveresize_frequency (window, grab_info, &remaining) && !force) { /* we are ignoring an event here, so we schedule a * compensation event when we would otherwise not ignore * an event. Otherwise we can become stuck if the user never * generates another event. */ - if (!window->display->grab_resize_timeout_id) + if (!grab_info->grab_resize_timeout_id) { - window->display->grab_resize_timeout_id = - g_timeout_add ((int)remaining, update_resize_timeout, window); + ResizeTimeoutData *data; + + data = g_new (ResizeTimeoutData, 1); + data->window = window; + data->device = device; + + grab_info->grab_resize_timeout_id = + g_timeout_add_full (G_PRIORITY_DEFAULT, + (int)remaining, update_resize_timeout_cb, + data, (GDestroyNotify) g_free); } return; @@ -8719,10 +8809,10 @@ update_resize (MetaWindow *window, meta_compositor_set_updates (window->display->compositor, window, TRUE); /* Remove any scheduled compensation events */ - if (window->display->grab_resize_timeout_id) + if (grab_info->grab_resize_timeout_id) { - g_source_remove (window->display->grab_resize_timeout_id); - window->display->grab_resize_timeout_id = 0; + g_source_remove (grab_info->grab_resize_timeout_id); + grab_info->grab_resize_timeout_id = 0; } old = window->rect; /* Don't actually care about x,y */ @@ -8731,7 +8821,7 @@ update_resize (MetaWindow *window, * aspect ratio windows don't interact nicely with the above stuff. So, * to avoid some nasty flicker, we enforce that. */ - switch (window->display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_RESIZING_S: case META_GRAB_OP_RESIZING_N: @@ -8748,11 +8838,12 @@ update_resize (MetaWindow *window, } /* compute gravity of client during operation */ - gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); + gravity = meta_resize_gravity_from_grab_op (grab_info->grab_op); g_assert (gravity >= 0); /* Do any edge resistance/snapping */ meta_window_edge_resistance_for_resize (window, + device, old.width, old.height, &new_w, @@ -8762,40 +8853,40 @@ update_resize (MetaWindow *window, snap, FALSE); - if (new_unmaximize == window->display->grab_resize_unmaximize) + if (new_unmaximize == grab_info->grab_resize_unmaximize) { /* We don't need to update unless the specified width and height * are actually different from what we had before. */ if (old.width != new_w || old.height != new_h) { - if ((window->display->grab_resize_unmaximize == new_unmaximize)) + if ((grab_info->grab_resize_unmaximize == new_unmaximize)) meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); } } else { - if ((new_unmaximize & ~window->display->grab_resize_unmaximize) != 0) + if ((new_unmaximize & ~grab_info->grab_resize_unmaximize) != 0) { meta_window_unmaximize_with_gravity (window, - (new_unmaximize & ~window->display->grab_resize_unmaximize), + (new_unmaximize & ~grab_info->grab_resize_unmaximize), new_w, new_h, gravity); } - if ((window->display->grab_resize_unmaximize & ~new_unmaximize)) + if ((grab_info->grab_resize_unmaximize & ~new_unmaximize)) { MetaRectangle saved_rect = window->saved_rect; meta_window_maximize (window, - (window->display->grab_resize_unmaximize & ~new_unmaximize)); + (grab_info->grab_resize_unmaximize & ~new_unmaximize)); window->saved_rect = saved_rect; } } - window->display->grab_resize_unmaximize = new_unmaximize; + grab_info->grab_resize_unmaximize = new_unmaximize; /* Store the latest resize time, if we actually resized. */ if (window->rect.width != old.width || window->rect.height != old.height) - g_get_current_time (&window->display->grab_last_moveresize_time); + g_get_current_time (&grab_info->grab_last_moveresize_time); } typedef struct @@ -8850,24 +8941,32 @@ check_use_this_motion_notify (MetaWindow *window, XEvent *event) { EventScannerData esd; + MetaDevice *device; + MetaGrabInfo *grab_info; XEvent useless; + device = meta_input_event_get_device (window->display, event); + grab_info = meta_display_get_grab_info (window->display, device); + + if (!grab_info) + return FALSE; + /* This code is copied from Owen's GDK code. */ - if (window->display->grab_motion_notify_time != 0) + if (grab_info->grab_motion_notify_time != 0) { Time evtime; evtime = meta_input_event_get_time (window->display, event); /* == is really the right test, but I'm all for paranoia */ - if (window->display->grab_motion_notify_time <= evtime) + if (grab_info->grab_motion_notify_time <= evtime) { meta_topic (META_DEBUG_RESIZING, "Arrived at event with time %u (waiting for %u), using it\n", (unsigned int) evtime, - window->display->grab_motion_notify_time); - window->display->grab_motion_notify_time = 0; + grab_info->grab_motion_notify_time); + grab_info->grab_motion_notify_time = 0; return TRUE; } else @@ -8900,7 +8999,7 @@ check_use_this_motion_notify (MetaWindow *window, /* Save this timestamp, and ignore all motion notify * until we get to the one with this stamp. */ - window->display->grab_motion_notify_time = esd.last_time; + grab_info->grab_motion_notify_time = esd.last_time; return FALSE; } } @@ -8928,15 +9027,20 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, { gdouble x_root, y_root; guint evtype, state; + MetaDevice *device; + MetaGrabInfo *grab_info; Window xroot; #ifdef HAVE_XSYNC if (event->type == (window->display->xsync_event_base + XSyncAlarmNotify)) { + grab_info = window->cur_grab; + g_assert (grab_info != NULL); + meta_topic (META_DEBUG_RESIZING, "Alarm event received last motion x = %d y = %d\n", - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y); + grab_info->grab_latest_motion_x, + grab_info->grab_latest_motion_y); /* If sync was previously disabled, turn it back on and hope * the application has come to its senses (maybe it was just @@ -8947,7 +9051,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, window->sync_request_time.tv_usec = 0; /* This means we are ready for another configure. */ - switch (window->display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_RESIZING_E: case META_GRAB_OP_RESIZING_W: @@ -8967,9 +9071,10 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, case META_GRAB_OP_KEYBOARD_RESIZING_NW: /* no pointer round trip here, to keep in sync */ update_resize (window, - window->display->grab_last_user_action_was_snap, - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y, + grab_info->grab_pointer, + grab_info->grab_last_user_action_was_snap, + grab_info->grab_latest_motion_x, + grab_info->grab_latest_motion_y, TRUE); break; @@ -8986,32 +9091,34 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, return; xroot = meta_input_event_get_root_window (window->display, event); + device = meta_input_event_get_device (window->display, event); + grab_info = meta_display_get_grab_info (window->display, device); switch (evtype) { case ButtonRelease: - meta_display_check_threshold_reached (window->display, + meta_display_check_threshold_reached (window->display, device, x_root, y_root); /* If the user was snap moving then ignore the button release * because they may have let go of shift before releasing the * mouse button and they almost certainly do not want a * non-snapped movement to occur from the button release. */ - if (!window->display->grab_last_user_action_was_snap) + if (!grab_info->grab_last_user_action_was_snap) { - if (meta_grab_op_is_moving (window->display->grab_op)) + if (meta_grab_op_is_moving (grab_info->grab_op)) { if (window->tile_mode != META_TILE_NONE) meta_window_tile (window); else if (xroot == window->screen->xroot) - update_move (window, + update_move (window, device, state & ShiftMask, x_root, y_root); } - else if (meta_grab_op_is_resizing (window->display->grab_op)) + else if (meta_grab_op_is_resizing (grab_info->grab_op)) { if (xroot == window->screen->xroot) - update_resize (window, + update_resize (window, device, state & ShiftMask, x_root, y_root, TRUE); @@ -9029,32 +9136,32 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, } } - meta_display_end_grab_op (window->display, + meta_display_end_grab_op (window->display, device, meta_input_event_get_time (window->display, event)); break; case MotionNotify: - meta_display_check_threshold_reached (window->display, + meta_display_check_threshold_reached (window->display, device, x_root, y_root); - if (meta_grab_op_is_moving (window->display->grab_op)) + if (meta_grab_op_is_moving (grab_info->grab_op)) { if (xroot == window->screen->xroot) { if (check_use_this_motion_notify (window, event)) - update_move (window, + update_move (window, device, state & ShiftMask, x_root, y_root); } } - else if (meta_grab_op_is_resizing (window->display->grab_op)) + else if (meta_grab_op_is_resizing (grab_info->grab_op)) { if (xroot == window->screen->xroot) { if (check_use_this_motion_notify (window, event)) - update_resize (window, + update_resize (window, device, state & ShiftMask, x_root, y_root, FALSE); @@ -9226,13 +9333,14 @@ meta_window_same_client (MetaWindow *window, void meta_window_refresh_resize_popup (MetaWindow *window) { - if (window->display->grab_op == META_GRAB_OP_NONE) + MetaGrabInfo *grab_info; + + grab_info = window->cur_grab; + + if (!grab_info) return; - if (window->display->grab_window != window) - return; - - switch (window->display->grab_op) + switch (grab_info->grab_op) { case META_GRAB_OP_RESIZING_SE: case META_GRAB_OP_RESIZING_S: @@ -9258,29 +9366,29 @@ meta_window_refresh_resize_popup (MetaWindow *window) return; } - if (window->display->grab_resize_popup == NULL) + if (grab_info->grab_resize_popup == NULL) { if (window->size_hints.width_inc > 1 || window->size_hints.height_inc > 1) - window->display->grab_resize_popup = + grab_info->grab_resize_popup = meta_ui_resize_popup_new (window->display->xdisplay, window->screen->number); } - if (window->display->grab_resize_popup != NULL) + if (grab_info->grab_resize_popup != NULL) { MetaRectangle rect; meta_window_get_client_root_coords (window, &rect); - meta_ui_resize_popup_set (window->display->grab_resize_popup, + meta_ui_resize_popup_set (grab_info->grab_resize_popup, rect, window->size_hints.base_width, window->size_hints.base_height, window->size_hints.width_inc, window->size_hints.height_inc); - meta_ui_resize_popup_set_showing (window->display->grab_resize_popup, + meta_ui_resize_popup_set_showing (grab_info->grab_resize_popup, TRUE); } } @@ -9403,17 +9511,22 @@ meta_window_is_ancestor_of_transient (MetaWindow *window, */ static gboolean warp_grab_pointer (MetaWindow *window, + MetaDevice *device, MetaGrabOp grab_op, int *x, int *y) { MetaRectangle rect; MetaDisplay *display; + MetaGrabInfo *grab_info; display = window->display; + grab_info = meta_display_get_grab_info (display, device); /* We may not have done begin_grab_op yet, i.e. may not be in a grab */ + if (!grab_info) + grab_info = meta_display_create_grab_info (display, device); meta_window_get_outer_rect (window, &rect); @@ -9486,12 +9599,12 @@ warp_grab_pointer (MetaWindow *window, * events generated by the XWarpPointer() call below don't cause complete * funkiness. See bug 124582 and bug 122670. */ - display->grab_anchor_root_x = *x; - display->grab_anchor_root_y = *y; - display->grab_latest_motion_x = *x; - display->grab_latest_motion_y = *y; + grab_info->grab_anchor_root_x = *x; + grab_info->grab_anchor_root_y = *y; + grab_info->grab_latest_motion_x = *x; + grab_info->grab_latest_motion_y = *y; meta_window_get_client_root_coords (window, - &display->grab_anchor_window_pos); + &grab_info->grab_anchor_window_pos); XWarpPointer (display->xdisplay, None, @@ -9511,18 +9624,20 @@ warp_grab_pointer (MetaWindow *window, void meta_window_begin_grab_op (MetaWindow *window, + MetaDevice *device, MetaGrabOp op, gboolean frame_action, guint32 timestamp) { int x, y; - warp_grab_pointer (window, + warp_grab_pointer (window, device, op, &x, &y); meta_display_begin_grab_op (window->display, window->screen, window, + device, op, FALSE, frame_action, @@ -9534,12 +9649,17 @@ meta_window_begin_grab_op (MetaWindow *window, void meta_window_update_keyboard_resize (MetaWindow *window, + MetaDevice *device, gboolean update_cursor) { + MetaGrabInfo *grab_info; int x, y; - warp_grab_pointer (window, - window->display->grab_op, + grab_info = meta_display_get_grab_info (window->display, device); + g_assert (grab_info != NULL); + + warp_grab_pointer (window, device, + grab_info->grab_op, &x, &y); if (update_cursor) @@ -9548,21 +9668,25 @@ meta_window_update_keyboard_resize (MetaWindow *window, /* FIXME: Using CurrentTime is really bad mojo */ timestamp = CurrentTime; meta_display_set_grab_op_cursor (window->display, - NULL, - window->display->grab_op, + NULL, device, + grab_info->grab_op, TRUE, - window->display->grab_xwindow, + grab_info->grab_xwindow, timestamp); } } void -meta_window_update_keyboard_move (MetaWindow *window) +meta_window_update_keyboard_move (MetaWindow *window, + MetaDevice *device) { + MetaGrabInfo *grab_info; int x, y; - warp_grab_pointer (window, - window->display->grab_op, + grab_info = meta_display_get_grab_info (window->display, device); + + warp_grab_pointer (window, device, + grab_info->grab_op, &x, &y); } @@ -10313,3 +10437,18 @@ meta_window_get_frame_bounds (MetaWindow *window) return window->frame_bounds; } + +/* Guesses the better device to grab on if a grab is to be started, + * only should be be used in circumstances where we don't know a + * device at all. + */ +MetaDevice * +meta_window_guess_grab_pointer (MetaWindow *window) +{ + /* FIXME: This ought to be the very last resort, ideally + * the current/last focus device should be used to find + * this out, or the client pointer. + */ + return meta_device_map_lookup (window->display->device_map, + META_CORE_POINTER_ID); +} diff --git a/src/core/workspace.c b/src/core/workspace.c index 66f9dd0ea..8bc64d561 100644 --- a/src/core/workspace.c +++ b/src/core/workspace.c @@ -538,7 +538,9 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace, MetaWorkspaceLayout layout1, layout2; gint num_workspaces, current_space, new_space; MetaMotionDirection direction; - + MetaGrabInfo *grab_info; + GHashTableIter iter; + meta_verbose ("Activating workspace %d\n", meta_workspace_index (workspace)); @@ -547,7 +549,7 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace, /* Free any cached pointers to the workspaces's edges from * a current resize or move operation */ - meta_display_cleanup_edges (workspace->screen->display); + meta_display_cleanup_edges (workspace->screen->display, workspace->screen); if (workspace->screen->active_workspace) workspace_switch_sound (workspace->screen->active_workspace, workspace); @@ -570,10 +572,22 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace, return; move_window = NULL; - if (workspace->screen->display->grab_op == META_GRAB_OP_MOVING || - workspace->screen->display->grab_op == META_GRAB_OP_KEYBOARD_MOVING) - move_window = workspace->screen->display->grab_window; - + + /* FIXME: not quite multidevice friendly, but the whole + * "move window to another workspace" isn't. + */ + g_hash_table_iter_init (&iter, workspace->screen->display->current_grabs); + + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &grab_info)) + { + if (grab_info->grab_op == META_GRAB_OP_MOVING || + grab_info->grab_op == META_GRAB_OP_KEYBOARD_MOVING) + { + move_window = grab_info->grab_window; + break; + } + } + if (move_window != NULL) { if (move_window->on_all_workspaces) @@ -774,7 +788,7 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace) /* If we are in the middle of a resize or move operation, we * might have cached pointers to the workspace's edges */ if (workspace == workspace->screen->active_workspace) - meta_display_cleanup_edges (workspace->screen->display); + meta_display_cleanup_edges (workspace->screen->display, workspace->screen); g_free (workspace->work_area_monitor); workspace->work_area_monitor = NULL; diff --git a/src/meta/display.h b/src/meta/display.h index 4196d7dc7..19d53e2f2 100644 --- a/src/meta/display.h +++ b/src/meta/display.h @@ -112,6 +112,7 @@ MetaWindow* meta_display_get_tab_current (MetaDisplay *display, gboolean meta_display_begin_grab_op (MetaDisplay *display, MetaScreen *screen, MetaWindow *window, + MetaDevice *device, MetaGrabOp op, gboolean pointer_already_grabbed, gboolean frame_action, @@ -121,10 +122,14 @@ gboolean meta_display_begin_grab_op (MetaDisplay *display, int root_x, int root_y); void meta_display_end_grab_op (MetaDisplay *display, + MetaDevice *device, guint32 timestamp); MetaGrabOp meta_display_get_grab_op (MetaDisplay *display); +MetaGrabOp meta_display_get_device_grab_op (MetaDisplay *display, + MetaDevice *device); + MetaKeyBindingAction meta_display_get_keybinding_action (MetaDisplay *display, unsigned int keycode, unsigned long mask); diff --git a/src/ui/frames.c b/src/ui/frames.c index d9e2bcacb..db44424e7 100644 --- a/src/ui/frames.c +++ b/src/ui/frames.c @@ -1555,7 +1555,9 @@ meta_frames_button_press_event (GtkWidget *widget, MetaFrames *frames; MetaFrameControl control; Display *display; - + GdkDevice *device; + int device_id; + frames = META_FRAMES (widget); display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); @@ -1588,7 +1590,10 @@ meta_frames_button_press_event (GtkWidget *widget, /* don't do the rest of this if on client area */ if (control == META_FRAME_CONTROL_CLIENT_AREA) return FALSE; /* not on the frame, just passed through from client */ - + + device = gdk_event_get_device ((GdkEvent *) event); + device_id = gdk_x11_device_get_id (device); + /* We want to shade even if we have a GrabOp, since we'll have a move grab * if we double click the titlebar. */ @@ -1596,13 +1601,13 @@ meta_frames_button_press_event (GtkWidget *widget, event->button == 1 && event->type == GDK_2BUTTON_PRESS) { - meta_core_end_grab_op (display, event->time); + meta_core_end_grab_op (display, device_id, event->time); return meta_frame_double_click_event (frame, event); } - if (meta_core_get_grab_op (display) != + if (meta_core_frame_has_grab (display, frame->xwindow, NULL, NULL) != META_GRAB_OP_NONE) - return FALSE; /* already up to something */ + return FALSE; /* already up to something */ if (event->button == 1 && (control == META_FRAME_CONTROL_MAXIMIZE || @@ -1661,6 +1666,7 @@ meta_frames_button_press_event (GtkWidget *widget, meta_core_begin_grab_op (display, frame->xwindow, + device_id, op, TRUE, TRUE, @@ -1746,6 +1752,7 @@ meta_frames_button_press_event (GtkWidget *widget, meta_core_begin_grab_op (display, frame->xwindow, + device_id, op, TRUE, TRUE, @@ -1768,6 +1775,7 @@ meta_frames_button_press_event (GtkWidget *widget, { meta_core_begin_grab_op (display, frame->xwindow, + device_id, META_GRAB_OP_MOVING, TRUE, TRUE, @@ -1791,28 +1799,28 @@ meta_frames_button_press_event (GtkWidget *widget, } void -meta_frames_notify_menu_hide (MetaFrames *frames) +meta_frames_notify_menu_hide (MetaFrames *frames, + Window client_xwindow) { Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - if (meta_core_get_grab_op (display) == + Window frame_xwindow; + int device_id; + + frame_xwindow = meta_core_get_frame (display, client_xwindow); + + if (frame_xwindow != None && + meta_core_frame_has_grab (display, frame_xwindow, &device_id, NULL) == META_GRAB_OP_CLICKING_MENU) { - Window grab_frame; + MetaUIFrame *frame; - grab_frame = meta_core_get_grab_frame (display); + frame = meta_frames_lookup_window (frames, frame_xwindow); - if (grab_frame != None) + if (frame) { - MetaUIFrame *frame; - - frame = meta_frames_lookup_window (frames, grab_frame); - - if (frame) - { - redraw_control (frames, frame, - META_FRAME_CONTROL_MENU); - meta_core_end_grab_op (display, CurrentTime); - } + redraw_control (frames, frame, + META_FRAME_CONTROL_MENU); + meta_core_end_grab_op (display, device_id, CurrentTime); } } } @@ -1825,7 +1833,10 @@ meta_frames_button_release_event (GtkWidget *widget, MetaFrames *frames; MetaGrabOp op; Display *display; - + int grab_button; + GdkDevice *device; + int device_id, grab_device_id; + frames = META_FRAMES (widget); display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); @@ -1835,17 +1846,21 @@ meta_frames_button_release_event (GtkWidget *widget, clear_tip (frames); - op = meta_core_get_grab_op (display); + op = meta_core_frame_has_grab (display, frame->xwindow, + &grab_device_id, &grab_button); - if (op == META_GRAB_OP_NONE) + device = gdk_event_get_device ((GdkEvent *) event); + device_id = gdk_x11_device_get_id (device); + + if (op == META_GRAB_OP_NONE || + grab_device_id != device_id) return FALSE; /* We only handle the releases we handled the presses for (things * involving frame controls). Window ops that don't require a * frame are handled in the Xlib part of the code, display.c/window.c */ - if (frame->xwindow == meta_core_get_grab_frame (display) && - ((int) event->button) == meta_core_get_grab_button (display)) + if (((int) event->button) == grab_button) { MetaFrameControl control; @@ -1856,8 +1871,8 @@ meta_frames_button_release_event (GtkWidget *widget, case META_GRAB_OP_CLICKING_MINIMIZE: if (control == META_FRAME_CONTROL_MINIMIZE) meta_core_minimize (display, frame->xwindow); - - meta_core_end_grab_op (display, event->time); + + meta_core_end_grab_op (display, device_id, event->time); break; case META_GRAB_OP_CLICKING_MAXIMIZE: @@ -1869,67 +1884,67 @@ meta_frames_button_release_event (GtkWidget *widget, event->time); meta_core_maximize (display, frame->xwindow); } - meta_core_end_grab_op (display, event->time); + meta_core_end_grab_op (display, device_id, event->time); break; case META_GRAB_OP_CLICKING_UNMAXIMIZE: if (control == META_FRAME_CONTROL_UNMAXIMIZE) meta_core_unmaximize (display, frame->xwindow); - - meta_core_end_grab_op (display, event->time); + + meta_core_end_grab_op (display, device_id, event->time); break; case META_GRAB_OP_CLICKING_DELETE: if (control == META_FRAME_CONTROL_DELETE) meta_core_delete (display, frame->xwindow, event->time); - - meta_core_end_grab_op (display, event->time); + + meta_core_end_grab_op (display, device_id, event->time); break; case META_GRAB_OP_CLICKING_MENU: - meta_core_end_grab_op (display, event->time); + meta_core_end_grab_op (display, device_id, event->time); break; case META_GRAB_OP_CLICKING_SHADE: if (control == META_FRAME_CONTROL_SHADE) meta_core_shade (display, frame->xwindow, event->time); - - meta_core_end_grab_op (display, event->time); + + meta_core_end_grab_op (display, device_id, event->time); break; case META_GRAB_OP_CLICKING_UNSHADE: if (control == META_FRAME_CONTROL_UNSHADE) meta_core_unshade (display, frame->xwindow, event->time); - meta_core_end_grab_op (display, event->time); + meta_core_end_grab_op (display, device_id, event->time); break; case META_GRAB_OP_CLICKING_ABOVE: if (control == META_FRAME_CONTROL_ABOVE) meta_core_make_above (display, frame->xwindow); - - meta_core_end_grab_op (display, event->time); + + meta_core_end_grab_op (display, device_id, event->time); break; case META_GRAB_OP_CLICKING_UNABOVE: if (control == META_FRAME_CONTROL_UNABOVE) meta_core_unmake_above (display, frame->xwindow); - meta_core_end_grab_op (display, event->time); + meta_core_end_grab_op (display, device_id, event->time); break; case META_GRAB_OP_CLICKING_STICK: if (control == META_FRAME_CONTROL_STICK) meta_core_stick (display, frame->xwindow); - meta_core_end_grab_op (display, event->time); + meta_core_end_grab_op (display, device_id, event->time); break; case META_GRAB_OP_CLICKING_UNSTICK: if (control == META_FRAME_CONTROL_UNSTICK) meta_core_unstick (display, frame->xwindow); - meta_core_end_grab_op (display, event->time); + meta_core_end_grab_op (display, device_id, event->time); break; default: @@ -2075,8 +2090,8 @@ meta_frames_motion_notify_event (GtkWidget *widget, frames->last_motion_frame = frame; - grab_op = meta_core_get_grab_op (display); - + grab_op = meta_core_frame_has_grab (display, frame->xwindow, NULL, NULL); + switch (grab_op) { case META_GRAB_OP_CLICKING_MENU: @@ -2472,7 +2487,6 @@ meta_frames_paint (MetaFrames *frames, GdkPixbuf *icon; int w, h; MetaButtonState button_states[META_BUTTON_TYPE_LAST]; - Window grab_frame; int i; MetaButtonLayout button_layout; MetaGrabOp grab_op; @@ -2484,11 +2498,8 @@ meta_frames_paint (MetaFrames *frames, for (i = 0; i < META_BUTTON_TYPE_LAST; i++) button_states[i] = META_BUTTON_STATE_NORMAL; - grab_frame = meta_core_get_grab_frame (display); - grab_op = meta_core_get_grab_op (display); - if (grab_frame != frame->xwindow) - grab_op = META_GRAB_OP_NONE; - + grab_op = meta_core_frame_has_grab (display, frame->xwindow, NULL, NULL); + /* Set prelight state */ switch (frame->prelit_control) { diff --git a/src/ui/frames.h b/src/ui/frames.h index 6ce5a3494..c92224a20 100644 --- a/src/ui/frames.h +++ b/src/ui/frames.h @@ -163,7 +163,8 @@ void meta_frames_move_resize_frame (MetaFrames *frames, void meta_frames_queue_draw (MetaFrames *frames, Window xwindow); -void meta_frames_notify_menu_hide (MetaFrames *frames); +void meta_frames_notify_menu_hide (MetaFrames *frames, + Window client_xwindow); Window meta_frames_get_moving_frame (MetaFrames *frames); diff --git a/src/ui/menu.c b/src/ui/menu.c index eef421a07..b3cad3255 100644 --- a/src/ui/menu.c +++ b/src/ui/menu.c @@ -137,7 +137,7 @@ menu_closed (GtkMenu *widget, menu = data; - meta_frames_notify_menu_hide (menu->frames); + meta_frames_notify_menu_hide (menu->frames, menu->client_xwindow); (* menu->func) (menu, GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), menu->client_xwindow, @@ -157,7 +157,7 @@ activate_cb (GtkWidget *menuitem, gpointer data) md = data; - meta_frames_notify_menu_hide (md->menu->frames); + meta_frames_notify_menu_hide (md->menu->frames, md->menu->client_xwindow); (* md->menu->func) (md->menu, GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), md->menu->client_xwindow, diff --git a/src/ui/tile-preview.c b/src/ui/tile-preview.c index f09c62a29..e0fecabbe 100644 --- a/src/ui/tile-preview.c +++ b/src/ui/tile-preview.c @@ -171,6 +171,7 @@ meta_tile_preview_free (MetaTilePreview *preview) void meta_tile_preview_show (MetaTilePreview *preview, + MetaDevice *pointer, MetaRectangle *tile_rect) { GdkWindow *window; @@ -187,6 +188,7 @@ meta_tile_preview_show (MetaTilePreview *preview, window = gtk_widget_get_window (preview->preview_window); meta_core_lower_beneath_grab_window (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), GDK_WINDOW_XID (window), + meta_device_get_id (pointer), gtk_get_current_event_time ()); old_rect.x = old_rect.y = 0; diff --git a/src/ui/tile-preview.h b/src/ui/tile-preview.h index 740f41f69..b331f79b4 100644 --- a/src/ui/tile-preview.h +++ b/src/ui/tile-preview.h @@ -24,6 +24,7 @@ #define META_TILE_PREVIEW_H #include +#include typedef struct _MetaTilePreview MetaTilePreview; @@ -31,6 +32,7 @@ MetaTilePreview *meta_tile_preview_new (int screen_number, gboolean composited); void meta_tile_preview_free (MetaTilePreview *preview); void meta_tile_preview_show (MetaTilePreview *preview, + MetaDevice *pointer, MetaRectangle *rect); void meta_tile_preview_hide (MetaTilePreview *preview); Window meta_tile_preview_get_xwindow (MetaTilePreview *preview,