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 d664579115
commit c352e1078e
23 changed files with 1122 additions and 664 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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,59 +679,60 @@ meta_core_begin_grab_op (Display *xdisplay,
void
meta_core_end_grab_op (Display *xdisplay,
int device_id,
guint32 timestamp)
{
MetaDisplay *display;
MetaDevice *device;
display = meta_display_for_x_display (xdisplay);
device = meta_device_map_lookup (display->device_map, device_id);
meta_display_end_grab_op (display, timestamp);
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;
MetaWindow *window;
display = meta_display_for_x_display (xdisplay);
window = get_window (xdisplay, frame_xwindow);
return display->grab_op;
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 (window &&
window->frame)
return window->frame->xwindow;
if (display->grab_op != META_GRAB_OP_NONE &&
display->grab_window &&
display->grab_window->frame)
return display->grab_window->frame->xwindow;
else
return None;
}
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;
}
void
meta_core_grab_buttons (Display *xdisplay,
Window frame_xwindow)

View File

@ -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);

View File

@ -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;

View File

@ -24,6 +24,7 @@
#include <config.h>
#include "screen-private.h"
#include "devices-core.h"
#include "device-map-private.h"
/* Common functions */
static void

View File

@ -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))

View File

@ -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

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,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))
{
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 (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);
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,6 +3550,7 @@ 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,
@ -3532,15 +3558,21 @@ meta_display_begin_grab_op (MetaDisplay *display,
op, window ? window->desc : "none", button, pointer_already_grabbed,
root_x, root_y);
if (display->grab_op != META_GRAB_OP_NONE)
grab_info = meta_display_get_grab_info (display, device);
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;
grab_info->grab_have_pointer = FALSE;
if (pointer_already_grabbed)
display->grab_have_pointer = TRUE;
grab_info->grab_have_pointer = TRUE;
meta_display_set_grab_op_cursor (display, screen, op, FALSE, grab_xwindow,
timestamp);
meta_display_set_grab_op_cursor (display, screen, device, op, FALSE,
grab_xwindow, timestamp);
if (!display->grab_have_pointer)
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;
@ -3665,17 +3698,17 @@ meta_display_begin_grab_op (MetaDisplay *display,
XSyncIntToValue (&init, 0);
XSyncSetCounter (display->xdisplay,
display->grab_window->sync_request_counter, init);
grab_info->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;
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 = display->grab_window->sync_request_counter;
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)
@ -3685,7 +3718,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
/* we want events (on by default anyway) */
values.events = True;
display->grab_sync_request_alarm = XSyncCreateAlarm (display->xdisplay,
grab_info->grab_sync_request_alarm = XSyncCreateAlarm (display->xdisplay,
XSyncCACounter |
XSyncCAValueType |
XSyncCAValue |
@ -3695,35 +3728,35 @@ meta_display_begin_grab_op (MetaDisplay *display,
&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;
@ -3731,21 +3764,34 @@ meta_display_begin_grab_op (MetaDisplay *display,
void
meta_display_end_grab_op (MetaDisplay *display,
MetaDevice *device,
guint32 timestamp)
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Ending grab op %u at time %u\n", display->grab_op, timestamp);
MetaGrabInfo *grab_info;
if (display->grab_op == META_GRAB_OP_NONE)
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", 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 (grab_info->grab_window != NULL)
grab_info->grab_window->shaken_loose = FALSE;
if (display->grab_window != NULL &&
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 (grab_info->grab_resize_popup)
meta_ui_resize_popup_free (grab_info->grab_resize_popup);
if (display->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;
}

View File

@ -30,10 +30,10 @@
/* 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) \
#define WINDOW_EDGES_RELEVANT(window, display, screen) \
meta_window_should_be_showing (window) && \
window->screen == display->grab_screen && \
window != display->grab_window && \
window->screen == screen && \
window->cur_grab == NULL && \
window->type != META_WINDOW_DESKTOP && \
window->type != META_WINDOW_MENU && \
window->type != META_WINDOW_SPLASHSCREEN
@ -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,16 +539,14 @@ 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,
MetaDevice *device,
const MetaRectangle *old_outer,
MetaRectangle *new_outer,
GSourceFunc timeout_func,
MetaEdgeResistanceFunc timeout_func,
gboolean auto_snap,
gboolean keyboard_op,
gboolean is_resize)
@ -552,10 +556,11 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
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,16 +1132,18 @@ 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,
edge_data = cache_edges (display, screen,
edges,
display->grab_screen->active_workspace->monitor_edges,
display->grab_screen->active_workspace->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
@ -1140,15 +1151,17 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
*/
void
meta_window_edge_resistance_for_move (MetaWindow *window,
MetaDevice *device,
int old_x,
int old_y,
int *new_x,
int *new_y,
GSourceFunc timeout_func,
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,
@ -1224,17 +1241,19 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
*/
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,
GSourceFunc timeout_func,
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,

View File

@ -26,21 +26,26 @@
#include "window-private.h"
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,
GSourceFunc timeout_func,
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,
GSourceFunc timeout_func,
MetaEdgeResistanceFunc func,
gboolean snap,
gboolean is_keyboard_op);

View File

@ -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);
}

View File

@ -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,7 +2124,7 @@ 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;
@ -2101,15 +2132,20 @@ process_keyboard_resize_grab (MetaDisplay *display,
static gboolean
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);

View File

@ -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);

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -538,6 +538,8 @@ 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,9 +572,21 @@ 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)
{
@ -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;

View File

@ -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);

View File

@ -1555,6 +1555,8 @@ 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 ());
@ -1589,6 +1591,9 @@ meta_frames_button_press_event (GtkWidget *widget,
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,11 +1601,11 @@ 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 */
@ -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;
grab_frame = meta_core_get_grab_frame (display);
if (grab_frame != None)
{
MetaUIFrame *frame;
frame = meta_frames_lookup_window (frames, grab_frame);
frame = meta_frames_lookup_window (frames, frame_xwindow);
if (frame)
{
redraw_control (frames, frame,
META_FRAME_CONTROL_MENU);
meta_core_end_grab_op (display, CurrentTime);
}
meta_core_end_grab_op (display, device_id, CurrentTime);
}
}
}
@ -1825,6 +1833,9 @@ 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;
@ -1857,7 +1872,7 @@ meta_frames_button_release_event (GtkWidget *widget,
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,7 +2090,7 @@ 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)
{
@ -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,10 +2498,7 @@ 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)

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -24,6 +24,7 @@
#define META_TILE_PREVIEW_H
#include <meta/boxes.h>
#include <meta/device.h>
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,