13
0

Implement YDK Touch API for Linux/X11

This commit is contained in:
Robin Gareus 2024-09-18 03:02:30 +02:00
parent 89da2f2c87
commit 5cf392b17a
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
5 changed files with 162 additions and 2 deletions

View File

@ -164,6 +164,7 @@ def configure(conf):
conf.check_cc(header_name='X11/extensions/Xinerama.h',
lib='Xinerama', uselib_store="XINERAMA", define_name='HAVE_XFREE_XINERAMA',
execute = False, mandatory=False)
autowaf.check_pkg(conf, 'xi', uselib_store='XINPUT2', mandatory=False, atleast_version='1.7.10')
def build(bld):
if not bld.is_defined('YTK'):
@ -202,7 +203,7 @@ def build(bld):
obj.ldflags = '-limm32 -lole32 -lgdi32 -lcomdlg32 -lwinspool -lcomctl32 -luuid'
else:
obj.source = libydk_sources + libydk_x11_sources
obj.uselib += ' GIO-UNIX X11 XEXT XINERAMA RANDR'
obj.uselib += ' GIO-UNIX X11 XEXT XINERAMA RANDR DL'
obj.includes += ['ydk/x11/gdk', 'ydk/gdk/x11']
obj.export_includes += ['ydk/gdk']
obj.export_includes += ['ydk/x11']

View File

@ -65,6 +65,9 @@
#include <X11/extensions/Xrandr.h>
#endif
#ifdef HAVE_XINPUT2
#include <dlfcn.h>
#endif
static void gdk_display_x11_dispose (GObject *object);
static void gdk_display_x11_finalize (GObject *object);
@ -864,6 +867,13 @@ gdk_display_x11_finalize (GObject *object)
g_hash_table_destroy (display_x11->atom_from_virtual);
g_hash_table_destroy (display_x11->atom_to_virtual);
/* Multitouch */
#ifdef HAVE_XINPUT2
if (display_x11->xi.libxi)
dlclose (display_x11->xi.libxi);
g_hash_table_destroy (display_x11->touch_devices);
#endif
/* Leader Window */
XDestroyWindow (display_x11->xdisplay, display_x11->leader_window);

View File

