[mutter/wip/tablet-protocol: 130/133] wayland: Maintain wl_tablet current focus window and tool.
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/tablet-protocol: 130/133] wayland: Maintain wl_tablet current focus window and tool.
- Date: Tue, 31 Mar 2015 11:58:18 +0000 (UTC)
commit a808ca061e31817418b28c375fd92343e9658371
Author: Carlos Garnacho <carlosg gnome org>
Date: Thu Feb 5 12:07:47 2015 +0100
wayland: Maintain wl_tablet current focus window and tool.
wl_tablet.proximity_in/out events are now sent, along with the necessary
wl_tablet_manager.tool_added if the tool wasn't known to the focused client
src/wayland/meta-wayland-tablet.c | 262 ++++++++++++++++++++++++++++++++++++-
src/wayland/meta-wayland-tablet.h | 11 ++
2 files changed, 272 insertions(+), 1 deletions(-)
---
diff --git a/src/wayland/meta-wayland-tablet.c b/src/wayland/meta-wayland-tablet.c
index 3d8eea4..81dcbaf 100644
--- a/src/wayland/meta-wayland-tablet.c
+++ b/src/wayland/meta-wayland-tablet.c
@@ -33,6 +33,10 @@
#include "meta-surface-actor-wayland.h"
#include "meta-wayland-private.h"
#include "meta-wayland-tablet.h"
+#include "meta-wayland-tablet-tool.h"
+
+static void meta_wayland_tablet_set_focus (MetaWaylandTablet *tablet,
+ MetaWaylandSurface *surface);
static void
unbind_resource (struct wl_resource *resource)
@@ -40,6 +44,39 @@ unbind_resource (struct wl_resource *resource)
wl_list_remove (wl_resource_get_link (resource));
}
+static void
+move_resources (struct wl_list *destination, struct wl_list *source)
+{
+ wl_list_insert_list (destination, source);
+ wl_list_init (source);
+}
+
+static void
+move_resources_for_client (struct wl_list *destination,
+ struct wl_list *source,
+ struct wl_client *client)
+{
+ struct wl_resource *resource, *tmp;
+ wl_resource_for_each_safe (resource, tmp, source)
+ {
+ if (wl_resource_get_client (resource) == client)
+ {
+ wl_list_remove (wl_resource_get_link (resource));
+ wl_list_insert (destination, wl_resource_get_link (resource));
+ }
+ }
+}
+
+static void
+tablet_handle_focus_surface_destroy (struct wl_listener *listener,
+ void *data)
+{
+ MetaWaylandTablet *tablet;
+
+ tablet = wl_container_of (listener, tablet, focus_surface_destroy_listener);
+ meta_wayland_tablet_set_focus (tablet, NULL);
+}
+
MetaWaylandTablet *
meta_wayland_tablet_new (ClutterInputDevice *device,
MetaWaylandTabletManager *manager)
@@ -48,9 +85,12 @@ meta_wayland_tablet_new (ClutterInputDevice *device,
tablet = g_slice_new0 (MetaWaylandTablet);
wl_list_init (&tablet->resource_list);
+ wl_list_init (&tablet->focus_resource_list);
tablet->device = device;
tablet->manager = manager;
+ tablet->focus_surface_destroy_listener.notify = tablet_handle_focus_surface_destroy;
+
tablet->cursor_renderer = meta_cursor_renderer_new ();
meta_cursor_renderer_set_cursor (tablet->cursor_renderer, NULL);
@@ -62,6 +102,9 @@ meta_wayland_tablet_free (MetaWaylandTablet *tablet)
{
struct wl_resource *resource, *next;
+ meta_wayland_tablet_set_focus (tablet, NULL);
+ g_hash_table_destroy (tablet->tools);
+
wl_resource_for_each_safe (resource, next, &tablet->resource_list)
{
wl_tablet_send_removed (resource);
@@ -72,10 +115,208 @@ meta_wayland_tablet_free (MetaWaylandTablet *tablet)
g_slice_free (MetaWaylandTablet, tablet);
}
+static struct wl_resource *
+meta_wayland_tablet_ensure_tool_resource_for_client (MetaWaylandTablet *tablet,
+ struct wl_client *client)
+{
+ struct wl_resource *tool_resource;
+
+ tool_resource = meta_wayland_tablet_tool_lookup_resource (tablet->current_tool,
+ client);
+ if (!tool_resource)
+ {
+ meta_wayland_tablet_manager_notify_tool (tablet->manager, tablet,
+ tablet->current_tool, client);
+ tool_resource = meta_wayland_tablet_tool_lookup_resource (tablet->current_tool,
+ client);
+ }
+
+ return tool_resource;
+}
+
+static void
+meta_wayland_tablet_set_focus (MetaWaylandTablet *tablet,
+ MetaWaylandSurface *surface)
+{
+ guint32 _time;
+
+ if (tablet->manager->wl_display == NULL)
+ return;
+
+ if (tablet->focus_surface == surface)
+ return;
+
+ _time = clutter_get_current_event_time ();
+
+ if (tablet->focus_surface != NULL)
+ {
+ struct wl_resource *resource;
+ struct wl_list *l;
+
+ l = &tablet->focus_resource_list;
+ if (!wl_list_empty (l))
+ {
+ wl_resource_for_each (resource, l)
+ {
+ wl_tablet_send_proximity_out (resource, _time);
+ }
+
+ move_resources (&tablet->resource_list, &tablet->focus_resource_list);
+ }
+
+ wl_list_remove (&tablet->focus_surface_destroy_listener.link);
+ tablet->focus_surface = NULL;
+ }
+
+ if (surface != NULL)
+ {
+ struct wl_resource *resource, *tool_resource;
+ struct wl_client *client;
+ struct wl_list *l;
+
+ tablet->focus_surface = surface;
+ client = wl_resource_get_client (tablet->focus_surface->resource);
+ wl_resource_add_destroy_listener (tablet->focus_surface->resource,
+ &tablet->focus_surface_destroy_listener);
+
+ move_resources_for_client (&tablet->focus_resource_list,
+ &tablet->resource_list, client);
+
+ tool_resource = meta_wayland_tablet_ensure_tool_resource_for_client (tablet, client);
+
+ l = &tablet->focus_resource_list;
+ if (!wl_list_empty (l))
+ {
+ struct wl_client *client = wl_resource_get_client (tablet->focus_surface->resource);
+ struct wl_display *display = wl_client_get_display (client);
+
+ tablet->proximity_serial = wl_display_next_serial (display);
+
+ wl_resource_for_each (resource, l)
+ {
+ wl_tablet_send_proximity_in (resource, tablet->proximity_serial, _time,
+ tool_resource, tablet->focus_surface->resource);
+ }
+ }
+ }
+}
+
+static void
+emit_proximity_in (MetaWaylandTablet *tablet,
+ struct wl_resource *resource)
+{
+ struct wl_resource *tool_resource;
+ struct wl_client *client;
+ guint32 _time;
+
+ if (!tablet->focus_surface || !tablet->current_tool)
+ return;
+
+ _time = clutter_get_current_event_time ();
+ client = wl_resource_get_client (resource);
+ tool_resource = meta_wayland_tablet_ensure_tool_resource_for_client (tablet, client);
+
+ wl_tablet_send_proximity_in (resource, tablet->proximity_serial, _time,
+ tool_resource, tablet->focus_surface->resource);
+}
+
+static void
+sync_focus_surface (MetaWaylandTablet *tablet)
+{
+ MetaDisplay *display = meta_get_display ();
+
+ switch (display->event_route)
+ {
+ case META_EVENT_ROUTE_WINDOW_OP:
+ case META_EVENT_ROUTE_COMPOSITOR_GRAB:
+ case META_EVENT_ROUTE_FRAME_BUTTON:
+ /* The compositor has a grab, so remove our focus */
+ meta_wayland_tablet_set_focus (tablet, NULL);
+ break;
+
+ case META_EVENT_ROUTE_NORMAL:
+ case META_EVENT_ROUTE_WAYLAND_POPUP:
+ meta_wayland_tablet_set_focus (tablet, tablet->current);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+repick_for_event (MetaWaylandTablet *tablet,
+ const ClutterEvent *for_event)
+{
+ ClutterActor *actor = NULL;
+
+ actor = clutter_event_get_source (for_event);
+
+ if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
+ tablet->current = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor));
+ else
+ tablet->current = NULL;
+
+ sync_focus_surface (tablet);
+}
+
+static MetaWaylandTabletTool *
+meta_wayland_tablet_ensure_tool (MetaWaylandTablet *tablet,
+ ClutterInputDeviceTool *device_tool)
+{
+ MetaWaylandTabletTool *tool;
+
+ tool = g_hash_table_lookup (tablet->tools, device_tool);
+
+ if (!tool)
+ {
+ tool = meta_wayland_tablet_tool_new (tablet->device, device_tool);
+ g_hash_table_insert (tablet->tools, device_tool, tool);
+ }
+
+ return tool;
+}
+
+static void
+meta_wayland_tablet_account_button (MetaWaylandTablet *tablet,
+ const ClutterEvent *event)
+{
+ if (event->type == CLUTTER_BUTTON_PRESS)
+ tablet->buttons = g_slist_append (tablet->buttons,
+ GUINT_TO_POINTER (event->button.button));
+ else
+ tablet->buttons = g_slist_remove (tablet->buttons,
+ GUINT_TO_POINTER (event->button.button));
+}
+
void
meta_wayland_tablet_update (MetaWaylandTablet *tablet,
const ClutterEvent *event)
{
+ switch (event->type)
+ {
+ case CLUTTER_BUTTON_PRESS:
+ case CLUTTER_BUTTON_RELEASE:
+ meta_wayland_tablet_account_button (tablet, event);
+ break;
+ case CLUTTER_MOTION:
+ if (!tablet->buttons)
+ repick_for_event (tablet, event);
+ break;
+ case CLUTTER_PROXIMITY_IN:
+ {
+ ClutterInputDeviceTool *tool;
+
+ tool = clutter_event_get_device_tool (event);
+ tablet->current_tool = meta_wayland_tablet_ensure_tool (tablet, tool);
+ break;
+ }
+ case CLUTTER_PROXIMITY_OUT:
+ tablet->current_tool = NULL;
+ break;
+ default:
+ break;
+ }
}
static void
@@ -96,6 +337,15 @@ meta_wayland_tablet_handle_event (MetaWaylandTablet *tablet,
{
switch (event->type)
{
+ case CLUTTER_PROXIMITY_IN:
+ /* We don't have much info here to make anything useful out of it,
+ * wait until the first motion event so we have both coordinates
+ * and tool.
+ */
+ break;
+ case CLUTTER_PROXIMITY_OUT:
+ meta_wayland_tablet_set_focus (tablet, NULL);
+ break;
case CLUTTER_MOTION:
handle_motion_event (tablet, event);
break;
@@ -144,7 +394,17 @@ meta_wayland_tablet_create_new_resource (MetaWaylandTablet *tablet,
wl_resource_set_implementation (resource, &tablet_interface,
tablet, unbind_resource);
wl_resource_set_user_data (resource, tablet);
- wl_list_insert (&tablet->resource_list, wl_resource_get_link (resource));
+
+ if (tablet->focus_surface &&
+ wl_resource_get_client (tablet->focus_surface->resource) == client)
+ {
+ wl_list_insert (&tablet->focus_resource_list, wl_resource_get_link (resource));
+ emit_proximity_in (tablet, resource);
+ }
+ else
+ {
+ wl_list_insert (&tablet->resource_list, wl_resource_get_link (resource));
+ }
return resource;
}
diff --git a/src/wayland/meta-wayland-tablet.h b/src/wayland/meta-wayland-tablet.h
index 34bc399..6e6230f 100644
--- a/src/wayland/meta-wayland-tablet.h
+++ b/src/wayland/meta-wayland-tablet.h
@@ -28,17 +28,28 @@
#include "meta-wayland-types.h"
#include "meta-cursor-renderer.h"
+#include "meta-wayland-tablet-tool.h"
struct _MetaWaylandTablet
{
MetaWaylandTabletManager *manager;
ClutterInputDevice *device;
+ GHashTable *tools;
+
+ MetaWaylandTabletTool *current_tool;
struct wl_list resource_list;
+ struct wl_list focus_resource_list;
+
+ MetaWaylandSurface *focus_surface;
+ struct wl_listener focus_surface_destroy_listener;
MetaCursorRenderer *cursor_renderer;
MetaWaylandSurface *current;
+ GSList *buttons;
+
+ guint32 proximity_serial;
};
MetaWaylandTablet * meta_wayland_tablet_new (ClutterInputDevice *device,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]