mirror of
https://github.com/brl/mutter.git
synced 2024-11-28 02:50:41 -05:00
core: Add XInput2 device map implementation
This commit is contained in:
parent
3f7193e558
commit
f0705e142c
@ -170,6 +170,8 @@ libmutter_la_SOURCES = \
|
|||||||
|
|
||||||
if HAVE_XINPUT2
|
if HAVE_XINPUT2
|
||||||
libmutter_la_SOURCES += \
|
libmutter_la_SOURCES += \
|
||||||
|
core/device-map-xi2.c \
|
||||||
|
core/device-map-xi2.h \
|
||||||
core/devices-xi2.c \
|
core/devices-xi2.c \
|
||||||
core/devices-xi2.h
|
core/devices-xi2.h
|
||||||
endif
|
endif
|
||||||
|
265
src/core/device-map-xi2.c
Normal file
265
src/core/device-map-xi2.c
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/* Input device map, XInput2 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-xi2.h"
|
||||||
|
#include <X11/extensions/XInput2.h>
|
||||||
|
#include "devices-xi2.h"
|
||||||
|
|
||||||
|
#define XINPUT2_VERSION_MAJOR 2
|
||||||
|
#define XINPUT2_VERSION_MINOR 0
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaDeviceMapXI2, meta_device_map_xi2, META_TYPE_DEVICE_MAP)
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_device_map_xi2_grab_key (MetaDeviceMap *device_map,
|
||||||
|
Window xwindow,
|
||||||
|
guint keycode,
|
||||||
|
guint modifiers,
|
||||||
|
gboolean sync)
|
||||||
|
{
|
||||||
|
XIGrabModifiers mods = { modifiers, 0 };
|
||||||
|
MetaDisplay *display;
|
||||||
|
XIEventMask mask;
|
||||||
|
gint retval;
|
||||||
|
|
||||||
|
display = meta_device_map_get_display (device_map);
|
||||||
|
|
||||||
|
mask.deviceid = XIAllMasterDevices;
|
||||||
|
mask.mask = meta_device_xi2_translate_event_mask (KeyPressMask |
|
||||||
|
KeyReleaseMask,
|
||||||
|
&mask.mask_len);
|
||||||
|
|
||||||
|
retval = XIGrabKeycode (display->xdisplay,
|
||||||
|
XIAllMasterDevices,
|
||||||
|
keycode, xwindow,
|
||||||
|
(sync) ? GrabModeSync : GrabModeAsync,
|
||||||
|
GrabModeAsync, /* Never care about the other device */
|
||||||
|
True, &mask, 1, &mods);
|
||||||
|
|
||||||
|
return (retval == Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_device_map_xi2_ungrab_key (MetaDeviceMap *device_map,
|
||||||
|
Window xwindow,
|
||||||
|
guint keycode,
|
||||||
|
guint modifiers)
|
||||||
|
{
|
||||||
|
XIGrabModifiers mods = { modifiers, 0 };
|
||||||
|
MetaDisplay *display;
|
||||||
|
|
||||||
|
display = meta_device_map_get_display (device_map);
|
||||||
|
XIUngrabKeycode (display->xdisplay,
|
||||||
|
XIAllMasterDevices,
|
||||||
|
keycode, xwindow,
|
||||||
|
1, &mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_device_map_xi2_grab_button (MetaDeviceMap *device_map,
|
||||||
|
Window xwindow,
|
||||||
|
guint n_button,
|
||||||
|
guint modifiers,
|
||||||
|
guint evmask,
|
||||||
|
gboolean sync)
|
||||||
|
{
|
||||||
|
XIGrabModifiers mods = { modifiers, 0 };
|
||||||
|
XIEventMask mask;
|
||||||
|
MetaDisplay *display;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
display = meta_device_map_get_display (device_map);
|
||||||
|
|
||||||
|
mask.deviceid = XIAllMasterDevices;
|
||||||
|
mask.mask = meta_device_xi2_translate_event_mask (evmask, &mask.mask_len);
|
||||||
|
|
||||||
|
retval = XIGrabButton (display->xdisplay,
|
||||||
|
XIAllMasterDevices,
|
||||||
|
n_button, xwindow, None,
|
||||||
|
(sync) ? GrabModeSync : GrabModeAsync,
|
||||||
|
GrabModeAsync, /* Never care about the other device */
|
||||||
|
False, &mask, 1, &mods);
|
||||||
|
|
||||||
|
return (retval == Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_device_map_xi2_ungrab_button (MetaDeviceMap *device_map,
|
||||||
|
Window xwindow,
|
||||||
|
guint n_button,
|
||||||
|
guint modifiers)
|
||||||
|
{
|
||||||
|
XIGrabModifiers mods = { modifiers, 0 };
|
||||||
|
MetaDisplay *display;
|
||||||
|
|
||||||
|
display = meta_device_map_get_display (device_map);
|
||||||
|
XIUngrabButton (display->xdisplay,
|
||||||
|
XIAllMasterDevices,
|
||||||
|
n_button, xwindow, 1, &mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_device_from_info (MetaDeviceMap *device_map,
|
||||||
|
gint use,
|
||||||
|
gint device_id)
|
||||||
|
{
|
||||||
|
MetaDevice *device;
|
||||||
|
MetaDisplay *display;
|
||||||
|
|
||||||
|
display = meta_device_map_get_display (device_map);
|
||||||
|
|
||||||
|
if (use == XIMasterPointer)
|
||||||
|
device = meta_device_pointer_xi2_new (display, device_id);
|
||||||
|
else if (use == XIMasterKeyboard)
|
||||||
|
device = meta_device_keyboard_xi2_new (display, device_id);
|
||||||
|
|
||||||
|
if (device)
|
||||||
|
{
|
||||||
|
meta_device_map_add_device (device_map, device);
|
||||||
|
g_object_unref (device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pair_devices (gpointer key,
|
||||||
|
gpointer value,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaDevice *device1, *device2;
|
||||||
|
MetaDeviceMap *device_map;
|
||||||
|
|
||||||
|
device_map = user_data;
|
||||||
|
device1 = meta_device_map_lookup (device_map, GPOINTER_TO_INT (key));
|
||||||
|
device2 = meta_device_map_lookup (device_map, GPOINTER_TO_INT (value));
|
||||||
|
|
||||||
|
meta_device_pair_devices (device1, device2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_device_map_xi2_constructed (GObject *object)
|
||||||
|
{
|
||||||
|
MetaDeviceMap *device_map = META_DEVICE_MAP (object);
|
||||||
|
MetaDisplay *display;
|
||||||
|
XIDeviceInfo *info;
|
||||||
|
GHashTable *pairs;
|
||||||
|
int n_devices, i;
|
||||||
|
|
||||||
|
display = meta_device_map_get_display (device_map);
|
||||||
|
|
||||||
|
/* We're only interested in master devices,
|
||||||
|
* detached slave devices are left for applications
|
||||||
|
* to handle.
|
||||||
|
*/
|
||||||
|
info = XIQueryDevice (display->xdisplay, XIAllMasterDevices, &n_devices);
|
||||||
|
pairs = g_hash_table_new (NULL, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < n_devices; i++)
|
||||||
|
{
|
||||||
|
add_device_from_info (device_map, info[i].use, info[i].deviceid);
|
||||||
|
g_hash_table_insert (pairs,
|
||||||
|
GINT_TO_POINTER (info[i].deviceid),
|
||||||
|
GINT_TO_POINTER (info[i].attachment));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_foreach (pairs, pair_devices, device_map);
|
||||||
|
g_hash_table_destroy (pairs);
|
||||||
|
|
||||||
|
XIFreeDeviceInfo (info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_device_map_xi2_class_init (MetaDeviceMapXI2Class *klass)
|
||||||
|
{
|
||||||
|
MetaDeviceMapClass *device_map_class = META_DEVICE_MAP_CLASS (klass);
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->constructed = meta_device_map_xi2_constructed;
|
||||||
|
|
||||||
|
device_map_class->grab_key = meta_device_map_xi2_grab_key;
|
||||||
|
device_map_class->ungrab_key = meta_device_map_xi2_ungrab_key;
|
||||||
|
device_map_class->grab_button = meta_device_map_xi2_grab_button;
|
||||||
|
device_map_class->ungrab_button = meta_device_map_xi2_ungrab_button;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_device_map_xi2_init (MetaDeviceMapXI2 *device_map)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_device_map_xi2_handle_hierarchy_event (MetaDeviceMapXI2 *device_map,
|
||||||
|
XEvent *ev)
|
||||||
|
{
|
||||||
|
MetaDisplay *display;
|
||||||
|
|
||||||
|
display = meta_device_map_get_display (META_DEVICE_MAP (device_map));
|
||||||
|
|
||||||
|
if (ev->type == GenericEvent &&
|
||||||
|
ev->xcookie.extension == display->xinput2_opcode)
|
||||||
|
{
|
||||||
|
XIHierarchyEvent *xev;
|
||||||
|
GHashTable *pairs;
|
||||||
|
gint i;
|
||||||
|
|
||||||
|
g_assert (display->have_xinput2 == TRUE);
|
||||||
|
|
||||||
|
xev = (XIHierarchyEvent *) ev->xcookie.data;
|
||||||
|
|
||||||
|
if (xev->evtype != XI_HierarchyChanged)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
pairs = g_hash_table_new (NULL, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < xev->num_info; i++)
|
||||||
|
{
|
||||||
|
if (xev->info[i].flags & XIMasterAdded)
|
||||||
|
{
|
||||||
|
add_device_from_info (META_DEVICE_MAP (device_map),
|
||||||
|
xev->info[i].use,
|
||||||
|
xev->info[i].deviceid);
|
||||||
|
g_hash_table_insert (pairs,
|
||||||
|
GINT_TO_POINTER (xev->info[i].deviceid),
|
||||||
|
GINT_TO_POINTER (xev->info[i].attachment));
|
||||||
|
}
|
||||||
|
else if (xev->info[i].flags & XIMasterRemoved)
|
||||||
|
{
|
||||||
|
MetaDevice *device;
|
||||||
|
|
||||||
|
device = meta_device_map_lookup (META_DEVICE_MAP (device_map),
|
||||||
|
xev->info[i].deviceid);
|
||||||
|
|
||||||
|
if (device)
|
||||||
|
meta_device_map_remove_device (META_DEVICE_MAP (device_map),
|
||||||
|
device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_foreach (pairs, pair_devices, device_map);
|
||||||
|
g_hash_table_destroy (pairs);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
59
src/core/device-map-xi2.h
Normal file
59
src/core/device-map-xi2.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file device-map-xi2.h device map for XInput2 devices
|
||||||
|
*
|
||||||
|
* Input devices.
|
||||||
|
* This file contains the XInput2 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_XI2_H
|
||||||
|
#define META_DEVICE_MAP_XI2_H
|
||||||
|
|
||||||
|
typedef struct _MetaDeviceMapXI2 MetaDeviceMapXI2;
|
||||||
|
typedef struct _MetaDeviceMapXI2Class MetaDeviceMapXI2Class;
|
||||||
|
|
||||||
|
#include "device-map.h"
|
||||||
|
|
||||||
|
#define META_TYPE_DEVICE_MAP_XI2 (meta_device_map_xi2_get_type ())
|
||||||
|
#define META_DEVICE_MAP_XI2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_MAP_XI2, MetaDeviceMapXI2))
|
||||||
|
#define META_DEVICE_MAP_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_MAP_XI2, MetaDeviceMapXI2Class))
|
||||||
|
#define META_IS_DEVICE_MAP_XI2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_MAP_XI2))
|
||||||
|
#define META_IS_DEVICE_MAP_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_MAP_XI2))
|
||||||
|
#define META_DEVICE_MAP_XI2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_MAP_XI2, MetaDeviceMapXI2Class))
|
||||||
|
|
||||||
|
struct _MetaDeviceMapXI2
|
||||||
|
{
|
||||||
|
MetaDeviceMap parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MetaDeviceMapXI2Class
|
||||||
|
{
|
||||||
|
MetaDeviceMapClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType meta_device_map_xi2_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
gboolean meta_device_map_xi2_handle_hierarchy_event (MetaDeviceMapXI2 *device_map,
|
||||||
|
XEvent *ev);
|
||||||
|
|
||||||
|
#endif /* META_DEVICE_MAP_XI2_H */
|
@ -25,6 +25,14 @@
|
|||||||
#include "device-map.h"
|
#include "device-map.h"
|
||||||
#include "device-map-core.h"
|
#include "device-map-core.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT2
|
||||||
|
#include <X11/extensions/XInput2.h>
|
||||||
|
#include "device-map-xi2.h"
|
||||||
|
|
||||||
|
#define XINPUT2_VERSION_MAJOR 2
|
||||||
|
#define XINPUT2_VERSION_MINOR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaDeviceMap, meta_device_map, G_TYPE_OBJECT)
|
G_DEFINE_TYPE (MetaDeviceMap, meta_device_map, G_TYPE_OBJECT)
|
||||||
|
|
||||||
typedef struct MetaDeviceMapPrivate MetaDeviceMapPrivate;
|
typedef struct MetaDeviceMapPrivate MetaDeviceMapPrivate;
|
||||||
@ -192,11 +200,52 @@ meta_device_map_remove_device (MetaDeviceMap *device_map,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT2
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
initialize_xinput (MetaDisplay *display)
|
||||||
|
{
|
||||||
|
int major, minor, opcode;
|
||||||
|
int unused;
|
||||||
|
|
||||||
|
if (!XQueryExtension (display->xdisplay,
|
||||||
|
"XInputExtension",
|
||||||
|
&opcode, &unused, &unused))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
major = XINPUT2_VERSION_MAJOR;
|
||||||
|
minor = XINPUT2_VERSION_MINOR;
|
||||||
|
|
||||||
|
XIQueryVersion (display->xdisplay, &major, &minor);
|
||||||
|
|
||||||
|
if (major == XINPUT2_VERSION_MAJOR &&
|
||||||
|
minor == XINPUT2_VERSION_MINOR)
|
||||||
|
{
|
||||||
|
display->have_xinput2 = TRUE;
|
||||||
|
display->xinput2_opcode = opcode;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_XINPUT2 */
|
||||||
|
|
||||||
MetaDeviceMap *
|
MetaDeviceMap *
|
||||||
meta_device_map_new (MetaDisplay *display,
|
meta_device_map_new (MetaDisplay *display,
|
||||||
gboolean force_core)
|
gboolean force_core)
|
||||||
{
|
{
|
||||||
return g_object_new (META_TYPE_DEVICE_MAP_CORE,
|
GType type = META_TYPE_DEVICE_MAP_CORE;
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT2
|
||||||
|
if (!force_core &&
|
||||||
|
initialize_xinput (display))
|
||||||
|
type = META_TYPE_DEVICE_MAP_XI2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return g_object_new (type,
|
||||||
"display", display,
|
"display", display,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,10 @@
|
|||||||
#ifdef HAVE_XCURSOR
|
#ifdef HAVE_XCURSOR
|
||||||
#include <X11/Xcursor/Xcursor.h>
|
#include <X11/Xcursor/Xcursor.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_XINPUT2
|
||||||
|
#include <X11/extensions/XInput2.h>
|
||||||
|
#include "device-map-xi2.h"
|
||||||
|
#endif
|
||||||
#include <X11/extensions/Xrender.h>
|
#include <X11/extensions/Xrender.h>
|
||||||
#include <X11/extensions/Xcomposite.h>
|
#include <X11/extensions/Xcomposite.h>
|
||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
@ -1725,6 +1729,17 @@ event_callback (XEvent *event,
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_SHAPE */
|
#endif /* HAVE_SHAPE */
|
||||||
|
|
||||||
|
#ifdef HAVE_XINPUT2
|
||||||
|
if (display->have_xinput2 &&
|
||||||
|
meta_device_map_xi2_handle_hierarchy_event (META_DEVICE_MAP_XI2 (display->device_map),
|
||||||
|
event))
|
||||||
|
{
|
||||||
|
/* Let GDK Handle the event too for its own device accounting */
|
||||||
|
filter_out_event = FALSE;
|
||||||
|
bypass_compositor = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if (meta_input_event_get_type (display, event, &evtype))
|
if (meta_input_event_get_type (display, event, &evtype))
|
||||||
{
|
{
|
||||||
Window xwindow = meta_input_event_get_window (display, event);
|
Window xwindow = meta_input_event_get_window (display, event);
|
||||||
|
Loading…
Reference in New Issue
Block a user