diff --git a/src/Makefile.am b/src/Makefile.am index 829f67edd..a8884ec32 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -81,6 +81,10 @@ libmutter_la_SOURCES = \ core/device-keyboard.h \ core/device-pointer.c \ core/device-pointer.h \ + core/device-map.c \ + core/device-map.h \ + core/device-map-core.c \ + core/device-map-core.h \ core/devices-core.c \ core/devices-core.h \ core/display.c \ diff --git a/src/core/device-map-core.c b/src/core/device-map-core.c new file mode 100644 index 000000000..ea34f28e5 --- /dev/null +++ b/src/core/device-map-core.c @@ -0,0 +1,134 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* Input device map, core protocol implementation */ + +/* + * Copyright (C) 2011 Carlos Garnacho + * + * 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. + */ + +#include "config.h" +#include "device-map-core.h" +#include "devices-core.h" + +G_DEFINE_TYPE (MetaDeviceMapCore, meta_device_map_core, META_TYPE_DEVICE_MAP) + +static gboolean +meta_device_map_core_grab_key (MetaDeviceMap *device_map, + Window xwindow, + guint keycode, + guint modifiers, + gboolean sync) +{ + MetaDisplay *display; + gint retval; + + display = meta_device_map_get_display (device_map); + retval = XGrabKey (display->xdisplay, keycode, modifiers, + xwindow, True, + GrabModeAsync, /* Never care about the other device */ + (sync) ? GrabModeSync : GrabModeAsync); + + return (retval == Success); +} + +static void +meta_device_map_core_ungrab_key (MetaDeviceMap *device_map, + Window xwindow, + guint keycode, + guint modifiers) +{ + MetaDisplay *display; + + display = meta_device_map_get_display (device_map); + XUngrabKey (display->xdisplay, keycode, modifiers, xwindow); +} + +static gboolean +meta_device_map_core_grab_button (MetaDeviceMap *device_map, + Window xwindow, + guint n_button, + guint modifiers, + guint evmask, + gboolean sync) +{ + MetaDisplay *display; + gint retval; + + display = meta_device_map_get_display (device_map); + retval = XGrabButton (display->xdisplay, n_button, + modifiers, xwindow, False, + evmask, + (sync) ? GrabModeSync : GrabModeAsync, + GrabModeAsync, /* Never care about the other device */ + None, None); + + return (retval == Success); +} + +static void +meta_device_map_core_ungrab_button (MetaDeviceMap *device_map, + Window xwindow, + guint n_button, + guint modifiers) +{ + MetaDisplay *display; + + display = meta_device_map_get_display (device_map); + XUngrabButton (display->xdisplay, n_button, modifiers, xwindow); +} + +static void +meta_device_map_core_constructed (GObject *object) +{ + MetaDeviceMap *device_map = META_DEVICE_MAP (object); + MetaDevice *pointer, *keyboard; + MetaDisplay *display; + + display = meta_device_map_get_display (device_map); + + /* Insert core devices */ + pointer = meta_device_pointer_core_new (display); + meta_device_map_add_device (device_map, pointer); + + keyboard = meta_device_keyboard_core_new (display); + meta_device_map_add_device (device_map, keyboard); + + meta_device_pair_devices (pointer, keyboard); + + g_object_unref (pointer); + g_object_unref (keyboard); +} + +static void +meta_device_map_core_class_init (MetaDeviceMapCoreClass *klass) +{ + MetaDeviceMapClass *device_map_class = META_DEVICE_MAP_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = meta_device_map_core_constructed; + + device_map_class->grab_key = meta_device_map_core_grab_key; + device_map_class->ungrab_key = meta_device_map_core_ungrab_key; + device_map_class->grab_button = meta_device_map_core_grab_button; + device_map_class->ungrab_button = meta_device_map_core_ungrab_button; +} + +static void +meta_device_map_core_init (MetaDeviceMapCore *device_map) +{ +} diff --git a/src/core/device-map-core.h b/src/core/device-map-core.h new file mode 100644 index 000000000..d9773de62 --- /dev/null +++ b/src/core/device-map-core.h @@ -0,0 +1,56 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/** + * \file device-map-core.h device map for core devices + * + * Input devices. + * This file contains the core protocol implementation of the device map + */ + +/* + * Copyright (C) 2011 Carlos Garnacho + * + * 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. + */ + +#ifndef META_DEVICE_MAP_CORE_H +#define META_DEVICE_MAP_CORE_H + +typedef struct _MetaDeviceMapCore MetaDeviceMapCore; +typedef struct _MetaDeviceMapCoreClass MetaDeviceMapCoreClass; + +#include "device-map.h" + +#define META_TYPE_DEVICE_MAP_CORE (meta_device_map_core_get_type ()) +#define META_DEVICE_MAP_CORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_MAP_CORE, MetaDeviceMapCore)) +#define META_DEVICE_MAP_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_MAP_CORE, MetaDeviceMapCoreClass)) +#define META_IS_DEVICE_MAP_CORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_MAP_CORE)) +#define META_IS_DEVICE_MAP_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_MAP_CORE)) +#define META_DEVICE_MAP_CORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_MAP_CORE, MetaDeviceMapCoreClass)) + +struct _MetaDeviceMapCore +{ + MetaDeviceMap parent_instance; +}; + +struct _MetaDeviceMapCoreClass +{ + MetaDeviceMapClass parent_class; +}; + +GType meta_device_map_core_get_type (void) G_GNUC_CONST; + +#endif /* META_DEVICE_MAP_CORE_H */ diff --git a/src/core/device-map.c b/src/core/device-map.c new file mode 100644 index 000000000..1f28ed407 --- /dev/null +++ b/src/core/device-map.c @@ -0,0 +1,302 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* Input device map */ + +/* + * Copyright (C) 2011 Carlos Garnacho + * + * 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. + */ + +#include "config.h" +#include "device-map.h" +#include "device-map-core.h" + +G_DEFINE_TYPE (MetaDeviceMap, meta_device_map, G_TYPE_OBJECT) + +typedef struct MetaDeviceMapPrivate MetaDeviceMapPrivate; + +struct MetaDeviceMapPrivate +{ + MetaDisplay *display; + GHashTable *devices; +}; + +enum { + PROP_0, + PROP_DISPLAY +}; + +enum { + DEVICE_ADDED, + DEVICE_REMOVED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void +meta_device_map_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + MetaDeviceMapPrivate *priv; + + priv = META_DEVICE_MAP (object)->priv; + + switch (param_id) + { + case PROP_DISPLAY: + g_value_set_object (value, priv->display); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +meta_device_map_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + MetaDeviceMapPrivate *priv; + + priv = META_DEVICE_MAP (object)->priv; + + switch (param_id) + { + case PROP_DISPLAY: + priv->display = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void +meta_device_map_finalize (GObject *object) +{ + MetaDeviceMapPrivate *priv; + GHashTableIter iter; + MetaDevice *device; + + priv = META_DEVICE_MAP (object)->priv; + g_hash_table_iter_init (&iter, priv->devices); + + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device)) + { + /* Detach the device */ + g_hash_table_iter_steal (&iter); + + g_signal_emit (object, signals[DEVICE_REMOVED], 0, device); + g_object_unref (device); + } + + g_hash_table_destroy (priv->devices); + G_OBJECT_CLASS (meta_device_map_parent_class)->finalize (object); +} + +static void +meta_device_map_class_init (MetaDeviceMapClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = meta_device_map_get_property; + object_class->set_property = meta_device_map_set_property; + object_class->finalize = meta_device_map_finalize; + + g_object_class_install_property (object_class, + PROP_DISPLAY, + g_param_spec_object ("display", + "Display", + "Display", + META_TYPE_DISPLAY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + signals[DEVICE_ADDED] = + g_signal_new ("device-added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, META_TYPE_DEVICE); + signals[DEVICE_REMOVED] = + g_signal_new ("device-removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, META_TYPE_DEVICE); + + g_type_class_add_private (klass, sizeof (MetaDeviceMapPrivate)); +} + +static void +meta_device_map_init (MetaDeviceMap *device_map) +{ + MetaDeviceMapPrivate *priv; + + priv = device_map->priv = G_TYPE_INSTANCE_GET_PRIVATE (device_map, + META_TYPE_DEVICE_MAP, + MetaDeviceMapPrivate); + priv->devices = g_hash_table_new_full (NULL, NULL, NULL, + (GDestroyNotify) g_object_unref); +} + +void +meta_device_map_add_device (MetaDeviceMap *device_map, + MetaDevice *device) +{ + MetaDeviceMapPrivate *priv; + + priv = device_map->priv; + g_hash_table_insert (priv->devices, + GINT_TO_POINTER (meta_device_get_id (device)), + g_object_ref (device)); + + g_signal_emit (device_map, signals[DEVICE_ADDED], 0, device); +} + +void +meta_device_map_remove_device (MetaDeviceMap *device_map, + MetaDevice *device) +{ + MetaDeviceMapPrivate *priv; + + priv = device_map->priv; + + if (g_hash_table_steal (priv->devices, + GINT_TO_POINTER (meta_device_get_id (device)))) + { + g_signal_emit (device_map, signals[DEVICE_REMOVED], 0, device); + g_object_unref (device); + } +} + +MetaDeviceMap * +meta_device_map_new (MetaDisplay *display, + gboolean force_core) +{ + return g_object_new (META_TYPE_DEVICE_MAP_CORE, + "display", display, + NULL); +} + +MetaDevice * +meta_device_map_lookup (MetaDeviceMap *device_map, + gint device_id) +{ + MetaDeviceMapPrivate *priv; + + g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), NULL); + + priv = device_map->priv; + return g_hash_table_lookup (priv->devices, + GINT_TO_POINTER (device_id)); +} + +MetaDisplay * +meta_device_map_get_display (MetaDeviceMap *device_map) +{ + MetaDeviceMapPrivate *priv; + + g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), NULL); + + priv = device_map->priv; + return priv->display; +} + +gboolean +meta_device_map_grab_key (MetaDeviceMap *device_map, + Window xwindow, + guint keycode, + guint modifiers, + gboolean sync) +{ + MetaDeviceMapClass *klass; + + g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), FALSE); + g_return_val_if_fail (xwindow != None, FALSE); + + klass = META_DEVICE_MAP_GET_CLASS (device_map); + + if (!klass->grab_key) + return FALSE; + + return (klass->grab_key) (device_map, xwindow, keycode, modifiers, sync); +} + +void +meta_device_map_ungrab_key (MetaDeviceMap *device_map, + Window xwindow, + guint keycode, + guint modifiers) +{ + MetaDeviceMapClass *klass; + + g_return_if_fail (META_IS_DEVICE_MAP (device_map)); + g_return_if_fail (xwindow != None); + + klass = META_DEVICE_MAP_GET_CLASS (device_map); + + if (klass->ungrab_key) + (klass->ungrab_key) (device_map, xwindow, keycode, modifiers); +} + +gboolean +meta_device_map_grab_button (MetaDeviceMap *device_map, + Window xwindow, + guint n_button, + guint modifiers, + guint evmask, + gboolean sync) +{ + MetaDeviceMapClass *klass; + + g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), FALSE); + g_return_val_if_fail (xwindow != None, FALSE); + + klass = META_DEVICE_MAP_GET_CLASS (device_map); + + if (!klass->grab_button) + return FALSE; + + return (klass->grab_button) (device_map, xwindow, n_button, + modifiers, evmask, sync); +} + +void +meta_device_map_ungrab_button (MetaDeviceMap *device_map, + Window xwindow, + guint n_button, + guint modifiers) +{ + MetaDeviceMapClass *klass; + + g_return_if_fail (META_IS_DEVICE_MAP (device_map)); + g_return_if_fail (xwindow != None); + + klass = META_DEVICE_MAP_GET_CLASS (device_map); + + if (klass->ungrab_button) + (klass->ungrab_button) (device_map, xwindow, n_button, modifiers); +} diff --git a/src/core/device-map.h b/src/core/device-map.h new file mode 100644 index 000000000..b0e31f9d9 --- /dev/null +++ b/src/core/device-map.h @@ -0,0 +1,119 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/** + * \file device-map.h object containing input devices + * + * Input devices. + * This file contains the device map, used to find out the device behind + * XInput2/core events. + */ + +/* + * Copyright (C) 2011 Carlos Garnacho + * + * 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. + */ + +#ifndef META_DEVICE_MAP_H +#define META_DEVICE_MAP_H + +typedef struct _MetaDeviceMap MetaDeviceMap; +typedef struct _MetaDeviceMapClass MetaDeviceMapClass; + +#include "display-private.h" +#include "device.h" + +#define META_TYPE_DEVICE_MAP (meta_device_map_get_type ()) +#define META_DEVICE_MAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_MAP, MetaDeviceMap)) +#define META_DEVICE_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_MAP, MetaDeviceMapClass)) +#define META_IS_DEVICE_MAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_MAP)) +#define META_IS_DEVICE_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_MAP)) +#define META_DEVICE_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_MAP, MetaDeviceMapClass)) + +struct _MetaDeviceMap +{ + GObject parent_instance; + gpointer priv; +}; + +struct _MetaDeviceMapClass +{ + GObjectClass parent_instance; + + void (* device_added) (MetaDeviceMap *device_map, + MetaDevice *device); + void (* device_removed) (MetaDeviceMap *device_map, + MetaDevice *device); + + gboolean (* grab_key) (MetaDeviceMap *device_map, + Window xwindow, + guint keycode, + guint modifiers, + gboolean sync); + void (* ungrab_key) (MetaDeviceMap *device_map, + Window xwindow, + guint keycode, + guint modifiers); + + gboolean (* grab_button) (MetaDeviceMap *device_map, + Window xwindow, + guint n_button, + guint modifiers, + guint evmask, + gboolean sync); + void (* ungrab_button) (MetaDeviceMap *pointer, + Window xwindow, + guint n_button, + guint modifiers); +}; + +GType meta_device_map_get_type (void) G_GNUC_CONST; + +MetaDeviceMap * meta_device_map_new (MetaDisplay *display, + gboolean force_core); + +void meta_device_map_add_device (MetaDeviceMap *device_map, + MetaDevice *device); +void meta_device_map_remove_device (MetaDeviceMap *device_map, + MetaDevice *device); + +MetaDevice * meta_device_map_lookup (MetaDeviceMap *device_map, + gint device_id); + +MetaDisplay * meta_device_map_get_display (MetaDeviceMap *device_map); + +gboolean meta_device_map_grab_key (MetaDeviceMap *device_map, + Window xwindow, + guint keycode, + guint modifiers, + gboolean sync); +void meta_device_map_ungrab_key (MetaDeviceMap *device_map, + Window xwindow, + guint keycode, + guint modifiers); +gboolean meta_device_map_grab_button (MetaDeviceMap *device_map, + Window xwindow, + guint n_button, + guint modifiers, + guint evmask, + gboolean sync); +void meta_device_map_ungrab_button (MetaDeviceMap *device_map, + Window xwindow, + guint n_button, + guint modifiers); + + +#endif /* META_DEVICE_MAP_H */ diff --git a/src/core/display-private.h b/src/core/display-private.h index edb3a584f..194ef1461 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -38,6 +38,7 @@ #include #include #include "keybindings-private.h" +#include "device-map.h" #include #ifdef HAVE_STARTUP_NOTIFICATION @@ -266,6 +267,9 @@ struct _MetaDisplay /* Managed by compositor.c */ MetaCompositor *compositor; + /* Managed by device-map.c */ + MetaDeviceMap *device_map; + int render_event_base; int render_error_base; diff --git a/src/core/display.c b/src/core/display.c index a34daa1e1..5ce306c36 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -48,6 +48,7 @@ #include "xprops.h" #include "workspace-private.h" #include "bell.h" +#include "device.h" #include "input-events.h" #include #include @@ -478,6 +479,7 @@ meta_display_open (void) the_display->static_gravity_works = g_getenv ("MUTTER_USE_STATIC_GRAVITY") != NULL; meta_bell_init (the_display); + the_display->device_map = meta_device_map_new (the_display, TRUE); meta_display_init_keys (the_display);