wayland: Implement the "inputfd" wayland protocols

This allows lending control to applications of evdev devices,
and withdrawing it with focus.
This commit is contained in:
Carlos Garnacho 2018-09-01 22:09:58 +02:00
parent 932340a989
commit 9321249b8d
12 changed files with 809 additions and 1 deletions

View File

@ -533,6 +533,12 @@ if have_wayland
'wayland/meta-wayland-inhibit-shortcuts-dialog.c', 'wayland/meta-wayland-inhibit-shortcuts-dialog.c',
'wayland/meta-wayland-inhibit-shortcuts-dialog.h', 'wayland/meta-wayland-inhibit-shortcuts-dialog.h',
'wayland/meta-wayland-inhibit-shortcuts.h', 'wayland/meta-wayland-inhibit-shortcuts.h',
'wayland/meta-wayland-inputfd-evdev-device.c',
'wayland/meta-wayland-inputfd-evdev-device.h',
'wayland/meta-wayland-inputfd-manager.c',
'wayland/meta-wayland-inputfd-manager.h',
'wayland/meta-wayland-inputfd-seat.c',
'wayland/meta-wayland-inputfd-seat.h',
'wayland/meta-wayland-input-device.c', 'wayland/meta-wayland-input-device.c',
'wayland/meta-wayland-input-device.h', 'wayland/meta-wayland-input-device.h',
'wayland/meta-wayland-keyboard.c', 'wayland/meta-wayland-keyboard.c',
@ -814,6 +820,7 @@ if have_wayland
['gtk-primary-selection', 'private', ], ['gtk-primary-selection', 'private', ],
['gtk-shell', 'private', ], ['gtk-shell', 'private', ],
['gtk-text-input', 'private', ], ['gtk-text-input', 'private', ],
['inputfd', 'unstable', 'v1', ],
['keyboard-shortcuts-inhibit', 'unstable', 'v1', ], ['keyboard-shortcuts-inhibit', 'unstable', 'v1', ],
['linux-dmabuf', 'unstable', 'v1', ], ['linux-dmabuf', 'unstable', 'v1', ],
['pointer-constraints', 'unstable', 'v1', ], ['pointer-constraints', 'unstable', 'v1', ],

View File