@ -62,6 +62,11 @@
#include <X11/extensions/Xrandr.h>
#endif
#ifdef HAVE_XINPUT2
#include <dlfcn.h>
#include <X11/extensions/XInput2.h>
#endif
#include <X11/Xatom.h>
typedef struct _GdkIOClosure GdkIOClosure;
@ -237,6 +242,64 @@ _gdk_events_init (GdkDisplay *display)
gdk_atom_intern_static_string ("WM_PROTOCOLS"),
gdk_wm_protocols_filter,
NULL);
#ifdef HAVE_XINPUT2
void* lxi = dlopen ("libXi.so", RTLD_NOW | RTLD_GLOBAL);
if (lxi)
{
display_x11->xi.XISelectEvents = dlsym (lxi, "XISelectEvents");
display_x11->xi.XIQueryDevice = dlsym (lxi, "XIQueryDevice");
display_x11->xi.XIFreeDeviceInfo = dlsym (lxi, "XIFreeDeviceInfo");
if (display_x11->xi.XISelectEvents && display_x11->xi.XIQueryDevice && display_x11->xi.XIFreeDeviceInfo)
{
display_x11->xi.libxi = lxi;
}
else
{
dlclose (lxi);
}
}
int firstevent, firsterror;
if (display_x11->xi.libxi && XQueryExtension (display_x11->xdisplay, "XInputExtension", &display_x11->xid_opcode, &firstevent, &firsterror))
{
printf ("CHECK FOR TOUCHSCREENs\n");
int n_devices;
XIDeviceInfo* info;
info = display_x11->xi.XIQueryDevice (display_x11->xdisplay, XIAllDevices, &n_devices);
for (int i = 0; i < n_devices; ++i) {
XIDeviceInfo* dev = &info[i];
if (!dev->enabled) {
continue;
}
if (!(dev->use == XISlavePointer || dev->use == XIFloatingSlave)) {
continue;
}
gboolean direct_touch = FALSE;
XITouchClassInfo* classInfo;
for (int j = 0; j < dev->num_classes; ++j) {
classInfo = (XITouchClassInfo*)(dev->classes[j]);
if (classInfo->type == XITouchClass && ((XITouchClassInfo *)dev->classes[j])->mode == XIDirectTouch) {
direct_touch = TRUE;
}
}
if (direct_touch) {
printf ("XI: touch-device id=%d name='%s' ntouch: %d\n", dev->deviceid, dev->name, classInfo->num_touches);
if (!display_x11->touch_devices) {
display_x11->touch_devices = g_hash_table_new (g_direct_hash, NULL);
}
g_hash_table_insert (display_x11->touch_devices, GUINT_TO_POINTER (dev->deviceid), GUINT_TO_POINTER(1));
}
}
display_x11->xi.XIFreeDeviceInfo (info);
}
#endif
}
void
@ -1233,7 +1296,7 @@ gdk_event_translate (GdkDisplay *display,
event->button.state = (GdkModifierType) xevent->xbutton.state;
event->button.button = xevent->xbutton.button;
event->button.device = display->core_pointer;
if (!set_screen_from_root (display, event, xevent->xbutton.root))
{
return_val = FALSE;
@ -2124,6 +2187,9 @@ gdk_event_translate (GdkDisplay *display,
break;
default:
if (xevent->xcookie.type == GenericEvent) {
XGetEventData (display_x11->xdisplay, &xevent->xcookie);
}
#ifdef HAVE_XKB
if (xevent->type == display_x11->xkb_event_type)
{
@ -2175,6 +2241,47 @@ gdk_event_translate (GdkDisplay *display,
}
else
#endif
#ifdef HAVE_XINPUT2
if (xevent->xcookie.type == GenericEvent && xevent->xcookie.extension == display_x11->xid_opcode
&& display_x11->touch_devices && g_hash_table_lookup (display_x11->touch_devices, GUINT_TO_POINTER (((XIDeviceEvent *)xevent->xcookie.data)->deviceid)))
{
XIDeviceEvent *xev = (XIDeviceEvent *) xevent->xcookie.data;
printf ("TOUCH dev=%d src=%d | dt: %u flags: %x\n", xev->deviceid, xev->sourceid, xev->detail, xev->flags);
window = gdk_window_lookup_for_display (display, xev->event);
g_object_ref (window);
event->touch.window = window;
event->touch.time = xev->time;
event->touch.x = xev->event_x;
event->touch.y = xev->event_y;
event->touch.x_root = xev->root_x;
event->touch.y_root = xev->root_y;
event->touch.state = 0 ; (GdkModifierType) xevent->xbutton.state;
event->touch.sequence = xev->detail;
event->touch.flags = xev->flags;
event->touch.deviceid = xev->deviceid;
switch (xevent->xcookie.evtype) {
case XI_TouchBegin:
event->touch.type = GDK_TOUCH_BEGIN;
break;
case XI_TouchUpdate:
event->touch.type = GDK_TOUCH_UPDATE;
break;
case XI_TouchEnd:
event->touch.type = GDK_TOUCH_END;
break;
default:
return FALSE;
break;
}
if (!set_screen_from_root (display, event, xev->root)) {
return_val = FALSE;
}
}
else
#endif
#if defined(HAVE_XCOMPOSITE) && defined (HAVE_XDAMAGE) && defined (HAVE_XFIXES)
if (display_x11->have_xdamage && window_private && window_private->composited &&
xevent->type == display_x11->xdamage_event_base + XDamageNotify &&

View File

@ -71,6 +71,10 @@
#include <X11/extensions/Xdamage.h>
#endif
#ifdef HAVE_XINPUT2
#include <X11/extensions/XInput2.h>
#endif
const int _gdk_event_mask_table[21] =
{
ExposureMask,
@ -797,6 +801,24 @@ _gdk_window_impl_new (GdkWindow *window,
g_object_ref (window);
_gdk_xid_table_insert (screen_x11->display, &draw_impl->xid, window);
#ifdef HAVE_XINPUT2
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
if (display_x11->touch_devices)
{
XIEventMask evmask;
unsigned char mask[XIMaskLen(XI_LASTEVENT)] = { 0 };
evmask.deviceid = XIAllDevices;
evmask.mask_len = sizeof(mask);
evmask.mask = mask;
XISetMask(evmask.mask, XI_TouchBegin);
XISetMask(evmask.mask, XI_TouchUpdate);
XISetMask(evmask.mask, XI_TouchEnd);
display_x11->xi.XISelectEvents (xdisplay, xid, &evmask, 1);
}
#endif
switch (GDK_WINDOW_TYPE (private))
{
case GDK_WINDOW_DIALOG:

View File

@ -36,6 +36,7 @@
G_BEGIN_DECLS
typedef struct _GdkDisplayX11 GdkDisplayX11;
typedef struct _GdkXInput2Fn GdkXInput2Fn;
typedef struct _GdkDisplayX11Class GdkDisplayX11Class;
#define GDK_TYPE_DISPLAY_X11 (_gdk_display_x11_get_type())
@ -52,6 +53,19 @@ typedef enum
GDK_YES
} GdkTristate;
#ifdef HAVE_XINPUT2
#include <X11/extensions/XInput2.h>
struct _GdkXInput2Fn
{
int (*XISelectEvents)(Display*, Window, XIEventMask*, int);
XIDeviceInfo* (*XIQueryDevice)(Display*, int, int*);
void (*XIFreeDeviceInfo)(XIDeviceInfo*);
void* libxi;
};
#endif
struct _GdkDisplayX11
{
GdkDisplay parent_instance;
@ -155,6 +169,12 @@ struct _GdkDisplayX11
/* The offscreen window that has the pointer in it (if any) */
GdkWindow *active_offscreen_window;
#ifdef HAVE_XINPUT2
int xid_opcode;
GHashTable* touch_devices;
GdkXInput2Fn xi;
#endif
};
struct _GdkDisplayX11Class