summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compositor/compositor.c139
-rw-r--r--src/wayland/meta-wayland-keyboard.c122
-rw-r--r--src/wayland/meta-wayland-keyboard.h7
-rw-r--r--src/wayland/meta-wayland-pointer.c62
-rw-r--r--src/wayland/meta-wayland-pointer.h5
5 files changed, 291 insertions, 44 deletions
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 215645265..866089861 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -85,6 +85,8 @@
#include "window-private.h" /* to check window->hidden */
#include "display-private.h" /* for meta_display_lookup_x_window() */
#include "meta-wayland-private.h"
+#include "meta-wayland-pointer.h"
+#include "meta-wayland-keyboard.h"
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
@@ -424,34 +426,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,
- 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;
- ClutterStage *stage;
- Window grab_window;
- Cursor cursor = None;
- gboolean pointer_grabbed = FALSE;
- gboolean keyboard_grabbed = FALSE;
- int result;
-
- stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
- if (!stage)
- return FALSE;
-
- grab_window = clutter_x11_get_stage_window (stage);
-
- 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)
{
@@ -501,14 +489,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:
@@ -520,6 +500,80 @@ 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,
+ timestamp))
+ 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, timestamp);
+
+ 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,
@@ -531,8 +585,19 @@ 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,
+ timestamp);
+ }
+ 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/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c
index 70d29b261..ef7c2071f 100644
--- a/src/wayland/meta-wayland-keyboard.c
+++ b/src/wayland/meta-wayland-keyboard.c
@@ -274,6 +274,29 @@ static const MetaWaylandKeyboardGrabInterface
default_grab_modifiers,
};
+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_init (MetaWaylandKeyboard *keyboard,
struct wl_display *display,
@@ -515,13 +538,29 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
display = wl_client_get_display (client);
serial = wl_display_next_serial (display);
- wl_keyboard_send_modifiers (resource, serial,
- keyboard->modifier_state.mods_depressed,
- keyboard->modifier_state.mods_latched,
- keyboard->modifier_state.mods_locked,
- keyboard->modifier_state.group);
- wl_keyboard_send_enter (resource, serial, surface->resource,
- &keyboard->keys);
+
+ /* If we're in a modal grab, the client is focused but doesn't see
+ modifiers or pressed keys (and fix that up when we exit the modal) */
+ if (keyboard->grab->interface == &modal_grab)
+ {
+ struct wl_array empty;
+ wl_array_init (&empty);
+
+ wl_keyboard_send_modifiers (resource, serial,
+ 0, 0, 0, 0);
+ wl_keyboard_send_enter (resource, serial, surface->resource,
+ &empty);
+ }
+ else
+ {
+ wl_keyboard_send_modifiers (resource, serial,
+ keyboard->modifier_state.mods_depressed,
+ keyboard->modifier_state.mods_latched,
+ keyboard->modifier_state.mods_locked,
+ keyboard->modifier_state.group);
+ wl_keyboard_send_enter (resource, serial, surface->resource,
+ &keyboard->keys);
+ }
wl_resource_add_destroy_listener (resource, &keyboard->focus_listener);
keyboard->focus_serial = serial;
}
@@ -565,3 +604,72 @@ meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
wl_list_remove (&keyboard->focus_listener.link);
wl_array_release (&keyboard->keys);
}
+
+gboolean
+meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
+ guint32 timestamp)
+{
+ MetaWaylandKeyboardGrab *grab;
+ uint32_t *end = (void *) ((char *) keyboard->keys.data +
+ keyboard->keys.size);
+ uint32_t *k;
+ uint32_t serial;
+
+ if (keyboard->grab != &keyboard->default_grab)
+ return FALSE;
+
+ if (keyboard->focus)
+ {
+ /* Fake key release events for the focused app */
+ serial = wl_display_next_serial (keyboard->display);
+ keyboard->grab->interface->modifiers (keyboard->grab,
+ serial,
+ 0, 0, 0, 0);
+
+ for (k = keyboard->keys.data; k < end; k++)
+ keyboard->grab->interface->key (keyboard->grab,
+ timestamp,
+ *k, 0);
+ }
+
+ 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,
+ guint32 timestamp)
+{
+ MetaWaylandKeyboardGrab *grab;
+ uint32_t *end = (void *) ((char *) keyboard->keys.data +
+ keyboard->keys.size);
+ uint32_t *k;
+ uint32_t serial;
+
+ grab = keyboard->grab;
+
+ g_assert (grab->interface == &modal_grab);
+
+ meta_wayland_keyboard_end_grab (keyboard);
+ g_slice_free (MetaWaylandKeyboardGrab, grab);
+
+ if (keyboard->focus)
+ {
+ /* Fake key press events for the focused app */
+ serial = wl_display_next_serial (keyboard->display);
+ keyboard->grab->interface->modifiers (keyboard->grab,
+ serial,
+ keyboard->modifier_state.mods_depressed,
+ keyboard->modifier_state.mods_latched,
+ keyboard->modifier_state.mods_locked,
+ keyboard->modifier_state.group);
+
+ for (k = keyboard->keys.data; k < end; k++)
+ keyboard->grab->interface->key (keyboard->grab,
+ timestamp,
+ *k, 1);
+ }
+}
diff --git a/src/wayland/meta-wayland-keyboard.h b/src/wayland/meta-wayland-keyboard.h
index e092366b9..57d7a878b 100644
--- a/src/wayland/meta-wayland-keyboard.h
+++ b/src/wayland/meta-wayland-keyboard.h
@@ -70,6 +70,13 @@ meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *device,
void
meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard);
+gboolean
+meta_wayland_keyboard_begin_modal (MetaWaylandKeyboard *keyboard,
+ guint32 timestamp);
+void
+meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
+ guint32 timestamp);
+
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);