seat: Listen for ClutterDeviceManager signals in order to update capabilities

The capability flags are determined from the device types of the slave devices
that are currently attached. This also happens whenever a device is added or
removed, so the capabilities are kept up to date, and clients know about these.

On VT switch, all slave devices are temporarily removed, so the cascade of
signals will make the seat end up with capabililities=0 while input is suspended.

https://bugzilla.gnome.org/show_bug.cgi?id=733563
This commit is contained in:
Carlos Garnacho 2014-07-23 15:33:03 +02:00
parent f55737ec06
commit ac448bd42b
2 changed files with 127 additions and 10 deletions

View File

@ -27,6 +27,9 @@
#include "meta-wayland-versions.h"
#include "meta-wayland-data-device.h"
#define CAPABILITY_ENABLED(prev, cur, capability) ((cur & (capability)) && !(prev & (capability)))
#define CAPABILITY_DISABLED(prev, cur, capability) ((prev & (capability)) && !(cur & (capability)))
static void
unbind_resource (struct wl_resource *resource)
{
@ -86,27 +89,136 @@ bind_seat (struct wl_client *client,
wl_resource_set_implementation (resource, &seat_interface, seat, unbind_resource);
wl_list_insert (&seat->base_resource_list, wl_resource_get_link (resource));
wl_seat_send_capabilities (resource,
WL_SEAT_CAPABILITY_POINTER |
WL_SEAT_CAPABILITY_KEYBOARD |
WL_SEAT_CAPABILITY_TOUCH);
wl_seat_send_capabilities (resource, seat->capabilities);
if (version >= WL_SEAT_NAME_SINCE_VERSION)
wl_seat_send_name (resource, "seat0");
}
static uint32_t
lookup_device_capabilities (ClutterDeviceManager *device_manager)
{
const GSList *devices, *l;
uint32_t capabilities = 0;
devices = clutter_device_manager_peek_devices (device_manager);
for (l = devices; l; l = l->next)
{
ClutterInputDeviceType device_type;
/* Only look for physical devices, master devices have rather generic
* keyboard/pointer device types, which is not truly representative of
* the slave devices connected to them.
*/
if (clutter_input_device_get_device_mode (l->data) == CLUTTER_INPUT_MODE_MASTER)
continue;
device_type = clutter_input_device_get_device_type (l->data);
switch (device_type)
{
case CLUTTER_POINTER_DEVICE:
capabilities |= WL_SEAT_CAPABILITY_POINTER;
break;
case CLUTTER_KEYBOARD_DEVICE:
capabilities |= WL_SEAT_CAPABILITY_KEYBOARD;
break;
case CLUTTER_TOUCHSCREEN_DEVICE:
capabilities |= WL_SEAT_CAPABILITY_TOUCH;
break;
default:
g_debug ("Ignoring device '%s' with unhandled type %d",
clutter_input_device_get_device_name (l->data),
device_type);
break;
}
}
return capabilities;
}
static void
meta_wayland_seat_set_capabilities (MetaWaylandSeat *seat,
uint32_t flags)
{
struct wl_resource *resource;
uint32_t prev_flags;
prev_flags = seat->capabilities;
if (prev_flags == flags)
return;
seat->capabilities = flags;
if (CAPABILITY_ENABLED (prev_flags, flags, WL_SEAT_CAPABILITY_POINTER))
meta_wayland_pointer_init (&seat->pointer, seat->wl_display);
else if (CAPABILITY_DISABLED (prev_flags, flags, WL_SEAT_CAPABILITY_POINTER))
meta_wayland_pointer_release (&seat->pointer);
if (CAPABILITY_ENABLED (prev_flags, flags, WL_SEAT_CAPABILITY_KEYBOARD))
{
MetaDisplay *display;
meta_wayland_keyboard_init (&seat->keyboard, seat->wl_display);
display = meta_get_display ();
/* Post-initialization, ensure the input focus is in sync */
if (display)
meta_display_sync_wayland_input_focus (display);
}
else if (CAPABILITY_DISABLED (prev_flags, flags, WL_SEAT_CAPABILITY_KEYBOARD))
meta_wayland_keyboard_release (&seat->keyboard);
if (CAPABILITY_ENABLED (prev_flags, flags, WL_SEAT_CAPABILITY_TOUCH))
meta_wayland_touch_init (&seat->touch, seat->wl_display);
else if (CAPABILITY_DISABLED (prev_flags, flags, WL_SEAT_CAPABILITY_TOUCH))
meta_wayland_touch_release (&seat->touch);
/* Broadcast capability changes */
wl_resource_for_each (resource, &seat->base_resource_list)
{
wl_seat_send_capabilities (resource, flags);
}
}
static void
meta_wayland_seat_update_capabilities (MetaWaylandSeat *seat,
ClutterDeviceManager *device_manager)
{
uint32_t capabilities;
capabilities = lookup_device_capabilities (device_manager);
meta_wayland_seat_set_capabilities (seat, capabilities);
}
static void
meta_wayland_seat_devices_updated (ClutterDeviceManager *device_manager,
ClutterInputDevice *input_device,
MetaWaylandSeat *seat)
{
meta_wayland_seat_update_capabilities (seat, device_manager);
}
static MetaWaylandSeat *
meta_wayland_seat_new (struct wl_display *display)
{
MetaWaylandSeat *seat = g_new0 (MetaWaylandSeat, 1);
ClutterDeviceManager *device_manager;
wl_list_init (&seat->base_resource_list);
seat->wl_display = display;
meta_wayland_pointer_init (&seat->pointer, display);
meta_wayland_keyboard_init (&seat->keyboard, display);
meta_wayland_touch_init (&seat->touch, display);
meta_wayland_data_device_init (&seat->data_device);
device_manager = clutter_device_manager_get_default ();
meta_wayland_seat_update_capabilities (seat, device_manager);
g_signal_connect (device_manager, "device-added",
G_CALLBACK (meta_wayland_seat_devices_updated), seat);
g_signal_connect (device_manager, "device-removed",
G_CALLBACK (meta_wayland_seat_devices_updated), seat);
wl_global_create (display, &wl_seat_interface, META_WL_SEAT_VERSION, seat, bind_seat);
return seat;
@ -121,9 +233,11 @@ meta_wayland_seat_init (MetaWaylandCompositor *compositor)
void
meta_wayland_seat_free (MetaWaylandSeat *seat)
{
meta_wayland_pointer_release (&seat->pointer);
meta_wayland_keyboard_release (&seat->keyboard);
meta_wayland_touch_release (&seat->touch);
ClutterDeviceManager *device_manager;
device_manager = clutter_device_manager_get_default ();
g_signal_handlers_disconnect_by_data (device_manager, seat);
meta_wayland_seat_set_capabilities (seat, 0);
g_slice_free (MetaWaylandSeat, seat);
}

View File

@ -34,11 +34,14 @@
struct _MetaWaylandSeat
{
struct wl_list base_resource_list;
struct wl_display *wl_display;
MetaWaylandPointer pointer;
MetaWaylandKeyboard keyboard;
MetaWaylandTouch touch;
MetaWaylandDataDevice data_device;
guint capabilities;
};
void meta_wayland_seat_init (MetaWaylandCompositor *compositor);