mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-24 12:41:16 +00:00
devicemanager,xi2: Implement smooth scrolling
XInput >= 2.1 allows for implementing smooth scrolling, reporting the different scrolling axes as valuators. Any change in those will be reported as GdkEventScroll events with delta_x/y information. the older kind of scroll events is still handled, and emulated in devices able to provide smooth scrolling, setting _gdk_event_set_pointer_emulated() in that case.
This commit is contained in:
parent
f941c78969
commit
147cdd8465
@ -33,11 +33,22 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct _ScrollValuator ScrollValuator;
|
||||||
|
|
||||||
|
struct _ScrollValuator
|
||||||
|
{
|
||||||
|
guint n_valuator : 4;
|
||||||
|
guint direction : 4;
|
||||||
|
guint last_value_valid : 1;
|
||||||
|
gdouble last_value;
|
||||||
|
};
|
||||||
|
|
||||||
struct _GdkX11DeviceXI2
|
struct _GdkX11DeviceXI2
|
||||||
{
|
{
|
||||||
GdkDevice parent_instance;
|
GdkDevice parent_instance;
|
||||||
|
|
||||||
gint device_id;
|
gint device_id;
|
||||||
|
GArray *scroll_valuators;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GdkX11DeviceXI2Class
|
struct _GdkX11DeviceXI2Class
|
||||||
@ -49,6 +60,7 @@ G_DEFINE_TYPE (GdkX11DeviceXI2, gdk_x11_device_xi2, GDK_TYPE_DEVICE)
|
|||||||
|
|
||||||
#ifdef XINPUT_2
|
#ifdef XINPUT_2
|
||||||
|
|
||||||
|
static void gdk_x11_device_xi2_finalize (GObject *object);
|
||||||
static void gdk_x11_device_xi2_get_property (GObject *object,
|
static void gdk_x11_device_xi2_get_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
GValue *value,
|
GValue *value,
|
||||||
@ -110,6 +122,7 @@ gdk_x11_device_xi2_class_init (GdkX11DeviceXI2Class *klass)
|
|||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
|
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = gdk_x11_device_xi2_finalize;
|
||||||
object_class->get_property = gdk_x11_device_xi2_get_property;
|
object_class->get_property = gdk_x11_device_xi2_get_property;
|
||||||
object_class->set_property = gdk_x11_device_xi2_set_property;
|
object_class->set_property = gdk_x11_device_xi2_set_property;
|
||||||
|
|
||||||
@ -134,6 +147,17 @@ gdk_x11_device_xi2_class_init (GdkX11DeviceXI2Class *klass)
|
|||||||
static void
|
static void
|
||||||
gdk_x11_device_xi2_init (GdkX11DeviceXI2 *device)
|
gdk_x11_device_xi2_init (GdkX11DeviceXI2 *device)
|
||||||
{
|
{
|
||||||
|
device->scroll_valuators = g_array_new (FALSE, FALSE, sizeof (ScrollValuator));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gdk_x11_device_xi2_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
GdkX11DeviceXI2 *device = GDK_X11_DEVICE_XI2 (object);
|
||||||
|
|
||||||
|
g_array_free (device->scroll_valuators, TRUE);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gdk_x11_device_xi2_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -777,6 +801,83 @@ _gdk_x11_device_xi2_translate_state (XIModifierState *mods_state,
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gdk_x11_device_xi2_add_scroll_valuator (GdkX11DeviceXI2 *device,
|
||||||
|
guint n_valuator,
|
||||||
|
GdkScrollDirection direction)
|
||||||
|
{
|
||||||
|
ScrollValuator scroll;
|
||||||
|
|
||||||
|
g_return_if_fail (GDK_IS_X11_DEVICE_XI2 (device));
|
||||||
|
g_return_if_fail (n_valuator < gdk_device_get_n_axes (GDK_DEVICE (device)));
|
||||||
|
|
||||||
|
scroll.n_valuator = n_valuator;
|
||||||
|
scroll.direction = direction;
|
||||||
|
scroll.last_value_valid = FALSE;
|
||||||
|
|
||||||
|
g_array_append_val (device->scroll_valuators, scroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_gdk_x11_device_xi2_get_scroll_delta (GdkX11DeviceXI2 *device,
|
||||||
|
guint n_valuator,
|
||||||
|
gdouble valuator_value,
|
||||||
|
GdkScrollDirection *direction_ret,
|
||||||
|
gdouble *delta_ret)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GDK_IS_X11_DEVICE_XI2 (device), FALSE);
|
||||||
|
g_return_val_if_fail (n_valuator < gdk_device_get_n_axes (GDK_DEVICE (device)), FALSE);
|
||||||
|
|
||||||
|
for (i = 0; i < device->scroll_valuators->len; i++)
|
||||||
|
{
|
||||||
|
ScrollValuator *scroll;
|
||||||
|
|
||||||
|
scroll = &g_array_index (device->scroll_valuators, ScrollValuator, i);
|
||||||
|
|
||||||
|
if (scroll->n_valuator == n_valuator)
|
||||||
|
{
|
||||||
|
if (direction_ret)
|
||||||
|
*direction_ret = scroll->direction;
|
||||||
|
|
||||||
|
if (delta_ret)
|
||||||
|
*delta_ret = 0;
|
||||||
|
|
||||||
|
if (scroll->last_value_valid)
|
||||||
|
{
|
||||||
|
if (delta_ret)
|
||||||
|
*delta_ret = valuator_value - scroll->last_value;
|
||||||
|
|
||||||
|
scroll->last_value = valuator_value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scroll->last_value = valuator_value;
|
||||||
|
scroll->last_value_valid = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_gdk_device_xi2_reset_scroll_valuators (GdkX11DeviceXI2 *device)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < device->scroll_valuators->len; i++)
|
||||||
|
{
|
||||||
|
ScrollValuator *scroll;
|
||||||
|
|
||||||
|
scroll = &g_array_index (device->scroll_valuators, ScrollValuator, i);
|
||||||
|
scroll->last_value_valid = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gint
|
gint
|
||||||
_gdk_x11_device_xi2_get_id (GdkX11DeviceXI2 *device)
|
_gdk_x11_device_xi2_get_id (GdkX11DeviceXI2 *device)
|
||||||
{
|
{
|
||||||
|
@ -241,6 +241,22 @@ translate_device_classes (GdkDisplay *display,
|
|||||||
valuator_info->resolution);
|
valuator_info->resolution);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#ifdef XINPUT_2_2
|
||||||
|
case XIScrollClass:
|
||||||
|
{
|
||||||
|
XIScrollClassInfo *scroll_info = (XIScrollClassInfo *) class_info;
|
||||||
|
GdkScrollDirection direction;
|
||||||
|
|
||||||
|
if (scroll_info->scroll_type == XIScrollTypeVertical)
|
||||||
|
direction = GDK_SCROLL_DOWN;
|
||||||
|
else
|
||||||
|
direction = GDK_SCROLL_RIGHT;
|
||||||
|
|
||||||
|
_gdk_x11_device_xi2_add_scroll_valuator (GDK_X11_DEVICE_XI2 (device),
|
||||||
|
scroll_info->number,
|
||||||
|
direction);
|
||||||
|
}
|
||||||
|
#endif /* XINPUT_2_2 */
|
||||||
default:
|
default:
|
||||||
/* Ignore */
|
/* Ignore */
|
||||||
break;
|
break;
|
||||||
@ -1036,6 +1052,47 @@ gdk_x11_device_manager_xi2_translate_core_event (GdkEventTranslator *translator,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
scroll_valuators_changed (GdkX11DeviceXI2 *device,
|
||||||
|
XIValuatorState *valuators,
|
||||||
|
gdouble *dx,
|
||||||
|
gdouble *dy)
|
||||||
|
{
|
||||||
|
gdouble has_scroll_valuators = FALSE;
|
||||||
|
GdkScrollDirection direction;
|
||||||
|
guint n_axes, i, n_val;
|
||||||
|
gdouble *vals;
|
||||||
|
|
||||||
|
n_axes = gdk_device_get_n_axes (GDK_DEVICE (device));
|
||||||
|
vals = valuators->values;
|
||||||
|
*dx = *dy = 0;
|
||||||
|
n_val = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++)
|
||||||
|
{
|
||||||
|
gdouble delta;
|
||||||
|
|
||||||
|
if (!XIMaskIsSet (valuators->mask, i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (_gdk_x11_device_xi2_get_scroll_delta (device, i, vals[n_val],
|
||||||
|
&direction, &delta))
|
||||||
|
{
|
||||||
|
has_scroll_valuators = TRUE;
|
||||||
|
|
||||||
|
if (direction == GDK_SCROLL_UP ||
|
||||||
|
direction == GDK_SCROLL_DOWN)
|
||||||
|
*dy = delta;
|
||||||
|
else
|
||||||
|
*dx = delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
n_val++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return has_scroll_valuators;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
||||||
GdkDisplay *display,
|
GdkDisplay *display,
|
||||||
@ -1142,8 +1199,11 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
|||||||
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
|
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
|
||||||
GdkDevice *source_device;
|
GdkDevice *source_device;
|
||||||
|
|
||||||
if (ev->evtype == XI_ButtonPress &&
|
if (ev->evtype == XI_ButtonRelease &&
|
||||||
(xev->detail >= 4 && xev->detail <= 7))
|
(xev->detail >= 4 && xev->detail <= 7))
|
||||||
|
return FALSE;
|
||||||
|
else if (ev->evtype == XI_ButtonPress &&
|
||||||
|
(xev->detail >= 4 && xev->detail <= 7))
|
||||||
{
|
{
|
||||||
/* Button presses of button 4-7 are scroll events */
|
/* Button presses of button 4-7 are scroll events */
|
||||||
event->scroll.type = GDK_SCROLL;
|
event->scroll.type = GDK_SCROLL;
|
||||||
@ -1163,6 +1223,8 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
|||||||
event->scroll.y = (gdouble) xev->event_y;
|
event->scroll.y = (gdouble) xev->event_y;
|
||||||
event->scroll.x_root = (gdouble) xev->root_x;
|
event->scroll.x_root = (gdouble) xev->root_x;
|
||||||
event->scroll.y_root = (gdouble) xev->root_y;
|
event->scroll.y_root = (gdouble) xev->root_y;
|
||||||
|
event->scroll.delta_x = 0;
|
||||||
|
event->scroll.delta_y = 0;
|
||||||
|
|
||||||
event->scroll.device = g_hash_table_lookup (device_manager->id_table,
|
event->scroll.device = g_hash_table_lookup (device_manager->id_table,
|
||||||
GUINT_TO_POINTER (xev->deviceid));
|
GUINT_TO_POINTER (xev->deviceid));
|
||||||
@ -1172,6 +1234,9 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
|||||||
gdk_event_set_source_device (event, source_device);
|
gdk_event_set_source_device (event, source_device);
|
||||||
|
|
||||||
event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
|
event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
|
||||||
|
|
||||||
|
if (xev->flags & XIPointerEmulated)
|
||||||
|
_gdk_event_set_pointer_emulated (event, TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1233,6 +1298,36 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
|||||||
{
|
{
|
||||||
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
|
XIDeviceEvent *xev = (XIDeviceEvent *) ev;
|
||||||
GdkDevice *source_device;
|
GdkDevice *source_device;
|
||||||
|
gdouble delta_x, delta_y;
|
||||||
|
|
||||||
|
source_device = g_hash_table_lookup (device_manager->id_table,
|
||||||
|
GUINT_TO_POINTER (xev->sourceid));
|
||||||
|
|
||||||
|
if (scroll_valuators_changed (GDK_X11_DEVICE_XI2 (source_device),
|
||||||
|
&xev->valuators, &delta_x, &delta_y))
|
||||||
|
{
|
||||||
|
event->scroll.type = GDK_SCROLL;
|
||||||
|
event->scroll.direction = GDK_SCROLL_SMOOTH;
|
||||||
|
|
||||||
|
event->scroll.window = window;
|
||||||
|
event->scroll.time = xev->time;
|
||||||
|
event->scroll.x = (gdouble) xev->event_x;
|
||||||
|
event->scroll.y = (gdouble) xev->event_y;
|
||||||
|
event->scroll.x_root = (gdouble) xev->root_x;
|
||||||
|
event->scroll.y_root = (gdouble) xev->root_y;
|
||||||
|
event->scroll.delta_x = delta_x;
|
||||||
|
event->scroll.delta_y = delta_y;
|
||||||
|
|
||||||
|
event->scroll.device = g_hash_table_lookup (device_manager->id_table,
|
||||||
|
GUINT_TO_POINTER (xev->deviceid));
|
||||||
|
|
||||||
|
gdk_event_set_source_device (event, source_device);
|
||||||
|
|
||||||
|
event->scroll.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
|
||||||
|
|
||||||
event->motion.type = GDK_MOTION_NOTIFY;
|
event->motion.type = GDK_MOTION_NOTIFY;
|
||||||
event->motion.window = window;
|
event->motion.window = window;
|
||||||
@ -1245,8 +1340,6 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
|||||||
event->motion.device = g_hash_table_lookup (device_manager->id_table,
|
event->motion.device = g_hash_table_lookup (device_manager->id_table,
|
||||||
GINT_TO_POINTER (xev->deviceid));
|
GINT_TO_POINTER (xev->deviceid));
|
||||||
|
|
||||||
source_device = g_hash_table_lookup (device_manager->id_table,
|
|
||||||
GUINT_TO_POINTER (xev->sourceid));
|
|
||||||
gdk_event_set_source_device (event, source_device);
|
gdk_event_set_source_device (event, source_device);
|
||||||
|
|
||||||
event->motion.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
|
event->motion.state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
|
||||||
|
@ -255,6 +255,15 @@ gint _gdk_x11_device_xi2_get_id (GdkX11DeviceXI2 *device);
|
|||||||
|
|
||||||
GdkDevice * _gdk_x11_device_manager_xi2_lookup (GdkX11DeviceManagerXI2 *device_manager_xi2,
|
GdkDevice * _gdk_x11_device_manager_xi2_lookup (GdkX11DeviceManagerXI2 *device_manager_xi2,
|
||||||
gint device_id);
|
gint device_id);
|
||||||
|
void _gdk_x11_device_xi2_add_scroll_valuator (GdkX11DeviceXI2 *device,
|
||||||
|
guint n_valuator,
|
||||||
|
GdkScrollDirection direction);
|
||||||
|
gboolean _gdk_x11_device_xi2_get_scroll_delta (GdkX11DeviceXI2 *device,
|
||||||
|
guint n_valuator,
|
||||||
|
gdouble valuator_value,
|
||||||
|
GdkScrollDirection *direction_ret,
|
||||||
|
gdouble *delta_ret);
|
||||||
|
void _gdk_device_xi2_reset_scroll_valuators (GdkX11DeviceXI2 *device);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user