core: Keep track of per pointer/keyboard grabs

There is now a MetaGrabInfo struct, holding all information about
an ongoing grab, there were unfortunately no means of making this
commit smaller, as things are too intertwined to separate it,

On places where it was most obvious, the correct device has been
used (in reaction to events, for example), in other parts, the
private API has been extended to include the MetaDevice (or device
ID for core.h functions), in other places, the virtual core
pointer/keyboard are used out of cluelessness.
This commit is contained in:
Carlos Garnacho
2011-06-19 00:55:10 +02:00
parent ab58d87142
commit 7c86cb85ba
23 changed files with 1128 additions and 672 deletions

View File

@@ -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 <meta/compositor.h>
@@ -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,21 +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_tile_monitor_number = -1;
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
{
@@ -995,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,
@@ -1594,6 +1579,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;
@@ -1678,15 +1664,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 */
@@ -1778,12 +1779,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
@@ -1803,26 +1805,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,
@@ -1830,13 +1833,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;
@@ -1929,6 +1935,7 @@ event_callback (XEvent *event,
meta_display_begin_grab_op (display,
window->screen,
window,
device,
op,
TRUE,
FALSE,
@@ -1985,6 +1992,7 @@ event_callback (XEvent *event,
meta_display_begin_grab_op (display,
window->screen,
window,
device,
META_GRAB_OP_MOVING,
TRUE,
FALSE,
@@ -1997,27 +2005,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;
@@ -2110,11 +2121,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)
{
@@ -2235,11 +2247,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)
{
@@ -2265,12 +2281,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)
{
@@ -3451,14 +3471,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 | \
@@ -3479,8 +3502,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
@@ -3497,7 +3520,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);
@@ -3521,6 +3544,7 @@ gboolean
meta_display_begin_grab_op (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
MetaDevice *device,
MetaGrabOp op,
gboolean pointer_already_grabbed,
gboolean frame_action,
@@ -3531,22 +3555,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)))
{
@@ -3554,9 +3585,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;
}
}
@@ -3581,15 +3612,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 && !grab_op_is_keyboard (op))
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 && !grab_op_is_keyboard (op))
{
meta_topic (META_DEBUG_WINDOW_OPS,
"XGrabPointer() failed\n");
@@ -3600,69 +3631,70 @@ 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;
display->grab_tile_monitor_number = window->tile_monitor_number;
grab_info->grab_tile_mode = window->tile_mode;
grab_info->grab_tile_monitor_number = window->tile_monitor_number;
}
else
{
display->grab_tile_mode = META_TILE_NONE;
display->grab_tile_monitor_number = -1;
}
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;
else
{
grab_info->grab_tile_mode = META_TILE_NONE;
grab_info->grab_tile_monitor_number = -1;
}
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;
@@ -3673,90 +3705,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
@@ -3764,86 +3809,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_tile_monitor_number = -1;
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;
}
/**
@@ -3858,22 +3912,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
@@ -5527,3 +5593,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;
}