gdk/x11: Implement XI2.4 touchpad gesture support

This commit is contained in:
Povilas Kanapickas 2021-09-06 01:32:16 +03:00
parent d981694c64
commit 68bd94fa25
6 changed files with 197 additions and 3 deletions

View File

@ -43,7 +43,8 @@ struct _GdkSeatDefaultPrivate
GDK_ENTER_NOTIFY_MASK | \
GDK_LEAVE_NOTIFY_MASK | \
GDK_PROXIMITY_IN_MASK | \
GDK_PROXIMITY_OUT_MASK)
GDK_PROXIMITY_OUT_MASK | \
GDK_TOUCHPAD_GESTURE_MASK)
G_DEFINE_TYPE_WITH_PRIVATE (GdkSeatDefault, gdk_seat_default, GDK_TYPE_SEAT)

View File

@ -619,6 +619,20 @@ _gdk_x11_device_xi2_translate_event_mask (GdkX11DeviceManagerXI2 *device_manager
}
#endif /* XINPUT_2_2 */
#ifdef XINPUT_2_4
/* XInput 2.4 includes touchpad gesture support */
if (minor >= 4 &&
event_mask & GDK_TOUCHPAD_GESTURE_MASK)
{
XISetMask (mask, XI_GesturePinchBegin);
XISetMask (mask, XI_GesturePinchUpdate);
XISetMask (mask, XI_GesturePinchEnd);
XISetMask (mask, XI_GestureSwipeBegin);
XISetMask (mask, XI_GestureSwipeUpdate);
XISetMask (mask, XI_GestureSwipeEnd);
}
#endif
return mask;
}
@ -667,6 +681,36 @@ _gdk_x11_device_xi2_translate_state (XIModifierState *mods_state,
return state;
}
#ifdef XINPUT_2_4
guint
_gdk_x11_device_xi2_gesture_type_to_phase (int evtype, int flags)
{
switch (evtype)
{
case XI_GesturePinchBegin:
case XI_GestureSwipeBegin:
return GDK_TOUCHPAD_GESTURE_PHASE_BEGIN;
case XI_GesturePinchUpdate:
case XI_GestureSwipeUpdate:
return GDK_TOUCHPAD_GESTURE_PHASE_UPDATE;
case XI_GesturePinchEnd:
if (flags & XIGesturePinchEventCancelled)
return GDK_TOUCHPAD_GESTURE_PHASE_CANCEL;
return GDK_TOUCHPAD_GESTURE_PHASE_END;
case XI_GestureSwipeEnd:
if (flags & XIGestureSwipeEventCancelled)
return GDK_TOUCHPAD_GESTURE_PHASE_CANCEL;
return GDK_TOUCHPAD_GESTURE_PHASE_END;
default:
g_assert_not_reached ();
return GDK_TOUCHPAD_GESTURE_PHASE_END;
}
}
#endif /* XINPUT_2_4 */
void
_gdk_x11_device_xi2_add_scroll_valuator (GdkX11DeviceXI2 *device,
guint n_valuator,

View File

@ -41,7 +41,7 @@ _gdk_x11_device_manager_new (GdkDisplay *display)
int major, minor;
major = 2;
minor = 3;
minor = 4;
if (XIQueryVersion (xdisplay, &major, &minor) != BadRequest)
{

View File

@ -1275,6 +1275,26 @@ get_event_surface (GdkEventTranslator *translator,
}
}
break;
#ifdef XINPUT_2_4
case XI_GesturePinchBegin:
case XI_GesturePinchUpdate:
case XI_GesturePinchEnd:
{
XIGesturePinchEvent *xev = (XIGesturePinchEvent *) ev;
surface = gdk_x11_surface_lookup_for_display (display, xev->event);
}
break;
case XI_GestureSwipeBegin:
case XI_GestureSwipeUpdate:
case XI_GestureSwipeEnd:
{
XIGestureSwipeEvent *xev = (XIGestureSwipeEvent *) ev;
surface = gdk_x11_surface_lookup_for_display (display, xev->event);
}
break;
#endif /* XINPUT_2_4 */
case XI_Enter:
case XI_Leave:
case XI_FocusIn:
@ -1881,6 +1901,126 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
break;
#endif /* XINPUT_2_2 */
#ifdef XINPUT_2_4
case XI_GesturePinchBegin:
case XI_GesturePinchUpdate:
case XI_GesturePinchEnd:
{
XIGesturePinchEvent *xev = (XIGesturePinchEvent *) ev;
GdkModifierType state;
GdkTouchpadGesturePhase phase;
double x, y;
#ifdef G_ENABLE_DEBUG
const char *event_name = "";
switch (xev->evtype)
{
case XI_GesturePinchBegin:
event_name = "begin";
break;
case XI_GesturePinchUpdate:
event_name = "update";
break;
case XI_GesturePinchEnd:
event_name = "end";
break;
default:
break;
}
#endif
GDK_NOTE (EVENTS,
g_message ("pinch gesture %s:\twindow %ld\n\tfinger_count: %u%s",
event_name,
xev->event,
xev->detail,
xev->flags & XIGesturePinchEventCancelled ? "\n\tcancelled" : ""));
device = g_hash_table_lookup (device_manager->id_table,
GINT_TO_POINTER (xev->deviceid));
state = _gdk_x11_device_xi2_translate_state (&xev->mods, NULL, &xev->group);
phase = _gdk_x11_device_xi2_gesture_type_to_phase (xev->evtype, xev->flags);
x = (double) xev->event_x / scale;
y = (double) xev->event_y / scale;
event = gdk_touchpad_event_new_pinch (surface,
device,
xev->time,
state,
phase,
x, y,
xev->detail,
xev->delta_x,
xev->delta_y,
xev->scale,
xev->delta_angle * G_PI / 180);
if (ev->evtype == XI_GesturePinchBegin)
set_user_time (event);
}
break;
case XI_GestureSwipeBegin:
case XI_GestureSwipeUpdate:
case XI_GestureSwipeEnd:
{
XIGestureSwipeEvent *xev = (XIGestureSwipeEvent *) ev;
GdkModifierType state;
GdkTouchpadGesturePhase phase;
double x, y;
#ifdef G_ENABLE_DEBUG
const char *event_name = "";
switch (xev->evtype)
{
case XI_GestureSwipeBegin:
event_name = "begin";
break;
case XI_GestureSwipeUpdate:
event_name = "update";
break;
case XI_GestureSwipeEnd:
event_name = "end";
break;
default:
break;
}
#endif
GDK_NOTE (EVENTS,
g_message ("swipe gesture %s:\twindow %ld\n\tfinger_count: %u%s",
event_name,
xev->event,
xev->detail,
xev->flags & XIGestureSwipeEventCancelled ? "\n\tcancelled" : ""));
device = g_hash_table_lookup (device_manager->id_table,
GINT_TO_POINTER (xev->deviceid));
state = _gdk_x11_device_xi2_translate_state (&xev->mods, NULL, &xev->group);
phase = _gdk_x11_device_xi2_gesture_type_to_phase (xev->evtype, xev->flags);
x = (double) xev->event_x / scale;
y = (double) xev->event_y / scale;
event = gdk_touchpad_event_new_swipe (surface,
device,
xev->time,
state,
phase,
x, y,
xev->detail,
xev->delta_x,
xev->delta_y);
if (ev->evtype == XI_GestureSwipeBegin)
set_user_time (event);
}
break;
#endif /* XINPUT_2_4 */
case XI_Enter:
case XI_Leave:
{
@ -1992,7 +2132,8 @@ gdk_x11_device_manager_xi2_get_handled_events (GdkEventTranslator *translator)
GDK_BUTTON3_MOTION_MASK |
GDK_BUTTON_MOTION_MASK |
GDK_FOCUS_CHANGE_MASK |
GDK_TOUCH_MASK);
GDK_TOUCH_MASK |
GDK_TOUCHPAD_GESTURE_MASK);
}
static void

View File

@ -140,6 +140,7 @@ guchar * _gdk_x11_device_xi2_translate_event_mask (GdkX11DeviceManagerXI2 *devic
guint _gdk_x11_device_xi2_translate_state (XIModifierState *mods_state,
XIButtonState *buttons_state,
XIGroupState *group_state);
guint _gdk_x11_device_xi2_gesture_type_to_phase (int evtype, int flags);
int _gdk_x11_device_xi2_get_id (GdkX11DeviceXI2 *device);
void _gdk_device_xi2_unset_scroll_valuators (GdkX11DeviceXI2 *device);

View File

@ -557,6 +557,13 @@ if x11_enabled
endif
cdata.set('XINPUT_2_2', 1)
has_gesture_pinch_event = cc.has_member('XIGesturePinchEvent', 'type', dependencies: xi_dep,
prefix: '''#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>''')
if has_gesture_pinch_event
cdata.set('XINPUT_2_4', 1)
endif
xinerama_dep = dependency('xinerama')
if not cc.has_header_symbol('X11/extensions/Xinerama.h', 'XineramaQueryExtension', dependencies: xinerama_dep)
error('X11 backend enabled, but Xinerama extension does not work.')