x11: Query pointer devices' scroll valuators on toplevel enter events

We used to "invalidate" scroll valuators, so the next scroll event could
be used as the base for the next scroll deltas. This has the inconvenience
that it invariably consumes the first event received after enter and,
due to interactions with WM overeager passive button grabs, there's a
possibility we don't scroll at all if we receive interleaved "smooth
scroll" XI_Motion events and XI_Enter events (Normally triggered by regular
scroll wheels in mice).

In order to fix this, and at the expense of some sync-call overhead on
XI_Enter events (one XIQueryDevice call per slave device), query the
current scroll valuator state for all the slaves of the entered pointer,
so we do know beforehand the right base values. If new devices are plugged
while the pointer is on top of the client, the initialized scroll values
will match the valuators'.

https://bugzilla.gnome.org/show_bug.cgi?id=750994
https://bugzilla.gnome.org/show_bug.cgi?id=750870
This commit is contained in:
Carlos Garnacho 2015-06-23 18:11:07 +02:00
parent 8c9e426dc5
commit 77b8495bc4
3 changed files with 30 additions and 26 deletions

View File

@ -40,7 +40,6 @@ struct _ScrollValuator
{
guint n_valuator : 4;
guint direction : 4;
guint last_value_valid : 1;
gdouble last_value;
gdouble increment;
};
@ -819,8 +818,8 @@ _gdk_x11_device_xi2_add_scroll_valuator (GdkX11DeviceXI2 *device,
scroll.n_valuator = n_valuator;
scroll.direction = direction;
scroll.last_value_valid = FALSE;
scroll.increment = increment;
scroll.last_value = 0;
g_array_append_val (device->scroll_valuators, scroll);
}
@ -851,18 +850,10 @@ _gdk_x11_device_xi2_get_scroll_delta (GdkX11DeviceXI2 *device,
if (delta_ret)
*delta_ret = 0;
if (scroll->last_value_valid)
{
if (delta_ret)
*delta_ret = (valuator_value - scroll->last_value) / scroll->increment;
if (delta_ret)
*delta_ret = (valuator_value - scroll->last_value) / scroll->increment;
scroll->last_value = valuator_value;
}
else
{
scroll->last_value = valuator_value;
scroll->last_value_valid = TRUE;
}
scroll->last_value = valuator_value;
return TRUE;
}
@ -872,17 +863,33 @@ _gdk_x11_device_xi2_get_scroll_delta (GdkX11DeviceXI2 *device,
}
void
_gdk_device_xi2_reset_scroll_valuators (GdkX11DeviceXI2 *device)
_gdk_device_xi2_revalidate_scroll_valuators (GdkX11DeviceXI2 *device)
{
guint i;
GdkDisplay *display;
XIDeviceInfo *info;
gint i, ndevices;
display = gdk_device_get_display (GDK_DEVICE (device));
gdk_x11_display_error_trap_push (display);
info = XIQueryDevice (GDK_DISPLAY_XDISPLAY (display),
device->device_id, &ndevices);
gdk_x11_display_error_trap_pop_ignored (display);
if (!info)
return;
for (i = 0; i < device->scroll_valuators->len; i++)
{
XIValuatorClassInfo *valuator;
ScrollValuator *scroll;
scroll = &g_array_index (device->scroll_valuators, ScrollValuator, i);
scroll->last_value_valid = FALSE;
valuator = (XIValuatorClassInfo *) info->classes[scroll->n_valuator + 1];
scroll->last_value = valuator->value;
}
XIFreeDeviceInfo (info);
}
void

View File

@ -824,13 +824,11 @@ handle_device_changed (GdkX11DeviceManagerXI2 *device_manager,
XIDeviceChangedEvent *ev)
{
GdkDisplay *display;
GdkDevice *device, *source_device;
GdkDevice *device;
display = gdk_device_manager_get_display (GDK_DEVICE_MANAGER (device_manager));
device = g_hash_table_lookup (device_manager->id_table,
GUINT_TO_POINTER (ev->deviceid));
source_device = g_hash_table_lookup (device_manager->id_table,
GUINT_TO_POINTER (ev->sourceid));
if (device)
{
@ -841,9 +839,6 @@ handle_device_changed (GdkX11DeviceManagerXI2 *device_manager,
g_signal_emit_by_name (G_OBJECT (device), "changed");
}
if (source_device)
_gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
}
static GdkCrossingMode
@ -1683,16 +1678,16 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
xev->detail != XINotifyInferior && xev->mode != XINotifyPassiveUngrab &&
gdk_window_get_window_type (window) == GDK_WINDOW_TOPLEVEL)
{
if (gdk_device_get_device_type (source_device) != GDK_DEVICE_TYPE_MASTER)
_gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER)
_gdk_device_xi2_revalidate_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
else
{
GList *slaves, *l;
slaves = gdk_device_list_slave_devices (source_device);
slaves = gdk_device_list_slave_devices (device);
for (l = slaves; l; l = l->next)
_gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (l->data));
_gdk_device_xi2_revalidate_scroll_valuators (l->data);
g_list_free (slaves);
}

View File

@ -246,6 +246,8 @@ gboolean _gdk_x11_device_xi2_get_scroll_delta (GdkX11DeviceXI2 *device,
GdkScrollDirection *direction_ret,
gdouble *delta_ret);
void _gdk_device_xi2_reset_scroll_valuators (GdkX11DeviceXI2 *device);
void _gdk_device_xi2_revalidate_scroll_valuators (GdkX11DeviceXI2 *device);
gdouble gdk_x11_device_xi2_get_last_axis_value (GdkX11DeviceXI2 *device,
gint n_axis);