mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 22:20:24 +00:00
c7d73ee587
* _gdk_device_set_associated_device() did not allow NULL device * GdkDisplay should dispose device manager to avoid devices trying to touch the display in finalize * GdkDeviceManagerXI did not ref devices in id hash * GdkDisplayX11 did not ref devices in ->input_devices
662 lines
21 KiB
C
662 lines
21 KiB
C
/* GDK - The GIMP Drawing Kit
|
|
* Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
|
|
*
|
|
* 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, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "gdkdevicemanager-xi.h"
|
|
#include "gdkeventtranslator.h"
|
|
#include "gdkdevice-xi.h"
|
|
#include "gdkintl.h"
|
|
#include "gdkx.h"
|
|
|
|
#include <X11/extensions/XInput.h>
|
|
|
|
|
|
struct _GdkDeviceManagerXIPrivate
|
|
{
|
|
GHashTable *id_table;
|
|
gint event_base;
|
|
GList *devices;
|
|
gboolean ignore_core_events;
|
|
};
|
|
|
|
static void gdk_device_manager_xi_constructed (GObject *object);
|
|
static void gdk_device_manager_xi_dispose (GObject *object);
|
|
static void gdk_device_manager_xi_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec);
|
|
static void gdk_device_manager_xi_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec);
|
|
|
|
static void gdk_device_manager_xi_event_translator_init (GdkEventTranslatorIface *iface);
|
|
static gboolean gdk_device_manager_xi_translate_event (GdkEventTranslator *translator,
|
|
GdkDisplay *display,
|
|
GdkEvent *event,
|
|
XEvent *xevent);
|
|
static GList * gdk_device_manager_xi_list_devices (GdkDeviceManager *device_manager,
|
|
GdkDeviceType type);
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (GdkDeviceManagerXI, gdk_device_manager_xi, GDK_TYPE_DEVICE_MANAGER_CORE,
|
|
G_IMPLEMENT_INTERFACE (GDK_TYPE_EVENT_TRANSLATOR,
|
|
gdk_device_manager_xi_event_translator_init))
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_EVENT_BASE
|
|
};
|
|
|
|
static void
|
|
gdk_device_manager_xi_class_init (GdkDeviceManagerXIClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
GdkDeviceManagerClass *device_manager_class = GDK_DEVICE_MANAGER_CLASS (klass);
|
|
|
|
object_class->constructed = gdk_device_manager_xi_constructed;
|
|
object_class->dispose = gdk_device_manager_xi_dispose;
|
|
object_class->set_property = gdk_device_manager_xi_set_property;
|
|
object_class->get_property = gdk_device_manager_xi_get_property;
|
|
|
|
device_manager_class->list_devices = gdk_device_manager_xi_list_devices;
|
|
|
|
g_object_class_install_property (object_class,
|
|
PROP_EVENT_BASE,
|
|
g_param_spec_int ("event-base",
|
|
P_("Event base"),
|
|
P_("Event base for XInput events"),
|
|
0, G_MAXINT, 0,
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
g_type_class_add_private (object_class, sizeof (GdkDeviceManagerXIPrivate));
|
|
}
|
|
|
|
static GdkFilterReturn
|
|
window_input_info_filter (GdkXEvent *xevent,
|
|
GdkEvent *event,
|
|
gpointer user_data)
|
|
{
|
|
GdkDeviceManager *device_manager;
|
|
GdkDisplay *display;
|
|
GdkWindow *window;
|
|
XEvent *xev;
|
|
|
|
device_manager = user_data;
|
|
xev = (XEvent *) xevent;
|
|
|
|
display = gdk_device_manager_get_display (device_manager);
|
|
window = gdk_window_lookup_for_display (display, xev->xany.window);
|
|
|
|
if (window && xev->type == ConfigureNotify)
|
|
gdk_device_xi_update_window_info (window);
|
|
|
|
return GDK_FILTER_CONTINUE;
|
|
}
|
|
|
|
static void
|
|
gdk_device_manager_xi_init (GdkDeviceManagerXI *device_manager)
|
|
{
|
|
GdkDeviceManagerXIPrivate *priv;
|
|
|
|
device_manager->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (device_manager,
|
|
GDK_TYPE_DEVICE_MANAGER_XI,
|
|
GdkDeviceManagerXIPrivate);
|
|
|
|
priv->id_table = g_hash_table_new_full (NULL, NULL, NULL,
|
|
(GDestroyNotify) g_object_unref);
|
|
|
|
gdk_window_add_filter (NULL, window_input_info_filter, device_manager);
|
|
}
|
|
|
|
static void
|
|
translate_class_info (GdkDevice *device,
|
|
XDeviceInfo *info)
|
|
{
|
|
GdkDeviceXI *device_xi;
|
|
XAnyClassPtr class;
|
|
gint i, j;
|
|
|
|
device_xi = GDK_DEVICE_XI (device);
|
|
class = info->inputclassinfo;
|
|
|
|
for (i = 0; i < info->num_classes; i++)
|
|
{
|
|
switch (class->class) {
|
|
case ButtonClass:
|
|
break;
|
|
case KeyClass:
|
|
{
|
|
XKeyInfo *xki = (XKeyInfo *)class;
|
|
guint num_keys;
|
|
|
|
num_keys = xki->max_keycode - xki->min_keycode + 1;
|
|
_gdk_device_set_keys (device, num_keys);
|
|
|
|
device_xi->min_keycode = xki->min_keycode;
|
|
|
|
break;
|
|
}
|
|
case ValuatorClass:
|
|
{
|
|
XValuatorInfo *xvi = (XValuatorInfo *)class;
|
|
|
|
for (j = 0; j < xvi->num_axes; j++)
|
|
{
|
|
GdkAxisUse use;
|
|
|
|
switch (j)
|
|
{
|
|
case 0:
|
|
use = GDK_AXIS_X;
|
|
break;
|
|
case 1:
|
|
use = GDK_AXIS_Y;
|
|
break;
|
|
case 2:
|
|
use = GDK_AXIS_PRESSURE;
|
|
break;
|
|
case 3:
|
|
use = GDK_AXIS_XTILT;
|
|
break;
|
|
case 4:
|
|
use = GDK_AXIS_YTILT;
|
|
break;
|
|
case 5:
|
|
use = GDK_AXIS_WHEEL;
|
|
break;
|
|
default:
|
|
use = GDK_AXIS_IGNORE;
|
|
}
|
|
|
|
_gdk_device_add_axis (device,
|
|
GDK_NONE,
|
|
use,
|
|
xvi->axes[j].min_value,
|
|
xvi->axes[j].max_value,
|
|
xvi->axes[j].resolution);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
class = (XAnyClassPtr) (((char *) class) + class->length);
|
|
}
|
|
}
|
|
|
|
/* old versions of XI.h don't define these */
|
|
#ifndef IsXExtensionKeyboard
|
|
#define IsXExtensionKeyboard 3
|
|
#define IsXExtensionPointer 4
|
|
#endif
|
|
|
|
static GdkDevice *
|
|
create_device (GdkDeviceManager *device_manager,
|
|
GdkDisplay *display,
|
|
XDeviceInfo *info)
|
|
{
|
|
GdkInputSource input_source;
|
|
GdkDevice *device;
|
|
|
|
if (info->use != IsXExtensionPointer &&
|
|
info->use != IsXExtensionKeyboard)
|
|
return NULL;
|
|
|
|
if (info->use == IsXExtensionKeyboard)
|
|
input_source = GDK_SOURCE_KEYBOARD;
|
|
else
|
|
{
|
|
gchar *tmp_name;
|
|
|
|
tmp_name = g_ascii_strdown (info->name, -1);
|
|
|
|
if (strstr (tmp_name, "eraser"))
|
|
input_source = GDK_SOURCE_ERASER;
|
|
else if (strstr (tmp_name, "cursor"))
|
|
input_source = GDK_SOURCE_CURSOR;
|
|
else if (strstr (tmp_name, "wacom") ||
|
|
strstr (tmp_name, "pen"))
|
|
input_source = GDK_SOURCE_PEN;
|
|
else
|
|
input_source = GDK_SOURCE_MOUSE;
|
|
|
|
g_free (tmp_name);
|
|
}
|
|
|
|
device = g_object_new (GDK_TYPE_DEVICE_XI,
|
|
"name", info->name,
|
|
"type", GDK_DEVICE_TYPE_FLOATING,
|
|
"input-source", input_source,
|
|
"input-mode", GDK_MODE_DISABLED,
|
|
"has-cursor", FALSE,
|
|
"display", display,
|
|
"device-manager", device_manager,
|
|
"device-id", info->id,
|
|
NULL);
|
|
translate_class_info (device, info);
|
|
|
|
return device;
|
|
}
|
|
|
|
static void
|
|
gdk_device_manager_xi_constructed (GObject *object)
|
|
{
|
|
GdkDeviceManagerXIPrivate *priv;
|
|
XDeviceInfo *devices;
|
|
gint i, num_devices;
|
|
GdkDisplay *display;
|
|
|
|
priv = GDK_DEVICE_MANAGER_XI (object)->priv;
|
|
display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (object));
|
|
devices = XListInputDevices(GDK_DISPLAY_XDISPLAY (display), &num_devices);
|
|
|
|
for(i = 0; i < num_devices; i++)
|
|
{
|
|
GdkDevice *device;
|
|
|
|
device = create_device (GDK_DEVICE_MANAGER (object),
|
|
display, &devices[i]);
|
|
if (device)
|
|
{
|
|
priv->devices = g_list_prepend (priv->devices, device);
|
|
g_hash_table_insert (priv->id_table,
|
|
GINT_TO_POINTER (devices[i].id),
|
|
g_object_ref (device));
|
|
}
|
|
}
|
|
|
|
XFreeDeviceList(devices);
|
|
|
|
gdk_x11_register_standard_event_type (display,
|
|
priv->event_base,
|
|
15 /* Number of events */);
|
|
|
|
if (G_OBJECT_CLASS (gdk_device_manager_xi_parent_class)->constructed)
|
|
G_OBJECT_CLASS (gdk_device_manager_xi_parent_class)->constructed (object);
|
|
}
|
|
|
|
static void
|
|
gdk_device_manager_xi_dispose (GObject *object)
|
|
{
|
|
GdkDeviceManagerXIPrivate *priv;
|
|
|
|
priv = GDK_DEVICE_MANAGER_XI (object)->priv;
|
|
|
|
g_list_foreach (priv->devices, (GFunc) g_object_unref, NULL);
|
|
g_list_free (priv->devices);
|
|
priv->devices = NULL;
|
|
|
|
if (priv->id_table != NULL)
|
|
{
|
|
g_hash_table_destroy (priv->id_table);
|
|
priv->id_table = NULL;
|
|
}
|
|
|
|
gdk_window_remove_filter (NULL, window_input_info_filter, object);
|
|
|
|
G_OBJECT_CLASS (gdk_device_manager_xi_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
gdk_device_manager_xi_set_property (GObject *object,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GdkDeviceManagerXIPrivate *priv;
|
|
|
|
priv = GDK_DEVICE_MANAGER_XI (object)->priv;
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_EVENT_BASE:
|
|
priv->event_base = g_value_get_int (value);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gdk_device_manager_xi_get_property (GObject *object,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GdkDeviceManagerXIPrivate *priv;
|
|
|
|
priv = GDK_DEVICE_MANAGER_XI (object)->priv;
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_EVENT_BASE:
|
|
g_value_set_int (value, priv->event_base);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gdk_device_manager_xi_event_translator_init (GdkEventTranslatorIface *iface)
|
|
{
|
|
iface->translate_event = gdk_device_manager_xi_translate_event;
|
|
}
|
|
|
|
/* combine the state of the core device and the device state
|
|
* into one - for now we do this in a simple-minded manner -
|
|
* we just take the keyboard portion of the core device and
|
|
* the button portion (all of?) the device state.
|
|
* Any button remapping should go on here.
|
|
*/
|
|
static guint
|
|
translate_state (guint state, guint device_state)
|
|
{
|
|
return device_state | (state & 0xFF);
|
|
}
|
|
|
|
static GdkDevice *
|
|
lookup_device (GdkDeviceManagerXI *device_manager,
|
|
XEvent *xevent)
|
|
{
|
|
GdkDeviceManagerXIPrivate *priv;
|
|
guint32 device_id;
|
|
|
|
priv = GDK_DEVICE_MANAGER_XI (device_manager)->priv;
|
|
|
|
/* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
|
|
but it's potentially faster than scanning through the types of
|
|
every device. If we were deceived, then it won't match any of
|
|
the types for the device anyways */
|
|
device_id = ((XDeviceButtonEvent *)xevent)->deviceid;
|
|
|
|
return g_hash_table_lookup (priv->id_table, GINT_TO_POINTER (device_id));
|
|
}
|
|
|
|
static gboolean
|
|
gdk_device_manager_xi_translate_event (GdkEventTranslator *translator,
|
|
GdkDisplay *display,
|
|
GdkEvent *event,
|
|
XEvent *xevent)
|
|
{
|
|
GdkDeviceManagerXIPrivate *priv;
|
|
GdkDeviceManagerXI *device_manager;
|
|
GdkEventTranslatorIface *parent_iface;
|
|
GdkDeviceXI *device_xi;
|
|
GdkDevice *device;
|
|
GdkWindow *window;
|
|
|
|
parent_iface = g_type_interface_peek_parent (GDK_EVENT_TRANSLATOR_GET_IFACE (translator));
|
|
device_manager = GDK_DEVICE_MANAGER_XI (translator);
|
|
priv = device_manager->priv;
|
|
|
|
if (!priv->ignore_core_events &&
|
|
parent_iface->translate_event (translator, display, event, xevent))
|
|
return TRUE;
|
|
|
|
device = lookup_device (device_manager, xevent);
|
|
device_xi = GDK_DEVICE_XI (device);
|
|
|
|
if (!device)
|
|
return FALSE;
|
|
|
|
window = gdk_window_lookup_for_display (display, xevent->xany.window);
|
|
|
|
if (!window)
|
|
return FALSE;
|
|
|
|
if ((xevent->type == device_xi->button_press_type) ||
|
|
(xevent->type == device_xi->button_release_type))
|
|
{
|
|
XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *) xevent;
|
|
|
|
event->button.type = (xdbe->type == device_xi->button_press_type) ?
|
|
GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE;
|
|
|
|
event->button.device = device;
|
|
event->button.window = g_object_ref (window);
|
|
event->button.time = xdbe->time;
|
|
|
|
event->button.x_root = (gdouble) xdbe->x_root;
|
|
event->button.y_root = (gdouble) xdbe->y_root;
|
|
|
|
event->button.axes = g_new0 (gdouble, device->num_axes);
|
|
gdk_device_xi_update_axes (device, xdbe->axes_count,
|
|
xdbe->first_axis, xdbe->axis_data);
|
|
gdk_device_xi_translate_axes (device, window,
|
|
device_xi->axis_data,
|
|
event->button.axes,
|
|
&event->button.x,
|
|
&event->button.y);
|
|
|
|
event->button.state = translate_state (xdbe->state, xdbe->device_state);
|
|
event->button.button = xdbe->button;
|
|
|
|
if (event->button.type == GDK_BUTTON_PRESS)
|
|
_gdk_event_button_generate (gdk_drawable_get_display (event->button.window),
|
|
event);
|
|
|
|
GDK_NOTE (EVENTS,
|
|
g_print ("button %s:\t\twindow: %ld device: %ld x,y: %f %f button: %d\n",
|
|
(event->button.type == GDK_BUTTON_PRESS) ? "press" : "release",
|
|
xdbe->window,
|
|
xdbe->deviceid,
|
|
event->button.x, event->button.y,
|
|
xdbe->button));
|
|
|
|
/* Update the timestamp of the latest user interaction, if the event has
|
|
* a valid timestamp.
|
|
*/
|
|
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
|
|
gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
|
|
gdk_event_get_time (event));
|
|
return TRUE;
|
|
}
|
|
|
|
if ((xevent->type == device_xi->key_press_type) ||
|
|
(xevent->type == device_xi->key_release_type))
|
|
{
|
|
XDeviceKeyEvent *xdke = (XDeviceKeyEvent *) xevent;
|
|
|
|
GDK_NOTE (EVENTS,
|
|
g_print ("device key %s:\twindow: %ld device: %ld keycode: %d\n",
|
|
(event->key.type == GDK_KEY_PRESS) ? "press" : "release",
|
|
xdke->window,
|
|
xdke->deviceid,
|
|
xdke->keycode));
|
|
|
|
if (xdke->keycode < device_xi->min_keycode ||
|
|
xdke->keycode >= device_xi->min_keycode + device->num_keys)
|
|
{
|
|
g_warning ("Invalid device key code received");
|
|
return FALSE;
|
|
}
|
|
|
|
event->key.keyval = device->keys[xdke->keycode - device_xi->min_keycode].keyval;
|
|
|
|
if (event->key.keyval == 0)
|
|
{
|
|
GDK_NOTE (EVENTS,
|
|
g_print ("\t\ttranslation - NONE\n"));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
event->key.type = (xdke->type == device_xi->key_press_type) ?
|
|
GDK_KEY_PRESS : GDK_KEY_RELEASE;
|
|
|
|
event->key.window = g_object_ref (window);
|
|
event->key.time = xdke->time;
|
|
|
|
event->key.state = translate_state (xdke->state, xdke->device_state)
|
|
| device->keys[xdke->keycode - device_xi->min_keycode].modifiers;
|
|
|
|
/* Add a string translation for the key event */
|
|
if ((event->key.keyval >= 0x20) && (event->key.keyval <= 0xFF))
|
|
{
|
|
event->key.length = 1;
|
|
event->key.string = g_new (gchar, 2);
|
|
event->key.string[0] = (gchar) event->key.keyval;
|
|
event->key.string[1] = 0;
|
|
}
|
|
else
|
|
{
|
|
event->key.length = 0;
|
|
event->key.string = g_new0 (gchar, 1);
|
|
}
|
|
|
|
GDK_NOTE (EVENTS,
|
|
g_print ("\t\ttranslation - keyval: %d modifiers: %#x\n",
|
|
event->key.keyval,
|
|
event->key.state));
|
|
|
|
/* Update the timestamp of the latest user interaction, if the event has
|
|
* a valid timestamp.
|
|
*/
|
|
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
|
|
gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
|
|
gdk_event_get_time (event));
|
|
return TRUE;
|
|
}
|
|
|
|
if (xevent->type == device_xi->motion_notify_type)
|
|
{
|
|
XDeviceMotionEvent *xdme = (XDeviceMotionEvent *) xevent;
|
|
|
|
event->motion.device = device;
|
|
|
|
if (device_xi->in_proximity)
|
|
priv->ignore_core_events = TRUE;
|
|
|
|
event->motion.x_root = (gdouble) xdme->x_root;
|
|
event->motion.y_root = (gdouble) xdme->y_root;
|
|
|
|
event->motion.axes = g_new0 (gdouble, device->num_axes);
|
|
gdk_device_xi_update_axes (device, xdme->axes_count,
|
|
xdme->first_axis, xdme->axis_data);
|
|
gdk_device_xi_translate_axes (device, window,
|
|
device_xi->axis_data,
|
|
event->motion.axes,
|
|
&event->motion.x,
|
|
&event->motion.y);
|
|
|
|
event->motion.type = GDK_MOTION_NOTIFY;
|
|
event->motion.window = g_object_ref (window);
|
|
event->motion.time = xdme->time;
|
|
event->motion.state = translate_state (xdme->state,
|
|
xdme->device_state);
|
|
event->motion.is_hint = xdme->is_hint;
|
|
|
|
GDK_NOTE (EVENTS,
|
|
g_print ("motion notify:\t\twindow: %ld device: %ld x,y: %f %f state %#4x hint: %s\n",
|
|
xdme->window,
|
|
xdme->deviceid,
|
|
event->motion.x, event->motion.y,
|
|
event->motion.state,
|
|
(xdme->is_hint) ? "true" : "false"));
|
|
|
|
|
|
/* Update the timestamp of the latest user interaction, if the event has
|
|
* a valid timestamp.
|
|
*/
|
|
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
|
|
gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
|
|
gdk_event_get_time (event));
|
|
return TRUE;
|
|
}
|
|
|
|
if (xevent->type == device_xi->proximity_in_type ||
|
|
xevent->type == device_xi->proximity_out_type)
|
|
{
|
|
XProximityNotifyEvent *xpne = (XProximityNotifyEvent *) xevent;
|
|
|
|
if (xevent->type == device_xi->proximity_in_type)
|
|
{
|
|
event->proximity.type = GDK_PROXIMITY_IN;
|
|
device_xi->in_proximity = TRUE;
|
|
priv->ignore_core_events = TRUE;
|
|
}
|
|
else
|
|
{
|
|
event->proximity.type = GDK_PROXIMITY_OUT;
|
|
device_xi->in_proximity = FALSE;
|
|
priv->ignore_core_events = FALSE;
|
|
}
|
|
|
|
event->proximity.device = device;
|
|
event->proximity.window = g_object_ref (window);
|
|
event->proximity.time = xpne->time;
|
|
|
|
/* Update the timestamp of the latest user interaction, if the event has
|
|
* a valid timestamp.
|
|
*/
|
|
if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
|
|
gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
|
|
gdk_event_get_time (event));
|
|
return TRUE;
|
|
}
|
|
|
|
if (xevent->type == device_xi->state_notify_type)
|
|
{
|
|
XDeviceStateNotifyEvent *xdse = (XDeviceStateNotifyEvent *) xevent;
|
|
XInputClass *input_class = (XInputClass *) xdse->data;
|
|
int i;
|
|
|
|
for (i = 0; i < xdse->num_classes; i++)
|
|
{
|
|
if (input_class->class == ValuatorClass)
|
|
gdk_device_xi_update_axes (device, device->num_axes, 0,
|
|
((XValuatorState *)input_class)->valuators);
|
|
|
|
input_class = (XInputClass *)(((char *)input_class)+input_class->length);
|
|
}
|
|
|
|
GDK_NOTE (EVENTS,
|
|
g_print ("device state notify:\t\twindow: %ld device: %ld\n",
|
|
xdse->window,
|
|
xdse->deviceid));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static GList *
|
|
gdk_device_manager_xi_list_devices (GdkDeviceManager *device_manager,
|
|
GdkDeviceType type)
|
|
{
|
|
GdkDeviceManagerXIPrivate *priv;
|
|
|
|
priv = GDK_DEVICE_MANAGER_XI (device_manager)->priv;
|
|
|
|
if (type == GDK_DEVICE_TYPE_MASTER)
|
|
return GDK_DEVICE_MANAGER_CLASS (gdk_device_manager_xi_parent_class)->list_devices (device_manager, type);
|
|
else if (type == GDK_DEVICE_TYPE_FLOATING)
|
|
{
|
|
return g_list_copy (priv->devices);
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|