summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ã…dahl <jadahl@gmail.com>2015-08-09 21:24:16 +0800
committerCarlos Garnacho <carlosg@gnome.org>2015-08-10 16:44:01 +0200
commit109389acf0d04100c06b42f311af894b9e879771 (patch)
tree01d35de5c3a256523a1eb126113079327a6151d1
parentb0b08d5010d3a47ae636310dbdecd175ffb54dc2 (diff)
downloadmutter-109389acf0d04100c06b42f311af894b9e879771.tar.gz
MetaWaylandPointer: Put client resources in its own struct
Instead of moving around all the bound pointer resources for a client when changing focus, keep all the resources bound by a client in a per client struct, and track the focus by having a pointer to the current active pointer client struct instance. This will simplify having wl_pointer extensinos sharing the pointer focus of the wl_pointer by only having to add them to the pointer client. https://bugzilla.gnome.org/show_bug.cgi?id=744104
-rw-r--r--src/wayland/meta-wayland-pointer.c236
-rw-r--r--src/wayland/meta-wayland-pointer.h13
-rw-r--r--src/wayland/meta-wayland-types.h2
3 files changed, 171 insertions, 80 deletions
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index a229fe224..d6706fa25 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -58,10 +58,107 @@
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
+static MetaWaylandPointerClient *
+meta_wayland_pointer_client_new (void)
+{
+ MetaWaylandPointerClient *pointer_client;
+
+ pointer_client = g_slice_new0 (MetaWaylandPointerClient);
+ wl_list_init (&pointer_client->pointer_resources);
+
+ return pointer_client;
+}
+
+static void
+meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client)
+{
+ struct wl_resource *resource;
+
+ /* Since we make every wl_pointer resource defunct when we stop advertising
+ * the pointer capability on the wl_seat, we need to make sure all the
+ * resources in the pointer client instance gets removed.
+ */
+ wl_resource_for_each (resource, &pointer_client->pointer_resources)
+ {
+ wl_list_remove (wl_resource_get_link (resource));
+ wl_list_init (wl_resource_get_link (resource));
+ }
+
+ g_slice_free (MetaWaylandPointerClient, pointer_client);
+}
+
+static gboolean
+meta_wayland_pointer_client_is_empty (MetaWaylandPointerClient *pointer_client)
+{
+ return wl_list_empty (&pointer_client->pointer_resources);
+}
+
+MetaWaylandPointerClient *
+meta_wayland_pointer_get_pointer_client (MetaWaylandPointer *pointer,
+ struct wl_client *client)
+{
+ return g_hash_table_lookup (pointer->pointer_clients, client);
+}
+
+static MetaWaylandPointerClient *
+meta_wayland_pointer_ensure_pointer_client (MetaWaylandPointer *pointer,
+ struct wl_client *client)
+{
+ MetaWaylandPointerClient *pointer_client;
+
+ pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client);
+ if (pointer_client)
+ return pointer_client;
+
+ pointer_client = meta_wayland_pointer_client_new ();
+ g_hash_table_insert (pointer->pointer_clients, client, pointer_client);
+
+ if (!pointer->focus_client &&
+ pointer->focus_surface &&
+ wl_resource_get_client (pointer->focus_surface->resource) == client)
+ pointer->focus_client = pointer_client;
+
+ return pointer_client;
+}
+
static void
-unbind_resource (struct wl_resource *resource)
+meta_wayland_pointer_cleanup_pointer_client (MetaWaylandPointer *pointer,
+ MetaWaylandPointerClient *pointer_client,
+ struct wl_client *client)
{
+ if (meta_wayland_pointer_client_is_empty (pointer_client))
+ {
+ if (pointer->focus_client == pointer_client)
+ pointer->focus_client = NULL;
+ g_hash_table_remove (pointer->pointer_clients, client);
+ }
+}
+
+void
+meta_wayland_pointer_unbind_pointer_client_resource (struct wl_resource *resource)
+{
+ MetaWaylandPointer *pointer = wl_resource_get_user_data (resource);
+ MetaWaylandPointerClient *pointer_client;
+ struct wl_client *client = wl_resource_get_client (resource);
+
wl_list_remove (wl_resource_get_link (resource));
+
+ pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client);
+ if (!pointer_client)
+ {
+ /* This happens if all pointer devices were unplugged and no new resources
+ * were created by the client.
+ *
+ * If this is a resource that was previously made defunct, pointer_client
+ * be non-NULL but it is harmless since the below cleanup call will be
+ * prevented from removing the pointer client because of valid resources.
+ */
+ return;
+ }
+
+ meta_wayland_pointer_cleanup_pointer_client (pointer,
+ pointer_client,
+ client);
}
static void
@@ -131,17 +228,20 @@ meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
struct wl_resource *resource;
- struct wl_list *l;
+ uint32_t time;
+ wl_fixed_t sx, sy;
- l = &pointer->focus_resource_list;
- wl_resource_for_each(resource, l)
- {
- wl_fixed_t sx, sy;
+ if (!pointer->focus_client)
+ return;
- meta_wayland_pointer_get_relative_coordinates (pointer,
- pointer->focus_surface,
- &sx, &sy);
- wl_pointer_send_motion (resource, clutter_event_get_time (event), sx, sy);
+ time = clutter_event_get_time (event);
+ meta_wayland_pointer_get_relative_coordinates (pointer,
+ pointer->focus_surface,
+ &sx, &sy);
+
+ wl_resource_for_each (resource, &pointer->focus_client->pointer_resources)
+ {
+ wl_pointer_send_motion (resource, time, sx, sy);
}
}
@@ -150,19 +250,21 @@ meta_wayland_pointer_send_button (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
struct wl_resource *resource;
- struct wl_list *l;
ClutterEventType event_type;
event_type = clutter_event_type (event);
- l = &pointer->focus_resource_list;
- if (!wl_list_empty (l))
+ if (pointer->focus_client &&
+ !wl_list_empty (&pointer->focus_client->pointer_resources))
{
struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
struct wl_display *display = wl_client_get_display (client);
+ uint32_t time;
uint32_t button;
uint32_t serial;
+ time = clutter_event_get_time (event);
+
button = clutter_event_get_button (event);
switch (button)
{
@@ -183,10 +285,10 @@ meta_wayland_pointer_send_button (MetaWaylandPointer *pointer,
serial = wl_display_next_serial (display);
- wl_resource_for_each(resource, l)
+ wl_resource_for_each (resource, &pointer->focus_client->pointer_resources)
{
wl_pointer_send_button (resource, serial,
- clutter_event_get_time (event), button,
+ time, button,
event_type == CLUTTER_BUTTON_PRESS ? 1 : 0);
}
}
@@ -241,8 +343,9 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
pointer->display = display;
- wl_list_init (&pointer->resource_list);
- wl_list_init (&pointer->focus_resource_list);
+ pointer->pointer_clients =
+ g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) meta_wayland_pointer_client_free);
pointer->focus_surface_listener.notify = pointer_handle_focus_surface_destroy;
@@ -265,6 +368,7 @@ meta_wayland_pointer_release (MetaWaylandPointer *pointer)
meta_wayland_pointer_set_focus (pointer, NULL);
set_cursor_surface (pointer, NULL);
+ g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref);
pointer->display = NULL;
}
@@ -358,7 +462,6 @@ handle_scroll_event (MetaWaylandPointer *pointer,
const ClutterEvent *event)
{
struct wl_resource *resource;
- struct wl_list *l;
wl_fixed_t x_value = 0, y_value = 0;
if (clutter_event_is_pointer_emulated (event))
@@ -399,15 +502,17 @@ handle_scroll_event (MetaWaylandPointer *pointer,
return;
}
- l = &pointer->focus_resource_list;
- wl_resource_for_each (resource, l)
+ if (pointer->focus_client)
{
- if (x_value)
- wl_pointer_send_axis (resource, clutter_event_get_time (event),
- WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value);
- if (y_value)
- wl_pointer_send_axis (resource, clutter_event_get_time (event),
- WL_POINTER_AXIS_VERTICAL_SCROLL, y_value);
+ wl_resource_for_each (resource, &pointer->focus_client->pointer_resources)
+ {
+ if (x_value)
+ wl_pointer_send_axis (resource, clutter_event_get_time (event),
+ WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value);
+ if (y_value)
+ wl_pointer_send_axis (resource, clutter_event_get_time (event),
+ WL_POINTER_AXIS_VERTICAL_SCROLL, y_value);
+ }
}
}
@@ -438,29 +543,6 @@ meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer,
}
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
broadcast_focus (MetaWaylandPointer *pointer,
struct wl_resource *resource)
{
@@ -482,22 +564,23 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
if (pointer->focus_surface != NULL)
{
+ struct wl_client *client =
+ wl_resource_get_client (pointer->focus_surface->resource);
+ struct wl_display *display = wl_client_get_display (client);
+ uint32_t serial;
struct wl_resource *resource;
- struct wl_list *l;
- l = &pointer->focus_resource_list;
- if (!wl_list_empty (l))
- {
- struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
- struct wl_display *display = wl_client_get_display (client);
- uint32_t serial = wl_display_next_serial (display);
+ serial = wl_display_next_serial (display);
- wl_resource_for_each (resource, l)
+ if (pointer->focus_client)
+ {
+ wl_resource_for_each (resource,
+ &pointer->focus_client->pointer_resources)
{
wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
}
- move_resources (&pointer->resource_list, &pointer->focus_resource_list);
+ pointer->focus_client = NULL;
}
wl_list_remove (&pointer->focus_surface_listener.link);
@@ -506,8 +589,9 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
if (surface != NULL)
{
+ struct wl_client *client = wl_resource_get_client (surface->resource);
+ struct wl_display *display = wl_client_get_display (client);
struct wl_resource *resource;
- struct wl_list *l;
ClutterPoint pos;
pointer->focus_surface = surface;
@@ -521,18 +605,14 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
clutter_get_current_event_time (),
pos.x, pos.y);
- move_resources_for_client (&pointer->focus_resource_list,
- &pointer->resource_list,
- wl_resource_get_client (pointer->focus_surface->resource));
-
- l = &pointer->focus_resource_list;
- if (!wl_list_empty (l))
+ pointer->focus_client =
+ meta_wayland_pointer_get_pointer_client (pointer, client);
+ if (pointer->focus_client)
{
- struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
- struct wl_display *display = wl_client_get_display (client);
pointer->focus_serial = wl_display_next_serial (display);
- wl_resource_for_each (resource, l)
+ wl_resource_for_each (resource,
+ &pointer->focus_client->pointer_resources)
{
broadcast_focus (pointer, resource);
}
@@ -707,19 +787,19 @@ meta_wayland_pointer_create_new_resource (MetaWaylandPointer *pointer,
uint32_t id)
{
struct wl_resource *cr;
+ MetaWaylandPointerClient *pointer_client;
cr = wl_resource_create (client, &wl_pointer_interface, wl_resource_get_version (seat_resource), id);
- wl_resource_set_implementation (cr, &pointer_interface, pointer, unbind_resource);
+ wl_resource_set_implementation (cr, &pointer_interface, pointer,
+ meta_wayland_pointer_unbind_pointer_client_resource);
- if (pointer->focus_surface && wl_resource_get_client (pointer->focus_surface->resource) == client)
- {
- wl_list_insert (&pointer->focus_resource_list, wl_resource_get_link (cr));
- broadcast_focus (pointer, cr);
- }
- else
- {
- wl_list_insert (&pointer->resource_list, wl_resource_get_link (cr));
- }
+ pointer_client = meta_wayland_pointer_ensure_pointer_client (pointer, client);
+
+ wl_list_insert (&pointer_client->pointer_resources,
+ wl_resource_get_link (cr));
+
+ if (pointer->focus_client == pointer_client)
+ broadcast_focus (pointer, cr);
}
gboolean
diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h
index 70b7b427a..68bbbc572 100644
--- a/src/wayland/meta-wayland-pointer.h
+++ b/src/wayland/meta-wayland-pointer.h
@@ -44,12 +44,17 @@ struct _MetaWaylandPointerGrab
MetaWaylandPointer *pointer;
};
+struct _MetaWaylandPointerClient
+{
+ struct wl_list pointer_resources;
+};
+
struct _MetaWaylandPointer
{
struct wl_display *display;
- struct wl_list resource_list;
- struct wl_list focus_resource_list;
+ MetaWaylandPointerClient *focus_client;
+ GHashTable *pointer_clients;
MetaWaylandSurface *focus_surface;
struct wl_listener focus_surface_listener;
@@ -127,4 +132,8 @@ gboolean meta_wayland_pointer_can_popup (MetaWaylandPointer *pointer,
MetaWaylandSurface *meta_wayland_pointer_get_top_popup (MetaWaylandPointer *pointer);
+MetaWaylandPointerClient * meta_wayland_pointer_get_pointer_client (MetaWaylandPointer *pointer,
+ struct wl_client *client);
+void meta_wayland_pointer_unbind_pointer_client_resource (struct wl_resource *resource);
+
#endif /* META_WAYLAND_POINTER_H */
diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h
index 6b134e61d..ba5b66e5d 100644
--- a/src/wayland/meta-wayland-types.h
+++ b/src/wayland/meta-wayland-types.h
@@ -43,4 +43,6 @@ typedef struct _MetaWaylandOutput MetaWaylandOutput;
typedef struct _MetaWaylandSerial MetaWaylandSerial;
+typedef struct _MetaWaylandPointerClient MetaWaylandPointerClient;
+
#endif