backends/native: Make MetaVirtualInputDevice vmethods "async"

These are one-way API calls, that now should get executed in the MetaSeatImpl
context. Use the MetaSeatImpl async task plumbing so that's the case.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1403>
This commit is contained in:
Carlos Garnacho 2020-08-12 17:01:02 +02:00 committed by Marge Bot
parent fd90e41e12
commit fb2440a1cf

View File

@ -41,16 +41,62 @@ enum
static GParamSpec *obj_props[PROP_LAST]; static GParamSpec *obj_props[PROP_LAST];
typedef struct _ImplState ImplState;
struct _ImplState
{
ClutterInputDevice *device;
int button_count[KEY_CNT];
};
struct _MetaVirtualInputDeviceNative struct _MetaVirtualInputDeviceNative
{ {
ClutterVirtualInputDevice parent; ClutterVirtualInputDevice parent;
ClutterInputDevice *device;
MetaSeatNative *seat; MetaSeatNative *seat;
guint slot_base; guint slot_base;
int button_count[KEY_CNT]; ImplState *impl_state;
}; };
typedef struct
{
uint64_t time_us;
double x;
double y;
} MetaVirtualEventMotion;
typedef struct
{
uint64_t time_us;
uint32_t button;
ClutterButtonState button_state;
} MetaVirtualEventButton;
typedef struct
{
uint64_t time_us;
double dx;
double dy;
ClutterScrollDirection direction;
ClutterScrollSource scroll_source;
ClutterScrollFinishFlags finish_flags;
} MetaVirtualEventScroll;
typedef struct
{
uint64_t time_us;
uint32_t key;
ClutterKeyState key_state;
} MetaVirtualEventKey;
typedef struct
{
uint64_t time_us;
int device_slot;
double x;
double y;
} MetaVirtualEventTouch;
G_DEFINE_TYPE (MetaVirtualInputDeviceNative, G_DEFINE_TYPE (MetaVirtualInputDeviceNative,
meta_virtual_input_device_native, meta_virtual_input_device_native,
CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE) CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE)
@ -68,9 +114,9 @@ update_button_count (MetaVirtualInputDeviceNative *virtual_evdev,
uint32_t state) uint32_t state)
{ {
if (state) if (state)
return ++virtual_evdev->button_count[button]; return ++virtual_evdev->impl_state->button_count[button];
else else
return --virtual_evdev->button_count[button]; return --virtual_evdev->impl_state->button_count[button];
} }
static EvdevButtonType static EvdevButtonType
@ -109,38 +155,41 @@ get_button_type (uint16_t code)
return EVDEV_BUTTON_TYPE_NONE; return EVDEV_BUTTON_TYPE_NONE;
} }
static void static gboolean
release_pressed_buttons (ClutterVirtualInputDevice *virtual_device) release_device (GTask *task)
{ {
MetaVirtualInputDeviceNative *virtual_evdev = ImplState *impl_state = g_task_get_task_data (task);
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); MetaInputDeviceNative *device_native;
MetaSeatImpl *seat_impl;
int code; int code;
uint64_t time_us; uint64_t time_us;
device_native = META_INPUT_DEVICE_NATIVE (impl_state->device);
seat_impl = meta_input_device_native_get_seat_impl (device_native);
time_us = g_get_monotonic_time (); time_us = g_get_monotonic_time ();
meta_topic (META_DEBUG_INPUT, meta_topic (META_DEBUG_INPUT,
"Releasing pressed buttons while destroying virtual input device " "Releasing pressed buttons while destroying virtual input device "
"(device %p)", virtual_device); "(device %p)", device_native);
for (code = 0; code < G_N_ELEMENTS (virtual_evdev->button_count); code++) for (code = 0; code < G_N_ELEMENTS (impl_state->button_count); code++)
{ {
if (virtual_evdev->button_count[code] == 0) if (impl_state->button_count[code] == 0)
continue; continue;
switch (get_button_type (code)) switch (get_button_type (code))
{ {
case EVDEV_BUTTON_TYPE_KEY: case EVDEV_BUTTON_TYPE_KEY:
meta_seat_impl_notify_key (virtual_evdev->seat->impl, meta_seat_impl_notify_key (seat_impl,
virtual_evdev->device, impl_state->device,
time_us, time_us,
code, code,
CLUTTER_KEY_STATE_RELEASED, CLUTTER_KEY_STATE_RELEASED,
TRUE); TRUE);
break; break;
case EVDEV_BUTTON_TYPE_BUTTON: case EVDEV_BUTTON_TYPE_BUTTON:
meta_seat_impl_notify_button (virtual_evdev->seat->impl, meta_seat_impl_notify_button (seat_impl,
virtual_evdev->device, impl_state->device,
time_us, time_us,
code, code,
CLUTTER_BUTTON_STATE_RELEASED); CLUTTER_BUTTON_STATE_RELEASED);
@ -148,9 +197,32 @@ release_pressed_buttons (ClutterVirtualInputDevice *virtual_device)
case EVDEV_BUTTON_TYPE_NONE: case EVDEV_BUTTON_TYPE_NONE:
g_assert_not_reached (); g_assert_not_reached ();
} }
update_button_count (virtual_evdev, code, 0);
} }
g_clear_object (&impl_state->device);
g_task_return_boolean (task, TRUE);
return G_SOURCE_REMOVE;
}
static gboolean
notify_relative_motion (GTask *task)
{
MetaVirtualInputDeviceNative *virtual_evdev =
g_task_get_source_object (task);
MetaSeatImpl *seat = virtual_evdev->seat->impl;
MetaVirtualEventMotion *event = g_task_get_task_data (task);
if (event->time_us == CLUTTER_CURRENT_TIME)
event->time_us = g_get_monotonic_time ();
meta_seat_impl_notify_relative_motion (seat,
virtual_evdev->impl_state->device,
event->time_us,
event->x, event->y,
event->x, event->y);
g_task_return_boolean (task, TRUE);
return G_SOURCE_REMOVE;
} }
static void static void
@ -159,19 +231,43 @@ meta_virtual_input_device_native_notify_relative_motion (ClutterVirtualInputDevi
double dx, double dx,
double dy) double dy)
{ {
MetaVirtualEventMotion *event;
MetaVirtualInputDeviceNative *virtual_evdev = MetaVirtualInputDeviceNative *virtual_evdev =
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
GTask *task;
g_return_if_fail (virtual_evdev->device != NULL); g_return_if_fail (virtual_evdev->impl_state->device != NULL);
if (time_us == CLUTTER_CURRENT_TIME) event = g_new0 (MetaVirtualEventMotion, 1);
time_us = g_get_monotonic_time (); event->time_us = time_us;
event->x = dx;
event->y = dy;
meta_seat_impl_notify_relative_motion (virtual_evdev->seat->impl, task = g_task_new (virtual_device, NULL, NULL, NULL);
virtual_evdev->device, g_task_set_task_data (task, event, g_free);
time_us, meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
dx, dy, (GSourceFunc) notify_relative_motion);
dx, dy); g_object_unref (task);
}
static gboolean
notify_absolute_motion (GTask *task)
{
MetaVirtualInputDeviceNative *virtual_evdev =
g_task_get_source_object (task);
MetaSeatImpl *seat = virtual_evdev->seat->impl;
MetaVirtualEventMotion *event = g_task_get_task_data (task);
if (event->time_us == CLUTTER_CURRENT_TIME)
event->time_us = g_get_monotonic_time ();
meta_seat_impl_notify_absolute_motion (seat,
virtual_evdev->impl_state->device,
event->time_us,
event->x, event->y,
NULL);
g_task_return_boolean (task, TRUE);
return G_SOURCE_REMOVE;
} }
static void static void
@ -180,19 +276,23 @@ meta_virtual_input_device_native_notify_absolute_motion (ClutterVirtualInputDevi
double x, double x,
double y) double y)
{ {
MetaVirtualEventMotion *event;
MetaVirtualInputDeviceNative *virtual_evdev = MetaVirtualInputDeviceNative *virtual_evdev =
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
GTask *task;
g_return_if_fail (virtual_evdev->device != NULL); g_return_if_fail (virtual_evdev->impl_state->device != NULL);
if (time_us == CLUTTER_CURRENT_TIME) event = g_new0 (MetaVirtualEventMotion, 1);
time_us = g_get_monotonic_time (); event->time_us = time_us;
event->x = x;
event->y = y;
meta_seat_impl_notify_absolute_motion (virtual_evdev->seat->impl, task = g_task_new (virtual_device, NULL, NULL, NULL);
virtual_evdev->device, g_task_set_task_data (task, event, g_free);
time_us, meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
x, y, (GSourceFunc) notify_absolute_motion);
NULL); g_object_unref (task);
} }
static int static int
@ -215,50 +315,123 @@ translate_to_evdev_button (int clutter_button)
} }
} }
static gboolean
notify_button (GTask *task)
{
MetaVirtualInputDeviceNative *virtual_evdev =
g_task_get_source_object (task);
MetaSeatImpl *seat = virtual_evdev->seat->impl;
MetaVirtualEventButton *event = g_task_get_task_data (task);
int button_count;
int evdev_button;
if (event->time_us == CLUTTER_CURRENT_TIME)
event->time_us = g_get_monotonic_time ();
evdev_button = translate_to_evdev_button (event->button);
if (get_button_type (evdev_button) != EVDEV_BUTTON_TYPE_BUTTON)
{
g_warning ("Unknown/invalid virtual device button 0x%x pressed",
evdev_button);
goto out;
}
button_count = update_button_count (virtual_evdev, evdev_button,
event->button_state);
if (button_count < 0 || button_count > 1)
{
g_warning ("Received multiple virtual 0x%x button %s (ignoring)", evdev_button,
event->button_state == CLUTTER_BUTTON_STATE_PRESSED ?
"presses" : "releases");
update_button_count (virtual_evdev, evdev_button, 1 - event->button_state);
goto out;
}
meta_topic (META_DEBUG_INPUT,
"Emitting virtual button-%s of button 0x%x (device %p)",
event->button_state == CLUTTER_BUTTON_STATE_PRESSED ?
"press" : "release",
evdev_button, virtual_evdev);
meta_seat_impl_notify_button (seat,
virtual_evdev->impl_state->device,
event->time_us,
evdev_button,
event->button_state);
out:
g_task_return_boolean (task, TRUE);
return G_SOURCE_REMOVE;
}
static void static void
meta_virtual_input_device_native_notify_button (ClutterVirtualInputDevice *virtual_device, meta_virtual_input_device_native_notify_button (ClutterVirtualInputDevice *virtual_device,
uint64_t time_us, uint64_t time_us,
uint32_t button, uint32_t button,
ClutterButtonState button_state) ClutterButtonState button_state)
{ {
MetaVirtualEventButton *event;
MetaVirtualInputDeviceNative *virtual_evdev = MetaVirtualInputDeviceNative *virtual_evdev =
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
int button_count; GTask *task;
int evdev_button;
g_return_if_fail (virtual_evdev->device != NULL); g_return_if_fail (virtual_evdev->impl_state->device != NULL);
if (time_us == CLUTTER_CURRENT_TIME) event = g_new0 (MetaVirtualEventButton, 1);
time_us = g_get_monotonic_time (); event->time_us = time_us;
event->button = button;
event->button_state = button_state;
evdev_button = translate_to_evdev_button (button); task = g_task_new (virtual_device, NULL, NULL, NULL);
g_task_set_task_data (task, event, g_free);
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
(GSourceFunc) notify_button);
g_object_unref (task);
}
if (get_button_type (evdev_button) != EVDEV_BUTTON_TYPE_BUTTON) static gboolean
notify_key (GTask *task)
{
MetaVirtualInputDeviceNative *virtual_evdev =
g_task_get_source_object (task);
MetaSeatImpl *seat = virtual_evdev->seat->impl;
MetaVirtualEventKey *event = g_task_get_task_data (task);
int key_count;
if (event->time_us == CLUTTER_CURRENT_TIME)
event->time_us = g_get_monotonic_time ();
if (get_button_type (event->key) != EVDEV_BUTTON_TYPE_KEY)
{ {
g_warning ("Unknown/invalid virtual device button 0x%x pressed", g_warning ("Unknown/invalid virtual device key 0x%x pressed", event->key);
evdev_button); goto out;
return;
} }
button_count = update_button_count (virtual_evdev, evdev_button, button_state); key_count = update_button_count (virtual_evdev, event->key, event->key_state);
if (button_count < 0 || button_count > 1) if (key_count < 0 || key_count > 1)
{ {
g_warning ("Received multiple virtual 0x%x button %s (ignoring)", evdev_button, g_warning ("Received multiple virtual 0x%x key %s (ignoring)", event->key,
button_state == CLUTTER_BUTTON_STATE_PRESSED ? "presses" : "releases"); event->key_state == CLUTTER_KEY_STATE_PRESSED ?
update_button_count (virtual_evdev, evdev_button, 1 - button_state); "presses" : "releases");
return; update_button_count (virtual_evdev, event->key, 1 - event->key_state);
goto out;
} }
meta_topic (META_DEBUG_INPUT, meta_topic (META_DEBUG_INPUT,
"Emitting virtual button-%s of button 0x%x (device %p)", "Emitting virtual key-%s of key 0x%x (device %p)",
button_state == CLUTTER_BUTTON_STATE_PRESSED ? "press" : "release", event->key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
evdev_button, virtual_device); event->key, virtual_evdev);
meta_seat_impl_notify_button (virtual_evdev->seat->impl, meta_seat_impl_notify_key (seat,
virtual_evdev->device, virtual_evdev->impl_state->device,
time_us, event->time_us,
evdev_button, event->key,
button_state); event->key_state,
TRUE);
out:
g_task_return_boolean (task, TRUE);
return G_SOURCE_REMOVE;
} }
static void static void
@ -267,41 +440,23 @@ meta_virtual_input_device_native_notify_key (ClutterVirtualInputDevice *virtual_
uint32_t key, uint32_t key,
ClutterKeyState key_state) ClutterKeyState key_state)
{ {
MetaVirtualEventKey *event;
MetaVirtualInputDeviceNative *virtual_evdev = MetaVirtualInputDeviceNative *virtual_evdev =
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
int key_count; GTask *task;
g_return_if_fail (virtual_evdev->device != NULL); g_return_if_fail (virtual_evdev->impl_state->device != NULL);
if (time_us == CLUTTER_CURRENT_TIME) event = g_new0 (MetaVirtualEventKey, 1);
time_us = g_get_monotonic_time (); event->time_us = time_us;
event->key = key;
event->key_state = key_state;
if (get_button_type (key) != EVDEV_BUTTON_TYPE_KEY) task = g_task_new (virtual_device, NULL, NULL, NULL);
{ g_task_set_task_data (task, event, g_free);
g_warning ("Unknown/invalid virtual device key 0x%x pressed", key); meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
return; (GSourceFunc) notify_key);
} g_object_unref (task);
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,
key_state == CLUTTER_KEY_STATE_PRESSED ? "presses" : "releases");
update_button_count (virtual_evdev, key, 1 - key_state);
return;
}
meta_topic (META_DEBUG_INPUT,
"Emitting virtual key-%s of key 0x%x (device %p)",
key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
key, virtual_device);
meta_seat_impl_notify_key (virtual_evdev->seat->impl,
virtual_evdev->device,
time_us,
key,
key_state,
TRUE);
} }
static gboolean static gboolean
@ -383,7 +538,7 @@ apply_level_modifiers (ClutterVirtualInputDevice *virtual_device,
&keycode, NULL)) &keycode, NULL))
return; return;
clutter_input_device_keycode_to_evdev (virtual_evdev->device, clutter_input_device_keycode_to_evdev (virtual_evdev->impl_state->device,
keycode, &evcode); keycode, &evcode);
meta_topic (META_DEBUG_INPUT, meta_topic (META_DEBUG_INPUT,
@ -392,72 +547,101 @@ apply_level_modifiers (ClutterVirtualInputDevice *virtual_device,
evcode, virtual_device); evcode, virtual_device);
meta_seat_impl_notify_key (virtual_evdev->seat->impl, meta_seat_impl_notify_key (virtual_evdev->seat->impl,
virtual_evdev->device, virtual_evdev->impl_state->device,
time_us, time_us,
evcode, evcode,
key_state, key_state,
TRUE); TRUE);
} }
static gboolean
notify_keyval (GTask *task)
{
MetaVirtualInputDeviceNative *virtual_evdev =
g_task_get_source_object (task);
ClutterVirtualInputDevice *virtual_device =
CLUTTER_VIRTUAL_INPUT_DEVICE (virtual_evdev);
MetaSeatImpl *seat = virtual_evdev->seat->impl;
MetaVirtualEventKey *event = g_task_get_task_data (task);
int key_count;
guint keycode = 0, level = 0, evcode = 0;
if (event->time_us == CLUTTER_CURRENT_TIME)
event->time_us = g_get_monotonic_time ();
if (!pick_keycode_for_keyval_in_current_group (virtual_device,
event->key, &keycode, &level))
{
g_warning ("No keycode found for keyval %x in current group", event->key);
goto out;
}
clutter_input_device_keycode_to_evdev (virtual_evdev->impl_state->device,
keycode, &evcode);
if (get_button_type (evcode) != EVDEV_BUTTON_TYPE_KEY)
{
g_warning ("Unknown/invalid virtual device key 0x%x pressed", evcode);
goto out;
}
key_count = update_button_count (virtual_evdev, evcode, event->key_state);
if (key_count < 0 || key_count > 1)
{
g_warning ("Received multiple virtual 0x%x key %s (ignoring)", evcode,
event->key_state == CLUTTER_KEY_STATE_PRESSED ?
"presses" : "releases");
update_button_count (virtual_evdev, evcode, 1 - event->key_state);
goto out;
}
meta_topic (META_DEBUG_INPUT,
"Emitting virtual key-%s of key 0x%x with modifier level %d, "
"press count %d (device %p)",
event->key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
evcode, level, key_count, virtual_evdev);
if (event->key_state)
apply_level_modifiers (virtual_device, event->time_us, level, event->key_state);
meta_seat_impl_notify_key (seat,
virtual_evdev->impl_state->device,
event->time_us,
evcode,
event->key_state,
TRUE);
if (!event->key_state)
apply_level_modifiers (virtual_device, event->time_us, level, event->key_state);
out:
g_task_return_boolean (task, TRUE);
return G_SOURCE_REMOVE;
}
static void static void
meta_virtual_input_device_native_notify_keyval (ClutterVirtualInputDevice *virtual_device, meta_virtual_input_device_native_notify_keyval (ClutterVirtualInputDevice *virtual_device,
uint64_t time_us, uint64_t time_us,
uint32_t keyval, uint32_t keyval,
ClutterKeyState key_state) ClutterKeyState key_state)
{ {
MetaVirtualEventKey *event;
MetaVirtualInputDeviceNative *virtual_evdev = MetaVirtualInputDeviceNative *virtual_evdev =
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
int key_count; GTask *task;
guint keycode = 0, level = 0, evcode = 0;
g_return_if_fail (virtual_evdev->device != NULL); g_return_if_fail (virtual_evdev->impl_state->device != NULL);
if (time_us == CLUTTER_CURRENT_TIME) event = g_new0 (MetaVirtualEventKey, 1);
time_us = g_get_monotonic_time (); event->time_us = time_us;
event->key = keyval;
event->key_state = key_state;
if (!pick_keycode_for_keyval_in_current_group (virtual_device, task = g_task_new (virtual_device, NULL, NULL, NULL);
keyval, &keycode, &level)) g_task_set_task_data (task, event, g_free);
{ meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
g_warning ("No keycode found for keyval %x in current group", keyval); (GSourceFunc) notify_keyval);
return; g_object_unref (task);
}
clutter_input_device_keycode_to_evdev (virtual_evdev->device,
keycode, &evcode);
if (get_button_type (evcode) != EVDEV_BUTTON_TYPE_KEY)
{
g_warning ("Unknown/invalid virtual device key 0x%x pressed", evcode);
return;
}
key_count = update_button_count (virtual_evdev, evcode, key_state);
if (key_count < 0 || key_count > 1)
{
g_warning ("Received multiple virtual 0x%x key %s (ignoring)", evcode,
key_state == CLUTTER_KEY_STATE_PRESSED ? "presses" : "releases");
update_button_count (virtual_evdev, evcode, 1 - key_state);
return;
}
meta_topic (META_DEBUG_INPUT,
"Emitting virtual key-%s of key 0x%x with modifier level %d, "
"press count %d (device %p)",
key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
evcode, level, key_count, virtual_device);
if (key_state)
apply_level_modifiers (virtual_device, time_us, level, key_state);
meta_seat_impl_notify_key (virtual_evdev->seat->impl,
virtual_evdev->device,
time_us,
evcode,
key_state,
TRUE);
if (!key_state)
apply_level_modifiers (virtual_device, time_us, level, key_state);
} }
static void static void
@ -489,28 +673,74 @@ direction_to_discrete (ClutterScrollDirection direction,
} }
} }
static gboolean
notify_discrete_scroll (GTask *task)
{
MetaVirtualInputDeviceNative *virtual_evdev =
g_task_get_source_object (task);
MetaSeatImpl *seat = virtual_evdev->seat->impl;
MetaVirtualEventScroll *event = g_task_get_task_data (task);
double discrete_dx = 0.0, discrete_dy = 0.0;
if (event->time_us == CLUTTER_CURRENT_TIME)
event->time_us = g_get_monotonic_time ();
direction_to_discrete (event->direction, &discrete_dx, &discrete_dy);
meta_seat_impl_notify_discrete_scroll (seat,
virtual_evdev->impl_state->device,
event->time_us,
discrete_dx, discrete_dy,
event->scroll_source);
g_task_return_boolean (task, TRUE);
return G_SOURCE_REMOVE;
}
static void static void
meta_virtual_input_device_native_notify_discrete_scroll (ClutterVirtualInputDevice *virtual_device, meta_virtual_input_device_native_notify_discrete_scroll (ClutterVirtualInputDevice *virtual_device,
uint64_t time_us, uint64_t time_us,
ClutterScrollDirection direction, ClutterScrollDirection direction,
ClutterScrollSource scroll_source) ClutterScrollSource scroll_source)
{ {
MetaVirtualEventScroll *event;
MetaVirtualInputDeviceNative *virtual_evdev = MetaVirtualInputDeviceNative *virtual_evdev =
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
double discrete_dx = 0.0, discrete_dy = 0.0; GTask *task;
g_return_if_fail (virtual_evdev->device != NULL); g_return_if_fail (virtual_evdev->impl_state->device != NULL);
if (time_us == CLUTTER_CURRENT_TIME) event = g_new0 (MetaVirtualEventScroll, 1);
time_us = g_get_monotonic_time (); event->time_us = time_us;
event->direction = direction;
event->scroll_source = scroll_source;
direction_to_discrete (direction, &discrete_dx, &discrete_dy); task = g_task_new (virtual_device, NULL, NULL, NULL);
g_task_set_task_data (task, event, g_free);
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
(GSourceFunc) notify_discrete_scroll);
g_object_unref (task);
}
meta_seat_impl_notify_discrete_scroll (virtual_evdev->seat->impl, static gboolean
virtual_evdev->device, notify_scroll_continuous (GTask *task)
time_us, {
discrete_dx, discrete_dy, MetaVirtualInputDeviceNative *virtual_evdev =
scroll_source); g_task_get_source_object (task);
MetaSeatImpl *seat = virtual_evdev->seat->impl;
MetaVirtualEventScroll *event = g_task_get_task_data (task);
if (event->time_us == CLUTTER_CURRENT_TIME)
event->time_us = g_get_monotonic_time ();
meta_seat_impl_notify_scroll_continuous (seat,
virtual_evdev->impl_state->device,
event->time_us,
event->dx, event->dy,
event->scroll_source,
CLUTTER_SCROLL_FINISHED_NONE);
g_task_return_boolean (task, TRUE);
return G_SOURCE_REMOVE;
} }
static void static void
@ -521,20 +751,58 @@ meta_virtual_input_device_native_notify_scroll_continuous (ClutterVirtualInputDe
ClutterScrollSource scroll_source, ClutterScrollSource scroll_source,
ClutterScrollFinishFlags finish_flags) ClutterScrollFinishFlags finish_flags)
{ {
MetaVirtualEventScroll *event;
MetaVirtualInputDeviceNative *virtual_evdev = MetaVirtualInputDeviceNative *virtual_evdev =
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
GTask *task;
g_return_if_fail (virtual_evdev->device != NULL); g_return_if_fail (virtual_evdev->impl_state->device != NULL);
if (time_us == CLUTTER_CURRENT_TIME) event = g_new0 (MetaVirtualEventScroll, 1);
time_us = g_get_monotonic_time (); event->time_us = time_us;
event->dx = dx;
event->dy = dy;
event->scroll_source = scroll_source;
event->finish_flags = finish_flags;
meta_seat_impl_notify_scroll_continuous (virtual_evdev->seat->impl, task = g_task_new (virtual_device, NULL, NULL, NULL);
virtual_evdev->device, g_task_set_task_data (task, event, g_free);
time_us, meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
dx, dy, (GSourceFunc) notify_scroll_continuous);
scroll_source, g_object_unref (task);
CLUTTER_SCROLL_FINISHED_NONE); }
static gboolean
notify_touch_down (GTask *task)
{
MetaVirtualInputDeviceNative *virtual_evdev =
g_task_get_source_object (task);
MetaSeatImpl *seat = virtual_evdev->seat->impl;
MetaVirtualEventTouch *event = g_task_get_task_data (task);
MetaTouchState *touch_state;
if (event->time_us == CLUTTER_CURRENT_TIME)
event->time_us = g_get_monotonic_time ();
touch_state = meta_seat_impl_acquire_touch_state (seat,
event->device_slot);
if (!touch_state)
goto out;
touch_state->coords.x = event->x;
touch_state->coords.y = event->y;
meta_seat_impl_notify_touch_event (seat,
virtual_evdev->impl_state->device,
CLUTTER_TOUCH_BEGIN,
event->time_us,
touch_state->seat_slot,
touch_state->coords.x,
touch_state->coords.y);
out:
g_task_return_boolean (task, TRUE);
return G_SOURCE_REMOVE;
} }
static void static void
@ -544,32 +812,57 @@ meta_virtual_input_device_native_notify_touch_down (ClutterVirtualInputDevice *v
double x, double x,
double y) double y)
{ {
MetaVirtualEventTouch *event;
MetaVirtualInputDeviceNative *virtual_evdev = MetaVirtualInputDeviceNative *virtual_evdev =
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
GTask *task;
g_return_if_fail (virtual_evdev->impl_state->device != NULL);
event = g_new0 (MetaVirtualEventTouch, 1);
event->time_us = time_us;
event->device_slot = virtual_evdev->slot_base + (guint) device_slot;
event->x = x;
event->y = y;
task = g_task_new (virtual_device, NULL, NULL, NULL);
g_task_set_task_data (task, event, g_free);
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
(GSourceFunc) notify_touch_down);
g_object_unref (task);
}
static gboolean
notify_touch_motion (GTask *task)
{
MetaVirtualInputDeviceNative *virtual_evdev =
g_task_get_source_object (task);
MetaSeatImpl *seat = virtual_evdev->seat->impl;
MetaVirtualEventTouch *event = g_task_get_task_data (task);
MetaTouchState *touch_state; MetaTouchState *touch_state;
guint seat_slot;
g_return_if_fail (virtual_evdev->device != NULL); if (event->time_us == CLUTTER_CURRENT_TIME)
event->time_us = g_get_monotonic_time ();
if (time_us == CLUTTER_CURRENT_TIME) touch_state = meta_seat_impl_lookup_touch_state (seat,
time_us = g_get_monotonic_time (); event->device_slot);
seat_slot = virtual_evdev->slot_base + (guint) device_slot;
touch_state = meta_seat_impl_acquire_touch_state (virtual_evdev->seat->impl,
seat_slot);
if (!touch_state) if (!touch_state)
return; goto out;
touch_state->coords.x = x; touch_state->coords.x = event->x;
touch_state->coords.y = y; touch_state->coords.y = event->y;
meta_seat_impl_notify_touch_event (virtual_evdev->seat->impl, meta_seat_impl_notify_touch_event (seat,
virtual_evdev->device, virtual_evdev->impl_state->device,
CLUTTER_TOUCH_BEGIN, CLUTTER_TOUCH_UPDATE,
time_us, event->time_us,
touch_state->seat_slot, touch_state->seat_slot,
touch_state->coords.x, touch_state->coords.x,
touch_state->coords.y); touch_state->coords.y);
out:
g_task_return_boolean (task, TRUE);
return G_SOURCE_REMOVE;
} }
static void static void
@ -579,32 +872,57 @@ meta_virtual_input_device_native_notify_touch_motion (ClutterVirtualInputDevice
double x, double x,
double y) double y)
{ {
MetaVirtualEventTouch *event;
MetaVirtualInputDeviceNative *virtual_evdev = MetaVirtualInputDeviceNative *virtual_evdev =
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
GTask *task;
g_return_if_fail (virtual_evdev->impl_state->device != NULL);
event = g_new0 (MetaVirtualEventTouch, 1);
event->time_us = time_us;
event->device_slot = virtual_evdev->slot_base + (guint) device_slot;
event->x = x;
event->y = y;
task = g_task_new (virtual_device, NULL, NULL, NULL);
g_task_set_task_data (task, event, g_free);
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
(GSourceFunc) notify_touch_motion);
g_object_unref (task);
}
static gboolean
notify_touch_up (GTask *task)
{
MetaVirtualInputDeviceNative *virtual_evdev =
g_task_get_source_object (task);
MetaSeatImpl *seat = virtual_evdev->seat->impl;
MetaVirtualEventTouch *event = g_task_get_task_data (task);
MetaTouchState *touch_state; MetaTouchState *touch_state;
guint seat_slot;
g_return_if_fail (virtual_evdev->device != NULL); if (event->time_us == CLUTTER_CURRENT_TIME)
event->time_us = g_get_monotonic_time ();
if (time_us == CLUTTER_CURRENT_TIME) touch_state = meta_seat_impl_lookup_touch_state (seat,
time_us = g_get_monotonic_time (); event->device_slot);
seat_slot = virtual_evdev->slot_base + (guint) device_slot;
touch_state = meta_seat_impl_lookup_touch_state (virtual_evdev->seat->impl,
seat_slot);
if (!touch_state) if (!touch_state)
return; goto out;
touch_state->coords.x = x; meta_seat_impl_notify_touch_event (seat,
touch_state->coords.y = y; virtual_evdev->impl_state->device,
CLUTTER_TOUCH_END,
meta_seat_impl_notify_touch_event (virtual_evdev->seat->impl, event->time_us,
virtual_evdev->device,
CLUTTER_TOUCH_BEGIN,
time_us,
touch_state->seat_slot, touch_state->seat_slot,
touch_state->coords.x, touch_state->coords.x,
touch_state->coords.y); touch_state->coords.y);
meta_seat_impl_release_touch_state (virtual_evdev->seat->impl,
touch_state->seat_slot);
out:
g_task_return_boolean (task, TRUE);
return G_SOURCE_REMOVE;
} }
static void static void
@ -612,32 +930,22 @@ meta_virtual_input_device_native_notify_touch_up (ClutterVirtualInputDevice *vir
uint64_t time_us, uint64_t time_us,
int device_slot) int device_slot)
{ {
MetaVirtualEventTouch *event;
MetaVirtualInputDeviceNative *virtual_evdev = MetaVirtualInputDeviceNative *virtual_evdev =
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
MetaTouchState *touch_state; GTask *task;
guint seat_slot;
g_return_if_fail (virtual_evdev->device != NULL); g_return_if_fail (virtual_evdev->impl_state->device != NULL);
if (time_us == CLUTTER_CURRENT_TIME) event = g_new0 (MetaVirtualEventTouch, 1);
time_us = g_get_monotonic_time (); event->time_us = time_us;
event->device_slot = virtual_evdev->slot_base + (guint) device_slot;
seat_slot = virtual_evdev->slot_base + (guint) device_slot; task = g_task_new (virtual_device, NULL, NULL, NULL);
touch_state = meta_seat_impl_lookup_touch_state (virtual_evdev->seat->impl, g_task_set_task_data (task, event, g_free);
seat_slot); meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
if (!touch_state) (GSourceFunc) notify_touch_up);
return; g_object_unref (task);
meta_seat_impl_notify_touch_event (virtual_evdev->seat->impl,
virtual_evdev->device,
CLUTTER_TOUCH_BEGIN,
time_us,
touch_state->seat_slot,
touch_state->coords.x,
touch_state->coords.y);
meta_seat_impl_release_touch_state (virtual_evdev->seat->impl,
touch_state->seat_slot);
} }
static void static void
@ -701,14 +1009,18 @@ meta_virtual_input_device_native_constructed (GObject *object)
"Creating new virtual input device of type %d (%p)", "Creating new virtual input device of type %d (%p)",
device_type, virtual_device); device_type, virtual_device);
virtual_evdev->device = virtual_evdev->impl_state = g_new0 (ImplState, 1);
virtual_evdev->impl_state->device =
meta_input_device_native_new_virtual (virtual_evdev->seat->impl, meta_input_device_native_new_virtual (virtual_evdev->seat->impl,
device_type, device_type,
CLUTTER_INPUT_MODE_PHYSICAL); CLUTTER_INPUT_MODE_PHYSICAL);
}
g_signal_emit_by_name (virtual_evdev->seat, static void
"device-added", impl_state_free (ImplState *impl_state)
virtual_evdev->device); {
g_clear_object (&impl_state->device);
g_free (impl_state);
} }
static void static void
@ -721,14 +1033,18 @@ meta_virtual_input_device_native_dispose (GObject *object)
GObjectClass *object_class = GObjectClass *object_class =
G_OBJECT_CLASS (meta_virtual_input_device_native_parent_class); G_OBJECT_CLASS (meta_virtual_input_device_native_parent_class);
if (virtual_evdev->device) if (virtual_evdev->impl_state)
{ {
release_pressed_buttons (virtual_device); GTask *task;
g_signal_emit_by_name (virtual_evdev->seat,
"device-removed",
virtual_evdev->device);
g_clear_object (&virtual_evdev->device); task = g_task_new (virtual_device, NULL, NULL, NULL);
g_task_set_task_data (task, virtual_evdev->impl_state,
(GDestroyNotify) impl_state_free);
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
(GSourceFunc) release_device);
g_object_unref (task);
virtual_evdev->impl_state = NULL;
} }
meta_seat_native_release_touch_slots (virtual_evdev->seat, meta_seat_native_release_touch_slots (virtual_evdev->seat,