device-manager/xi2: Fix device hotplugging
Hierarchy and Device changed events come through with the X window set to be the root window, not the stage window. We need to whitelist them so that we can actually support hotplugging and device changes.
This commit is contained in:
parent
7514f5fe92
commit
0e99346915
@ -235,9 +235,6 @@ add_device (ClutterDeviceManagerXI2 *manager_xi2,
|
|||||||
|
|
||||||
/* we don't go through the DeviceManager::add_device() vfunc because
|
/* we don't go through the DeviceManager::add_device() vfunc because
|
||||||
* that emits the signal, and we only do it conditionally
|
* that emits the signal, and we only do it conditionally
|
||||||
*
|
|
||||||
* FIXME: add a boolean "emit_signal" argument to the add_device()
|
|
||||||
* wrapper in ClutterDeviceManager, and emit the signal only if true
|
|
||||||
*/
|
*/
|
||||||
g_hash_table_replace (manager_xi2->devices_by_id,
|
g_hash_table_replace (manager_xi2->devices_by_id,
|
||||||
GINT_TO_POINTER (info->deviceid),
|
GINT_TO_POINTER (info->deviceid),
|
||||||
@ -329,6 +326,8 @@ translate_hierarchy_event (ClutterBackendX11 *backend_x11,
|
|||||||
XIDeviceInfo *info;
|
XIDeviceInfo *info;
|
||||||
int n_devices;
|
int n_devices;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (EVENT, "Hierarchy event: device enabled");
|
||||||
|
|
||||||
info = XIQueryDevice (backend_x11->xdpy,
|
info = XIQueryDevice (backend_x11->xdpy,
|
||||||
ev->info[i].deviceid,
|
ev->info[i].deviceid,
|
||||||
&n_devices);
|
&n_devices);
|
||||||
@ -336,6 +335,8 @@ translate_hierarchy_event (ClutterBackendX11 *backend_x11,
|
|||||||
}
|
}
|
||||||
else if (ev->info[i].flags & XIDeviceDisabled)
|
else if (ev->info[i].flags & XIDeviceDisabled)
|
||||||
{
|
{
|
||||||
|
CLUTTER_NOTE (EVENT, "Hierarchy event: device disabled");
|
||||||
|
|
||||||
remove_device (manager_xi2, ev->info[i].deviceid);
|
remove_device (manager_xi2, ev->info[i].deviceid);
|
||||||
}
|
}
|
||||||
else if ((ev->info[i].flags & XISlaveAttached) ||
|
else if ((ev->info[i].flags & XISlaveAttached) ||
|
||||||
@ -345,6 +346,11 @@ translate_hierarchy_event (ClutterBackendX11 *backend_x11,
|
|||||||
XIDeviceInfo *info;
|
XIDeviceInfo *info;
|
||||||
int n_devices;
|
int n_devices;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (EVENT, "Hierarchy event: slave %s",
|
||||||
|
(ev->info[i].flags & XISlaveAttached)
|
||||||
|
? "attached"
|
||||||
|
: "detached");
|
||||||
|
|
||||||
slave = g_hash_table_lookup (manager_xi2->devices_by_id,
|
slave = g_hash_table_lookup (manager_xi2->devices_by_id,
|
||||||
GINT_TO_POINTER (ev->info[i].deviceid));
|
GINT_TO_POINTER (ev->info[i].deviceid));
|
||||||
master = clutter_input_device_get_associated_device (slave);
|
master = clutter_input_device_get_associated_device (slave);
|
||||||
@ -533,8 +539,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
|||||||
ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (translator);
|
ClutterDeviceManagerXI2 *manager_xi2 = CLUTTER_DEVICE_MANAGER_XI2 (translator);
|
||||||
ClutterTranslateReturn retval = CLUTTER_TRANSLATE_CONTINUE;
|
ClutterTranslateReturn retval = CLUTTER_TRANSLATE_CONTINUE;
|
||||||
ClutterBackendX11 *backend_x11;
|
ClutterBackendX11 *backend_x11;
|
||||||
ClutterStageX11 *stage_x11;
|
ClutterStageX11 *stage_x11 = NULL;
|
||||||
ClutterStage *stage;
|
ClutterStage *stage = NULL;
|
||||||
ClutterInputDevice *device;
|
ClutterInputDevice *device;
|
||||||
XGenericEventCookie *cookie;
|
XGenericEventCookie *cookie;
|
||||||
XIEvent *xi_event;
|
XIEvent *xi_event;
|
||||||
@ -558,14 +564,18 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
|||||||
|
|
||||||
xi_event = (XIEvent *) cookie->data;
|
xi_event = (XIEvent *) cookie->data;
|
||||||
|
|
||||||
|
if (!(xi_event->evtype == XI_HierarchyChanged ||
|
||||||
|
xi_event->evtype == XI_DeviceChanged))
|
||||||
|
{
|
||||||
stage = get_event_stage (translator, xi_event);
|
stage = get_event_stage (translator, xi_event);
|
||||||
if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
|
if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
|
||||||
{
|
{
|
||||||
XFreeEventData (backend_x11->xdpy, cookie);
|
XFreeEventData (backend_x11->xdpy, cookie);
|
||||||
return CLUTTER_TRANSLATE_CONTINUE;
|
return CLUTTER_TRANSLATE_CONTINUE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
|
stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
|
||||||
|
}
|
||||||
|
|
||||||
event->any.stage = stage;
|
event->any.stage = stage;
|
||||||
|
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
#include <clutter/x11/clutter-x11.h>
|
#include <clutter/x11/clutter-x11.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
ClutterActor *stage;
|
||||||
|
|
||||||
GHashTable *devices;
|
GHashTable *devices;
|
||||||
|
|
||||||
} TestDevicesApp;
|
} TestDevicesApp;
|
||||||
|
|
||||||
static const gchar *
|
static const gchar *
|
||||||
@ -79,9 +79,8 @@ axis_type_name (ClutterInputAxis axis)
|
|||||||
static gboolean
|
static gboolean
|
||||||
stage_button_event_cb (ClutterActor *actor,
|
stage_button_event_cb (ClutterActor *actor,
|
||||||
ClutterEvent *event,
|
ClutterEvent *event,
|
||||||
gpointer userdata)
|
TestDevicesApp *app)
|
||||||
{
|
{
|
||||||
TestDevicesApp *app = (TestDevicesApp *)userdata;
|
|
||||||
ClutterInputDevice *device;
|
ClutterInputDevice *device;
|
||||||
ClutterInputDevice *source_device;
|
ClutterInputDevice *source_device;
|
||||||
ClutterActor *hand = NULL;
|
ClutterActor *hand = NULL;
|
||||||
@ -130,9 +129,8 @@ stage_button_event_cb (ClutterActor *actor,
|
|||||||
static gboolean
|
static gboolean
|
||||||
stage_motion_event_cb (ClutterActor *actor,
|
stage_motion_event_cb (ClutterActor *actor,
|
||||||
ClutterEvent *event,
|
ClutterEvent *event,
|
||||||
gpointer userdata)
|
TestDevicesApp *app)
|
||||||
{
|
{
|
||||||
TestDevicesApp *app = (TestDevicesApp *)userdata;
|
|
||||||
ClutterInputDevice *device;
|
ClutterInputDevice *device;
|
||||||
ClutterActor *hand = NULL;
|
ClutterActor *hand = NULL;
|
||||||
|
|
||||||
@ -152,6 +150,65 @@ stage_motion_event_cb (ClutterActor *actor,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
manager_device_added_cb (ClutterDeviceManager *manager,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
TestDevicesApp *app)
|
||||||
|
{
|
||||||
|
ClutterInputDeviceType device_type;
|
||||||
|
ClutterActor *hand = NULL;
|
||||||
|
|
||||||
|
g_print ("got a %s device '%s' with id %d\n",
|
||||||
|
device_type_name (device),
|
||||||
|
clutter_input_device_get_device_name (device),
|
||||||
|
clutter_input_device_get_device_id (device));
|
||||||
|
|
||||||
|
device_type = clutter_input_device_get_device_type (device);
|
||||||
|
if (device_type == CLUTTER_POINTER_DEVICE ||
|
||||||
|
device_type == CLUTTER_PEN_DEVICE ||
|
||||||
|
device_type == CLUTTER_POINTER_DEVICE)
|
||||||
|
{
|
||||||
|
g_print ("*** enabling device '%s' ***\n",
|
||||||
|
clutter_input_device_get_device_name (device));
|
||||||
|
|
||||||
|
clutter_input_device_set_enabled (device, TRUE);
|
||||||
|
|
||||||
|
hand = clutter_texture_new_from_file (TESTS_DATADIR
|
||||||
|
G_DIR_SEPARATOR_S
|
||||||
|
"redhand.png",
|
||||||
|
NULL);
|
||||||
|
g_hash_table_insert (app->devices, device, hand);
|
||||||
|
|
||||||
|
clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
manager_device_removed_cb (ClutterDeviceManager *manager,
|
||||||
|
ClutterInputDevice *device,
|
||||||
|
TestDevicesApp *app)
|
||||||
|
{
|
||||||
|
ClutterInputDeviceType device_type;
|
||||||
|
ClutterActor *hand = NULL;
|
||||||
|
|
||||||
|
g_print ("removed a %s device '%s' with id %d\n",
|
||||||
|
device_type_name (device),
|
||||||
|
clutter_input_device_get_device_name (device),
|
||||||
|
clutter_input_device_get_device_id (device));
|
||||||
|
|
||||||
|
device_type = clutter_input_device_get_device_type (device);
|
||||||
|
if (device_type == CLUTTER_POINTER_DEVICE ||
|
||||||
|
device_type == CLUTTER_PEN_DEVICE ||
|
||||||
|
device_type == CLUTTER_POINTER_DEVICE)
|
||||||
|
{
|
||||||
|
hand = g_hash_table_lookup (app->devices, device);
|
||||||
|
if (hand != NULL)
|
||||||
|
clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand);
|
||||||
|
|
||||||
|
g_hash_table_remove (app->devices, device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
G_MODULE_EXPORT int
|
G_MODULE_EXPORT int
|
||||||
test_devices_main (int argc, char **argv)
|
test_devices_main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -181,10 +238,18 @@ test_devices_main (int argc, char **argv)
|
|||||||
g_signal_connect (stage,
|
g_signal_connect (stage,
|
||||||
"button-press-event", G_CALLBACK (stage_button_event_cb),
|
"button-press-event", G_CALLBACK (stage_button_event_cb),
|
||||||
app);
|
app);
|
||||||
|
app->stage = stage;
|
||||||
|
|
||||||
clutter_actor_show_all (stage);
|
clutter_actor_show_all (stage);
|
||||||
|
|
||||||
manager = clutter_device_manager_get_default ();
|
manager = clutter_device_manager_get_default ();
|
||||||
|
g_signal_connect (manager,
|
||||||
|
"device-added", G_CALLBACK (manager_device_added_cb),
|
||||||
|
app);
|
||||||
|
g_signal_connect (manager,
|
||||||
|
"device-removed", G_CALLBACK (manager_device_removed_cb),
|
||||||
|
app);
|
||||||
|
|
||||||
stage_devices = clutter_device_manager_peek_devices (manager);
|
stage_devices = clutter_device_manager_peek_devices (manager);
|
||||||
|
|
||||||
if (stage_devices == NULL)
|
if (stage_devices == NULL)
|
||||||
|
Loading…
Reference in New Issue
Block a user