mirror of
https://github.com/brl/mutter.git
synced 2024-11-30 12:00:44 -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
|
||||
libmutter_la_SOURCES += \
|
||||
core/device-map-xi2.c \
|
||||
core/device-map-xi2.h \
|
||||
core/devices-xi2.c \
|
||||
core/devices-xi2.h
|
||||
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-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)
|
||||
|
||||
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 *
|
||||
meta_device_map_new (MetaDisplay *display,
|
||||
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,
|
||||
NULL);
|
||||
}
|
||||
|
@ -71,6 +71,10 @@
|
||||
#ifdef HAVE_XCURSOR
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
#endif
|
||||
#ifdef HAVE_XINPUT2
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include "device-map-xi2.h"
|
||||
#endif
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
@ -1725,6 +1729,17 @@ event_callback (XEvent *event,
|
||||
}
|
||||
#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))
|
||||
{
|
||||
Window xwindow = meta_input_event_get_window (display, event);
|
||||
|
Loading…
Reference in New Issue
Block a user