@ -0,0 +1,287 @@
/*
* Wayland Support
*
* Copyright (C) 2018 Red Hat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#include "config.h"
#include <linux/input.h>
#include <sys/ioctl.h>
#include "backends/native/meta-backend-native.h"
#include "compositor/meta-surface-actor-wayland.h"
#include "inputfd-unstable-v1-server-protocol.h"
#include "wayland/meta-wayland-inputfd-evdev-device.h"
static void device_open_fd (MetaWaylandInputFdEvdevDevice *device);
static void
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
evdev_device_handle_focus_surface_destroy (struct wl_listener *listener,
void *data)
{
MetaWaylandInputFdEvdevDevice *device = wl_container_of (listener, device,
focus_surface_listener);
meta_wayland_inputfd_evdev_device_set_focus (device, NULL);
}
static gboolean
check_device_qualifies (GUdevDevice *device)
{
const gchar *path = g_udev_device_get_device_file (device);
if (!path || !strstr (path, "/event"))
return FALSE;
if (!g_udev_device_get_property_as_boolean (device, "ID_INPUT_JOYSTICK"))
return FALSE;
return TRUE;
}
MetaWaylandInputFdEvdevDevice *
meta_wayland_inputfd_evdev_device_new (MetaWaylandInputFdSeat *seat,
GUdevDevice *device)
{
MetaWaylandInputFdEvdevDevice *evdev_device;
GUdevDevice *parent;
if (!check_device_qualifies (device))
return NULL;
parent = g_udev_device_get_parent (device);
evdev_device = g_slice_new0 (MetaWaylandInputFdEvdevDevice);
evdev_device->udev_device = g_object_ref (device);
wl_list_init (&evdev_device->resource_list);
wl_list_init (&evdev_device->focus_resource_list);
evdev_device->focus_surface_listener.notify =
evdev_device_handle_focus_surface_destroy;
evdev_device->fd = -1;
evdev_device->name =
g_udev_device_get_sysfs_attr (parent, "name");
evdev_device->vid =
strtol (g_udev_device_get_property (device, "ID_VENDOR_ID"),
NULL, 16);
evdev_device->pid =
strtol (g_udev_device_get_property (device, "ID_MODEL_ID"),
NULL, 16);
g_object_unref (parent);
return evdev_device;
}
void
meta_wayland_inputfd_evdev_device_free (MetaWaylandInputFdEvdevDevice *evdev_device)
{
struct wl_resource *resource, *next;
meta_wayland_inputfd_evdev_device_set_focus (evdev_device, NULL);
wl_resource_for_each_safe (resource, next, &evdev_device->resource_list)
{
zwp_inputfd_device_evdev_v1_send_removed (resource);
wl_list_remove (wl_resource_get_link (resource));
wl_list_init (wl_resource_get_link (resource));
}
g_object_unref (evdev_device->udev_device);
g_slice_free (MetaWaylandInputFdEvdevDevice, evdev_device);
}
static void
inputfd_device_evdev_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct zwp_inputfd_device_evdev_v1_interface inputfd_device_evdev_interface = {
inputfd_device_evdev_destroy,
};
struct wl_resource *
meta_wayland_inputfd_evdev_device_create_new_resource (MetaWaylandInputFdEvdevDevice *device,
struct wl_client *client,
struct wl_resource *seat_resource,
uint32_t id)
{
struct wl_resource *resource;
resource = wl_resource_create (client, &zwp_inputfd_device_evdev_v1_interface,
wl_resource_get_version (seat_resource),
id);
wl_resource_set_implementation (resource, &inputfd_device_evdev_interface,
device, unbind_resource);
wl_resource_set_user_data (resource, device);
wl_list_insert (&device->resource_list, wl_resource_get_link (resource));
return resource;
}
void
meta_wayland_inputfd_evdev_device_notify (MetaWaylandInputFdEvdevDevice *device,
struct wl_resource *resource)
{
zwp_inputfd_device_evdev_v1_send_name (resource, device->name);
zwp_inputfd_device_evdev_v1_send_usb_id (resource, device->vid, device->pid);
zwp_inputfd_device_evdev_v1_send_done (resource);
}
static void
device_open_fd (MetaWaylandInputFdEvdevDevice *device)
{
MetaBackend *backend;
MetaLauncher *launcher;
const char *path;
g_assert (device->fd == -1);
path = g_udev_device_get_device_file (device->udev_device);
backend = meta_get_backend ();
if (!META_IS_BACKEND_NATIVE (backend))
return;
launcher = meta_backend_native_get_launcher (META_BACKEND_NATIVE (backend));
device->fd = meta_launcher_open_restricted (launcher, path, NULL);
}
static void
device_close_fd (MetaWaylandInputFdEvdevDevice *device)
{
MetaBackend *backend;
MetaLauncher *launcher;
ioctl(device->fd, EVIOCREVOKE, NULL);
backend = meta_get_backend ();
if (!META_IS_BACKEND_NATIVE (backend))
return;
launcher = meta_backend_native_get_launcher (META_BACKEND_NATIVE (backend));
meta_launcher_close_restricted (launcher, device->fd);
device->fd = -1;
}
static void
meta_wayland_inputfd_evdev_device_broadcast_focus_in (MetaWaylandInputFdEvdevDevice *device,
MetaWaylandSurface *surface,
uint32_t serial)
{
struct wl_resource *resource;
wl_resource_for_each (resource, &device->focus_resource_list)
{
zwp_inputfd_device_evdev_v1_send_focus_in (resource,
serial,
device->fd,
surface->resource);
}
}
static void
meta_wayland_inputfd_evdev_device_broadcast_focus_out (MetaWaylandInputFdEvdevDevice *device)
{
struct wl_resource *resource;
wl_resource_for_each (resource, &device->focus_resource_list)
{
zwp_inputfd_device_evdev_v1_send_focus_out (resource);
}
}
void
meta_wayland_inputfd_evdev_device_set_focus (MetaWaylandInputFdEvdevDevice *device,
MetaWaylandSurface *surface)
{
if (device->focus_surface == surface)
return;
if (device->focus_surface != NULL)
{
struct wl_list *focus_resources = &device->focus_resource_list;
if (!wl_list_empty (focus_resources))
{
meta_wayland_inputfd_evdev_device_broadcast_focus_out (device);
move_resources (&device->resource_list, &device->focus_resource_list);
}
wl_list_remove (&device->focus_surface_listener.link);
device->focus_surface = NULL;
device_close_fd (device);
}
if (surface != NULL)
device_open_fd (device);
if (surface != NULL && device->fd >= 0)
{
struct wl_client *client;
device->focus_surface = surface;
wl_resource_add_destroy_listener (device->focus_surface->resource,
&device->focus_surface_listener);
client = wl_resource_get_client (device->focus_surface->resource);
move_resources_for_client (&device->focus_resource_list,
&device->resource_list, client);
if (!wl_list_empty (&device->focus_resource_list))
{
struct wl_display *display = wl_client_get_display (client);
uint32_t serial = wl_display_next_serial (display);
meta_wayland_inputfd_evdev_device_broadcast_focus_in (device,
surface,
serial);
}
}
}

View File

@ -0,0 +1,64 @@
/*
* Wayland Support
*
* Copyright (C) 2018 Red Hat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_WAYLAND_INPUTFD_EVDEV_DEVICE_H
#define META_WAYLAND_INPUTFD_EVDEV_DEVICE_H
#include <glib.h>
#include <gudev/gudev.h>
#include <wayland-server.h>
#include "meta-wayland-types.h"
struct _MetaWaylandInputFdEvdevDevice
{
GUdevDevice *udev_device;
struct wl_list resource_list;
struct wl_list focus_resource_list;
MetaWaylandSurface *focus_surface;
struct wl_listener focus_surface_listener;
const gchar *name;
uint32_t vid;
uint32_t pid;
int fd;
};
MetaWaylandInputFdEvdevDevice *
meta_wayland_inputfd_evdev_device_new (MetaWaylandInputFdSeat *seat,
GUdevDevice *device);
void meta_wayland_inputfd_evdev_device_free (MetaWaylandInputFdEvdevDevice *evdev_device);
struct wl_resource *
meta_wayland_inputfd_evdev_device_create_new_resource (MetaWaylandInputFdEvdevDevice *device,
struct wl_client *client,
struct wl_resource *seat_resource,
uint32_t id);
void meta_wayland_inputfd_evdev_device_set_focus (MetaWaylandInputFdEvdevDevice *device,
MetaWaylandSurface *surface);
void meta_wayland_inputfd_evdev_device_notify (MetaWaylandInputFdEvdevDevice *device,
struct wl_resource *resource);
#endif /* META_WAYLAND_INPUTFD_EVDEV_DEVICE_H */

