This will be used for pad devices, better than the current way of comparing name strings coming from libwacom. https://gitlab.gnome.org/GNOME/gnome-control-center/issues/415
692 lines
17 KiB
C
692 lines
17 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
|
*
|
|
* Copyright (C) 2014 Red Hat
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* Author: Carlos Garnacho <carlosg@gnome.org>
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <string.h>
|
|
#include <gudev/gudev.h>
|
|
|
|
#include "gsd-device-manager.h"
|
|
#include "gsd-common-enums.h"
|
|
#include "gnome-settings-bus.h"
|
|
#include "gsd-input-helper.h"
|
|
|
|
#ifdef GDK_WINDOWING_X11
|
|
#include <gdk/gdkx.h>
|
|
#endif
|
|
#ifdef GDK_WINDOWING_WAYLAND
|
|
#include <gdk/gdkwayland.h>
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
gchar *name;
|
|
gchar *device_file;
|
|
gchar *vendor_id;
|
|
gchar *product_id;
|
|
gchar *group;
|
|
GsdDeviceType type;
|
|
guint width;
|
|
guint height;
|
|
} GsdDevicePrivate;
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (GsdDevice, gsd_device, G_TYPE_OBJECT)
|
|
|
|
typedef struct
|
|
{
|
|
GObject parent_instance;
|
|
GHashTable *devices;
|
|
GUdevClient *udev_client;
|
|
} GsdDeviceManagerPrivate;
|
|
|
|
enum {
|
|
PROP_NAME = 1,
|
|
PROP_DEVICE_FILE,
|
|
PROP_VENDOR_ID,
|
|
PROP_PRODUCT_ID,
|
|
PROP_TYPE,
|
|
PROP_WIDTH,
|
|
PROP_HEIGHT,
|
|
PROP_GROUP
|
|
};
|
|
|
|
enum {
|
|
DEVICE_ADDED,
|
|
DEVICE_REMOVED,
|
|
DEVICE_CHANGED,
|
|
N_SIGNALS
|
|
};
|
|
|
|
/* Index matches GsdDeviceType */
|
|
const gchar *udev_ids[] = {
|
|
"ID_INPUT_MOUSE",
|
|
"ID_INPUT_KEYBOARD",
|
|
"ID_INPUT_TOUCHPAD",
|
|
"ID_INPUT_TABLET",
|
|
"ID_INPUT_TOUCHSCREEN",
|
|
"ID_INPUT_TABLET_PAD",
|
|
};
|
|
|
|
static guint signals[N_SIGNALS] = { 0 };
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (GsdDeviceManager, gsd_device_manager, G_TYPE_OBJECT)
|
|
|
|
static void
|
|
gsd_device_init (GsdDevice *device)
|
|
{
|
|
}
|
|
|
|
static void
|
|
gsd_device_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GsdDevicePrivate *priv;
|
|
|
|
priv = gsd_device_get_instance_private (GSD_DEVICE (object));
|
|
|
|
switch (prop_id) {
|
|
case PROP_NAME:
|
|
priv->name = g_value_dup_string (value);
|
|
break;
|
|
case PROP_DEVICE_FILE:
|
|
priv->device_file = g_value_dup_string (value);
|
|
break;
|
|
case PROP_VENDOR_ID:
|
|
priv->vendor_id = g_value_dup_string (value);
|
|
break;
|
|
case PROP_PRODUCT_ID:
|
|
priv->product_id = g_value_dup_string (value);
|
|
break;
|
|
case PROP_TYPE:
|
|
priv->type = g_value_get_flags (value);
|
|
break;
|
|
case PROP_WIDTH:
|
|
priv->width = g_value_get_uint (value);
|
|
break;
|
|
case PROP_HEIGHT:
|
|
priv->height = g_value_get_uint (value);
|
|
break;
|
|
case PROP_GROUP:
|
|
priv->group = g_value_dup_string (value);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gsd_device_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GsdDevicePrivate *priv;
|
|
|
|
priv = gsd_device_get_instance_private (GSD_DEVICE (object));
|
|
|
|
switch (prop_id) {
|
|
case PROP_NAME:
|
|
g_value_set_string (value, priv->name);
|
|
break;
|
|
case PROP_DEVICE_FILE:
|
|
g_value_set_string (value, priv->device_file);
|
|
break;
|
|
case PROP_VENDOR_ID:
|
|
g_value_set_string (value, priv->vendor_id);
|
|
break;
|
|
case PROP_PRODUCT_ID:
|
|
g_value_set_string (value, priv->product_id);
|
|
break;
|
|
case PROP_TYPE:
|
|
g_value_set_flags (value, priv->type);
|
|
break;
|
|
case PROP_WIDTH:
|
|
g_value_set_uint (value, priv->width);
|
|
break;
|
|
case PROP_HEIGHT:
|
|
g_value_set_uint (value, priv->height);
|
|
break;
|
|
case PROP_GROUP:
|
|
g_value_set_string (value, priv->group);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gsd_device_finalize (GObject *object)
|
|
{
|
|
GsdDevicePrivate *priv;
|
|
|
|
priv = gsd_device_get_instance_private (GSD_DEVICE (object));
|
|
|
|
g_free (priv->name);
|
|
g_free (priv->vendor_id);
|
|
g_free (priv->product_id);
|
|
g_free (priv->device_file);
|
|
g_free (priv->group);
|
|
|
|
G_OBJECT_CLASS (gsd_device_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gsd_device_class_init (GsdDeviceClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->set_property = gsd_device_set_property;
|
|
object_class->get_property = gsd_device_get_property;
|
|
object_class->finalize = gsd_device_finalize;
|
|
|
|
g_object_class_install_property (object_class,
|
|
PROP_NAME,
|
|
g_param_spec_string ("name",
|
|
"Name",
|
|
"Name",
|
|
NULL,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
g_object_class_install_property (object_class,
|
|
PROP_DEVICE_FILE,
|
|
g_param_spec_string ("device-file",
|
|
"Device file",
|
|
"Device file",
|
|
NULL,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
g_object_class_install_property (object_class,
|
|
PROP_VENDOR_ID,
|
|
g_param_spec_string ("vendor-id",
|
|
"Vendor ID",
|
|
"Vendor ID",
|
|
NULL,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
g_object_class_install_property (object_class,
|
|
PROP_PRODUCT_ID,
|
|
g_param_spec_string ("product-id",
|
|
"Product ID",
|
|
"Product ID",
|
|
NULL,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
g_object_class_install_property (object_class,
|
|
PROP_TYPE,
|
|
g_param_spec_flags ("type",
|
|
"Device type",
|
|
"Device type",
|
|
GSD_TYPE_DEVICE_TYPE, 0,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
g_object_class_install_property (object_class,
|
|
PROP_WIDTH,
|
|
g_param_spec_uint ("width",
|
|
"Width",
|
|
"Width",
|
|
0, G_MAXUINT, 0,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
g_object_class_install_property (object_class,
|
|
PROP_HEIGHT,
|
|
g_param_spec_uint ("height",
|
|
"Height",
|
|
"Height",
|
|
0, G_MAXUINT, 0,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
g_object_class_install_property (object_class,
|
|
PROP_GROUP,
|
|
g_param_spec_string ("group",
|
|
"Group",
|
|
"Group",
|
|
NULL,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
}
|
|
|
|
static void
|
|
gsd_device_manager_finalize (GObject *object)
|
|
{
|
|
GsdDeviceManager *manager = GSD_DEVICE_MANAGER (object);
|
|
GsdDeviceManagerPrivate *priv = gsd_device_manager_get_instance_private (manager);
|
|
|
|
g_hash_table_destroy (priv->devices);
|
|
g_object_unref (priv->udev_client);
|
|
|
|
G_OBJECT_CLASS (gsd_device_manager_parent_class)->finalize (object);
|
|
}
|
|
|
|
static GList *
|
|
gsd_device_manager_real_list_devices (GsdDeviceManager *manager,
|
|
GsdDeviceType type)
|
|
{
|
|
GsdDeviceManagerPrivate *priv = gsd_device_manager_get_instance_private (manager);
|
|
GsdDeviceType device_type;
|
|
GList *devices = NULL;
|
|
GHashTableIter iter;
|
|
GsdDevice *device;
|
|
|
|
g_hash_table_iter_init (&iter, priv->devices);
|
|
|
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device)) {
|
|
device_type = gsd_device_get_device_type (device);
|
|
|
|
if ((device_type & type) == type)
|
|
devices = g_list_prepend (devices, device);
|
|
}
|
|
|
|
return devices;
|
|
}
|
|
|
|
static GsdDevice *
|
|
gsd_device_manager_real_lookup_device (GsdDeviceManager *manager,
|
|
GdkDevice *gdk_device)
|
|
{
|
|
GsdDeviceManagerPrivate *priv = gsd_device_manager_get_instance_private (manager);
|
|
GdkDisplay *display = gdk_device_get_display (gdk_device);
|
|
const gchar *node_path = NULL;
|
|
GHashTableIter iter;
|
|
GsdDevice *device;
|
|
|
|
#ifdef GDK_WINDOWING_X11
|
|
if (GDK_IS_X11_DISPLAY (display))
|
|
node_path = xdevice_get_device_node (gdk_x11_device_get_id (gdk_device));
|
|
#endif
|
|
#ifdef GDK_WINDOWING_WAYLAND
|
|
if (GDK_IS_WAYLAND_DISPLAY (display))
|
|
node_path = g_strdup (gdk_wayland_device_get_node_path (gdk_device));
|
|
#endif
|
|
if (!node_path)
|
|
return NULL;
|
|
|
|
g_hash_table_iter_init (&iter, priv->devices);
|
|
|
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device)) {
|
|
if (g_strcmp0 (node_path,
|
|
gsd_device_get_device_file (device)) == 0) {
|
|
return device;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
gsd_device_manager_class_init (GsdDeviceManagerClass *klass)
|
|
{
|
|
GsdDeviceManagerClass *manager_class = GSD_DEVICE_MANAGER_CLASS (klass);
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->finalize = gsd_device_manager_finalize;
|
|
manager_class->list_devices = gsd_device_manager_real_list_devices;
|
|
manager_class->lookup_device = gsd_device_manager_real_lookup_device;
|
|
|
|
signals[DEVICE_ADDED] =
|
|
g_signal_new ("device-added",
|
|
GSD_TYPE_DEVICE_MANAGER,
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (GsdDeviceManagerClass, device_added),
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 1,
|
|
GSD_TYPE_DEVICE | G_SIGNAL_TYPE_STATIC_SCOPE);
|
|
|
|
signals[DEVICE_REMOVED] =
|
|
g_signal_new ("device-removed",
|
|
GSD_TYPE_DEVICE_MANAGER,
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (GsdDeviceManagerClass, device_removed),
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 1,
|
|
GSD_TYPE_DEVICE | G_SIGNAL_TYPE_STATIC_SCOPE);
|
|
|
|
signals[DEVICE_CHANGED] =
|
|
g_signal_new ("device-changed",
|
|
GSD_TYPE_DEVICE_MANAGER,
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (GsdDeviceManagerClass, device_changed),
|
|
NULL, NULL, NULL,
|
|
G_TYPE_NONE, 1,
|
|
GSD_TYPE_DEVICE | G_SIGNAL_TYPE_STATIC_SCOPE);
|
|
}
|
|
|
|
static GsdDeviceType
|
|
udev_device_get_device_type (GUdevDevice *device)
|
|
{
|
|
GsdDeviceType type = 0;
|
|
gint i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (udev_ids); i++) {
|
|
if (g_udev_device_get_property_as_boolean (device, udev_ids[i]))
|
|
type |= (1 << i);
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
static gboolean
|
|
device_is_evdev (GUdevDevice *device)
|
|
{
|
|
const gchar *device_file;
|
|
|
|
device_file = g_udev_device_get_device_file (device);
|
|
|
|
if (!device_file || strstr (device_file, "/event") == NULL)
|
|
return FALSE;
|
|
|
|
return g_udev_device_get_property_as_boolean (device, "ID_INPUT");
|
|
}
|
|
|
|
static GsdDevice *
|
|
create_device (GUdevDevice *udev_device)
|
|
{
|
|
const gchar *vendor, *product, *name, *group;
|
|
guint width, height;
|
|
g_autoptr(GUdevDevice) parent = NULL;
|
|
|
|
parent = g_udev_device_get_parent (udev_device);
|
|
g_assert (parent != NULL);
|
|
|
|
name = g_udev_device_get_sysfs_attr (parent, "name");
|
|
vendor = g_udev_device_get_property (udev_device, "ID_VENDOR_ID");
|
|
product = g_udev_device_get_property (udev_device, "ID_MODEL_ID");
|
|
|
|
if (!vendor || !product) {
|
|
vendor = g_udev_device_get_sysfs_attr (udev_device, "device/id/vendor");
|
|
product = g_udev_device_get_sysfs_attr (udev_device, "device/id/product");
|
|
}
|
|
|
|
width = g_udev_device_get_property_as_int (udev_device, "ID_INPUT_WIDTH_MM");
|
|
height = g_udev_device_get_property_as_int (udev_device, "ID_INPUT_HEIGHT_MM");
|
|
|
|
group = g_udev_device_get_property (udev_device, "LIBINPUT_DEVICE_GROUP");
|
|
|
|
return g_object_new (GSD_TYPE_DEVICE,
|
|
"name", name,
|
|
"device-file", g_udev_device_get_device_file (udev_device),
|
|
"type", udev_device_get_device_type (udev_device),
|
|
"vendor-id", vendor,
|
|
"product-id", product,
|
|
"width", width,
|
|
"height", height,
|
|
"group", group,
|
|
NULL);
|
|
}
|
|
|
|
static void
|
|
add_device (GsdDeviceManager *manager,
|
|
GUdevDevice *udev_device)
|
|
{
|
|
GsdDeviceManagerPrivate *priv = gsd_device_manager_get_instance_private (manager);
|
|
GUdevDevice *parent;
|
|
GsdDevice *device;
|
|
const gchar *syspath;
|
|
|
|
parent = g_udev_device_get_parent (udev_device);
|
|
|
|
if (!parent)
|
|
return;
|
|
|
|
device = create_device (udev_device);
|
|
syspath = g_udev_device_get_sysfs_path (udev_device);
|
|
g_hash_table_insert (priv->devices, g_strdup (syspath), device);
|
|
g_signal_emit_by_name (manager, "device-added", device);
|
|
}
|
|
|
|
static void
|
|
remove_device (GsdDeviceManager *manager,
|
|
GUdevDevice *udev_device)
|
|
{
|
|
GsdDeviceManagerPrivate *priv = gsd_device_manager_get_instance_private (manager);
|
|
GsdDevice *device;
|
|
const gchar *syspath;
|
|
|
|
syspath = g_udev_device_get_sysfs_path (udev_device);
|
|
device = g_hash_table_lookup (priv->devices, syspath);
|
|
|
|
if (!device)
|
|
return;
|
|
|
|
g_hash_table_steal (priv->devices, syspath);
|
|
g_signal_emit_by_name (manager, "device-removed", device);
|
|
|
|
g_object_unref (device);
|
|
}
|
|
|
|
static void
|
|
udev_event_cb (GUdevClient *client,
|
|
gchar *action,
|
|
GUdevDevice *device,
|
|
GsdDeviceManager *manager)
|
|
{
|
|
if (!device_is_evdev (device))
|
|
return;
|
|
|
|
if (g_strcmp0 (action, "add") == 0) {
|
|
add_device (manager, device);
|
|
} else if (g_strcmp0 (action, "remove") == 0) {
|
|
remove_device (manager, device);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gsd_device_manager_init (GsdDeviceManager *manager)
|
|
{
|
|
GsdDeviceManagerPrivate *priv = gsd_device_manager_get_instance_private (manager);
|
|
const gchar *subsystems[] = { "input", NULL };
|
|
g_autoptr(GList) devices = NULL;
|
|
GList *l;
|
|
|
|
priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal,
|
|
(GDestroyNotify) g_free,
|
|
(GDestroyNotify) g_object_unref);
|
|
|
|
priv->udev_client = g_udev_client_new (subsystems);
|
|
g_signal_connect (priv->udev_client, "uevent",
|
|
G_CALLBACK (udev_event_cb), manager);
|
|
|
|
devices = g_udev_client_query_by_subsystem (priv->udev_client,
|
|
subsystems[0]);
|
|
|
|
for (l = devices; l; l = l->next) {
|
|
g_autoptr(GUdevDevice) device = l->data;
|
|
|
|
if (device_is_evdev (device))
|
|
add_device (manager, device);
|
|
}
|
|
}
|
|
|
|
GsdDeviceManager *
|
|
gsd_device_manager_get (void)
|
|
{
|
|
GsdDeviceManager *manager;
|
|
GdkScreen *screen;
|
|
|
|
screen = gdk_screen_get_default ();
|
|
g_return_val_if_fail (screen != NULL, NULL);
|
|
|
|
manager = g_object_get_data (G_OBJECT (screen), "gsd-device-manager-data");
|
|
|
|
if (!manager) {
|
|
manager = g_object_new (GSD_TYPE_DEVICE_MANAGER,
|
|
NULL);
|
|
|
|
g_object_set_data_full (G_OBJECT (screen), "gsd-device-manager-data",
|
|
manager, (GDestroyNotify) g_object_unref);
|
|
}
|
|
|
|
return manager;
|
|
}
|
|
|
|
GList *
|
|
gsd_device_manager_list_devices (GsdDeviceManager *manager,
|
|
GsdDeviceType type)
|
|
{
|
|
g_return_val_if_fail (GSD_IS_DEVICE_MANAGER (manager), NULL);
|
|
|
|
return GSD_DEVICE_MANAGER_GET_CLASS (manager)->list_devices (manager, type);
|
|
}
|
|
|
|
GsdDeviceType
|
|
gsd_device_get_device_type (GsdDevice *device)
|
|
{
|
|
GsdDevicePrivate *priv;
|
|
|
|
g_return_val_if_fail (GSD_IS_DEVICE (device), 0);
|
|
|
|
priv = gsd_device_get_instance_private (device);
|
|
|
|
return priv->type;
|
|
}
|
|
|
|
void
|
|
gsd_device_get_device_ids (GsdDevice *device,
|
|
const gchar **vendor,
|
|
const gchar **product)
|
|
{
|
|
GsdDevicePrivate *priv;
|
|
|
|
g_return_if_fail (GSD_IS_DEVICE (device));
|
|
|
|
priv = gsd_device_get_instance_private (device);
|
|
|
|
if (vendor)
|
|
*vendor = priv->vendor_id;
|
|
if (product)
|
|
*product = priv->product_id;
|
|
}
|
|
|
|
GSettings *
|
|
gsd_device_get_settings (GsdDevice *device)
|
|
{
|
|
const gchar *schema = NULL, *vendor, *product;
|
|
GsdDeviceType type;
|
|
g_autofree gchar *path = NULL;
|
|
|
|
g_return_val_if_fail (GSD_IS_DEVICE (device), NULL);
|
|
|
|
type = gsd_device_get_device_type (device);
|
|
|
|
if (type & (GSD_DEVICE_TYPE_TOUCHSCREEN | GSD_DEVICE_TYPE_TABLET)) {
|
|
gsd_device_get_device_ids (device, &vendor, &product);
|
|
|
|
if (type & GSD_DEVICE_TYPE_TOUCHSCREEN) {
|
|
schema = "org.gnome.desktop.peripherals.touchscreen";
|
|
path = g_strdup_printf ("/org/gnome/desktop/peripherals/touchscreens/%s:%s/",
|
|
vendor, product);
|
|
} else if (type & GSD_DEVICE_TYPE_TABLET) {
|
|
schema = "org.gnome.desktop.peripherals.tablet";
|
|
path = g_strdup_printf ("/org/gnome/desktop/peripherals/tablets/%s:%s/",
|
|
vendor, product);
|
|
}
|
|
} else if (type & (GSD_DEVICE_TYPE_MOUSE | GSD_DEVICE_TYPE_TOUCHPAD)) {
|
|
schema = "org.gnome.desktop.peripherals.mouse";
|
|
} else if (type & GSD_DEVICE_TYPE_KEYBOARD) {
|
|
schema = "org.gnome.desktop.peripherals.keyboard";
|
|
} else {
|
|
return NULL;
|
|
}
|
|
|
|
if (path) {
|
|
return g_settings_new_with_path (schema, path);
|
|
} else {
|
|
return g_settings_new (schema);
|
|
}
|
|
}
|
|
|
|
const gchar *
|
|
gsd_device_get_name (GsdDevice *device)
|
|
{
|
|
GsdDevicePrivate *priv;
|
|
|
|
g_return_val_if_fail (GSD_IS_DEVICE (device), NULL);
|
|
|
|
priv = gsd_device_get_instance_private (device);
|
|
|
|
return priv->name;
|
|
}
|
|
|
|
const gchar *
|
|
gsd_device_get_device_file (GsdDevice *device)
|
|
{
|
|
GsdDevicePrivate *priv;
|
|
|
|
g_return_val_if_fail (GSD_IS_DEVICE (device), NULL);
|
|
|
|
priv = gsd_device_get_instance_private (device);
|
|
|
|
return priv->device_file;
|
|
}
|
|
|
|
gboolean
|
|
gsd_device_get_dimensions (GsdDevice *device,
|
|
guint *width,
|
|
guint *height)
|
|
{
|
|
GsdDevicePrivate *priv;
|
|
|
|
g_return_val_if_fail (GSD_IS_DEVICE (device), FALSE);
|
|
|
|
priv = gsd_device_get_instance_private (device);
|
|
|
|
if (width)
|
|
*width = priv->width;
|
|
if (height)
|
|
*height = priv->height;
|
|
|
|
return priv->width > 0 && priv->height > 0;
|
|
}
|
|
|
|
GsdDevice *
|
|
gsd_device_manager_lookup_gdk_device (GsdDeviceManager *manager,
|
|
GdkDevice *gdk_device)
|
|
{
|
|
GsdDeviceManagerClass *klass;
|
|
|
|
g_return_val_if_fail (GSD_IS_DEVICE_MANAGER (manager), NULL);
|
|
g_return_val_if_fail (GDK_IS_DEVICE (gdk_device), NULL);
|
|
|
|
klass = GSD_DEVICE_MANAGER_GET_CLASS (manager);
|
|
if (!klass->lookup_device)
|
|
return NULL;
|
|
|
|
return klass->lookup_device (manager, gdk_device);
|
|
}
|
|
|
|
gboolean
|
|
gsd_device_shares_group (GsdDevice *device1,
|
|
GsdDevice *device2)
|
|
{
|
|
GsdDevicePrivate *priv1, *priv2;
|
|
|
|
priv1 = gsd_device_get_instance_private (GSD_DEVICE (device1));
|
|
priv2 = gsd_device_get_instance_private (GSD_DEVICE (device2));
|
|
|
|
/* Don't group NULLs together */
|
|
if (!priv1->group && !priv2->group)
|
|
return FALSE;
|
|
|
|
return g_strcmp0 (priv1->group, priv2->group) == 0;
|
|
}
|