2016-06-16 23:36:46 +00:00
|
|
|
/*
|
|
|
|
* Clutter.
|
|
|
|
*
|
|
|
|
* An OpenGL based 'interactive canvas' library.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010 Intel Corp.
|
|
|
|
* Copyright (C) 2014 Jonas Ådahl
|
|
|
|
* Copyright (C) 2016 Red Hat Inc.
|
|
|
|
*
|
|
|
|
* 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: Damien Lespiau <damien.lespiau@intel.com>
|
|
|
|
* Author: Jonas Ådahl <jadahl@gmail.com>
|
|
|
|
*/
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
#include "config.h"
|
2016-06-16 23:36:46 +00:00
|
|
|
|
2016-06-17 21:42:16 +00:00
|
|
|
#include <linux/input.h>
|
2016-08-23 07:38:00 +00:00
|
|
|
#include <math.h>
|
2016-06-17 21:42:16 +00:00
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
#include "backends/native/meta-seat-native.h"
|
|
|
|
#include "backends/native/meta-event-native.h"
|
|
|
|
#include "backends/native/meta-input-device-native.h"
|
|
|
|
#include "backends/native/meta-input-device-tool-native.h"
|
|
|
|
#include "backends/native/meta-keymap-native.h"
|
|
|
|
#include "clutter/clutter-mutter.h"
|
2016-06-16 23:36:46 +00:00
|
|
|
|
|
|
|
/* Try to keep the pointer inside the stage. Hopefully no one is using
|
|
|
|
* this backend with stages smaller than this. */
|
|
|
|
#define INITIAL_POINTER_X 16
|
|
|
|
#define INITIAL_POINTER_Y 16
|
|
|
|
|
2016-06-17 21:42:16 +00:00
|
|
|
#define AUTOREPEAT_VALUE 2
|
|
|
|
|
2016-08-23 07:38:00 +00:00
|
|
|
#define DISCRETE_SCROLL_STEP 10.0
|
|
|
|
|
2017-10-10 16:18:25 +00:00
|
|
|
#ifndef BTN_STYLUS3
|
|
|
|
#define BTN_STYLUS3 0x149 /* Linux 4.15 */
|
|
|
|
#endif
|
|
|
|
|
2016-06-16 23:36:46 +00:00
|
|
|
void
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_set_libinput_seat (MetaSeatNative *seat,
|
|
|
|
struct libinput_seat *libinput_seat)
|
2016-06-16 23:36:46 +00:00
|
|
|
{
|
|
|
|
g_assert (seat->libinput_seat == NULL);
|
|
|
|
|
|
|
|
libinput_seat_ref (libinput_seat);
|
|
|
|
libinput_seat_set_user_data (libinput_seat, seat);
|
|
|
|
seat->libinput_seat = libinput_seat;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_sync_leds (MetaSeatNative *seat)
|
2016-06-16 23:36:46 +00:00
|
|
|
{
|
|
|
|
GSList *iter;
|
2019-03-29 21:03:27 +00:00
|
|
|
MetaInputDeviceNative *device_evdev;
|
2016-06-16 23:36:46 +00:00
|
|
|
int caps_lock, num_lock, scroll_lock;
|
|
|
|
enum libinput_led leds = 0;
|
|
|
|
|
|
|
|
caps_lock = xkb_state_led_index_is_active (seat->xkb, seat->caps_lock_led);
|
|
|
|
num_lock = xkb_state_led_index_is_active (seat->xkb, seat->num_lock_led);
|
|
|
|
scroll_lock = xkb_state_led_index_is_active (seat->xkb, seat->scroll_lock_led);
|
|
|
|
|
|
|
|
if (caps_lock)
|
|
|
|
leds |= LIBINPUT_LED_CAPS_LOCK;
|
|
|
|
if (num_lock)
|
|
|
|
leds |= LIBINPUT_LED_NUM_LOCK;
|
|
|
|
if (scroll_lock)
|
|
|
|
leds |= LIBINPUT_LED_SCROLL_LOCK;
|
|
|
|
|
|
|
|
for (iter = seat->devices; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
device_evdev = iter->data;
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_input_device_native_update_leds (device_evdev, leds);
|
2016-06-16 23:36:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-29 21:03:27 +00:00
|
|
|
clutter_touch_state_free (MetaTouchState *touch_state)
|
2016-06-16 23:36:46 +00:00
|
|
|
{
|
2019-03-29 21:03:27 +00:00
|
|
|
g_slice_free (MetaTouchState, touch_state);
|
2016-06-16 23:36:46 +00:00
|
|
|
}
|
|
|
|
|
2018-01-26 16:25:56 +00:00
|
|
|
static void
|
2019-03-29 21:03:27 +00:00
|
|
|
ensure_seat_slot_allocated (MetaSeatNative *seat,
|
|
|
|
int seat_slot)
|
2018-01-26 16:25:56 +00:00
|
|
|
{
|
|
|
|
if (seat_slot >= seat->n_alloc_touch_states)
|
|
|
|
{
|
|
|
|
const int size_increase = 5;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
seat->n_alloc_touch_states += size_increase;
|
|
|
|
seat->touch_states = g_realloc_n (seat->touch_states,
|
|
|
|
seat->n_alloc_touch_states,
|
2019-03-29 21:03:27 +00:00
|
|
|
sizeof (MetaTouchState *));
|
2018-01-26 16:25:56 +00:00
|
|
|
for (i = 0; i < size_increase; i++)
|
|
|
|
seat->touch_states[seat->n_alloc_touch_states - (i + 1)] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
MetaTouchState *
|
|
|
|
meta_seat_native_acquire_touch_state (MetaSeatNative *seat,
|
|
|
|
int device_slot)
|
2016-06-16 23:36:46 +00:00
|
|
|
{
|
2019-03-29 21:03:27 +00:00
|
|
|
MetaTouchState *touch_state;
|
2018-01-26 16:25:56 +00:00
|
|
|
int seat_slot;
|
2016-06-16 23:36:46 +00:00
|
|
|
|
2018-01-26 16:25:56 +00:00
|
|
|
for (seat_slot = 0; seat_slot < seat->n_alloc_touch_states; seat_slot++)
|
|
|
|
{
|
|
|
|
if (!seat->touch_states[seat_slot])
|
|
|
|
break;
|
|
|
|
}
|
2016-06-16 23:36:46 +00:00
|
|
|
|
2018-01-26 16:25:56 +00:00
|
|
|
ensure_seat_slot_allocated (seat, seat_slot);
|
2016-06-16 23:36:46 +00:00
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
touch_state = g_slice_new0 (MetaTouchState);
|
|
|
|
*touch_state = (MetaTouchState) {
|
2018-01-26 16:25:56 +00:00
|
|
|
.seat = seat,
|
|
|
|
.seat_slot = seat_slot,
|
|
|
|
.device_slot = device_slot,
|
|
|
|
};
|
2016-06-16 23:36:46 +00:00
|
|
|
|
2018-01-26 16:25:56 +00:00
|
|
|
seat->touch_states[seat_slot] = touch_state;
|
|
|
|
|
|
|
|
return touch_state;
|
2016-06-16 23:36:46 +00:00
|
|
|
}
|
|
|
|
|
2018-01-26 16:25:56 +00:00
|
|
|
void
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_release_touch_state (MetaSeatNative *seat,
|
|
|
|
MetaTouchState *touch_state)
|
2016-06-16 23:36:46 +00:00
|
|
|
{
|
2018-01-26 16:25:56 +00:00
|
|
|
g_clear_pointer (&seat->touch_states[touch_state->seat_slot],
|
2018-07-23 17:22:51 +00:00
|
|
|
clutter_touch_state_free);
|
2016-06-16 23:36:46 +00:00
|
|
|
}
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
MetaSeatNative *
|
|
|
|
meta_seat_native_new (MetaDeviceManagerNative *manager_evdev)
|
2016-06-16 23:36:46 +00:00
|
|
|
{
|
|
|
|
ClutterDeviceManager *manager = CLUTTER_DEVICE_MANAGER (manager_evdev);
|
2019-03-29 21:03:27 +00:00
|
|
|
MetaSeatNative *seat;
|
2016-06-16 23:36:46 +00:00
|
|
|
ClutterInputDevice *device;
|
|
|
|
ClutterStage *stage;
|
2019-01-10 15:13:20 +00:00
|
|
|
ClutterKeymap *keymap;
|
|
|
|
struct xkb_keymap *xkb_keymap;
|
2016-06-16 23:36:46 +00:00
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
seat = g_new0 (MetaSeatNative, 1);
|
2016-06-16 23:36:46 +00:00
|
|
|
if (!seat)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
seat->manager_evdev = manager_evdev;
|
2019-03-29 21:03:27 +00:00
|
|
|
device = meta_input_device_native_new_virtual (
|
2016-07-11 16:37:36 +00:00
|
|
|
manager, seat, CLUTTER_POINTER_DEVICE,
|
|
|
|
CLUTTER_INPUT_MODE_MASTER);
|
2019-03-29 21:03:27 +00:00
|
|
|
stage = meta_device_manager_native_get_stage (manager_evdev);
|
2016-06-16 23:36:46 +00:00
|
|
|
_clutter_input_device_set_stage (device, stage);
|
|
|
|
seat->pointer_x = INITIAL_POINTER_X;
|
|
|
|
seat->pointer_y = INITIAL_POINTER_Y;
|
|
|
|
_clutter_input_device_set_coords (device, NULL,
|
|
|
|
seat->pointer_x, seat->pointer_y,
|
|
|
|
NULL);
|
|
|
|
_clutter_device_manager_add_device (manager, device);
|
|
|
|
seat->core_pointer = device;
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
device = meta_input_device_native_new_virtual (
|
2016-07-11 16:37:36 +00:00
|
|
|
manager, seat, CLUTTER_KEYBOARD_DEVICE,
|
|
|
|
CLUTTER_INPUT_MODE_MASTER);
|
2016-06-16 23:36:46 +00:00
|
|
|
_clutter_input_device_set_stage (device, stage);
|
|
|
|
_clutter_device_manager_add_device (manager, device);
|
|
|
|
seat->core_keyboard = device;
|
|
|
|
|
|
|
|
seat->repeat = TRUE;
|
|
|
|
seat->repeat_delay = 250; /* ms */
|
|
|
|
seat->repeat_interval = 33; /* ms */
|
|
|
|
|
2019-01-10 15:13:20 +00:00
|
|
|
keymap = clutter_backend_get_keymap (clutter_get_default_backend ());
|
2019-03-29 21:03:27 +00:00
|
|
|
xkb_keymap = meta_keymap_native_get_keyboard_map (META_KEYMAP_NATIVE (keymap));
|
2019-01-10 15:13:20 +00:00
|
|
|
|
|
|
|
if (xkb_keymap)
|
2016-06-16 23:36:46 +00:00
|
|
|
{
|
2019-01-10 15:13:20 +00:00
|
|
|
seat->xkb = xkb_state_new (xkb_keymap);
|
2016-06-16 23:36:46 +00:00
|
|
|
|
|
|
|
seat->caps_lock_led =
|
2019-01-10 15:13:20 +00:00
|
|
|
xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_CAPS);
|
2016-06-16 23:36:46 +00:00
|
|
|
seat->num_lock_led =
|
2019-01-10 15:13:20 +00:00
|
|
|
xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_NUM);
|
2016-06-16 23:36:46 +00:00
|
|
|
seat->scroll_lock_led =
|
2019-01-10 15:13:20 +00:00
|
|
|
xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL);
|
2016-06-16 23:36:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return seat;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_clear_repeat_timer (MetaSeatNative *seat)
|
2016-06-16 23:36:46 +00:00
|
|
|
{
|
|
|
|
if (seat->repeat_timer)
|
|
|
|
{
|
|
|
|
g_source_remove (seat->repeat_timer);
|
|
|
|
seat->repeat_timer = 0;
|
|
|
|
g_clear_object (&seat->repeat_device);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-17 21:42:16 +00:00
|
|
|
static gboolean
|
|
|
|
keyboard_repeat (gpointer data)
|
|
|
|
{
|
2019-03-29 21:03:27 +00:00
|
|
|
MetaSeatNative *seat = data;
|
2016-06-17 21:42:16 +00:00
|
|
|
GSource *source;
|
|
|
|
|
2016-11-25 11:44:56 +00:00
|
|
|
/* There might be events queued in libinput that could cancel the
|
|
|
|
repeat timer. */
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_device_manager_native_dispatch (seat->manager_evdev);
|
2016-11-25 11:44:56 +00:00
|
|
|
if (!seat->repeat_timer)
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
2016-06-17 21:42:16 +00:00
|
|
|
g_return_val_if_fail (seat->repeat_device != NULL, G_SOURCE_REMOVE);
|
|
|
|
source = g_main_context_find_source_by_id (NULL, seat->repeat_timer);
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_notify_key (seat,
|
|
|
|
seat->repeat_device,
|
|
|
|
g_source_get_time (source),
|
|
|
|
seat->repeat_key,
|
|
|
|
AUTOREPEAT_VALUE,
|
|
|
|
FALSE);
|
2016-06-17 21:42:16 +00:00
|
|
|
|
|
|
|
return G_SOURCE_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
queue_event (ClutterEvent *event)
|
|
|
|
{
|
|
|
|
_clutter_event_push (event, FALSE);
|
|
|
|
}
|
|
|
|
|
2016-06-22 09:55:58 +00:00
|
|
|
static int
|
2019-03-29 21:03:27 +00:00
|
|
|
update_button_count (MetaSeatNative *seat,
|
|
|
|
uint32_t button,
|
|
|
|
uint32_t state)
|
2016-06-22 09:55:58 +00:00
|
|
|
{
|
|
|
|
if (state)
|
|
|
|
{
|
|
|
|
return ++seat->button_count[button];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Handle cases where we newer saw the initial pressed event. */
|
|
|
|
if (seat->button_count[button] == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return --seat->button_count[button];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-17 21:42:16 +00:00
|
|
|
void
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_notify_key (MetaSeatNative *seat,
|
|
|
|
ClutterInputDevice *device,
|
|
|
|
uint64_t time_us,
|
|
|
|
uint32_t key,
|
|
|
|
uint32_t state,
|
|
|
|
gboolean update_keys)
|
2016-06-17 21:42:16 +00:00
|
|
|
{
|
|
|
|
ClutterStage *stage;
|
|
|
|
ClutterEvent *event = NULL;
|
|
|
|
enum xkb_state_component changed_state;
|
|
|
|
|
2016-06-22 09:55:58 +00:00
|
|
|
if (state != AUTOREPEAT_VALUE)
|
|
|
|
{
|
|
|
|
/* Drop any repeated button press (for example from virtual devices. */
|
|
|
|
int count = update_button_count (seat, key, state);
|
|
|
|
if (state && count > 1)
|
|
|
|
return;
|
|
|
|
if (!state && count != 0)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-06-17 21:42:16 +00:00
|
|
|
/* We can drop the event on the floor if no stage has been
|
|
|
|
* associated with the device yet. */
|
|
|
|
stage = _clutter_input_device_get_stage (device);
|
|
|
|
if (stage == NULL)
|
|
|
|
{
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_clear_repeat_timer (seat);
|
2016-06-17 21:42:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
event = meta_key_event_new_from_evdev (device,
|
|
|
|
seat->core_keyboard,
|
|
|
|
stage,
|
|
|
|
seat->xkb,
|
|
|
|
seat->button_state,
|
|
|
|
us2ms (time_us), key, state);
|
|
|
|
meta_event_native_set_event_code (event, key);
|
2016-06-17 21:42:16 +00:00
|
|
|
|
|
|
|
/* We must be careful and not pass multiple releases to xkb, otherwise it gets
|
|
|
|
confused and locks the modifiers */
|
|
|
|
if (state != AUTOREPEAT_VALUE)
|
|
|
|
{
|
|
|
|
changed_state = xkb_state_update_key (seat->xkb,
|
|
|
|
event->key.hardware_keycode,
|
|
|
|
state ? XKB_KEY_DOWN : XKB_KEY_UP);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
changed_state = 0;
|
2018-06-25 15:21:16 +00:00
|
|
|
clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_REPEATED);
|
2016-06-17 21:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
queue_event (event);
|
|
|
|
|
|
|
|
if (update_keys && (changed_state & XKB_STATE_LEDS))
|
2019-01-10 15:13:20 +00:00
|
|
|
{
|
|
|
|
ClutterBackend *backend;
|
|
|
|
|
|
|
|
backend = clutter_get_default_backend ();
|
|
|
|
g_signal_emit_by_name (clutter_backend_get_keymap (backend), "state-changed");
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_sync_leds (seat);
|
|
|
|
meta_input_device_native_a11y_maybe_notify_toggle_keys (META_INPUT_DEVICE_NATIVE (seat->core_keyboard));
|
2019-01-10 15:13:20 +00:00
|
|
|
}
|
2016-06-17 21:42:16 +00:00
|
|
|
|
|
|
|
if (state == 0 || /* key release */
|
|
|
|
!seat->repeat ||
|
|
|
|
!xkb_keymap_key_repeats (xkb_state_get_keymap (seat->xkb),
|
|
|
|
event->key.hardware_keycode))
|
|
|
|
{
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_clear_repeat_timer (seat);
|
2016-06-17 21:42:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state == 1) /* key press */
|
|
|
|
seat->repeat_count = 0;
|
|
|
|
|
|
|
|
seat->repeat_count += 1;
|
|
|
|
seat->repeat_key = key;
|
|
|
|
|
|
|
|
switch (seat->repeat_count)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
guint32 interval;
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_clear_repeat_timer (seat);
|
2016-06-17 21:42:16 +00:00
|
|
|
seat->repeat_device = g_object_ref (device);
|
|
|
|
|
|
|
|
if (seat->repeat_count == 1)
|
|
|
|
interval = seat->repeat_delay;
|
|
|
|
else
|
|
|
|
interval = seat->repeat_interval;
|
|
|
|
|
|
|
|
seat->repeat_timer =
|
|
|
|
clutter_threads_add_timeout_full (CLUTTER_PRIORITY_EVENTS,
|
|
|
|
interval,
|
|
|
|
keyboard_repeat,
|
|
|
|
seat,
|
|
|
|
NULL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static ClutterEvent *
|
2019-03-29 21:03:27 +00:00
|
|
|
new_absolute_motion_event (MetaSeatNative *seat,
|
2016-06-17 21:42:16 +00:00
|
|
|
ClutterInputDevice *input_device,
|
|
|
|
guint64 time_us,
|
|
|
|
gfloat x,
|
|
|
|
gfloat y,
|
|
|
|
gdouble *axes)
|
|
|
|
{
|
|
|
|
ClutterStage *stage = _clutter_input_device_get_stage (input_device);
|
|
|
|
ClutterEvent *event;
|
|
|
|
|
|
|
|
event = clutter_event_new (CLUTTER_MOTION);
|
|
|
|
|
|
|
|
if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
|
2019-03-29 21:03:27 +00:00
|
|
|
{
|
|
|
|
meta_device_manager_native_constrain_pointer (seat->manager_evdev,
|
|
|
|
seat->core_pointer,
|
|
|
|
time_us,
|
|
|
|
seat->pointer_x,
|
|
|
|
seat->pointer_y,
|
|
|
|
&x, &y);
|
|
|
|
}
|
2016-06-17 21:42:16 +00:00
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_event_native_set_time_usec (event, time_us);
|
2016-06-17 21:42:16 +00:00
|
|
|
event->motion.time = us2ms (time_us);
|
|
|
|
event->motion.stage = stage;
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_xkb_translate_state (event, seat->xkb, seat->button_state);
|
2016-06-17 21:42:16 +00:00
|
|
|
event->motion.x = x;
|
|
|
|
event->motion.y = y;
|
|
|
|
event->motion.axes = axes;
|
|
|
|
clutter_event_set_device (event, seat->core_pointer);
|
|
|
|
clutter_event_set_source_device (event, input_device);
|
|
|
|
|
|
|
|
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
|
|
|
{
|
2019-03-29 21:03:27 +00:00
|
|
|
MetaInputDeviceNative *device_evdev =
|
|
|
|
META_INPUT_DEVICE_NATIVE (input_device);
|
2016-06-17 21:42:16 +00:00
|
|
|
|
|
|
|
clutter_event_set_device_tool (event, device_evdev->last_tool);
|
|
|
|
clutter_event_set_device (event, input_device);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
clutter_event_set_device (event, seat->core_pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
|
|
|
|
|
|
|
if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
|
|
|
|
{
|
|
|
|
seat->pointer_x = x;
|
|
|
|
seat->pointer_y = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
return event;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_notify_relative_motion (MetaSeatNative *seat,
|
|
|
|
ClutterInputDevice *input_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
float dx,
|
|
|
|
float dy,
|
|
|
|
float dx_unaccel,
|
|
|
|
float dy_unaccel)
|
2016-06-17 21:42:16 +00:00
|
|
|
{
|
|
|
|
gfloat new_x, new_y;
|
|
|
|
ClutterEvent *event;
|
|
|
|
|
|
|
|
/* We can drop the event on the floor if no stage has been
|
|
|
|
* associated with the device yet. */
|
|
|
|
if (!_clutter_input_device_get_stage (input_device))
|
|
|
|
return;
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_device_manager_native_filter_relative_motion (seat->manager_evdev,
|
|
|
|
input_device,
|
|
|
|
seat->pointer_x,
|
|
|
|
seat->pointer_y,
|
|
|
|
&dx,
|
|
|
|
&dy);
|
2017-02-03 05:02:50 +00:00
|
|
|
|
2016-06-17 21:42:16 +00:00
|
|
|
new_x = seat->pointer_x + dx;
|
|
|
|
new_y = seat->pointer_y + dy;
|
|
|
|
event = new_absolute_motion_event (seat, input_device,
|
|
|
|
time_us, new_x, new_y, NULL);
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_event_native_set_relative_motion (event,
|
|
|
|
dx, dy,
|
|
|
|
dx_unaccel, dy_unaccel);
|
2016-06-17 21:42:16 +00:00
|
|
|
|
|
|
|
queue_event (event);
|
|
|
|
}
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
void
|
|
|
|
meta_seat_native_notify_absolute_motion (MetaSeatNative *seat,
|
|
|
|
ClutterInputDevice *input_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
float x,
|
|
|
|
float y,
|
|
|
|
double *axes)
|
2016-06-17 21:42:16 +00:00
|
|
|
{
|
|
|
|
ClutterEvent *event;
|
|
|
|
|
2016-08-29 15:10:17 +00:00
|
|
|
event = new_absolute_motion_event (seat, input_device, time_us, x, y, axes);
|
2016-06-17 21:42:16 +00:00
|
|
|
|
|
|
|
queue_event (event);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_notify_button (MetaSeatNative *seat,
|
|
|
|
ClutterInputDevice *input_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
uint32_t button,
|
|
|
|
uint32_t state)
|
2016-06-17 21:42:16 +00:00
|
|
|
{
|
2019-03-29 21:03:27 +00:00
|
|
|
MetaInputDeviceNative *device_evdev = (MetaInputDeviceNative *) input_device;
|
2016-06-17 21:42:16 +00:00
|
|
|
ClutterStage *stage;
|
|
|
|
ClutterEvent *event = NULL;
|
|
|
|
gint button_nr;
|
|
|
|
static gint maskmap[8] =
|
|
|
|
{
|
|
|
|
CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON3_MASK, CLUTTER_BUTTON2_MASK,
|
|
|
|
CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0
|
|
|
|
};
|
2016-06-22 09:55:58 +00:00
|
|
|
int button_count;
|
|
|
|
|
|
|
|
/* Drop any repeated button press (for example from virtual devices. */
|
|
|
|
button_count = update_button_count (seat, button, state);
|
|
|
|
if (state && button_count > 1)
|
|
|
|
return;
|
|
|
|
if (!state && button_count != 0)
|
|
|
|
return;
|
2016-06-17 21:42:16 +00:00
|
|
|
|
|
|
|
/* We can drop the event on the floor if no stage has been
|
|
|
|
* associated with the device yet. */
|
|
|
|
stage = _clutter_input_device_get_stage (input_device);
|
|
|
|
if (stage == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* The evdev button numbers don't map sequentially to clutter button
|
|
|
|
* numbers (the right and middle mouse buttons are in the opposite
|
|
|
|
* order) so we'll map them directly with a switch statement */
|
|
|
|
switch (button)
|
|
|
|
{
|
|
|
|
case BTN_LEFT:
|
|
|
|
case BTN_TOUCH:
|
|
|
|
button_nr = CLUTTER_BUTTON_PRIMARY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BTN_RIGHT:
|
|
|
|
case BTN_STYLUS:
|
|
|
|
button_nr = CLUTTER_BUTTON_SECONDARY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BTN_MIDDLE:
|
|
|
|
case BTN_STYLUS2:
|
|
|
|
button_nr = CLUTTER_BUTTON_MIDDLE;
|
|
|
|
break;
|
|
|
|
|
2017-10-10 16:18:25 +00:00
|
|
|
case 0x149: /* BTN_STYLUS3 */
|
|
|
|
button_nr = 8;
|
|
|
|
break;
|
|
|
|
|
2016-06-17 21:42:16 +00:00
|
|
|
default:
|
|
|
|
/* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */
|
|
|
|
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
|
|
|
button_nr = button - BTN_TOOL_PEN + 4;
|
|
|
|
else
|
|
|
|
button_nr = button - (BTN_LEFT - 1) + 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (button_nr < 1 || button_nr > 12)
|
|
|
|
{
|
|
|
|
g_warning ("Unhandled button event 0x%x", button);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state)
|
|
|
|
event = clutter_event_new (CLUTTER_BUTTON_PRESS);
|
|
|
|
else
|
|
|
|
event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
|
|
|
|
|
|
|
|
if (button_nr < G_N_ELEMENTS (maskmap))
|
|
|
|
{
|
|
|
|
/* Update the modifiers */
|
|
|
|
if (state)
|
|
|
|
seat->button_state |= maskmap[button_nr - 1];
|
|
|
|
else
|
|
|
|
seat->button_state &= ~maskmap[button_nr - 1];
|
|
|
|
}
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_event_native_set_time_usec (event, time_us);
|
2016-06-17 21:42:16 +00:00
|
|
|
event->button.time = us2ms (time_us);
|
|
|
|
event->button.stage = CLUTTER_STAGE (stage);
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_xkb_translate_state (event, seat->xkb, seat->button_state);
|
2016-06-17 21:42:16 +00:00
|
|
|
event->button.button = button_nr;
|
|
|
|
|
|
|
|
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
|
|
|
{
|
|
|
|
ClutterPoint point;
|
|
|
|
|
|
|
|
clutter_input_device_get_coords (input_device, NULL, &point);
|
|
|
|
event->button.x = point.x;
|
|
|
|
event->button.y = point.y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
event->button.x = seat->pointer_x;
|
|
|
|
event->button.y = seat->pointer_y;
|
|
|
|
}
|
|
|
|
|
|
|
|
clutter_event_set_device (event, seat->core_pointer);
|
|
|
|
clutter_event_set_source_device (event, input_device);
|
|
|
|
|
2016-10-31 16:43:38 +00:00
|
|
|
if (device_evdev->last_tool)
|
|
|
|
{
|
|
|
|
/* Apply the button event code as per the tool mapping */
|
|
|
|
guint mapped_button;
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
mapped_button = meta_input_device_tool_native_get_button_code (device_evdev->last_tool,
|
|
|
|
button_nr);
|
2016-10-31 16:43:38 +00:00
|
|
|
if (mapped_button != 0)
|
|
|
|
button = mapped_button;
|
|
|
|
}
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_event_native_set_event_code (event, button);
|
2016-06-17 21:42:16 +00:00
|
|
|
|
|
|
|
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
|
|
|
{
|
|
|
|
clutter_event_set_device_tool (event, device_evdev->last_tool);
|
|
|
|
clutter_event_set_device (event, input_device);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
clutter_event_set_device (event, seat->core_pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
|
|
|
|
|
|
|
queue_event (event);
|
|
|
|
}
|
|
|
|
|
2016-08-23 07:38:00 +00:00
|
|
|
static void
|
|
|
|
notify_scroll (ClutterInputDevice *input_device,
|
|
|
|
guint64 time_us,
|
|
|
|
gdouble dx,
|
|
|
|
gdouble dy,
|
|
|
|
ClutterScrollSource scroll_source,
|
|
|
|
ClutterScrollFinishFlags flags,
|
|
|
|
gboolean emulated)
|
|
|
|
{
|
2019-03-29 21:03:27 +00:00
|
|
|
MetaInputDeviceNative *device_evdev;
|
|
|
|
MetaSeatNative *seat;
|
2016-08-23 07:38:00 +00:00
|
|
|
ClutterStage *stage;
|
|
|
|
ClutterEvent *event = NULL;
|
|
|
|
gdouble scroll_factor;
|
|
|
|
|
|
|
|
/* We can drop the event on the floor if no stage has been
|
|
|
|
* associated with the device yet. */
|
|
|
|
stage = _clutter_input_device_get_stage (input_device);
|
|
|
|
if (stage == NULL)
|
|
|
|
return;
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
device_evdev = META_INPUT_DEVICE_NATIVE (input_device);
|
|
|
|
seat = meta_input_device_native_get_seat (device_evdev);
|
2016-08-23 07:38:00 +00:00
|
|
|
|
|
|
|
event = clutter_event_new (CLUTTER_SCROLL);
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_event_native_set_time_usec (event, time_us);
|
2016-08-23 07:38:00 +00:00
|
|
|
event->scroll.time = us2ms (time_us);
|
|
|
|
event->scroll.stage = CLUTTER_STAGE (stage);
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_xkb_translate_state (event, seat->xkb, seat->button_state);
|
2016-08-23 07:38:00 +00:00
|
|
|
|
|
|
|
/* libinput pointer axis events are in pointer motion coordinate space.
|
|
|
|
* To convert to Xi2 discrete step coordinate space, multiply the factor
|
|
|
|
* 1/10. */
|
|
|
|
event->scroll.direction = CLUTTER_SCROLL_SMOOTH;
|
|
|
|
scroll_factor = 1.0 / DISCRETE_SCROLL_STEP;
|
|
|
|
clutter_event_set_scroll_delta (event,
|
|
|
|
scroll_factor * dx,
|
|
|
|
scroll_factor * dy);
|
|
|
|
|
|
|
|
event->scroll.x = seat->pointer_x;
|
|
|
|
event->scroll.y = seat->pointer_y;
|
|
|
|
clutter_event_set_device (event, seat->core_pointer);
|
|
|
|
clutter_event_set_source_device (event, input_device);
|
|
|
|
event->scroll.scroll_source = scroll_source;
|
|
|
|
event->scroll.finish_flags = flags;
|
|
|
|
|
|
|
|
_clutter_event_set_pointer_emulated (event, emulated);
|
|
|
|
|
|
|
|
queue_event (event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
notify_discrete_scroll (ClutterInputDevice *input_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
ClutterScrollDirection direction,
|
|
|
|
ClutterScrollSource scroll_source,
|
|
|
|
gboolean emulated)
|
|
|
|
{
|
2019-03-29 21:03:27 +00:00
|
|
|
MetaInputDeviceNative *device_evdev;
|
|
|
|
MetaSeatNative *seat;
|
2016-08-23 07:38:00 +00:00
|
|
|
ClutterStage *stage;
|
|
|
|
ClutterEvent *event = NULL;
|
|
|
|
|
|
|
|
if (direction == CLUTTER_SCROLL_SMOOTH)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* We can drop the event on the floor if no stage has been
|
|
|
|
* associated with the device yet. */
|
|
|
|
stage = _clutter_input_device_get_stage (input_device);
|
|
|
|
if (stage == NULL)
|
|
|
|
return;
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
device_evdev = META_INPUT_DEVICE_NATIVE (input_device);
|
|
|
|
seat = meta_input_device_native_get_seat (device_evdev);
|
2016-08-23 07:38:00 +00:00
|
|
|
|
|
|
|
event = clutter_event_new (CLUTTER_SCROLL);
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_event_native_set_time_usec (event, time_us);
|
2016-08-23 07:38:00 +00:00
|
|
|
event->scroll.time = us2ms (time_us);
|
|
|
|
event->scroll.stage = CLUTTER_STAGE (stage);
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_xkb_translate_state (event, seat->xkb, seat->button_state);
|
2016-08-23 07:38:00 +00:00
|
|
|
|
|
|
|
event->scroll.direction = direction;
|
|
|
|
|
|
|
|
event->scroll.x = seat->pointer_x;
|
|
|
|
event->scroll.y = seat->pointer_y;
|
|
|
|
clutter_event_set_device (event, seat->core_pointer);
|
|
|
|
clutter_event_set_source_device (event, input_device);
|
|
|
|
event->scroll.scroll_source = scroll_source;
|
|
|
|
|
|
|
|
_clutter_event_set_pointer_emulated (event, emulated);
|
|
|
|
|
|
|
|
queue_event (event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-29 21:03:27 +00:00
|
|
|
check_notify_discrete_scroll (MetaSeatNative *seat,
|
2016-08-23 07:38:00 +00:00
|
|
|
ClutterInputDevice *device,
|
|
|
|
uint64_t time_us,
|
|
|
|
ClutterScrollSource scroll_source)
|
|
|
|
{
|
|
|
|
int i, n_xscrolls, n_yscrolls;
|
|
|
|
|
|
|
|
n_xscrolls = floor (fabs (seat->accum_scroll_dx) / DISCRETE_SCROLL_STEP);
|
|
|
|
n_yscrolls = floor (fabs (seat->accum_scroll_dy) / DISCRETE_SCROLL_STEP);
|
|
|
|
|
|
|
|
for (i = 0; i < n_xscrolls; i++)
|
|
|
|
{
|
|
|
|
notify_discrete_scroll (device, time_us,
|
|
|
|
seat->accum_scroll_dx > 0 ?
|
|
|
|
CLUTTER_SCROLL_RIGHT : CLUTTER_SCROLL_LEFT,
|
|
|
|
scroll_source, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < n_yscrolls; i++)
|
|
|
|
{
|
|
|
|
notify_discrete_scroll (device, time_us,
|
|
|
|
seat->accum_scroll_dy > 0 ?
|
|
|
|
CLUTTER_SCROLL_DOWN : CLUTTER_SCROLL_UP,
|
|
|
|
scroll_source, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
seat->accum_scroll_dx = fmodf (seat->accum_scroll_dx, DISCRETE_SCROLL_STEP);
|
|
|
|
seat->accum_scroll_dy = fmodf (seat->accum_scroll_dy, DISCRETE_SCROLL_STEP);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_notify_scroll_continuous (MetaSeatNative *seat,
|
|
|
|
ClutterInputDevice *input_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
double dx,
|
|
|
|
double dy,
|
|
|
|
ClutterScrollSource scroll_source,
|
|
|
|
ClutterScrollFinishFlags finish_flags)
|
2016-08-23 07:38:00 +00:00
|
|
|
{
|
|
|
|
if (finish_flags & CLUTTER_SCROLL_FINISHED_HORIZONTAL)
|
|
|
|
seat->accum_scroll_dx = 0;
|
|
|
|
else
|
|
|
|
seat->accum_scroll_dx += dx;
|
|
|
|
|
|
|
|
if (finish_flags & CLUTTER_SCROLL_FINISHED_VERTICAL)
|
|
|
|
seat->accum_scroll_dy = 0;
|
|
|
|
else
|
|
|
|
seat->accum_scroll_dy += dy;
|
|
|
|
|
|
|
|
notify_scroll (input_device, time_us, dx, dy, scroll_source,
|
|
|
|
finish_flags, FALSE);
|
|
|
|
check_notify_discrete_scroll (seat, input_device, time_us, scroll_source);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ClutterScrollDirection
|
|
|
|
discrete_to_direction (double discrete_dx,
|
|
|
|
double discrete_dy)
|
|
|
|
{
|
|
|
|
if (discrete_dx > 0)
|
|
|
|
return CLUTTER_SCROLL_RIGHT;
|
|
|
|
else if (discrete_dx < 0)
|
|
|
|
return CLUTTER_SCROLL_LEFT;
|
|
|
|
else if (discrete_dy > 0)
|
|
|
|
return CLUTTER_SCROLL_DOWN;
|
|
|
|
else if (discrete_dy < 0)
|
|
|
|
return CLUTTER_SCROLL_UP;
|
|
|
|
else
|
|
|
|
g_assert_not_reached ();
|
2019-01-24 22:09:15 +00:00
|
|
|
return 0;
|
2016-08-23 07:38:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_notify_discrete_scroll (MetaSeatNative *seat,
|
|
|
|
ClutterInputDevice *input_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
double discrete_dx,
|
|
|
|
double discrete_dy,
|
|
|
|
ClutterScrollSource scroll_source)
|
2016-08-23 07:38:00 +00:00
|
|
|
{
|
|
|
|
notify_scroll (input_device, time_us,
|
|
|
|
discrete_dx * DISCRETE_SCROLL_STEP,
|
|
|
|
discrete_dy * DISCRETE_SCROLL_STEP,
|
|
|
|
scroll_source, CLUTTER_SCROLL_FINISHED_NONE,
|
|
|
|
TRUE);
|
|
|
|
notify_discrete_scroll (input_device, time_us,
|
|
|
|
discrete_to_direction (discrete_dx, discrete_dy),
|
|
|
|
scroll_source, FALSE);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-01-26 16:18:49 +00:00
|
|
|
void
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_notify_touch_event (MetaSeatNative *seat,
|
|
|
|
ClutterInputDevice *input_device,
|
|
|
|
ClutterEventType evtype,
|
|
|
|
uint64_t time_us,
|
|
|
|
int slot,
|
|
|
|
double x,
|
|
|
|
double y)
|
2018-01-26 16:18:49 +00:00
|
|
|
{
|
|
|
|
ClutterStage *stage;
|
|
|
|
ClutterEvent *event = NULL;
|
|
|
|
|
|
|
|
/* We can drop the event on the floor if no stage has been
|
|
|
|
* associated with the device yet. */
|
|
|
|
stage = _clutter_input_device_get_stage (input_device);
|
|
|
|
if (stage == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
event = clutter_event_new (evtype);
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_event_native_set_time_usec (event, time_us);
|
2018-01-26 16:18:49 +00:00
|
|
|
event->touch.time = us2ms (time_us);
|
|
|
|
event->touch.stage = CLUTTER_STAGE (stage);
|
|
|
|
event->touch.x = x;
|
|
|
|
event->touch.y = y;
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_input_device_native_translate_coordinates (input_device, stage,
|
|
|
|
&event->touch.x,
|
|
|
|
&event->touch.y);
|
2018-01-26 16:18:49 +00:00
|
|
|
|
|
|
|
/* "NULL" sequences are special cased in clutter */
|
|
|
|
event->touch.sequence = GINT_TO_POINTER (MAX (1, slot + 1));
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_xkb_translate_state (event, seat->xkb, seat->button_state);
|
2018-01-26 16:18:49 +00:00
|
|
|
|
|
|
|
if (evtype == CLUTTER_TOUCH_BEGIN ||
|
|
|
|
evtype == CLUTTER_TOUCH_UPDATE)
|
|
|
|
event->touch.modifier_state |= CLUTTER_BUTTON1_MASK;
|
|
|
|
|
|
|
|
clutter_event_set_device (event, seat->core_pointer);
|
|
|
|
clutter_event_set_source_device (event, input_device);
|
|
|
|
|
|
|
|
queue_event (event);
|
|
|
|
}
|
|
|
|
|
2016-06-16 23:36:46 +00:00
|
|
|
void
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_free (MetaSeatNative *seat)
|
2016-06-16 23:36:46 +00:00
|
|
|
{
|
|
|
|
GSList *iter;
|
|
|
|
|
|
|
|
for (iter = seat->devices; iter; iter = g_slist_next (iter))
|
|
|
|
{
|
|
|
|
ClutterInputDevice *device = iter->data;
|
|
|
|
|
|
|
|
g_object_unref (device);
|
|
|
|
}
|
|
|
|
g_slist_free (seat->devices);
|
2018-01-26 16:25:56 +00:00
|
|
|
g_free (seat->touch_states);
|
2016-06-16 23:36:46 +00:00
|
|
|
|
|
|
|
xkb_state_unref (seat->xkb);
|
|
|
|
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_clear_repeat_timer (seat);
|
2016-06-16 23:36:46 +00:00
|
|
|
|
|
|
|
if (seat->libinput_seat)
|
|
|
|
libinput_seat_unref (seat->libinput_seat);
|
|
|
|
|
|
|
|
g_free (seat);
|
|
|
|
}
|
|
|
|
|
2018-05-15 11:04:56 +00:00
|
|
|
ClutterInputDevice *
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_get_device (MetaSeatNative *seat,
|
|
|
|
gint id)
|
2018-05-15 11:04:56 +00:00
|
|
|
{
|
|
|
|
ClutterInputDevice *device;
|
|
|
|
GSList *l;
|
|
|
|
|
|
|
|
for (l = seat->devices; l; l = l->next)
|
|
|
|
{
|
|
|
|
device = l->data;
|
|
|
|
|
|
|
|
if (clutter_input_device_get_device_id (device) == id)
|
|
|
|
return device;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-06-16 23:36:46 +00:00
|
|
|
void
|
2019-03-29 21:03:27 +00:00
|
|
|
meta_seat_native_set_stage (MetaSeatNative *seat,
|
|
|
|
ClutterStage *stage)
|
2016-06-16 23:36:46 +00:00
|
|
|
{
|
|
|
|
GSList *l;
|
|
|
|
|
|
|
|
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
|
|
|
_clutter_input_device_set_stage (seat->core_keyboard, stage);
|
|
|
|
|
|
|
|
for (l = seat->devices; l; l = l->next)
|
|
|
|
{
|
|
|
|
ClutterInputDevice *device = l->data;
|
|
|
|
|
|
|
|
_clutter_input_device_set_stage (device, stage);
|
|
|
|
}
|
|
|
|
}
|