View File

@ -0,0 +1,128 @@
/*
* Wayland Support
*
* Copyright (C) 2018 Red Hat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#include "config.h"
#include "inputfd-unstable-v1-server-protocol.h"
#include "wayland/meta-wayland-inputfd-manager.h"
#include "wayland/meta-wayland-inputfd-seat.h"
#include "wayland/meta-wayland-private.h"
static void
unbind_resource (struct wl_resource *resource)
{
wl_list_remove (wl_resource_get_link (resource));
}
static void
inputfd_manager_get_seat_evdev (struct wl_client *client,
struct wl_resource *resource,
uint32_t id,
struct wl_resource *seat_resource)
{
MetaWaylandInputFdManager *manager = wl_resource_get_user_data (resource);
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
MetaWaylandInputFdSeat *inputfd_seat;
inputfd_seat = meta_wayland_inputfd_manager_ensure_seat (manager, seat);
meta_wayland_inputfd_seat_create_new_evdev_resource (inputfd_seat, client,
resource, id);
}
static void
inputfd_manager_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct zwp_inputfd_manager_v1_interface inputfd_manager_interface = {
inputfd_manager_get_seat_evdev,
inputfd_manager_destroy
};
static void
bind_inputfd_manager (struct wl_client *client,
void *data,
uint32_t version,
uint32_t id)
{
MetaWaylandCompositor *compositor = data;
MetaWaylandInputFdManager *manager = compositor->inputfd_manager;
struct wl_resource *resource;
resource = wl_resource_create (client, &zwp_inputfd_manager_v1_interface,
MIN (version, 1), id);
wl_resource_set_implementation (resource, &inputfd_manager_interface,
manager, unbind_resource);
wl_resource_set_user_data (resource, manager);
wl_list_insert (&manager->resource_list,
wl_resource_get_link (resource));
}
static MetaWaylandInputFdManager *
meta_wayland_inputfd_manager_new (MetaWaylandCompositor *compositor)
{
MetaWaylandInputFdManager *manager;
manager = g_slice_new0 (MetaWaylandInputFdManager);
manager->compositor = compositor;
manager->wl_display = compositor->wayland_display;
manager->seats = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) meta_wayland_inputfd_seat_free);
wl_list_init (&manager->resource_list);
wl_global_create (manager->wl_display,
&zwp_inputfd_manager_v1_interface,
META_ZWP_INPUTFD_V1_VERSION,
compositor, bind_inputfd_manager);
return manager;
}
void
meta_wayland_inputfd_manager_init (MetaWaylandCompositor *compositor)
{
compositor->inputfd_manager = meta_wayland_inputfd_manager_new (compositor);
}
void
meta_wayland_inputfd_manager_free (MetaWaylandInputFdManager *manager)
{
g_hash_table_destroy (manager->seats);
g_slice_free (MetaWaylandInputFdManager, manager);
}
MetaWaylandInputFdSeat *
meta_wayland_inputfd_manager_ensure_seat (MetaWaylandInputFdManager *manager,
MetaWaylandSeat *seat)
{
MetaWaylandInputFdSeat *inputfd_seat;
inputfd_seat = g_hash_table_lookup (manager->seats, seat);
if (!inputfd_seat)
{
inputfd_seat = meta_wayland_inputfd_seat_new (manager, seat);
g_hash_table_insert (manager->seats, seat, inputfd_seat);
}
return inputfd_seat;
}

View File

@ -0,0 +1,47 @@
/*
* Wayland Support
*
* Copyright (C) 2018 Red Hat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_WAYLAND_INPUTFD_MANAGER_H
#define META_WAYLAND_INPUTFD_MANAGER_H
#include <wayland-server.h>
#include <glib.h>
#include "meta-wayland-types.h"
struct _MetaWaylandInputFdManager
{
MetaWaylandCompositor *compositor;
struct wl_display *wl_display;
struct wl_list resource_list;
GHashTable *seats;
};
void meta_wayland_inputfd_manager_init (MetaWaylandCompositor *compositor);
void meta_wayland_inputfd_manager_free (MetaWaylandInputFdManager *manager);
MetaWaylandInputFdSeat *
meta_wayland_inputfd_manager_ensure_seat (MetaWaylandInputFdManager *manager,
MetaWaylandSeat *seat);
#endif /* META_WAYLAND_INPUTFD_MANAGER_H */

