ecore-x - add some xi2 api's for fiddling with device properties
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>
Sat, 16 Nov 2019 13:00:21 +0000 (13:00 +0000)
committerJongmin Lee <jm105.lee@samsung.com>
Sun, 17 Nov 2019 21:03:58 +0000 (06:03 +0900)
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
src/lib/ecore_x/Ecore_X_Atoms.h
src/lib/ecore_x/ecore_x.c
src/lib/ecore_x/ecore_x_atoms_decl.h
src/lib/ecore_x/ecore_x_xi2.c

index 223bc91..7d44230 100644 (file)
@@ -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
index 15c8037..35f3a88 100644 (file)
@@ -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;
index a32f42f..cbe2d13 100644 (file)
@@ -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();
index 78545c7..c4d8ead 100644 (file)
@@ -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 },
index 089c2a7..6bbbd85 100644 (file)
@@ -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.