2016-05-02 23:27:57 -04:00
|
|
|
/*
|
|
|
|
* 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: Jonas Ådahl <jadahl@gmail.com>
|
|
|
|
*/
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
#include "config.h"
|
2016-05-02 23:27:57 -04:00
|
|
|
|
|
|
|
#include <glib-object.h>
|
2016-06-22 05:56:44 -04:00
|
|
|
#include <linux/input.h>
|
2016-05-02 23:27:57 -04:00
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
#include "backends/native/meta-input-device-native.h"
|
|
|
|
#include "backends/native/meta-keymap-native.h"
|
|
|
|
#include "backends/native/meta-seat-native.h"
|
|
|
|
#include "backends/native/meta-virtual-input-device-native.h"
|
|
|
|
#include "clutter/clutter-mutter.h"
|
2020-02-18 08:56:25 -05:00
|
|
|
#include "meta/util.h"
|
2016-05-02 23:27:57 -04:00
|
|
|
|
2016-06-22 05:46:25 -04:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
|
|
|
|
PROP_SEAT,
|
|
|
|
|
|
|
|
PROP_LAST
|
|
|
|
};
|
|
|
|
|
|
|
|
static GParamSpec *obj_props[PROP_LAST];
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
struct _MetaVirtualInputDeviceNative
|
2016-05-02 23:27:57 -04:00
|
|
|
{
|
|
|
|
ClutterVirtualInputDevice parent;
|
2016-06-22 05:46:25 -04:00
|
|
|
|
2016-06-22 05:51:38 -04:00
|
|
|
ClutterInputDevice *device;
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaSeatNative *seat;
|
2016-06-22 05:56:44 -04:00
|
|
|
int button_count[KEY_CNT];
|
2016-05-02 23:27:57 -04:00
|
|
|
};
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
G_DEFINE_TYPE (MetaVirtualInputDeviceNative,
|
|
|
|
meta_virtual_input_device_native,
|
2016-05-02 23:27:57 -04:00
|
|
|
CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE)
|
|
|
|
|
2016-06-22 05:56:44 -04:00
|
|
|
typedef enum _EvdevButtonType
|
|
|
|
{
|
|
|
|
EVDEV_BUTTON_TYPE_NONE,
|
|
|
|
EVDEV_BUTTON_TYPE_KEY,
|
|
|
|
EVDEV_BUTTON_TYPE_BUTTON,
|
|
|
|
} EvdevButtonType;
|
|
|
|
|
|
|
|
static int
|
2019-03-29 17:03:27 -04:00
|
|
|
update_button_count (MetaVirtualInputDeviceNative *virtual_evdev,
|
|
|
|
uint32_t button,
|
|
|
|
uint32_t state)
|
2016-06-22 05:56:44 -04:00
|
|
|
{
|
|
|
|
if (state)
|
|
|
|
return ++virtual_evdev->button_count[button];
|
|
|
|
else
|
|
|
|
return --virtual_evdev->button_count[button];
|
|
|
|
}
|
|
|
|
|
|
|
|
static EvdevButtonType
|
|
|
|
get_button_type (uint16_t code)
|
|
|
|
{
|
|
|
|
switch (code)
|
|
|
|
{
|
|
|
|
case BTN_TOOL_PEN:
|
|
|
|
case BTN_TOOL_RUBBER:
|
|
|
|
case BTN_TOOL_BRUSH:
|
|
|
|
case BTN_TOOL_PENCIL:
|
|
|
|
case BTN_TOOL_AIRBRUSH:
|
|
|
|
case BTN_TOOL_MOUSE:
|
|
|
|
case BTN_TOOL_LENS:
|
|
|
|
case BTN_TOOL_QUINTTAP:
|
|
|
|
case BTN_TOOL_DOUBLETAP:
|
|
|
|
case BTN_TOOL_TRIPLETAP:
|
|
|
|
case BTN_TOOL_QUADTAP:
|
|
|
|
case BTN_TOOL_FINGER:
|
|
|
|
case BTN_TOUCH:
|
|
|
|
return EVDEV_BUTTON_TYPE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (code >= KEY_ESC && code <= KEY_MICMUTE)
|
|
|
|
return EVDEV_BUTTON_TYPE_KEY;
|
|
|
|
if (code >= BTN_MISC && code <= BTN_GEAR_UP)
|
|
|
|
return EVDEV_BUTTON_TYPE_BUTTON;
|
|
|
|
if (code >= KEY_OK && code <= KEY_LIGHTS_TOGGLE)
|
|
|
|
return EVDEV_BUTTON_TYPE_KEY;
|
|
|
|
if (code >= BTN_DPAD_UP && code <= BTN_DPAD_RIGHT)
|
|
|
|
return EVDEV_BUTTON_TYPE_BUTTON;
|
|
|
|
if (code >= KEY_ALS_TOGGLE && code <= KEY_KBDINPUTASSIST_CANCEL)
|
|
|
|
return EVDEV_BUTTON_TYPE_KEY;
|
|
|
|
if (code >= BTN_TRIGGER_HAPPY && code <= BTN_TRIGGER_HAPPY40)
|
|
|
|
return EVDEV_BUTTON_TYPE_BUTTON;
|
|
|
|
return EVDEV_BUTTON_TYPE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
release_pressed_buttons (ClutterVirtualInputDevice *virtual_device)
|
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
2016-06-22 05:56:44 -04:00
|
|
|
int code;
|
|
|
|
uint64_t time_us;
|
|
|
|
|
|
|
|
time_us = g_get_monotonic_time ();
|
|
|
|
|
2020-02-18 08:56:25 -05:00
|
|
|
meta_topic (META_DEBUG_INPUT,
|
|
|
|
"Releasing pressed buttons while destroying virtual input device "
|
2020-10-02 11:47:22 -04:00
|
|
|
"(device %p)", virtual_device);
|
2020-02-18 08:56:25 -05:00
|
|
|
|
2016-06-22 05:56:44 -04:00
|
|
|
for (code = 0; code < G_N_ELEMENTS (virtual_evdev->button_count); code++)
|
|
|
|
{
|
|
|
|
if (virtual_evdev->button_count[code] == 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (get_button_type (code))
|
|
|
|
{
|
|
|
|
case EVDEV_BUTTON_TYPE_KEY:
|
2020-05-07 12:20:32 -04:00
|
|
|
meta_seat_native_notify_key (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
time_us,
|
|
|
|
code,
|
|
|
|
CLUTTER_KEY_STATE_RELEASED,
|
|
|
|
TRUE);
|
2016-06-22 05:56:44 -04:00
|
|
|
break;
|
|
|
|
case EVDEV_BUTTON_TYPE_BUTTON:
|
2020-05-07 12:20:32 -04:00
|
|
|
meta_seat_native_notify_button (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
time_us,
|
|
|
|
code,
|
|
|
|
CLUTTER_BUTTON_STATE_RELEASED);
|
2016-06-22 05:56:44 -04:00
|
|
|
break;
|
|
|
|
case EVDEV_BUTTON_TYPE_NONE:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
2020-05-07 12:20:32 -04:00
|
|
|
|
|
|
|
update_button_count (virtual_evdev, code, 0);
|
2016-06-22 05:56:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-02 23:27:57 -04:00
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_notify_relative_motion (ClutterVirtualInputDevice *virtual_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
double dx,
|
|
|
|
double dy)
|
2016-05-02 23:27:57 -04:00
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
2016-06-22 05:52:43 -04:00
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
g_return_if_fail (virtual_evdev->device != NULL);
|
|
|
|
|
2016-08-23 03:36:31 -04:00
|
|
|
if (time_us == CLUTTER_CURRENT_TIME)
|
|
|
|
time_us = g_get_monotonic_time ();
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_seat_native_notify_relative_motion (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
time_us,
|
|
|
|
dx, dy,
|
|
|
|
dx, dy);
|
2016-05-02 23:27:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
double x,
|
|
|
|
double y)
|
2016-05-02 23:27:57 -04:00
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
2016-06-22 05:52:43 -04:00
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
g_return_if_fail (virtual_evdev->device != NULL);
|
|
|
|
|
2016-08-23 03:36:31 -04:00
|
|
|
if (time_us == CLUTTER_CURRENT_TIME)
|
|
|
|
time_us = g_get_monotonic_time ();
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_seat_native_notify_absolute_motion (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
time_us,
|
|
|
|
x, y,
|
|
|
|
NULL);
|
2016-05-02 23:27:57 -04:00
|
|
|
}
|
|
|
|
|
2018-08-06 15:00:23 -04:00
|
|
|
static int
|
|
|
|
translate_to_evdev_button (int clutter_button)
|
|
|
|
{
|
|
|
|
switch (clutter_button)
|
|
|
|
{
|
|
|
|
case CLUTTER_BUTTON_PRIMARY:
|
|
|
|
return BTN_LEFT;
|
|
|
|
case CLUTTER_BUTTON_SECONDARY:
|
|
|
|
return BTN_RIGHT;
|
|
|
|
case CLUTTER_BUTTON_MIDDLE:
|
|
|
|
return BTN_MIDDLE;
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* For compatibility reasons, all additional buttons go after the old
|
|
|
|
* 4-7 scroll ones.
|
|
|
|
*/
|
|
|
|
return clutter_button + (BTN_LEFT - 1) - 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-02 23:27:57 -04:00
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_notify_button (ClutterVirtualInputDevice *virtual_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
uint32_t button,
|
|
|
|
ClutterButtonState button_state)
|
2016-05-02 23:27:57 -04:00
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
2016-06-22 05:56:44 -04:00
|
|
|
int button_count;
|
2018-08-06 15:00:23 -04:00
|
|
|
int evdev_button;
|
2016-06-22 05:56:44 -04:00
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
g_return_if_fail (virtual_evdev->device != NULL);
|
|
|
|
|
2016-08-23 03:36:31 -04:00
|
|
|
if (time_us == CLUTTER_CURRENT_TIME)
|
|
|
|
time_us = g_get_monotonic_time ();
|
|
|
|
|
2018-08-06 15:00:23 -04:00
|
|
|
evdev_button = translate_to_evdev_button (button);
|
|
|
|
|
|
|
|
if (get_button_type (evdev_button) != EVDEV_BUTTON_TYPE_BUTTON)
|
2016-06-22 05:56:44 -04:00
|
|
|
{
|
|
|
|
g_warning ("Unknown/invalid virtual device button 0x%x pressed",
|
2018-08-06 15:00:23 -04:00
|
|
|
evdev_button);
|
2016-06-22 05:56:44 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-08-06 15:00:23 -04:00
|
|
|
button_count = update_button_count (virtual_evdev, evdev_button, button_state);
|
2016-06-22 05:56:44 -04:00
|
|
|
if (button_count < 0 || button_count > 1)
|
|
|
|
{
|
2018-08-06 15:00:23 -04:00
|
|
|
g_warning ("Received multiple virtual 0x%x button %s (ignoring)", evdev_button,
|
2016-06-22 05:56:44 -04:00
|
|
|
button_state == CLUTTER_BUTTON_STATE_PRESSED ? "presses" : "releases");
|
2018-08-06 15:00:23 -04:00
|
|
|
update_button_count (virtual_evdev, evdev_button, 1 - button_state);
|
2016-06-22 05:56:44 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-18 08:56:25 -05:00
|
|
|
meta_topic (META_DEBUG_INPUT,
|
2020-10-02 11:47:22 -04:00
|
|
|
"Emitting virtual button-%s of button 0x%x (device %p)",
|
2020-02-18 08:56:25 -05:00
|
|
|
button_state == CLUTTER_BUTTON_STATE_PRESSED ? "press" : "release",
|
|
|
|
evdev_button, virtual_device);
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_seat_native_notify_button (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
time_us,
|
|
|
|
evdev_button,
|
|
|
|
button_state);
|
2016-05-02 23:27:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_notify_key (ClutterVirtualInputDevice *virtual_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
uint32_t key,
|
|
|
|
ClutterKeyState key_state)
|
2016-05-02 23:27:57 -04:00
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
2016-06-22 05:56:44 -04:00
|
|
|
int key_count;
|
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
g_return_if_fail (virtual_evdev->device != NULL);
|
|
|
|
|
2016-08-23 03:36:31 -04:00
|
|
|
if (time_us == CLUTTER_CURRENT_TIME)
|
|
|
|
time_us = g_get_monotonic_time ();
|
|
|
|
|
2016-06-22 05:56:44 -04:00
|
|
|
if (get_button_type (key) != EVDEV_BUTTON_TYPE_KEY)
|
|
|
|
{
|
2020-10-02 11:54:56 -04:00
|
|
|
g_warning ("Unknown/invalid virtual device key 0x%x pressed", key);
|
2016-06-22 05:56:44 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
key_count = update_button_count (virtual_evdev, key, key_state);
|
|
|
|
if (key_count < 0 || key_count > 1)
|
|
|
|
{
|
|
|
|
g_warning ("Received multiple virtual 0x%x key %s (ignoring)", key,
|
2020-02-19 13:21:32 -05:00
|
|
|
key_state == CLUTTER_KEY_STATE_PRESSED ? "presses" : "releases");
|
2016-06-22 05:56:44 -04:00
|
|
|
update_button_count (virtual_evdev, key, 1 - key_state);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-18 08:56:25 -05:00
|
|
|
meta_topic (META_DEBUG_INPUT,
|
2020-10-02 11:47:22 -04:00
|
|
|
"Emitting virtual key-%s of key 0x%x (device %p)",
|
2020-02-18 08:56:25 -05:00
|
|
|
key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
|
|
|
|
key, virtual_device);
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_seat_native_notify_key (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
time_us,
|
|
|
|
key,
|
|
|
|
key_state,
|
|
|
|
TRUE);
|
2016-05-02 23:27:57 -04:00
|
|
|
}
|
|
|
|
|
2016-07-20 12:03:44 -04:00
|
|
|
static gboolean
|
|
|
|
pick_keycode_for_keyval_in_current_group (ClutterVirtualInputDevice *virtual_device,
|
|
|
|
guint keyval,
|
|
|
|
guint *keycode_out,
|
|
|
|
guint *level_out)
|
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
2019-10-01 11:27:23 -04:00
|
|
|
ClutterBackend *backend;
|
2019-01-10 10:13:20 -05:00
|
|
|
ClutterKeymap *keymap;
|
2016-07-20 12:03:44 -04:00
|
|
|
struct xkb_keymap *xkb_keymap;
|
|
|
|
struct xkb_state *state;
|
|
|
|
guint keycode, layout;
|
|
|
|
xkb_keycode_t min_keycode, max_keycode;
|
|
|
|
|
2019-10-01 11:27:23 -04:00
|
|
|
backend = clutter_get_default_backend ();
|
|
|
|
keymap = clutter_seat_get_keymap (clutter_backend_get_default_seat (backend));
|
2019-03-29 17:03:27 -04:00
|
|
|
xkb_keymap = meta_keymap_native_get_keyboard_map (META_KEYMAP_NATIVE (keymap));
|
2016-07-20 12:03:44 -04:00
|
|
|
state = virtual_evdev->seat->xkb;
|
|
|
|
|
|
|
|
layout = xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE);
|
|
|
|
min_keycode = xkb_keymap_min_keycode (xkb_keymap);
|
|
|
|
max_keycode = xkb_keymap_max_keycode (xkb_keymap);
|
|
|
|
for (keycode = min_keycode; keycode < max_keycode; keycode++)
|
|
|
|
{
|
|
|
|
gint num_levels, level;
|
|
|
|
num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout);
|
|
|
|
for (level = 0; level < num_levels; level++)
|
|
|
|
{
|
|
|
|
const xkb_keysym_t *syms;
|
|
|
|
gint num_syms, sym;
|
|
|
|
num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, keycode, layout, level, &syms);
|
|
|
|
for (sym = 0; sym < num_syms; sym++)
|
|
|
|
{
|
|
|
|
if (syms[sym] == keyval)
|
|
|
|
{
|
|
|
|
*keycode_out = keycode;
|
|
|
|
if (level_out)
|
|
|
|
*level_out = level;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
apply_level_modifiers (ClutterVirtualInputDevice *virtual_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
uint32_t level,
|
|
|
|
uint32_t key_state)
|
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
2016-07-20 12:03:44 -04:00
|
|
|
guint keysym, keycode, evcode;
|
|
|
|
|
|
|
|
if (level == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (level == 1)
|
|
|
|
{
|
|
|
|
keysym = XKB_KEY_Shift_L;
|
|
|
|
}
|
|
|
|
else if (level == 2)
|
|
|
|
{
|
|
|
|
keysym = XKB_KEY_ISO_Level3_Shift;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-10-02 11:54:56 -04:00
|
|
|
g_warning ("Unhandled level: %d", level);
|
2016-07-20 12:03:44 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pick_keycode_for_keyval_in_current_group (virtual_device, keysym,
|
|
|
|
&keycode, NULL))
|
|
|
|
return;
|
|
|
|
|
|
|
|
clutter_input_device_keycode_to_evdev (virtual_evdev->device,
|
|
|
|
keycode, &evcode);
|
2020-02-18 08:56:25 -05:00
|
|
|
|
|
|
|
meta_topic (META_DEBUG_INPUT,
|
2020-10-02 11:47:22 -04:00
|
|
|
"Emitting virtual key-%s of modifier key 0x%x (device %p)",
|
2020-02-18 08:56:25 -05:00
|
|
|
key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
|
|
|
|
evcode, virtual_device);
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_seat_native_notify_key (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
time_us,
|
|
|
|
evcode,
|
|
|
|
key_state,
|
|
|
|
TRUE);
|
2016-07-20 12:03:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_notify_keyval (ClutterVirtualInputDevice *virtual_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
uint32_t keyval,
|
|
|
|
ClutterKeyState key_state)
|
2016-07-20 12:03:44 -04:00
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
2016-07-20 12:03:44 -04:00
|
|
|
int key_count;
|
|
|
|
guint keycode = 0, level = 0, evcode = 0;
|
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
g_return_if_fail (virtual_evdev->device != NULL);
|
|
|
|
|
2016-08-23 03:36:31 -04:00
|
|
|
if (time_us == CLUTTER_CURRENT_TIME)
|
|
|
|
time_us = g_get_monotonic_time ();
|
|
|
|
|
2016-07-20 12:03:44 -04:00
|
|
|
if (!pick_keycode_for_keyval_in_current_group (virtual_device,
|
|
|
|
keyval, &keycode, &level))
|
|
|
|
{
|
|
|
|
g_warning ("No keycode found for keyval %x in current group", keyval);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
clutter_input_device_keycode_to_evdev (virtual_evdev->device,
|
|
|
|
keycode, &evcode);
|
|
|
|
|
|
|
|
if (get_button_type (evcode) != EVDEV_BUTTON_TYPE_KEY)
|
|
|
|
{
|
2020-10-02 11:54:56 -04:00
|
|
|
g_warning ("Unknown/invalid virtual device key 0x%x pressed", evcode);
|
2016-07-20 12:03:44 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
key_count = update_button_count (virtual_evdev, evcode, key_state);
|
|
|
|
if (key_count < 0 || key_count > 1)
|
|
|
|
{
|
2020-02-18 08:58:51 -05:00
|
|
|
g_warning ("Received multiple virtual 0x%x key %s (ignoring)", evcode,
|
|
|
|
key_state == CLUTTER_KEY_STATE_PRESSED ? "presses" : "releases");
|
2016-07-20 12:03:44 -04:00
|
|
|
update_button_count (virtual_evdev, evcode, 1 - key_state);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-02-18 08:56:25 -05:00
|
|
|
meta_topic (META_DEBUG_INPUT,
|
|
|
|
"Emitting virtual key-%s of key 0x%x with modifier level %d, "
|
2020-10-02 11:47:22 -04:00
|
|
|
"press count %d (device %p)",
|
2020-02-18 08:56:25 -05:00
|
|
|
key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
|
|
|
|
evcode, level, key_count, virtual_device);
|
|
|
|
|
2016-07-20 12:03:44 -04:00
|
|
|
if (key_state)
|
|
|
|
apply_level_modifiers (virtual_device, time_us, level, key_state);
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_seat_native_notify_key (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
time_us,
|
|
|
|
evcode,
|
|
|
|
key_state,
|
|
|
|
TRUE);
|
2016-07-20 12:03:44 -04:00
|
|
|
|
|
|
|
if (!key_state)
|
|
|
|
apply_level_modifiers (virtual_device, time_us, level, key_state);
|
|
|
|
}
|
|
|
|
|
2016-08-23 03:39:02 -04:00
|
|
|
static void
|
|
|
|
direction_to_discrete (ClutterScrollDirection direction,
|
|
|
|
double *discrete_dx,
|
|
|
|
double *discrete_dy)
|
|
|
|
{
|
|
|
|
switch (direction)
|
|
|
|
{
|
|
|
|
case CLUTTER_SCROLL_UP:
|
|
|
|
*discrete_dx = 0.0;
|
|
|
|
*discrete_dy = -1.0;
|
|
|
|
break;
|
|
|
|
case CLUTTER_SCROLL_DOWN:
|
|
|
|
*discrete_dx = 0.0;
|
|
|
|
*discrete_dy = 1.0;
|
|
|
|
break;
|
|
|
|
case CLUTTER_SCROLL_LEFT:
|
|
|
|
*discrete_dx = -1.0;
|
|
|
|
*discrete_dy = 0.0;
|
|
|
|
break;
|
|
|
|
case CLUTTER_SCROLL_RIGHT:
|
|
|
|
*discrete_dx = 1.0;
|
|
|
|
*discrete_dy = 0.0;
|
|
|
|
break;
|
|
|
|
case CLUTTER_SCROLL_SMOOTH:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_notify_discrete_scroll (ClutterVirtualInputDevice *virtual_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
ClutterScrollDirection direction,
|
|
|
|
ClutterScrollSource scroll_source)
|
2016-08-23 03:39:02 -04:00
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
2016-08-23 03:39:02 -04:00
|
|
|
double discrete_dx = 0.0, discrete_dy = 0.0;
|
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
g_return_if_fail (virtual_evdev->device != NULL);
|
|
|
|
|
2016-08-23 03:39:02 -04:00
|
|
|
if (time_us == CLUTTER_CURRENT_TIME)
|
|
|
|
time_us = g_get_monotonic_time ();
|
|
|
|
|
|
|
|
direction_to_discrete (direction, &discrete_dx, &discrete_dy);
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_seat_native_notify_discrete_scroll (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
time_us,
|
|
|
|
discrete_dx, discrete_dy,
|
|
|
|
scroll_source);
|
2016-08-23 03:39:02 -04:00
|
|
|
}
|
|
|
|
|
2018-01-29 01:21:11 -05:00
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_notify_scroll_continuous (ClutterVirtualInputDevice *virtual_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
double dx,
|
|
|
|
double dy,
|
|
|
|
ClutterScrollSource scroll_source,
|
|
|
|
ClutterScrollFinishFlags finish_flags)
|
2018-01-29 01:21:11 -05:00
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
2018-01-29 01:21:11 -05:00
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
g_return_if_fail (virtual_evdev->device != NULL);
|
|
|
|
|
2018-01-29 01:21:11 -05:00
|
|
|
if (time_us == CLUTTER_CURRENT_TIME)
|
|
|
|
time_us = g_get_monotonic_time ();
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_seat_native_notify_scroll_continuous (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
time_us,
|
|
|
|
dx, dy,
|
|
|
|
scroll_source,
|
|
|
|
CLUTTER_SCROLL_FINISHED_NONE);
|
2018-01-29 01:21:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_notify_touch_down (ClutterVirtualInputDevice *virtual_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
int device_slot,
|
|
|
|
double x,
|
|
|
|
double y)
|
2018-01-29 01:21:11 -05:00
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
|
|
|
MetaInputDeviceNative *device_evdev =
|
|
|
|
META_INPUT_DEVICE_NATIVE (virtual_evdev->device);
|
|
|
|
MetaTouchState *touch_state;
|
2018-01-29 01:21:11 -05:00
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
g_return_if_fail (virtual_evdev->device != NULL);
|
|
|
|
|
2018-01-29 01:21:11 -05:00
|
|
|
if (time_us == CLUTTER_CURRENT_TIME)
|
|
|
|
time_us = g_get_monotonic_time ();
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
touch_state = meta_input_device_native_acquire_touch_state (device_evdev,
|
|
|
|
device_slot);
|
2018-01-29 01:21:11 -05:00
|
|
|
if (!touch_state)
|
|
|
|
return;
|
|
|
|
|
|
|
|
touch_state->coords.x = x;
|
|
|
|
touch_state->coords.y = y;
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_seat_native_notify_touch_event (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
CLUTTER_TOUCH_BEGIN,
|
|
|
|
time_us,
|
|
|
|
touch_state->seat_slot,
|
|
|
|
touch_state->coords.x,
|
|
|
|
touch_state->coords.y);
|
2018-01-29 01:21:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_notify_touch_motion (ClutterVirtualInputDevice *virtual_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
int device_slot,
|
|
|
|
double x,
|
|
|
|
double y)
|
2018-01-29 01:21:11 -05:00
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
|
|
|
MetaInputDeviceNative *device_evdev =
|
|
|
|
META_INPUT_DEVICE_NATIVE (virtual_evdev->device);
|
|
|
|
MetaTouchState *touch_state;
|
2018-01-29 01:21:11 -05:00
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
g_return_if_fail (virtual_evdev->device != NULL);
|
|
|
|
|
2018-01-29 01:21:11 -05:00
|
|
|
if (time_us == CLUTTER_CURRENT_TIME)
|
|
|
|
time_us = g_get_monotonic_time ();
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
touch_state = meta_input_device_native_lookup_touch_state (device_evdev,
|
|
|
|
device_slot);
|
2018-01-29 01:21:11 -05:00
|
|
|
if (!touch_state)
|
|
|
|
return;
|
|
|
|
|
|
|
|
touch_state->coords.x = x;
|
|
|
|
touch_state->coords.y = y;
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_seat_native_notify_touch_event (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
CLUTTER_TOUCH_BEGIN,
|
|
|
|
time_us,
|
|
|
|
touch_state->seat_slot,
|
|
|
|
touch_state->coords.x,
|
|
|
|
touch_state->coords.y);
|
2018-01-29 01:21:11 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_notify_touch_up (ClutterVirtualInputDevice *virtual_device,
|
|
|
|
uint64_t time_us,
|
|
|
|
int device_slot)
|
2018-01-29 01:21:11 -05:00
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
|
|
|
MetaInputDeviceNative *device_evdev =
|
|
|
|
META_INPUT_DEVICE_NATIVE (virtual_evdev->device);
|
|
|
|
MetaTouchState *touch_state;
|
2018-01-29 01:21:11 -05:00
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
g_return_if_fail (virtual_evdev->device != NULL);
|
|
|
|
|
2018-01-29 01:21:11 -05:00
|
|
|
if (time_us == CLUTTER_CURRENT_TIME)
|
|
|
|
time_us = g_get_monotonic_time ();
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
touch_state = meta_input_device_native_lookup_touch_state (device_evdev,
|
|
|
|
device_slot);
|
2018-01-29 01:21:11 -05:00
|
|
|
if (!touch_state)
|
|
|
|
return;
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_seat_native_notify_touch_event (virtual_evdev->seat,
|
|
|
|
virtual_evdev->device,
|
|
|
|
CLUTTER_TOUCH_BEGIN,
|
|
|
|
time_us,
|
|
|
|
touch_state->seat_slot,
|
|
|
|
touch_state->coords.x,
|
|
|
|
touch_state->coords.y);
|
2018-01-29 01:21:11 -05:00
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_input_device_native_release_touch_state (device_evdev, touch_state);
|
2018-01-29 01:21:11 -05:00
|
|
|
}
|
|
|
|
|
2016-06-22 05:46:25 -04:00
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_get_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
2016-06-22 05:46:25 -04:00
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (object);
|
2016-06-22 05:46:25 -04:00
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_SEAT:
|
|
|
|
g_value_set_pointer (value, virtual_evdev->seat);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_set_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
2016-06-22 05:46:25 -04:00
|
|
|
{
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (object);
|
2016-06-22 05:46:25 -04:00
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
|
|
|
case PROP_SEAT:
|
|
|
|
virtual_evdev->seat = g_value_get_pointer (value);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-22 05:51:38 -04:00
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_constructed (GObject *object)
|
2016-06-22 05:51:38 -04:00
|
|
|
{
|
|
|
|
ClutterVirtualInputDevice *virtual_device =
|
|
|
|
CLUTTER_VIRTUAL_INPUT_DEVICE (object);
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (object);
|
2016-06-22 05:51:38 -04:00
|
|
|
ClutterInputDeviceType device_type;
|
|
|
|
ClutterStage *stage;
|
|
|
|
|
|
|
|
device_type = clutter_virtual_input_device_get_device_type (virtual_device);
|
|
|
|
|
2020-02-18 08:56:25 -05:00
|
|
|
meta_topic (META_DEBUG_INPUT,
|
2020-10-02 11:47:22 -04:00
|
|
|
"Creating new virtual input device of type %d (%p)",
|
2020-02-18 08:56:25 -05:00
|
|
|
device_type, virtual_device);
|
|
|
|
|
2016-06-22 05:51:38 -04:00
|
|
|
virtual_evdev->device =
|
2019-09-25 17:04:25 -04:00
|
|
|
meta_input_device_native_new_virtual (virtual_evdev->seat,
|
2019-03-29 17:03:27 -04:00
|
|
|
device_type,
|
2020-08-31 12:47:23 -04:00
|
|
|
CLUTTER_INPUT_MODE_PHYSICAL);
|
2016-06-22 05:51:38 -04:00
|
|
|
|
2019-09-25 17:04:25 -04:00
|
|
|
stage = meta_seat_native_get_stage (virtual_evdev->seat);
|
2016-06-22 05:51:38 -04:00
|
|
|
_clutter_input_device_set_stage (virtual_evdev->device, stage);
|
2020-02-04 12:06:29 -05:00
|
|
|
|
|
|
|
g_signal_emit_by_name (virtual_evdev->seat,
|
|
|
|
"device-added",
|
|
|
|
virtual_evdev->device);
|
2016-06-22 05:51:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-03-28 06:34:49 -04:00
|
|
|
meta_virtual_input_device_native_dispose (GObject *object)
|
2016-06-22 05:51:38 -04:00
|
|
|
{
|
|
|
|
ClutterVirtualInputDevice *virtual_device =
|
|
|
|
CLUTTER_VIRTUAL_INPUT_DEVICE (object);
|
2019-03-29 17:03:27 -04:00
|
|
|
MetaVirtualInputDeviceNative *virtual_evdev =
|
|
|
|
META_VIRTUAL_INPUT_DEVICE_NATIVE (object);
|
2020-03-28 06:34:49 -04:00
|
|
|
GObjectClass *object_class =
|
|
|
|
G_OBJECT_CLASS (meta_virtual_input_device_native_parent_class);
|
2016-06-22 05:51:38 -04:00
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
if (virtual_evdev->device)
|
|
|
|
{
|
|
|
|
release_pressed_buttons (virtual_device);
|
|
|
|
g_signal_emit_by_name (virtual_evdev->seat,
|
|
|
|
"device-removed",
|
|
|
|
virtual_evdev->device);
|
2020-02-04 12:06:29 -05:00
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
g_clear_object (&virtual_evdev->device);
|
|
|
|
}
|
2016-06-22 05:51:38 -04:00
|
|
|
|
2020-03-28 06:34:49 -04:00
|
|
|
object_class->dispose (object);
|
2016-06-22 05:51:38 -04:00
|
|
|
}
|
|
|
|
|
2016-05-02 23:27:57 -04:00
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_init (MetaVirtualInputDeviceNative *virtual_device_evdev)
|
2016-05-02 23:27:57 -04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-29 17:03:27 -04:00
|
|
|
meta_virtual_input_device_native_class_init (MetaVirtualInputDeviceNativeClass *klass)
|
2016-05-02 23:27:57 -04:00
|
|
|
{
|
2016-06-22 05:46:25 -04:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
2016-05-02 23:27:57 -04:00
|
|
|
ClutterVirtualInputDeviceClass *virtual_input_device_class =
|
|
|
|
CLUTTER_VIRTUAL_INPUT_DEVICE_CLASS (klass);
|
|
|
|
|
2019-03-29 17:03:27 -04:00
|
|
|
object_class->get_property = meta_virtual_input_device_native_get_property;
|
|
|
|
object_class->set_property = meta_virtual_input_device_native_set_property;
|
|
|
|
object_class->constructed = meta_virtual_input_device_native_constructed;
|
2020-03-28 06:34:49 -04:00
|
|
|
object_class->dispose = meta_virtual_input_device_native_dispose;
|
2019-03-29 17:03:27 -04:00
|
|
|
|
|
|
|
virtual_input_device_class->notify_relative_motion = meta_virtual_input_device_native_notify_relative_motion;
|
|
|
|
virtual_input_device_class->notify_absolute_motion = meta_virtual_input_device_native_notify_absolute_motion;
|
|
|
|
virtual_input_device_class->notify_button = meta_virtual_input_device_native_notify_button;
|
|
|
|
virtual_input_device_class->notify_key = meta_virtual_input_device_native_notify_key;
|
|
|
|
virtual_input_device_class->notify_keyval = meta_virtual_input_device_native_notify_keyval;
|
|
|
|
virtual_input_device_class->notify_discrete_scroll = meta_virtual_input_device_native_notify_discrete_scroll;
|
|
|
|
virtual_input_device_class->notify_scroll_continuous = meta_virtual_input_device_native_notify_scroll_continuous;
|
|
|
|
virtual_input_device_class->notify_touch_down = meta_virtual_input_device_native_notify_touch_down;
|
|
|
|
virtual_input_device_class->notify_touch_motion = meta_virtual_input_device_native_notify_touch_motion;
|
|
|
|
virtual_input_device_class->notify_touch_up = meta_virtual_input_device_native_notify_touch_up;
|
2016-06-22 05:46:25 -04:00
|
|
|
|
|
|
|
obj_props[PROP_SEAT] = g_param_spec_pointer ("seat",
|
2019-08-24 10:57:51 -04:00
|
|
|
"Seat",
|
|
|
|
"Seat",
|
2016-06-22 05:46:25 -04:00
|
|
|
CLUTTER_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY);
|
|
|
|
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
2016-05-02 23:27:57 -04:00
|
|
|
}
|