View File

@ -0,0 +1,201 @@
/*
* Wayland Support
*
* Copyright (C) 2018 Red Hat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#include "config.h"
#include "inputfd-unstable-v1-server-protocol.h"
#include "wayland/meta-wayland-inputfd-seat.h"
#include "wayland/meta-wayland-inputfd-evdev-device.h"
static void
unbind_resource (struct wl_resource *resource)
{
wl_list_remove (wl_resource_get_link (resource));
}
static void
notify_evdev_device_added (MetaWaylandInputFdSeat *seat,
MetaWaylandInputFdEvdevDevice *evdev_device,
struct wl_resource *seat_resource)
{
struct wl_resource *resource;
struct wl_client *client;
client = wl_resource_get_client (seat_resource);
resource = meta_wayland_inputfd_evdev_device_create_new_resource (evdev_device,
client,
seat_resource,
0);
zwp_inputfd_seat_evdev_v1_send_device_added (seat_resource, resource);
}
static void
broadcast_evdev_device_added (MetaWaylandInputFdSeat *seat,
MetaWaylandInputFdEvdevDevice *evdev_device)
{
struct wl_resource *seat_resource;
wl_resource_for_each (seat_resource, &seat->evdev_seat_resources)
{
notify_evdev_device_added (seat, evdev_device, seat_resource);
}
}
static void
check_add_device (MetaWaylandInputFdSeat *inputfd_seat,
GUdevDevice *device)
{
MetaWaylandInputFdEvdevDevice *evdev_device;
evdev_device = meta_wayland_inputfd_evdev_device_new (inputfd_seat,
device);
if (evdev_device)
{
g_hash_table_insert (inputfd_seat->evdev_devices,
(gpointer) g_udev_device_get_sysfs_path (device),
evdev_device);
broadcast_evdev_device_added (inputfd_seat, evdev_device);
return;
}
}
static void
remove_device (MetaWaylandInputFdSeat *inputfd_seat,
GUdevDevice *device)
{
g_hash_table_remove (inputfd_seat->evdev_devices,
g_udev_device_get_sysfs_path (device));
}
static void
udev_event_cb (GUdevClient *client,
char *action,
GUdevDevice *device,
MetaWaylandInputFdSeat *seat)
{
if (g_strcmp0 (action, "add") == 0)
check_add_device (seat, device);
else if (g_strcmp0 (action, "remove") == 0)
remove_device (seat, device);
}
MetaWaylandInputFdSeat *
meta_wayland_inputfd_seat_new (MetaWaylandInputFdManager *manager,
MetaWaylandSeat *seat)
{
const char * const subsystems[] = { "input", NULL };
MetaWaylandInputFdSeat *inputfd_seat;
GList *devices;
inputfd_seat = g_slice_new0 (MetaWaylandInputFdSeat);
wl_list_init (&inputfd_seat->evdev_seat_resources);
inputfd_seat->evdev_devices =
g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
(GDestroyNotify) meta_wayland_inputfd_evdev_device_free);
inputfd_seat->udev_client = g_udev_client_new (subsystems);
g_signal_connect (inputfd_seat->udev_client, "uevent",
G_CALLBACK (udev_event_cb), inputfd_seat);
devices = g_udev_client_query_by_subsystem (inputfd_seat->udev_client,
subsystems[0]);
while (devices)
{
GUdevDevice *device = devices->data;
check_add_device (inputfd_seat, device);
g_object_unref (device);
devices = g_list_delete_link (devices, devices);
}
return inputfd_seat;
}
void
meta_wayland_inputfd_seat_free (MetaWaylandInputFdSeat *inputfd_seat)
{
g_hash_table_destroy (inputfd_seat->evdev_devices);
g_signal_handlers_disconnect_by_func (inputfd_seat->udev_client,
udev_event_cb, inputfd_seat);
g_object_unref (inputfd_seat->udev_client);
g_slice_free (MetaWaylandInputFdSeat, inputfd_seat);
}
static void
notify_evdev_devices (MetaWaylandInputFdSeat *seat,
struct wl_resource *seat_resource)
{
MetaWaylandInputFdEvdevDevice *device;
GHashTableIter iter;
g_hash_table_iter_init (&iter, seat->evdev_devices);
while (g_hash_table_iter_next (&iter, NULL, (void **) &device))
{
notify_evdev_device_added (seat, device, seat_resource);
}
}
static void
inputfd_seat_evdev_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct zwp_inputfd_seat_evdev_v1_interface inputfd_seat_evdev_interface = {
inputfd_seat_evdev_destroy
};
struct wl_resource *
meta_wayland_inputfd_seat_create_new_evdev_resource (MetaWaylandInputFdSeat *seat,
struct wl_client *client,
struct wl_resource *manager_resource,
uint32_t id)
{
struct wl_resource *resource;
resource = wl_resource_create (client, &zwp_inputfd_seat_evdev_v1_interface,
wl_resource_get_version (manager_resource),
id);
wl_resource_set_implementation (resource, &inputfd_seat_evdev_interface,
seat, unbind_resource);
wl_resource_set_user_data (resource, seat);
wl_list_insert (&seat->evdev_seat_resources, wl_resource_get_link (resource));
notify_evdev_devices (seat, resource);
return resource;
}
void
meta_wayland_inputfd_seat_set_focus (MetaWaylandInputFdSeat *seat,
MetaWaylandSurface *surface)
{
MetaWaylandInputFdEvdevDevice *device;
GHashTableIter iter;
g_hash_table_iter_init (&iter, seat->evdev_devices);
while (g_hash_table_iter_next (&iter, NULL, (void **) &device))
meta_wayland_inputfd_evdev_device_set_focus (device, surface);
}

View File

@ -0,0 +1,51 @@
/*
* Wayland Support
*
* Copyright (C) 2018 Red Hat
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_WAYLAND_INPUTFD_SEAT_H
#define META_WAYLAND_INPUTFD_SEAT_H
#include <glib.h>
#include <gudev/gudev.h>
#include <wayland-server.h>
#include "meta-wayland-types.h"
struct _MetaWaylandInputFdSeat
{
GUdevClient *udev_client;
struct wl_list evdev_seat_resources;
GHashTable *evdev_devices;
};
MetaWaylandInputFdSeat *
meta_wayland_inputfd_seat_new (MetaWaylandInputFdManager *manager,
MetaWaylandSeat *seat);
void meta_wayland_inputfd_seat_free (MetaWaylandInputFdSeat *inputfd_seat);
struct wl_resource *
meta_wayland_inputfd_seat_create_new_evdev_resource (MetaWaylandInputFdSeat *seat,
struct wl_client *client,
struct wl_resource *resource,
uint32_t id);
void meta_wayland_inputfd_seat_set_focus (MetaWaylandInputFdSeat *seat,
MetaWaylandSurface *surface);
#endif /* META_WAYLAND_INPUTFD_SEAT_H */

