59f1e531f9
When talking to other applications or serializing the modifier state (and in particular when implementing a wayland compositor), the effective modifier state alone is not sufficient, one needs to know the base, latched and locked modifiers. Previously one could do with backend specific functionality such as clutter_device_manager_evdev_get_xkb_state(), but the problem is that the internal data structures are updated as soon as the events are fetched from the upstream source, but the events are reported to the application some time later, and thus the two can get out of sync. This way, on the other hand, the information is cached in the event, and provided to the application with the value that was current when the event was generated. https://bugzilla.gnome.org/show_bug.cgi?id=706494
162 lines
4.3 KiB
C
162 lines
4.3 KiB
C
/*
|
|
* Clutter.
|
|
*
|
|
* An OpenGL based 'interactive canvas' library.
|
|
*
|
|
* Copyright © 2011 Intel Corp.
|
|
*
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "clutter-input-device-xi2.h"
|
|
|
|
#include "clutter-debug.h"
|
|
#include "clutter-device-manager-private.h"
|
|
#include "clutter-event-private.h"
|
|
#include "clutter-private.h"
|
|
#include "clutter-stage-private.h"
|
|
|
|
#include "clutter-backend-x11.h"
|
|
#include "clutter-stage-x11.h"
|
|
|
|
#include <X11/extensions/XInput2.h>
|
|
|
|
typedef struct _ClutterInputDeviceClass ClutterInputDeviceXI2Class;
|
|
|
|
/* a specific XI2 input device */
|
|
struct _ClutterInputDeviceXI2
|
|
{
|
|
ClutterInputDevice device;
|
|
|
|
gint device_id;
|
|
};
|
|
|
|
#define N_BUTTONS 5
|
|
|
|
#define clutter_input_device_xi2_get_type _clutter_input_device_xi2_get_type
|
|
|
|
G_DEFINE_TYPE (ClutterInputDeviceXI2,
|
|
clutter_input_device_xi2,
|
|
CLUTTER_TYPE_INPUT_DEVICE);
|
|
|
|
static void
|
|
clutter_input_device_xi2_constructed (GObject *gobject)
|
|
{
|
|
ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (gobject);
|
|
|
|
g_object_get (gobject, "id", &device_xi2->device_id, NULL);
|
|
|
|
if (G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed)
|
|
G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed (gobject);
|
|
}
|
|
|
|
static gboolean
|
|
clutter_input_device_xi2_keycode_to_evdev (ClutterInputDevice *device,
|
|
guint hardware_keycode,
|
|
guint *evdev_keycode)
|
|
{
|
|
/* When using evdev under X11 the hardware keycodes are the evdev
|
|
keycodes plus 8. I haven't been able to find any documentation to
|
|
know what the +8 is for. FIXME: This should probably verify that
|
|
X server is using evdev. */
|
|
*evdev_keycode = hardware_keycode - 8;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
clutter_input_device_xi2_class_init (ClutterInputDeviceXI2Class *klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_CLASS (klass);
|
|
|
|
gobject_class->constructed = clutter_input_device_xi2_constructed;
|
|
|
|
device_class->keycode_to_evdev = clutter_input_device_xi2_keycode_to_evdev;
|
|
}
|
|
|
|
static void
|
|
clutter_input_device_xi2_init (ClutterInputDeviceXI2 *self)
|
|
{
|
|
}
|
|
|
|
void
|
|
_clutter_input_device_xi2_translate_state (ClutterEvent *event,
|
|
XIModifierState *modifiers_state,
|
|
XIButtonState *buttons_state,
|
|
XIGroupState *group_state)
|
|
{
|
|
guint button = 0;
|
|
guint base = 0;
|
|
guint latched = 0;
|
|
guint locked = 0;
|
|
guint effective;
|
|
|
|
if (modifiers_state)
|
|
{
|
|
base = (guint) modifiers_state->base;
|
|
latched = (guint) modifiers_state->latched;
|
|
locked = (guint) modifiers_state->locked;
|
|
}
|
|
|
|
if (buttons_state)
|
|
{
|
|
int len, i;
|
|
|
|
len = MIN (N_BUTTONS, buttons_state->mask_len * 8);
|
|
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
if (!XIMaskIsSet (buttons_state->mask, i))
|
|
continue;
|
|
|
|
switch (i)
|
|
{
|
|
case 1:
|
|
button |= CLUTTER_BUTTON1_MASK;
|
|
break;
|
|
|
|
case 2:
|
|
button |= CLUTTER_BUTTON2_MASK;
|
|
break;
|
|
|
|
case 3:
|
|
button |= CLUTTER_BUTTON3_MASK;
|
|
break;
|
|
|
|
case 4:
|
|
button |= CLUTTER_BUTTON4_MASK;
|
|
break;
|
|
|
|
case 5:
|
|
button |= CLUTTER_BUTTON5_MASK;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
effective = button | base | latched | locked;
|
|
if (group_state)
|
|
effective |= (group_state->effective) << 13;
|
|
|
|
_clutter_event_set_state_full (event, button, base, latched, locked, effective);
|
|
}
|