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,