View File

@ -26,6 +26,7 @@
#include "clutter/clutter.h" #include "clutter/clutter.h"
#include "core/window-private.h" #include "core/window-private.h"
#include "meta/meta-cursor-tracker.h" #include "meta/meta-cursor-tracker.h"
#include "wayland/meta-wayland-inputfd-manager.h"
#include "wayland/meta-wayland-pointer-gestures.h" #include "wayland/meta-wayland-pointer-gestures.h"
#include "wayland/meta-wayland-seat.h" #include "wayland/meta-wayland-seat.h"
#include "wayland/meta-wayland-surface.h" #include "wayland/meta-wayland-surface.h"
@ -85,6 +86,7 @@ struct _MetaWaylandCompositor
MetaWaylandSeat *seat; MetaWaylandSeat *seat;
MetaWaylandTabletManager *tablet_manager; MetaWaylandTabletManager *tablet_manager;
MetaWaylandInputFdManager *inputfd_manager;
GHashTable *scheduled_surface_associations; GHashTable *scheduled_surface_associations;
}; };

View File

@ -25,6 +25,7 @@
#include "wayland/meta-wayland-data-device.h" #include "wayland/meta-wayland-data-device.h"
#include "wayland/meta-wayland-data-device-primary-legacy.h" #include "wayland/meta-wayland-data-device-primary-legacy.h"
#include "wayland/meta-wayland-inputfd-seat.h"
#include "wayland/meta-wayland-private.h" #include "wayland/meta-wayland-private.h"
#include "wayland/meta-wayland-tablet-seat.h" #include "wayland/meta-wayland-tablet-seat.h"
#include "wayland/meta-wayland-versions.h" #include "wayland/meta-wayland-versions.h"
@ -176,7 +177,16 @@ meta_wayland_seat_set_capabilities (MetaWaylandSeat *seat,
meta_display_sync_wayland_input_focus (display); meta_display_sync_wayland_input_focus (display);
} }
else if (CAPABILITY_DISABLED (prev_flags, flags, WL_SEAT_CAPABILITY_KEYBOARD)) else if (CAPABILITY_DISABLED (prev_flags, flags, WL_SEAT_CAPABILITY_KEYBOARD))
meta_wayland_keyboard_disable (seat->keyboard); {
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaWaylandInputFdSeat *inputfd_seat;
meta_wayland_keyboard_disable (seat->keyboard);
inputfd_seat = meta_wayland_inputfd_manager_ensure_seat (compositor->inputfd_manager,
seat);
meta_wayland_inputfd_seat_set_focus (inputfd_seat, NULL);
}
if (CAPABILITY_ENABLED (prev_flags, flags, WL_SEAT_CAPABILITY_TOUCH)) if (CAPABILITY_ENABLED (prev_flags, flags, WL_SEAT_CAPABILITY_TOUCH))
meta_wayland_touch_enable (seat->touch); meta_wayland_touch_enable (seat->touch);
@ -428,6 +438,7 @@ meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
MetaWaylandSurface *surface) MetaWaylandSurface *surface)
{ {
MetaWaylandTabletSeat *tablet_seat; MetaWaylandTabletSeat *tablet_seat;
MetaWaylandInputFdSeat *inputfd_seat;
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
if (meta_wayland_seat_has_keyboard (seat)) if (meta_wayland_seat_has_keyboard (seat))
@ -443,6 +454,10 @@ meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
meta_wayland_text_input_set_focus (seat->text_input, surface); meta_wayland_text_input_set_focus (seat->text_input, surface);
meta_wayland_gtk_text_input_set_focus (seat->gtk_text_input, surface); meta_wayland_gtk_text_input_set_focus (seat->gtk_text_input, surface);
inputfd_seat = meta_wayland_inputfd_manager_ensure_seat (compositor->inputfd_manager,
seat);
meta_wayland_inputfd_seat_set_focus (inputfd_seat, surface);
} }
gboolean gboolean

