From 42e691d9b4de72755747a376655663b1079bb592 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Sat, 16 Nov 2019 13:00:21 +0000 Subject: [PATCH] ecore-x - add some xi2 api's for fiddling with device properties add some infra to be able to get and set device properties (as well as know if devices changed to we can refersh a gui or re-apply saved settings etc.). it doesn't do everything but... it adds enough to build on in e. --- src/lib/ecore_x/Ecore_X.h | 11 ++ src/lib/ecore_x/Ecore_X_Atoms.h | 2 + src/lib/ecore_x/ecore_x.c | 4 + src/lib/ecore_x/ecore_x_atoms_decl.h | 4 + src/lib/ecore_x/ecore_x_xi2.c | 179 +++++++++++++++++++++++++++ 5 files changed, 200 insertions(+) diff --git a/src/lib/ecore_x/Ecore_X.h b/src/lib/ecore_x/Ecore_X.h index 223bc912ae..7d4423048b 100644 --- a/src/lib/ecore_x/Ecore_X.h +++ b/src/lib/ecore_x/Ecore_X.h @@ -1197,6 +1197,8 @@ EAPI extern int ECORE_X_RAW_BUTTON_PRESS; /**< @since 1.8 */ EAPI extern int ECORE_X_RAW_BUTTON_RELEASE; /**< @since 1.8 */ EAPI extern int ECORE_X_RAW_MOTION; /**< @since 1.8 */ +EAPI extern int ECORE_X_DEVICES_CHANGE; /**< @since 1.24 */ + typedef enum _Ecore_X_WM_Protocol { /** If enabled the window manager will be asked to send a @@ -2568,6 +2570,15 @@ EAPI Eina_Bool ecore_x_input_raw_select(Ecore_X_Window win); /**< @since 1.8 EAPI Eina_Bool ecore_x_input_touch_devices_grab(Ecore_X_Window win); /**< @since 1.15 */ EAPI Eina_Bool ecore_x_input_touch_devices_ungrab(void); /**< @since 1.15 */ +EAPI void ecore_x_input_devices_update(void); /**< @since 1.24 */ +EAPI int ecore_x_input_device_num_get(void); /**< @since 1.24 */ +EAPI int ecore_x_input_device_id_get(int slot); /**< @since 1.24 */ +EAPI const char *ecore_x_input_device_name_get(int slot); /**< @since 1.24 */ +EAPI char **ecore_x_input_device_properties_list(int slot, int *num_ret); /**< @since 1.24 */ +EAPI void ecore_x_input_device_properties_free(char **list, int num); /**< @since 1.24 */ +EAPI void *ecore_x_input_device_property_get(int slot, const char *prop, int *num_ret, Ecore_X_Atom *format_ret, int *unit_size_ret); /**< @since 1.24 */ +EAPI void ecore_x_input_device_property_set(int slot, const char *prop, void *data, int num, Ecore_X_Atom format, int unit_size); /**< @since 1.24 */ + EAPI Eina_Bool ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win); typedef enum _Ecore_X_Gesture_Event_Mask diff --git a/src/lib/ecore_x/Ecore_X_Atoms.h b/src/lib/ecore_x/Ecore_X_Atoms.h index 15c8037c97..35f3a885c2 100644 --- a/src/lib/ecore_x/Ecore_X_Atoms.h +++ b/src/lib/ecore_x/Ecore_X_Atoms.h @@ -9,6 +9,8 @@ /* generic atoms */ EAPI extern Ecore_X_Atom ECORE_X_ATOM_ATOM; EAPI extern Ecore_X_Atom ECORE_X_ATOM_CARDINAL; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_INTEGER; /**< @since 1.24 */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_FLOAT; /**< @since 1.24 */ EAPI extern Ecore_X_Atom ECORE_X_ATOM_COMPOUND_TEXT; EAPI extern Ecore_X_Atom ECORE_X_ATOM_FILE_NAME; EAPI extern Ecore_X_Atom ECORE_X_ATOM_STRING; diff --git a/src/lib/ecore_x/ecore_x.c b/src/lib/ecore_x/ecore_x.c index a32f42f641..cbe2d137cd 100644 --- a/src/lib/ecore_x/ecore_x.c +++ b/src/lib/ecore_x/ecore_x.c @@ -167,6 +167,8 @@ EAPI int ECORE_X_RAW_BUTTON_PRESS = 0; EAPI int ECORE_X_RAW_BUTTON_RELEASE = 0; EAPI int ECORE_X_RAW_MOTION = 0; +EAPI int ECORE_X_DEVICES_CHANGE = 0; + #ifdef LOGRT static double t0 = 0.0; static Status (*_logrt_real_reply)(Display *disp, @@ -655,6 +657,8 @@ _ecore_x_init2(void) ECORE_X_RAW_BUTTON_RELEASE = ecore_event_type_new(); ECORE_X_RAW_MOTION = ecore_event_type_new(); + ECORE_X_DEVICES_CHANGE = ecore_event_type_new(); + _ecore_x_modifiers_get(); _ecore_x_atoms_init(); diff --git a/src/lib/ecore_x/ecore_x_atoms_decl.h b/src/lib/ecore_x/ecore_x_atoms_decl.h index 78545c7d5e..c4d8ead63f 100644 --- a/src/lib/ecore_x/ecore_x_atoms_decl.h +++ b/src/lib/ecore_x/ecore_x_atoms_decl.h @@ -1,6 +1,8 @@ /* generic atoms */ EAPI Ecore_X_Atom ECORE_X_ATOM_ATOM = 0; EAPI Ecore_X_Atom ECORE_X_ATOM_CARDINAL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_INTEGER = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_FLOAT = 0; EAPI Ecore_X_Atom ECORE_X_ATOM_COMPOUND_TEXT = 0; EAPI Ecore_X_Atom ECORE_X_ATOM_FILE_NAME = 0; EAPI Ecore_X_Atom ECORE_X_ATOM_STRING = 0; @@ -398,6 +400,8 @@ const Atom_Item atom_items[] = { { "ATOM", &ECORE_X_ATOM_ATOM }, { "CARDINAL", &ECORE_X_ATOM_CARDINAL }, + { "INTEGER", &ECORE_X_ATOM_INTEGER }, + { "FLOAT", &ECORE_X_ATOM_FLOAT }, { "COMPOUND_TEXT", &ECORE_X_ATOM_COMPOUND_TEXT }, { "FILE_NAME", &ECORE_X_ATOM_FILE_NAME }, { "STRING", &ECORE_X_ATOM_STRING }, diff --git a/src/lib/ecore_x/ecore_x_xi2.c b/src/lib/ecore_x/ecore_x_xi2.c index 089c2a7029..6bbbd855b6 100644 --- a/src/lib/ecore_x/ecore_x_xi2.c +++ b/src/lib/ecore_x/ecore_x_xi2.c @@ -36,6 +36,7 @@ typedef struct _Ecore_X_Touch_Device_Info } Ecore_X_Touch_Device_Info; #endif /* ifdef ECORE_XI2_2 */ +static Ecore_Job *update_devices_job = NULL; static XIDeviceInfo *_ecore_x_xi2_devs = NULL; static int _ecore_x_xi2_num = 0; #ifdef ECORE_XI2_2 @@ -64,6 +65,18 @@ _ecore_x_input_init(void) return; } + // listen for device changes + XIEventMask m; + m.deviceid = XIAllDevices; + m.mask_len = XIMaskLen(XI_LASTEVENT); + m.mask = calloc( m.mask_len, 1); + if (!m.mask) return; + XISetMask(m.mask, XI_DeviceChanged); + XISetMask(m.mask, XI_HierarchyChanged); + XISetMask(m.mask, XI_PropertyEvent); + XISelectEvents(_ecore_x_disp, DefaultRootWindow(_ecore_x_disp), &m, 1); + free(m.mask); + _ecore_x_xi2_devs = XIQueryDevice(_ecore_x_disp, XIAllDevices, &_ecore_x_xi2_num); #endif /* ifdef ECORE_XI2 */ @@ -130,6 +143,15 @@ _ecore_x_input_get_axis_label(char *axis_name) void _ecore_x_input_shutdown(void) { + XIEventMask m; + m.deviceid = XIAllDevices; + m.mask_len = XIMaskLen(XI_LASTEVENT); + m.mask = calloc( m.mask_len, 1); + if (m.mask) + { + XISelectEvents(_ecore_x_disp, DefaultRootWindow(_ecore_x_disp), &m, 1); + free(m.mask); + } #ifdef ECORE_XI2 if (_ecore_x_xi2_devs) { @@ -147,6 +169,8 @@ _ecore_x_input_shutdown(void) eina_list_free(_ecore_x_xi2_grabbed_devices_list); _ecore_x_xi2_grabbed_devices_list = NULL; #endif /* ifdef ECORE_XI2 */ + if (update_devices_job) ecore_job_del(update_devices_job); + update_devices_job = NULL; } #ifdef ECORE_XI2 @@ -655,6 +679,14 @@ _ecore_x_input_device_lookup(int deviceid) } #endif +static void +_cb_update_devices(void *data EINA_UNUSED) +{ + update_devices_job = NULL; + ecore_x_input_devices_update(); + ecore_event_add(ECORE_X_DEVICES_CHANGE, NULL, NULL, NULL); +} + void _ecore_x_input_handler(XEvent *xevent) { @@ -663,6 +695,14 @@ _ecore_x_input_handler(XEvent *xevent) switch (xevent->xcookie.evtype) { + case XI_DeviceChanged: + case XI_HierarchyChanged: + case XI_PropertyEvent: + if (update_devices_job) ecore_job_del(update_devices_job); + update_devices_job = ecore_job_add(_cb_update_devices, NULL); + // XXX: post change event + break; + case XI_RawMotion: case XI_RawButtonPress: case XI_RawButtonRelease: @@ -904,3 +944,142 @@ ecore_x_input_touch_devices_ungrab(void) { return _ecore_x_input_touch_devices_grab(0, EINA_FALSE); } + +// XXX +EAPI void +ecore_x_input_devices_update(void) +{ + if (_ecore_x_xi2_devs) XIFreeDeviceInfo(_ecore_x_xi2_devs); + _ecore_x_xi2_num = 0; + _ecore_x_xi2_devs = XIQueryDevice(_ecore_x_disp, XIAllDevices, + &_ecore_x_xi2_num); +} + +EAPI int +ecore_x_input_device_num_get(void) +{ + return _ecore_x_xi2_num; +} + +EAPI int +ecore_x_input_device_id_get(int slot) +{ + if ((slot < 0) || (slot >= _ecore_x_xi2_num)) return 0; + return _ecore_x_xi2_devs[slot].deviceid; +} + +EAPI const char * +ecore_x_input_device_name_get(int slot) +{ + if ((slot < 0) || (slot >= _ecore_x_xi2_num)) return NULL; + return _ecore_x_xi2_devs[slot].name; +} + +EAPI char ** +ecore_x_input_device_properties_list(int slot, int *num_ret) +{ + char **atoms = NULL; + int num = 0, i; + Atom *a; + + if ((slot < 0) || (slot >= _ecore_x_xi2_num)) goto err; + a = XIListProperties(_ecore_x_disp, _ecore_x_xi2_devs[slot].deviceid, &num); + if (!a) goto err; + atoms = calloc(num, sizeof(char *)); + if (!atoms) goto err; + for (i = 0; i < num; i++) + { + Ecore_X_Atom at = a[i]; + atoms[i] = ecore_x_atom_name_get(at); + if (!atoms[i]) goto err; + } + XFree(a); + *num_ret = num; + return atoms; +err: + if (atoms) + { + for (i = 0; i < num; i++) free(atoms[i]); + free(atoms); + } + *num_ret = 0; + return NULL; +} + +EAPI void +ecore_x_input_device_properties_free(char **list, int num) +{ + int i; + + for (i = 0; i < num; i++) free(list[i]); + free(list); +} + +// unit_size_ret will be 8, 16, 32 +// fromat_ret will almost be one of: +// ECORE_X_ATOM_CARDINAL +// ECORE_X_ATOM_INTEGER +// ECORE_X_ATOM_FLOAT (unit_size 32 only) +// ECORE_X_ATOM_ATOM // very rare +// ECORE_X_ATOM_STRING (unit_size 8 only - guaratee nul termination) + +EAPI void * +ecore_x_input_device_property_get(int slot, const char *prop, int *num_ret, + Ecore_X_Atom *format_ret, int *unit_size_ret) +{ + Atom a, a_type = 0; + int fmt = 0; + unsigned long num = 0, dummy; + unsigned char *data = NULL; + unsigned char *d = NULL; + + if ((slot < 0) || (slot >= _ecore_x_xi2_num)) goto err; + a = XInternAtom(_ecore_x_disp, prop, False); + if (!XIGetProperty(_ecore_x_disp, _ecore_x_xi2_devs[slot].deviceid, + a, 0, 65536, False, AnyPropertyType, &a_type, &fmt, + &num, &dummy, &data)) goto err; + *format_ret = a_type; + *num_ret = num; + *unit_size_ret = fmt; + if ((a_type == ECORE_X_ATOM_STRING) && (fmt == 8)) + { + d = malloc(num + 1); + if (!d) goto err2; + memcpy(d, data, num); + d[num] = 0; + } + else + { + if (fmt == 8 ) d = malloc(num); + else if (fmt == 16) d = malloc(num * 2); + else if (fmt == 32) d = malloc(num * 4); + if (!d) goto err2; + memcpy(d, data, num * (fmt / 8)); + } + XFree(data); + return d; +err2: + XFree(data); +err: + *num_ret = 0; + *format_ret = 0; + *unit_size_ret = 0; + return NULL; +} + +EAPI void +ecore_x_input_device_property_set(int slot, const char *prop, void *data, + int num, Ecore_X_Atom format, int unit_size) +{ + Atom a, a_type = 0; + if ((slot < 0) || (slot >= _ecore_x_xi2_num)) return; + a = XInternAtom(_ecore_x_disp, prop, False); + a_type = format; + XIChangeProperty(_ecore_x_disp, _ecore_x_xi2_devs[slot].deviceid, + a, a_type, unit_size, XIPropModeReplace, data, num); +} + +// XXX: add api's to get XIDeviceInfo->... stuff like +// use, attachement, enabled, num_classes, classes (which list number of +// buttons and their names, keycodes, valuators (mouse etc.), touch devices +// etc.