mirror of
https://github.com/brl/mutter.git
synced 2024-09-21 06:56:12 -04:00
c6493885c3
This backend is a event backend that can be enabled for EGL (for now). It uses udev (gudev) to query input devices on a linux system, listens to keyboard events from input devices and xkbcommon to translate raw key codes into key keysyms. This commit only supports key events, more to follow.
277 lines
8.2 KiB
C
277 lines
8.2 KiB
C
/*
|
|
* Clutter.
|
|
*
|
|
* An OpenGL based 'interactive canvas' library.
|
|
*
|
|
* Copyright (C) 2010 Intel Corp.
|
|
*
|
|
* 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: Damien Lespiau <damien.lespiau@intel.com>
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <linux/input.h>
|
|
|
|
#include <gudev/gudev.h>
|
|
|
|
#include "clutter-backend.h"
|
|
#include "clutter-debug.h"
|
|
#include "clutter-device-manager.h"
|
|
#include "clutter-device-manager-private.h"
|
|
#include "clutter-input-device-evdev.h"
|
|
#include "clutter-private.h"
|
|
|
|
#include "clutter-device-manager-evdev.h"
|
|
|
|
#define CLUTTER_DEVICE_MANAGER_EVDEV_GET_PRIVATE(obj) \
|
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
|
|
CLUTTER_TYPE_DEVICE_MANAGER_EVDEV, \
|
|
ClutterDeviceManagerEvdevPrivate))
|
|
|
|
G_DEFINE_TYPE (ClutterDeviceManagerEvdev,
|
|
clutter_device_manager_evdev,
|
|
CLUTTER_TYPE_DEVICE_MANAGER);
|
|
|
|
struct _ClutterDeviceManagerEvdevPrivate
|
|
{
|
|
GUdevClient *udev_client;
|
|
|
|
GSList *devices;
|
|
|
|
ClutterInputDevice *core_pointer;
|
|
ClutterInputDevice *core_keyboard;
|
|
};
|
|
|
|
static const gchar *subsystems[] = { "input", NULL };
|
|
|
|
static void
|
|
evdev_add_device (ClutterDeviceManagerEvdev *manager_evdev,
|
|
GUdevDevice *udev_device)
|
|
{
|
|
ClutterDeviceManager *manager = (ClutterDeviceManager *) manager_evdev;
|
|
ClutterInputDeviceType type = CLUTTER_EXTENSION_DEVICE;
|
|
ClutterInputDevice *device;
|
|
const gchar *dev_file;
|
|
const gchar * const *keys;
|
|
guint i;
|
|
|
|
dev_file = g_udev_device_get_device_file (udev_device);
|
|
|
|
if (g_udev_device_get_property (udev_device, "ID_INPUT") == NULL)
|
|
{
|
|
CLUTTER_NOTE (EVENT, "Ignoring device %s without ID_INPUT set", dev_file);
|
|
return;
|
|
}
|
|
|
|
keys = g_udev_device_get_property_keys (udev_device);
|
|
for (i = 0; keys[i]; i++)
|
|
{
|
|
/* Clutter assumes that device types are exclusive in the
|
|
* ClutterInputDevice API */
|
|
if (strcmp (keys[i], "ID_INPUT_KEY") == 0)
|
|
type = CLUTTER_KEYBOARD_DEVICE;
|
|
else if (strcmp (keys[i], "ID_INPUT_MOUSE") == 0)
|
|
type = CLUTTER_POINTER_DEVICE;
|
|
else if (strcmp (keys[i], "ID_INPUT_JOYSTICK") == 0)
|
|
type = CLUTTER_JOYSTICK_DEVICE;
|
|
else if (strcmp (keys[i], "ID_INPUT_TABLET") == 0)
|
|
type = CLUTTER_TABLET_DEVICE;
|
|
else if (strcmp (keys[i], "ID_INPUT_TOUCHPAD") == 0)
|
|
type = CLUTTER_TOUCHPAD_DEVICE;
|
|
else if (strcmp (keys[i], "ID_INPUT_TOUCHSCREEN") == 0)
|
|
type = CLUTTER_TOUCHSCREEN_DEVICE;
|
|
}
|
|
|
|
device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_EVDEV,
|
|
"id", 0,
|
|
"name", "Evdev device", /* FIXME */
|
|
"device-type", type,
|
|
"sysfs-path", sysfs_path,
|
|
"device-path", device_file,
|
|
NULL);
|
|
_clutter_device_manager_add_device (manager, device);
|
|
|
|
CLUTTER_NOTE (EVENT, "Added device %s, type %d", dev_file, type);
|
|
}
|
|
|
|
/*
|
|
* ClutterDeviceManager implementation
|
|
*/
|
|
|
|
static void
|
|
clutter_device_manager_evdev_add_device (ClutterDeviceManager *manager,
|
|
ClutterInputDevice *device)
|
|
{
|
|
ClutterDeviceManagerEvdev *manager_evdev;
|
|
ClutterDeviceManagerEvdevPrivate *priv;
|
|
ClutterInputDeviceType device_type;
|
|
gboolean is_pointer, is_keyboard;
|
|
|
|
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
|
|
priv = manager_evdev->priv;
|
|
|
|
device_type = clutter_input_device_get_device_type (device);
|
|
is_pointer = device_type == CLUTTER_POINTER_DEVICE;
|
|
is_keyboard = device_type == CLUTTER_KEYBOARD_DEVICE;
|
|
|
|
priv->devices = g_slist_prepend (priv->devices, device);
|
|
|
|
if (is_pointer && priv->core_pointer == NULL)
|
|
priv->core_pointer = device;
|
|
|
|
if (is_keyboard && priv->core_keyboard == NULL)
|
|
priv->core_keyboard = device;
|
|
}
|
|
|
|
static void
|
|
clutter_device_manager_evdev_remove_device (ClutterDeviceManager *manager,
|
|
ClutterInputDevice *device)
|
|
{
|
|
ClutterDeviceManagerEvdev *manager_evdev;
|
|
ClutterDeviceManagerEvdevPrivate *priv;
|
|
|
|
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
|
|
priv = manager_evdev->priv;
|
|
|
|
priv->devices = g_slist_remove (priv->devices, device);
|
|
}
|
|
|
|
static const GSList *
|
|
clutter_device_manager_evdev_get_devices (ClutterDeviceManager *manager)
|
|
{
|
|
return CLUTTER_DEVICE_MANAGER_EVDEV (manager)->priv->devices;
|
|
}
|
|
|
|
static ClutterInputDevice *
|
|
clutter_device_manager_evdev_get_core_device (ClutterDeviceManager *manager,
|
|
ClutterInputDeviceType type)
|
|
{
|
|
ClutterDeviceManagerEvdev *manager_evdev;
|
|
ClutterDeviceManagerEvdevPrivate *priv;
|
|
|
|
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
|
|
priv = manager_evdev->priv;
|
|
|
|
switch (type)
|
|
{
|
|
case CLUTTER_POINTER_DEVICE:
|
|
return priv->core_pointer;
|
|
|
|
case CLUTTER_KEYBOARD_DEVICE:
|
|
return priv->core_keyboard;
|
|
|
|
case CLUTTER_EXTENSION_DEVICE:
|
|
default:
|
|
return NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static ClutterInputDevice *
|
|
clutter_device_manager_evdev_get_device (ClutterDeviceManager *manager,
|
|
gint id)
|
|
{
|
|
ClutterDeviceManagerEvdev *manager_evdev;
|
|
ClutterDeviceManagerEvdevPrivate *priv;
|
|
GSList *l;
|
|
|
|
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
|
|
priv = manager_evdev->priv;
|
|
|
|
for (l = priv->devices; l; l = l->next)
|
|
{
|
|
ClutterInputDevice *device = l->data;
|
|
|
|
if (clutter_input_device_get_device_id (device) == id)
|
|
return device;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* GObject implementation
|
|
*/
|
|
|
|
static void
|
|
clutter_device_manager_evdev_constructed (GObject *gobject)
|
|
{
|
|
ClutterDeviceManagerEvdev *manager_evdev;
|
|
ClutterDeviceManagerEvdevPrivate *priv;
|
|
GList *devices, *l;
|
|
|
|
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (gobject);
|
|
priv = manager_evdev->priv;
|
|
|
|
priv->udev_client = g_udev_client_new (subsystems);
|
|
|
|
devices = g_udev_client_query_by_subsystem (priv->udev_client, subsystems[0]);
|
|
for (l = devices; l; l = g_list_next (l))
|
|
{
|
|
GUdevDevice *device = l->data;
|
|
|
|
evdev_add_device (manager_evdev, device);
|
|
g_object_unref (device);
|
|
}
|
|
g_list_free (devices);
|
|
|
|
/* subcribe for events on input devices */
|
|
g_signal_connect (priv->udev_client, "uevent",
|
|
G_CALLBACK (on_uevent), manager_evdev);
|
|
}
|
|
|
|
static void
|
|
clutter_device_manager_evdev_finalize (GObject *object)
|
|
{
|
|
ClutterDeviceManagerEvdev *manager_evdev;
|
|
ClutterDeviceManagerEvdevPrivate *priv;
|
|
|
|
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (object);
|
|
priv = manager_evdev->priv;
|
|
|
|
g_object_unref (priv->udev_client);
|
|
|
|
G_OBJECT_CLASS (clutter_device_manager_evdev_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
clutter_device_manager_evdev_class_init (ClutterDeviceManagerEvdevClass *klass)
|
|
{
|
|
ClutterDeviceManagerClass *manager_class;
|
|
GObjectClass *gobject_class = (GObjectClass *) klass;
|
|
|
|
g_type_class_add_private (klass, sizeof (ClutterDeviceManagerEvdevPrivate));
|
|
|
|
gobject_class->constructed = clutter_device_manager_evdev_constructed;
|
|
gobject_class->finalize = clutter_device_manager_evdev_finalize;
|
|
|
|
manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass);
|
|
manager_class->add_device = clutter_device_manager_evdev_add_device;
|
|
manager_class->remove_device = clutter_device_manager_evdev_remove_device;
|
|
manager_class->get_devices = clutter_device_manager_evdev_get_devices;
|
|
manager_class->get_core_device = clutter_device_manager_evdev_get_core_device;
|
|
manager_class->get_device = clutter_device_manager_evdev_get_device;
|
|
}
|
|
|
|
static void
|
|
clutter_device_manager_evdev_init (ClutterDeviceManagerEvdev *self)
|
|
{
|
|
self->priv = CLUTTER_DEVICE_MANAGER_EVDEV_GET_PRIVATE (self);
|
|
}
|