View File

@ -61,4 +61,8 @@ typedef struct _MetaWaylandWindowConfiguration MetaWaylandWindowConfiguration;
typedef struct _MetaWaylandPointerClient MetaWaylandPointerClient; typedef struct _MetaWaylandPointerClient MetaWaylandPointerClient;
typedef struct _MetaWaylandInputFdManager MetaWaylandInputFdManager;
typedef struct _MetaWaylandInputFdSeat MetaWaylandInputFdSeat;
typedef struct _MetaWaylandInputFdEvdevDevice MetaWaylandInputFdEvdevDevice;
#endif #endif

View File

@ -55,5 +55,6 @@
#define META_GTK_TEXT_INPUT_VERSION 1 #define META_GTK_TEXT_INPUT_VERSION 1
#define META_ZWP_TEXT_INPUT_V3_VERSION 1 #define META_ZWP_TEXT_INPUT_V3_VERSION 1
#define META_WP_VIEWPORTER_VERSION 1 #define META_WP_VIEWPORTER_VERSION 1
#define META_ZWP_INPUTFD_V1_VERSION 1
#endif #endif

View File

@ -438,6 +438,7 @@ meta_wayland_compositor_setup (MetaWaylandCompositor *wayland_compositor)
meta_wayland_surface_inhibit_shortcuts_dialog_init (); meta_wayland_surface_inhibit_shortcuts_dialog_init ();
meta_wayland_text_input_init (compositor); meta_wayland_text_input_init (compositor);
meta_wayland_gtk_text_input_init (compositor); meta_wayland_gtk_text_input_init (compositor);
meta_wayland_inputfd_manager_init (compositor);
/* Xwayland specific protocol, needs to be filtered out for all other clients */ /* Xwayland specific protocol, needs to be filtered out for all other clients */
if (meta_xwayland_grab_keyboard_init (compositor)) if (meta_xwayland_grab_keyboard_init (compositor))