GNOME Bugzilla – Bug 682362
Multi touch events skipped
Last modified: 2012-09-03 20:55:46 UTC
803b3bafb617c2df703aa8b834ff0df2f0c5c26c introduced a new issue for multi touch events. In the case where 2 touch events for 2 different touch points are processed in the same iteration, a call to _clutter_stage_remove_device() when processing the first event will remove the stage setting of the InputDevice. That means Clutter will skip the second event, because it can't find a stage to which relate the event, so no related actor and so no emission. To fix this we move the _clutter_stage_(add/remove)_device() calls into the input device. This way the input device can find out exactly when to call these functions (i.e. when no touch point were previously active or when no touch point remain active).
Created attachment 222018 [details] [review] Patch v1
Doesn't seem to work here, with this patch applied, touch events have no stage defined and thus aren't delivered: Clutter-Message: [ +448153]:[EVENT]:./clutter-input-device.c:861: No stage defined for device 'Virtual core pointer'
Could you put a break point on the _clutter_input_device_set_stage() function and print the backtrace when that function gets called with NULL as second argument? That will cause the reset of the stage value of the input device which ends up generating that message. Thanks
Backtrace:
+ Trace 230727
Device: $1 = {parent_instance = {g_type_instance = {g_class = 0x464260}, ref_count = 2, qdata = 0x0}, id = 2, device_type = CLUTTER_POINTER_DEVICE, device_mode = CLUTTER_INPUT_MODE_MASTER, device_name = 0x630960 "Virtual core pointer", device_manager = 0x467d20, backend = 0x416080, associated = 0x5bfb90, slaves = 0x0, cursor_actor = 0x0, inv_touch_sequence_actors = 0x65ecc0, pointer_grab_actor = 0x0, keyboard_grab_actor = 0x0, sequence_grab_actors = 0x0, inv_sequence_grab_actors = 0x0, click_count = 0, stage = 0x74aea0, current_x = 432, current_y = 169, current_time = 12910520, current_button_number = -1, current_state = 0, touch_sequences_info = 0x65ec60, previous_x = -1, previous_y = -1, previous_time = 0, previous_button_number = -1, previous_state = 0, axes = 0x466ec0, n_keys = 0, keys = 0x0, scroll_info = 0x0, has_cursor = 1, is_enabled = 1} ClutterEvent: $2 = {type = CLUTTER_LEAVE, any = {type = CLUTTER_LEAVE, time = 12910520, flags = CLUTTER_EVENT_NONE, stage = 0x74aea0, source = 0x74aea0}, button = { type = CLUTTER_LEAVE, time = 12910520, flags = CLUTTER_EVENT_NONE, stage = 0x74aea0, source = 0x74aea0, x = 432, y = 169, modifier_state = 0, button = 0, click_count = 0, axes = 0x0, device = 0x0}, key = {type = CLUTTER_LEAVE, time = 12910520, flags = CLUTTER_EVENT_NONE, stage = 0x74aea0, source = 0x74aea0, modifier_state = 1138229248, keyval = 1126760448, hardware_keycode = 0, unicode_value = 0, device = 0x0}, motion = {type = CLUTTER_LEAVE, time = 12910520, flags = CLUTTER_EVENT_NONE, stage = 0x74aea0, source = 0x74aea0, x = 432, y = 169, modifier_state = 0, axes = 0x0, device = 0x0}, scroll = {type = CLUTTER_LEAVE, time = 12910520, flags = CLUTTER_EVENT_NONE, stage = 0x74aea0, source = 0x74aea0, x = 432, y = 169, direction = CLUTTER_SCROLL_UP, modifier_state = 0, axes = 0x0, device = 0x0}, stage_state = {type = CLUTTER_LEAVE, time = 12910520, flags = CLUTTER_EVENT_NONE, stage = 0x74aea0, source = 0x74aea0, changed_mask = (unknown: 1138229248), new_state = (unknown: 1126760448)}, crossing = { type = CLUTTER_LEAVE, time = 12910520, flags = CLUTTER_EVENT_NONE, stage = 0x74aea0, source = 0x74aea0, x = 432, y = 169, device = 0x0, related = 0x0}, touch = { type = CLUTTER_LEAVE, time = 12910520, flags = CLUTTER_EVENT_NONE, stage = 0x74aea0, source = 0x74aea0, x = 432, y = 169, sequence = 0x0, modifier_state = 0, axes = 0x0, device = 0x0}} XIDeviceEvent (XI_Leave): $3 = {type = 35, serial = 0, send_event = 0, display = 0x44c6a0, extension = 131, evtype = 8, time = 12910520, deviceid = 2, sourceid = 2, detail = 2, root = 99, event = 8388631, child = 0, root_x = 432, root_y = 169, event_x = 432, event_y = 169, mode = 0, focus = 0, same_screen = 1, buttons = {mask_len = 4, mask = 0x7e37b8 ""}, mods = {base = 8, latched = 0, locked = 18, effective = 0}, group = {base = 0, latched = 0, locked = 0, effective = 0}}
Ah! Really interesting that this is done by the backend. The purpose of my patch was to move the device/stage association to the generic part of clutter (clutter-main.c/clutter-input-device.c). I suppose if I remove all these calls from the backends, then things should work. At the moment we call _clutter_stage_add_device()/_clutter_stage_remove_device() from the backend side at event translation time and then we do it again when processing the event in clutter-main.c. Emmanuele any advice on this?
in theory, it should be possible to do it from the event processing stage, instead of the event translation stage; I'm just a bit worried to break existing invariants - e.g. crossing events get delivered to an actor placed at the edge of the stage before sending the crossing event to the stage (tests/interactive/test-events has a purple actor positioned there just for this use case).
Created attachment 223082 [details] [review] input-device: don't reset a device's stage until all touch points are gone 803b3bafb617c2df703aa8b834ff0df2f0c5c26c introduced a new issue for multi touch events. In the case where 2 touch events for 2 different touch points are processed in the same iteration, a call to _clutter_stage_remove_device() when processing the first event will remove the stage setting of the InputDevice. That means Clutter will skip the second event, because it can't find a stage to which relate the event, so no related actor and so no emission. To fix this we move the _clutter_stage_(add/remove)_device() calls into the input device. This way the input device can find out exactly when to call these functions (i.e. when no touch point were previously active or when no touch point remain active).
Created attachment 223296 [details] [review] input-device: don't reset a device's stage until all touch points are gone The previous patch didn't apply cleanly, this one should.
The patch (https://bugzilla.gnome.org/attachment.cgi?id=223082) works for fine for me on top of https://bugzilla.gnome.org/show_bug.cgi?id=683126 But not sure why the last one do not apply on top of https://bugzilla.gnome.org/show_bug.cgi?id=683126 Anyway, thanks problem solved!
Attachment 223296 [details] pushed as d6a0f7e - input-device: don't reset a device's stage until all touch points are gone