From b1419e2966cca39938d4bca47854fedda6e9e293 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Tue, 13 Aug 2013 16:51:33 +0200 Subject: [PATCH] wayland: implement support for plugin modality Calling XIGrabDevice has no effect under wayland, because the xserver is getting events from us. Instead, we need to use our own interfaces for grabs. At the same time, we can simplify the public API, as plugins should always listen for events using clutter. https://bugzilla.gnome.org/show_bug.cgi?id=705917 --- src/compositor/compositor-private.h | 2 - src/compositor/compositor.c | 130 +++++++++++++++++++++------- src/compositor/meta-plugin.c | 8 +- src/core/display.c | 1 + src/meta/meta-plugin.h | 2 - src/wayland/meta-wayland-keyboard.c | 51 +++++++++++ src/wayland/meta-wayland-keyboard.h | 5 ++ src/wayland/meta-wayland-pointer.c | 62 +++++++++++++ src/wayland/meta-wayland-pointer.h | 5 ++ 9 files changed, 225 insertions(+), 41 deletions(-) diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h index acb8d3c22..0ebf3a439 100644 --- a/src/compositor/compositor-private.h +++ b/src/compositor/compositor-private.h @@ -66,8 +66,6 @@ void meta_switch_workspace_completed (MetaScreen *screen); gboolean meta_begin_modal_for_plugin (MetaScreen *screen, MetaPlugin *plugin, - Window grab_window, - Cursor cursor, MetaModalOptions options, guint32 timestamp); void meta_end_modal_for_plugin (MetaScreen *screen, diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index 7f9a04717..12427b9aa 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -86,6 +86,8 @@ #include "display-private.h" /* for meta_display_lookup_x_window() */ #ifdef HAVE_WAYLAND #include "meta-wayland-private.h" +#include "meta-wayland-pointer.h" +#include "meta-wayland-keyboard.h" #endif #include #include @@ -426,27 +428,20 @@ meta_stage_is_focused (MetaScreen *screen) return (screen->display->focus_type == META_FOCUS_STAGE); } -gboolean -meta_begin_modal_for_plugin (MetaScreen *screen, - MetaPlugin *plugin, - Window grab_window, - Cursor cursor, - MetaModalOptions options, - guint32 timestamp) +static gboolean +begin_modal_x11 (MetaScreen *screen, + MetaPlugin *plugin, + MetaModalOptions options, + guint32 timestamp) { - /* To some extent this duplicates code in meta_display_begin_grab_op(), but there - * are significant differences in how we handle grabs that make it difficult to - * merge the two. - */ - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdpy = meta_display_get_xdisplay (display); - MetaCompositor *compositor = display->compositor; - gboolean pointer_grabbed = FALSE; - gboolean keyboard_grabbed = FALSE; - int result; - - if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE) - return FALSE; + MetaDisplay *display = meta_screen_get_display (screen); + Display *xdpy = meta_display_get_xdisplay (display); + MetaCompScreen *info = meta_screen_get_compositor_data (screen); + Window grab_window = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)); + Cursor cursor = None; + int result; + gboolean pointer_grabbed = FALSE; + gboolean keyboard_grabbed = FALSE; if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0) { @@ -496,14 +491,6 @@ 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; - - compositor->modal_plugin = plugin; - return TRUE; fail: @@ -515,6 +502,79 @@ meta_begin_modal_for_plugin (MetaScreen *screen, return FALSE; } +static gboolean +begin_modal_wayland (MetaScreen *screen, + MetaPlugin *plugin, + MetaModalOptions options, + guint32 timestamp) +{ + MetaWaylandCompositor *compositor; + gboolean pointer_grabbed = FALSE; + gboolean keyboard_grabbed = FALSE; + + compositor = meta_wayland_compositor_get_default (); + + if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0) + { + if (!meta_wayland_pointer_begin_modal (&compositor->seat->pointer)) + goto fail; + + pointer_grabbed = TRUE; + } + if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0) + { + if (!meta_wayland_keyboard_begin_modal (&compositor->seat->keyboard)) + goto fail; + + keyboard_grabbed = TRUE; + } + + return TRUE; + + fail: + if (pointer_grabbed) + meta_wayland_pointer_end_modal (&compositor->seat->pointer); + if (keyboard_grabbed) + meta_wayland_keyboard_end_modal (&compositor->seat->keyboard); + + return FALSE; +} + +gboolean +meta_begin_modal_for_plugin (MetaScreen *screen, + MetaPlugin *plugin, + MetaModalOptions options, + guint32 timestamp) +{ + /* To some extent this duplicates code in meta_display_begin_grab_op(), but there + * are significant differences in how we handle grabs that make it difficult to + * merge the two. + */ + MetaDisplay *display = meta_screen_get_display (screen); + MetaCompositor *compositor = display->compositor; + gboolean ok; + + if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE) + return FALSE; + + if (meta_is_wayland_compositor ()) + ok = begin_modal_wayland (screen, plugin, options, timestamp); + else + ok = begin_modal_x11 (screen, plugin, options, timestamp); + if (!ok) + return FALSE; + + 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; + + compositor->modal_plugin = plugin; + + return TRUE; +} + void meta_end_modal_for_plugin (MetaScreen *screen, MetaPlugin *plugin, @@ -526,8 +586,18 @@ meta_end_modal_for_plugin (MetaScreen *screen, g_return_if_fail (compositor->modal_plugin == plugin); - XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp); - XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp); + if (meta_is_wayland_compositor ()) + { + MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); + + meta_wayland_pointer_end_modal (&compositor->seat->pointer); + meta_wayland_keyboard_end_modal (&compositor->seat->keyboard); + } + else + { + XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp); + XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp); + } display->grab_op = META_GRAB_OP_NONE; display->grab_window = NULL; diff --git a/src/compositor/meta-plugin.c b/src/compositor/meta-plugin.c index daf582435..ba8b9cbd9 100644 --- a/src/compositor/meta-plugin.c +++ b/src/compositor/meta-plugin.c @@ -267,10 +267,6 @@ meta_plugin_destroy_completed (MetaPlugin *plugin, /** * meta_plugin_begin_modal: * @plugin: a #MetaPlugin - * @grab_window: the X window to grab the keyboard and mouse on - * @cursor: the cursor to use for the pointer grab, or None, - * to use the normal cursor for the grab window and - * its descendants. * @options: flags that modify the behavior of the modal grab * @timestamp: the timestamp used for establishing grabs * @@ -291,15 +287,13 @@ meta_plugin_destroy_completed (MetaPlugin *plugin, */ gboolean meta_plugin_begin_modal (MetaPlugin *plugin, - Window grab_window, - Cursor cursor, MetaModalOptions options, guint32 timestamp) { MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv; return meta_begin_modal_for_plugin (priv->screen, plugin, - grab_window, cursor, options, timestamp); + options, timestamp); } /** diff --git a/src/core/display.c b/src/core/display.c index 5fd423d00..74b83edc0 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -1910,6 +1910,7 @@ update_focus_window (MetaDisplay *display, display->focus_serial = serial; if (display->focus_xwindow == xwindow && + display->focus_type == type && display->focus_window == window) return; diff --git a/src/meta/meta-plugin.h b/src/meta/meta-plugin.h index d2643c2a9..0587551c8 100644 --- a/src/meta/meta-plugin.h +++ b/src/meta/meta-plugin.h @@ -396,8 +396,6 @@ typedef enum { gboolean meta_plugin_begin_modal (MetaPlugin *plugin, - Window grab_window, - Cursor cursor, MetaModalOptions options, guint32 timestamp); diff --git a/src/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c index 4a38b42cd..603cd8de7 100644 --- a/src/wayland/meta-wayland-keyboard.c +++ b/src/wayland/meta-wayland-keyboard.c @@ -565,3 +565,54 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard) wl_list_remove (&keyboard->focus_listener.link); wl_array_release (&keyboard->keys); } + +static void +modal_key (MetaWaylandKeyboardGrab *grab, + uint32_t time, + uint32_t key, + uint32_t state) +{ +} + +static void +modal_modifiers (MetaWaylandKeyboardGrab *grab, + uint32_t serial, + uint32_t mods_depressed, + uint32_t mods_latched, + uint32_t mods_locked, + uint32_t group) +{ +} + +static MetaWaylandKeyboardGrabInterface modal_grab = { + modal_key, + modal_modifiers, +}; + +gboolean +meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard) +{ + MetaWaylandKeyboardGrab *grab; + + if (keyboard->grab != &keyboard->default_grab) + return FALSE; + + grab = g_slice_new0 (MetaWaylandKeyboardGrab); + grab->interface = &modal_grab; + meta_wayland_keyboard_start_grab (keyboard, grab); + + return TRUE; +} + +void +meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard) +{ + MetaWaylandKeyboardGrab *grab; + + grab = keyboard->grab; + + g_assert (grab->interface == &modal_grab); + + meta_wayland_keyboard_end_grab (keyboard); + g_slice_free (MetaWaylandKeyboardGrab, grab); +} diff --git a/src/wayland/meta-wayland-keyboard.h b/src/wayland/meta-wayland-keyboard.h index e092366b9..c49eebebc 100644 --- a/src/wayland/meta-wayland-keyboard.h +++ b/src/wayland/meta-wayland-keyboard.h @@ -70,6 +70,11 @@ meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *device, void meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard); +gboolean +meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard); +void +meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard); + void meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard); diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c index 49ac2ec98..758d60a85 100644 --- a/src/wayland/meta-wayland-pointer.c +++ b/src/wayland/meta-wayland-pointer.c @@ -262,3 +262,65 @@ meta_wayland_pointer_set_current (MetaWaylandPointer *pointer, &pointer->current_listener); pointer->current_listener.notify = current_surface_destroy; } + +static void +modal_focus (MetaWaylandPointerGrab *grab, + MetaWaylandSurface *surface, + wl_fixed_t x, + wl_fixed_t y) +{ +} + +static void +modal_motion (MetaWaylandPointerGrab *grab, + uint32_t time, + wl_fixed_t x, + wl_fixed_t y) +{ +} + +static void +modal_button (MetaWaylandPointerGrab *grab, + uint32_t time, + uint32_t button, + uint32_t state) +{ +} + +static MetaWaylandPointerGrabInterface modal_grab = { + modal_focus, + modal_motion, + modal_button +}; + +gboolean +meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer) +{ + MetaWaylandPointerGrab *grab; + + if (pointer->grab != &pointer->default_grab) + return FALSE; + + meta_wayland_pointer_set_focus (pointer, NULL, + wl_fixed_from_int (0), + wl_fixed_from_int (0)); + + grab = g_slice_new0 (MetaWaylandPointerGrab); + grab->interface = &modal_grab; + meta_wayland_pointer_start_grab (pointer, grab); + + return TRUE; +} + +void +meta_wayland_pointer_end_modal (MetaWaylandPointer *pointer) +{ + MetaWaylandPointerGrab *grab; + + grab = pointer->grab; + + g_assert (grab->interface == &modal_grab); + + meta_wayland_pointer_end_grab (pointer); + g_slice_free (MetaWaylandPointerGrab, grab); +} diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h index a1e5f3854..db6d3bf9b 100644 --- a/src/wayland/meta-wayland-pointer.h +++ b/src/wayland/meta-wayland-pointer.h @@ -42,6 +42,11 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer, void meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer); +gboolean +meta_wayland_pointer_begin_modal (MetaWaylandPointer *pointer); +void +meta_wayland_pointer_end_modal (MetaWaylandPointer *pointer); + void meta_wayland_pointer_set_current (MetaWaylandPointer *pointer, MetaWaylandSurface *surface);