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