mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
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
|
||||
* 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,
|
||||
GINT_TO_POINTER (info->deviceid),
|
||||
@ -329,6 +326,8 @@ translate_hierarchy_event (ClutterBackendX11 *backend_x11,
|
||||
XIDeviceInfo *info;
|
||||
int n_devices;
|
||||
|
||||
CLUTTER_NOTE (EVENT, "Hierarchy event: device enabled");
|
||||
|
||||
info = XIQueryDevice (backend_x11->xdpy,
|
||||
ev->info[i].deviceid,
|
||||
&n_devices);
|
||||
@ -336,6 +335,8 @@ translate_hierarchy_event (ClutterBackendX11 *backend_x11,
|
||||
}
|
||||
else if (ev->info[i].flags & XIDeviceDisabled)
|
||||
{
|
||||
CLUTTER_NOTE (EVENT, "Hierarchy event: device disabled");
|
||||
|
||||
remove_device (manager_xi2, ev->info[i].deviceid);
|
||||
}
|
||||
else if ((ev->info[i].flags & XISlaveAttached) ||
|
||||
@ -345,6 +346,11 @@ translate_hierarchy_event (ClutterBackendX11 *backend_x11,
|
||||
XIDeviceInfo *info;
|
||||
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,
|
||||
GINT_TO_POINTER (ev->info[i].deviceid));
|
||||
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);
|
||||
ClutterTranslateReturn retval = CLUTTER_TRANSLATE_CONTINUE;
|
||||
ClutterBackendX11 *backend_x11;
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterStage *stage;
|
||||
ClutterStageX11 *stage_x11 = NULL;
|
||||
ClutterStage *stage = NULL;
|
||||
ClutterInputDevice *device;
|
||||
XGenericEventCookie *cookie;
|
||||
XIEvent *xi_event;
|
||||
@ -558,14 +564,18 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
||||
|
||||
xi_event = (XIEvent *) cookie->data;
|
||||
|
||||
if (!(xi_event->evtype == XI_HierarchyChanged ||
|
||||
xi_event->evtype == XI_DeviceChanged))
|
||||
{
|
||||
stage = get_event_stage (translator, xi_event);
|
||||
if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
|
||||
{
|
||||
XFreeEventData (backend_x11->xdpy, cookie);
|
||||
return CLUTTER_TRANSLATE_CONTINUE;
|
||||
}
|
||||
|
||||
else
|
||||
stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
|
||||
}
|
||||
|
||||
event->any.stage = stage;
|
||||
|
||||
|
@ -4,9 +4,9 @@
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
typedef struct {
|
||||
ClutterActor *stage;
|
||||
|
||||
GHashTable *devices;
|
||||
|
||||
} TestDevicesApp;
|
||||
|
||||
static const gchar *
|
||||
@ -79,9 +79,8 @@ axis_type_name (ClutterInputAxis axis)
|
||||
static gboolean
|
||||
stage_button_event_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer userdata)
|
||||
TestDevicesApp *app)
|
||||
{
|
||||
TestDevicesApp *app = (TestDevicesApp *)userdata;
|
||||
ClutterInputDevice *device;
|
||||
ClutterInputDevice *source_device;
|
||||
ClutterActor *hand = NULL;
|
||||
@ -130,9 +129,8 @@ stage_button_event_cb (ClutterActor *actor,
|
||||
static gboolean
|
||||
stage_motion_event_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer userdata)
|
||||
TestDevicesApp *app)
|
||||
{
|
||||
TestDevicesApp *app = (TestDevicesApp *)userdata;
|
||||
ClutterInputDevice *device;
|
||||
ClutterActor *hand = NULL;
|
||||
|
||||
@ -152,6 +150,65 @@ stage_motion_event_cb (ClutterActor *actor,
|
||||
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
|
||||
test_devices_main (int argc, char **argv)
|
||||
{
|
||||
@ -181,10 +238,18 @@ test_devices_main (int argc, char **argv)
|
||||
g_signal_connect (stage,
|
||||
"button-press-event", G_CALLBACK (stage_button_event_cb),
|
||||
app);
|
||||
app->stage = stage;
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
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);
|
||||
|
||||
if (stage_devices == NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user