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.