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
This commit is contained in:
parent
cba2ab445e
commit
1ee387bb31
@ -58,10 +58,107 @@
|
||||
|
||||
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
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
|
||||
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)
|
||||
if (!pointer->focus_client)
|
||||
return;
|
||||
|
||||
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_fixed_t sx, sy;
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (pointer,
|
||||
pointer->focus_surface,
|
||||
&sx, &sy);
|
||||
wl_pointer_send_motion (resource, clutter_event_get_time (event), sx, sy);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,29 +542,6 @@ meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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))
|
||||
serial = wl_display_next_serial (display);
|
||||
|
||||
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);
|
||||
uint32_t 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_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
|
||||
|
@ -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 */
|
||||
|
@ -43,4 +43,6 @@ typedef struct _MetaWaylandOutput MetaWaylandOutput;
|
||||
|
||||
typedef struct _MetaWaylandSerial MetaWaylandSerial;
|
||||
|
||||
typedef struct _MetaWaylandPointerClient MetaWaylandPointerClient;
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user