Commit 77b8495b authored by Carlos Garnacho's avatar Carlos Garnacho

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
parent 8c9e426d
......@@ -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
......
......@@ -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);
}
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment