[mutter/wip/wayland-work: 32/44] wayland: implement support for plugin modality
- From: Giovanni Campagna <gcampagna src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/wayland-work: 32/44] wayland: implement support for plugin modality
- Date: Tue, 27 Aug 2013 08:18:45 +0000 (UTC)
commit ea7c7de578ef9120feff1ffbf8ed8cf87b2ac880
Author: Giovanni Campagna <gcampagn redhat com>
Date: Tue Aug 13 16:51:33 2013 +0200
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.c | 139 +++++++++++++++++++++++++---------
src/wayland/meta-wayland-keyboard.c | 122 +++++++++++++++++++++++++++++--
src/wayland/meta-wayland-keyboard.h | 7 ++
src/wayland/meta-wayland-pointer.c | 62 ++++++++++++++++
src/wayland/meta-wayland-pointer.h | 5 +
src/wayland/meta-wayland.c | 2 +-
6 files changed, 292 insertions(+), 45 deletions(-)
---
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 5565dd0..7991ce1 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 70d29b2..ef7c207 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 e092366..57d7a87 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 49ac2ec..758d60a 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 a1e5f38..db6d3bf 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);
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 12ce3ff..f0aaccf 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -524,7 +524,7 @@ meta_wayland_surface_resource_destroy_cb (struct wl_resource *resource)
meta_window_unmanage (surface->window, timestamp);
}
- else
+ else if (!surface->window)
meta_wayland_surface_free (surface);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]