raster pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=26c943bac0d4b62bce63a6b575c58d15e5e6113f

commit 26c943bac0d4b62bce63a6b575c58d15e5e6113f
Author: Jason Gerecke <killert...@gmail.com>
Date:   Tue Nov 25 12:07:50 2014 +0900

    Expose device (e.g. pen) axis information to applications
    
    Summary:
    This patch set adds the necessary code to expose device axis state to 
applications. This was primarily written with graphics tablets in mind, which 
-- in addition to acting like a mouse -- also provide information about pen 
pressure, tilt, etc. Other devices could potentially benefit from this API as 
well: touchscreens, joysticks, knob controllers, "spaceballs", etc.
    
    Whenever an update to the device state is recieved, an "Axis update" event 
is synthesized. This event contains the updated information, typically scaled 
and normalized to a particular logical range (e.g. zero to one for pressure, 
-pi to pi radians for angles, etc.). Information about the tool which generated 
the event is also stored so that applications can disambiguate events from 
multiple devices (or in the case of multitouch screens, individual fingers).
    
    This API is only wired up for use with X11 at the moment. Support for other 
backends (e.g. Wayland) should be easy to add for those familiar them.
    
    **Note**: The following is a list of changes from the "v2" patches 
originally sent to the mailinglist
    
    //Define and implement new Ecore_Event_Axis_Update events//
     * Harcode axis labels instead of including xserver-properties.h
     * Use C89-style comments
     * Use doxygen comments
     * Update comment text to note axes with unbounded/undefined ranges/units
     * Create "Ecore_Axis" and "Ecore_Axis_Label" typedefs
     * Reference typedef'd instead of raw types
     * Adjust how we count through valuators to support tilt/az
     * Add support for tilt and azimuth
     * Tweak memory management in case number of valuators differ
     * Expand TWIST axis normalization to declared range
     * Only normalize TWIST axis if resolution == 1 (wacom bug)
     * Cache label atoms on first use to minimize round-trips
    
    //Implement EVAS_CALLBACK_AXIS_UPDATE event and friends//
     * Update to doxygen comments
     * Update comment text to note axes with unbounded/undefined ranges/units
     * Typedef 'Evas_Axis_Label', 'Evas_Axis'
     * Move typedef for 'Evas_Event_Axis_Update'
     * Reference typedef'd instead of raw types
    
    //Wire the Ecore and Evas implementations of axis update events together//
     * Expose ecore_event_evas_axis_update in Ecore_Input_Evas.h
     * Move ecore_event_evas_axis_update to more logical position
    
    //DEBUG: Add axis update logging to evas-multi-touch.c//
     * Removed from patch set
    
    //Make evas-multi-touch demo use new axis functionality//
     * Have pressure adjust rectangle brightness instead of size
     * Use more available axis data when rendering rectangle (azimuth, tilt, 
twist)
    
    Test Plan: The evas-multi-touch demo was updated to support axis update 
events. A graphics tablet was then used to verify that the pressure, azimuth, 
tilt, and twist data was coming through correctly.
    
    Reviewers: cedric, raster
    
    Subscribers: cedric
    
    Differential Revision: https://phab.enlightenment.org/D1514
    
    Conflicts:
        src/lib/ecore_input/Ecore_Input.h
    
    Carsten Haitzler -
    
    ** fixed forward enum typedefs (make things unhappy)
    ** fixed conflict above
    ** fixed wrong param type for _evas_canvas_event_feed_axis_update()
    ** fixed @sinces to be 1.13
    ** fixed formatting/indeting
    ** fixed order of operation reliance in if's with ()'s to be clear
    ** fixed functions to be static that should have been
---
 src/examples/evas/evas-multi-touch.c            |  70 +++++
 src/lib/ecore_input/Ecore_Input.h               |  39 +++
 src/lib/ecore_input/ecore_input.c               |   3 +
 src/lib/ecore_input_evas/Ecore_Input_Evas.h     |   1 +
 src/lib/ecore_input_evas/ecore_input_evas.c     |  18 +-
 src/lib/ecore_x/Ecore_X.h                       |   2 +-
 src/lib/ecore_x/xlib/ecore_x_events.c           |  47 +++
 src/lib/ecore_x/xlib/ecore_x_private.h          |  10 +
 src/lib/ecore_x/xlib/ecore_x_xi2.c              | 375 +++++++++++++++++-------
 src/lib/evas/Evas_Common.h                      |  39 +++
 src/lib/evas/Evas_Eo.h                          |   2 +
 src/lib/evas/Evas_Legacy.h                      |   4 +
 src/lib/evas/canvas/evas_callbacks.c            |   6 +-
 src/lib/evas/canvas/evas_canvas.eo              |  19 ++
 src/lib/evas/canvas/evas_events.c               |  55 ++++
 src/lib/evas/include/evas_private.h             |   1 +
 src/modules/ecore_evas/engines/x/ecore_evas_x.c |  14 +-
 17 files changed, 592 insertions(+), 113 deletions(-)

diff --git a/src/examples/evas/evas-multi-touch.c 
b/src/examples/evas/evas-multi-touch.c
index ac90363..6cd5b4d 100644
--- a/src/examples/evas/evas-multi-touch.c
+++ b/src/examples/evas/evas-multi-touch.c
@@ -98,6 +98,38 @@ _touch_move(Touch_Point *tp, int x, int y)
 }
 
 static void
+_touch_update(Touch_Point *tp, float azimuth, float tilt, float twist, float 
pressure)
+{
+   Evas_Map* m = evas_map_new(4);
+   evas_map_util_points_populate_from_object(m, tp->move);
+
+   int r = tp->r * (1+pressure);
+   int g = tp->g * (1+pressure);
+   int b = tp->b * (1+pressure);
+
+   int x, y, w, h;
+   evas_object_geometry_get(tp->move, &x, &y, &w, &h);
+
+   float vheight = cos(tilt);
+   float vbase = sin(tilt);
+   float vx = cos(azimuth) * vbase;
+   float vy = sin(azimuth) * vbase;
+   float rx = (-atan2(vheight,vy) + M_PI/2) * 180.0/M_PI;
+   float ry = (-atan2(vheight,vx) + M_PI/2) * 180.0/M_PI;
+   float rz = (twist) * 180.0/M_PI;
+
+   /* apply */
+   evas_object_color_set(tp->move, r, g, b, ALPHA_MOVE);
+   evas_map_util_3d_rotate(m, rx, ry, rz, x+w/2, y+w/2, 0);
+   evas_map_util_3d_perspective(m, x+w/2, y+w/2, 10, 100);
+   evas_map_util_3d_lighting(m, WIDTH/2,HEIGHT/2, -500, 255, 255, 255, 192, 
192, 192 );
+
+   evas_object_map_set(tp->move, m);
+   evas_object_map_enable_set(tp->move, EINA_TRUE);
+   evas_map_free(m);
+}
+
+static void
 _touch_end(Touch_Point *tp, int x, int y)
 {
    evas_object_hide(tp->move);
@@ -140,6 +172,18 @@ _mouse_move_handle(int device, int x, int y)
 }
 
 static void
+_mouse_update_handle(int device, float azimuth, float tilt, float twist, float 
pressure)
+{
+   Touch_Point *tp;
+
+   tp = eina_hash_find(d.hash, &device);
+   if (!tp)
+     return;
+
+   _touch_update(tp, azimuth, tilt, twist, pressure);
+}
+
+static void
 _mouse_up_handle(int device, int x, int y)
 {
    Touch_Point *tp;
@@ -202,6 +246,30 @@ _multi_up_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, 
Evas_Object *obj EINA_
    _mouse_up_handle(ev->device, ev->cur.canvas.x, ev->cur.canvas.y);
 }
 
+static void
+_axis_update_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj 
EINA_UNUSED, void *event_info)
+{
+   Evas_Event_Axis_Update *ev = event_info;
+   float twist = 0, azimuth = 0, tilt = 0;
+   float pressure = 1;
+   int i;
+
+   for (i = 0; i < ev->naxis; i++)
+     {
+        float val = ev->axis[i].value;
+        switch (ev->axis[i].label)
+          {
+          case EVAS_AXIS_LABEL_PRESSURE: pressure = val; break;
+          case EVAS_AXIS_LABEL_TWIST:    twist    = val; break;
+          case EVAS_AXIS_LABEL_AZIMUTH:  azimuth  = val; break;
+          case EVAS_AXIS_LABEL_TILT:     tilt     = val; break;
+          default: break;
+          }
+     }
+
+    _mouse_update_handle(ev->toolid, azimuth, tilt, twist, pressure);
+}
+
 int
 main(void)
 {
@@ -242,6 +310,8 @@ main(void)
    evas_object_event_callback_add(d.bg, EVAS_CALLBACK_MULTI_MOVE, 
_multi_move_cb, &d);
    evas_object_event_callback_add(d.bg, EVAS_CALLBACK_MOUSE_MOVE, 
_mouse_move_cb, &d);
 
+   evas_object_event_callback_add(d.bg, EVAS_CALLBACK_AXIS_UPDATE, 
_axis_update_cb, &d);
+
    evas_object_focus_set(d.bg, EINA_TRUE); /* so we get input events */
 
    ecore_main_loop_begin();
diff --git a/src/lib/ecore_input/Ecore_Input.h 
b/src/lib/ecore_input/Ecore_Input.h
index e6e1259..b9723c8 100644
--- a/src/lib/ecore_input/Ecore_Input.h
+++ b/src/lib/ecore_input/Ecore_Input.h
@@ -53,6 +53,7 @@ extern "C" {
    EAPI extern int ECORE_EVENT_MOUSE_WHEEL;
    EAPI extern int ECORE_EVENT_MOUSE_IN;
    EAPI extern int ECORE_EVENT_MOUSE_OUT;
+   EAPI extern int ECORE_EVENT_AXIS_UPDATE; /**< @since 1.13 */
 
 #define ECORE_EVENT_MODIFIER_SHIFT      0x0001
 #define ECORE_EVENT_MODIFIER_CTRL       0x0002
@@ -78,6 +79,8 @@ extern "C" {
    typedef struct _Ecore_Event_Mouse_Move   Ecore_Event_Mouse_Move;
    typedef struct _Ecore_Event_Mouse_IO     Ecore_Event_Mouse_IO;
    typedef struct _Ecore_Event_Modifiers    Ecore_Event_Modifiers;
+   typedef struct _Ecore_Event_Axis_Update  Ecore_Event_Axis_Update; /**< 
@since 1.13 */
+   typedef struct _Ecore_Axis               Ecore_Axis; /**< @since 1.13 */
 
    /**
     * @typedef Ecore_Event_Modifier
@@ -246,6 +249,42 @@ extern "C" {
         } multi;
      };
 
+   typedef enum _Ecore_Axis_Label
+     {
+        ECORE_AXIS_LABEL_UNKNOWN,       /**< Axis type is not known. Range: 
Unbounded. Unit: Undefined. @since 1.13 */
+        ECORE_AXIS_LABEL_X,             /**< Position along physical X axis; 
not window relative. Range: Unbounded. Unit: Undefined. @since 1.13 */
+        ECORE_AXIS_LABEL_Y,             /**< Position along physical Y axis; 
not window relative. Range: Unbounded. Unit: Undefined. @since 1.13 */
+        ECORE_AXIS_LABEL_PRESSURE,      /**< Force applied to tool tip. Range: 
[0.0, 1.0]. Unit: Unitless. @since 1.13 */
+        ECORE_AXIS_LABEL_DISTANCE,      /**< Relative distance along physical 
Z axis. Range: [0.0, 1.0]. Unit: Unitless. @since 1.13 */
+        ECORE_AXIS_LABEL_AZIMUTH,       /**< Angle of tool about the Z axis 
from positive X axis. Range: [-PI, PI]. Unit: Radians. @since 1.13*/
+        ECORE_AXIS_LABEL_TILT,          /**< Angle of tool about plane of 
sensor from positive Z axis. Range: [0.0, PI]. Unit: Radians. @since 1.13 */
+        ECORE_AXIS_LABEL_TWIST,         /**< Rotation of tool about its major 
axis from its "natural" position. Range: [-PI, PI] Unit: Radians. @since 1.13 */
+        ECORE_AXIS_LABEL_TOUCH_WIDTH_MAJOR,   /**< Length of contact ellipse 
along AZIMUTH. Range: Unbounded: Unit: Same as ECORE_AXIS_LABEL_{X,Y}. @since 
1.13 */
+        ECORE_AXIS_LABEL_TOUCH_WIDTH_MINOR,   /**< Length of contact ellipse 
perpendicular to AZIMUTH. Range: Unbounded. Unit: Same as 
ECORE_AXIS_LABEL_{X,Y}. @since 1.13 */
+        ECORE_AXIS_LABEL_TOOL_WIDTH_MAJOR,    /**< Length of tool ellipse 
along AZIMUTH. Range: Unbounded. Unit: Same as ECORE_AXIS_LABEL_{X,Y}. @since 
1.13 */
+        ECORE_AXIS_LABEL_TOOL_WIDTH_MINOR     /**< Length of tool ellipse 
perpendicular to AZIMUTH. Range: Unbounded. Unit: Same as 
ECORE_AXIS_LABEL_{X,Y}. @since 1.13 */
+   } Ecore_Axis_Label; /**< @since 1.13 */
+
+   struct _Ecore_Axis
+     {
+        Ecore_Axis_Label label;
+        double value;
+     };
+
+   struct _Ecore_Event_Axis_Update
+     {
+        Ecore_Window     window;
+        Ecore_Window     root_window;
+        Ecore_Window     event_window;
+
+        unsigned int timestamp;
+        int device;
+        int toolid;
+
+        int naxis;
+        Ecore_Axis *axis;
+     };
+
    /**
     * @struct _Ecore_Event_Mouse_IO
     * Contains information about an Ecore mouse input/output event.
diff --git a/src/lib/ecore_input/ecore_input.c 
b/src/lib/ecore_input/ecore_input.c
index 8f4b1f9..ac8b60d 100644
--- a/src/lib/ecore_input/ecore_input.c
+++ b/src/lib/ecore_input/ecore_input.c
@@ -22,6 +22,7 @@ EAPI int ECORE_EVENT_MOUSE_MOVE = 0;
 EAPI int ECORE_EVENT_MOUSE_WHEEL = 0;
 EAPI int ECORE_EVENT_MOUSE_IN = 0;
 EAPI int ECORE_EVENT_MOUSE_OUT = 0;
+EAPI int ECORE_EVENT_AXIS_UPDATE = 0;
 
 static int _ecore_event_init_count = 0;
 
@@ -52,6 +53,7 @@ ecore_event_init(void)
    ECORE_EVENT_MOUSE_WHEEL = ecore_event_type_new();
    ECORE_EVENT_MOUSE_IN = ecore_event_type_new();
    ECORE_EVENT_MOUSE_OUT = ecore_event_type_new();
+   ECORE_EVENT_AXIS_UPDATE = ecore_event_type_new();
 
    return _ecore_event_init_count;
 }
@@ -70,6 +72,7 @@ ecore_event_shutdown(void)
    ECORE_EVENT_MOUSE_WHEEL = 0;
    ECORE_EVENT_MOUSE_IN = 0;
    ECORE_EVENT_MOUSE_OUT = 0;
+   ECORE_EVENT_AXIS_UPDATE = 0;
    eina_log_domain_unregister(_ecore_input_log_dom);
    _ecore_input_log_dom = -1;
    ecore_shutdown();
diff --git a/src/lib/ecore_input_evas/Ecore_Input_Evas.h 
b/src/lib/ecore_input_evas/Ecore_Input_Evas.h
index c97274e..82f81c8 100644
--- a/src/lib/ecore_input_evas/Ecore_Input_Evas.h
+++ b/src/lib/ecore_input_evas/Ecore_Input_Evas.h
@@ -49,6 +49,7 @@ EAPI Eina_Bool ecore_event_evas_mouse_wheel(void *data, int 
type, void *event);
 EAPI Eina_Bool ecore_event_evas_mouse_move(void *data, int type, void *event);
 EAPI Eina_Bool ecore_event_evas_mouse_in(void *data, int type, void *event);
 EAPI Eina_Bool ecore_event_evas_mouse_out(void *data, int type, void *event);
+EAPI Eina_Bool ecore_event_evas_axis_update(void *data, int type, void *event);
 
 EAPI void      ecore_event_window_register(Ecore_Window id, void *window, Evas 
*evas, Ecore_Event_Mouse_Move_Cb move_mouse, Ecore_Event_Multi_Move_Cb 
move_multi, Ecore_Event_Multi_Down_Cb down_multi, Ecore_Event_Multi_Up_Cb 
up_multi);
 EAPI void      ecore_event_window_unregister(Ecore_Window id);
diff --git a/src/lib/ecore_input_evas/ecore_input_evas.c 
b/src/lib/ecore_input_evas/ecore_input_evas.c
index 5205862..e9e7fb9 100644
--- a/src/lib/ecore_input_evas/ecore_input_evas.c
+++ b/src/lib/ecore_input_evas/ecore_input_evas.c
@@ -46,7 +46,7 @@ struct _Ecore_Input_Last
 };
 
 static int _ecore_event_evas_init_count = 0;
-static Ecore_Event_Handler *ecore_event_evas_handlers[8];
+static Ecore_Event_Handler *ecore_event_evas_handlers[9];
 static Eina_Hash *_window_hash = NULL;
 
 static Eina_List *_last_events = NULL;
@@ -541,6 +541,19 @@ ecore_event_evas_mouse_out(void *data EINA_UNUSED, int 
type EINA_UNUSED, void *e
    return _ecore_event_evas_mouse_io((Ecore_Event_Mouse_IO *)event, ECORE_OUT);
 }
 
+EAPI Eina_Bool
+ecore_event_evas_axis_update(void *data EINA_UNUSED, int type EINA_UNUSED, 
void *event)
+{
+   Ecore_Event_Axis_Update *e;
+   Ecore_Input_Window *lookup;
+
+   e = event;
+   lookup = _ecore_event_window_match(e->event_window);
+   if (!lookup) return ECORE_CALLBACK_PASS_ON;
+   evas_event_feed_axis_update(lookup->evas, e->timestamp, e->device, 
e->toolid, e->naxis, e->axis, NULL);
+   return ECORE_CALLBACK_PASS_ON;
+}
+
 EAPI int
 ecore_event_evas_init(void)
 {
@@ -589,6 +602,9 @@ ecore_event_evas_init(void)
    ecore_event_evas_handlers[7] = 
ecore_event_handler_add(ECORE_EVENT_MOUSE_OUT,
                                                           
ecore_event_evas_mouse_out,
                                                           NULL);
+   ecore_event_evas_handlers[8] = 
ecore_event_handler_add(ECORE_EVENT_AXIS_UPDATE,
+                                                          
ecore_event_evas_axis_update,
+                                                          NULL);
 
    _window_hash = eina_hash_pointer_new(free);
 
diff --git a/src/lib/ecore_x/Ecore_X.h b/src/lib/ecore_x/Ecore_X.h
index 7272b6a..d03003b 100644
--- a/src/lib/ecore_x/Ecore_X.h
+++ b/src/lib/ecore_x/Ecore_X.h
@@ -2529,7 +2529,7 @@ EAPI Eina_Bool      
ecore_x_image_is_argb32_get(Ecore_X_Image *im);
 
 EAPI Eina_Bool      ecore_x_image_to_argb_convert(void *src, int sbpp, int 
sbpl, Ecore_X_Colormap c, Ecore_X_Visual v, int x, int y, int w, int h, 
unsigned int *dst, int dbpl, int dx, int dy);
 
-EAPI Eina_Bool      ecore_x_input_multi_select(Ecore_X_Window win);
+EAPI Eina_Bool      ecore_x_input_select(Ecore_X_Window win);
 EAPI Eina_Bool     ecore_x_input_raw_select(Ecore_X_Window win); /**< @since 
1.8 */
 
 EAPI Eina_Bool      ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win);
diff --git a/src/lib/ecore_x/xlib/ecore_x_events.c 
b/src/lib/ecore_x/xlib/ecore_x_events.c
index d4049d2..80c289c 100644
--- a/src/lib/ecore_x/xlib/ecore_x_events.c
+++ b/src/lib/ecore_x/xlib/ecore_x_events.c
@@ -270,6 +270,53 @@ _ecore_mouse_move(unsigned int timestamp,
 }
 
 static void
+_ecore_x_event_free_axis_update_event(void *data, void *ev)
+{
+   Ecore_Event_Axis_Update *e = ev;
+   if (e) free(e->axis);
+   free(e);
+}
+
+void
+_ecore_x_axis_update(Ecore_Window window,
+                     Ecore_Window event_window,
+                     Ecore_Window root_window,
+                     unsigned int timestamp,
+                     int devid,
+                     int toolid,
+                     int naxis,
+                     Ecore_Axis *axis)
+{
+   Ecore_Event_Axis_Update *e;
+   int i;
+
+   e = malloc(sizeof(Ecore_Event_Axis_Update));
+   if (!e) return;
+
+   e->window = window;
+   e->event_window = event_window;
+   e->root_window = root_window;
+
+   e->timestamp = timestamp;
+
+   e->device = devid;
+   e->toolid = toolid;
+
+   e->naxis = naxis;
+   e->axis = axis;
+
+   INF("Axis update [%d] (%d) with %d events:", ECORE_EVENT_AXIS_UPDATE, 
e->device, e->naxis);
+   for (i = 0; i < naxis; i++)
+     {
+        INF("AXIS %d = %f", e->axis[i].label, e->axis[i].value);
+     }
+
+   ecore_event_add(ECORE_EVENT_AXIS_UPDATE, e, 
_ecore_x_event_free_axis_update_event, NULL);
+
+   _ecore_x_event_last_time = timestamp;
+}
+
+static void
 _ecore_key_press(int event,
                  XKeyEvent *xevent)
 {
diff --git a/src/lib/ecore_x/xlib/ecore_x_private.h 
b/src/lib/ecore_x/xlib/ecore_x_private.h
index cbfa4f7..97b3858 100644
--- a/src/lib/ecore_x/xlib/ecore_x_private.h
+++ b/src/lib/ecore_x/xlib/ecore_x_private.h
@@ -344,6 +344,16 @@ void _ecore_x_input_shutdown(void);
 void _ecore_x_input_handler(XEvent *xevent);
 /* from sync */
 
+void
+_ecore_x_axis_update(Ecore_Window window,
+                     Ecore_Window event_window,
+                     Ecore_Window root_window,
+                     unsigned int timestamp,
+                     int devid,
+                     int toolid,
+                     int naxis,
+                     Ecore_Axis *axis);
+
 void _ecore_mouse_move(unsigned int timestamp,
                        unsigned int xmodifiers,
                        int x,
diff --git a/src/lib/ecore_x/xlib/ecore_x_xi2.c 
b/src/lib/ecore_x/xlib/ecore_x_xi2.c
index 2a49d0c..d5139c7 100644
--- a/src/lib/ecore_x/xlib/ecore_x_xi2.c
+++ b/src/lib/ecore_x/xlib/ecore_x_xi2.c
@@ -3,6 +3,7 @@
 #endif /* ifdef HAVE_CONFIG_H */
 
 #include <string.h>
+#include <math.h>
 
 #include "Ecore.h"
 #include "ecore_x_private.h"
@@ -88,6 +89,42 @@ _ecore_x_input_touch_info_clear(void)
 #endif /* ifdef ECORE_XI2_2 */
 #endif /* ifdef ECORE_XI2 */
 
+#ifdef ECORE_XI2
+static Atom
+_ecore_x_input_get_axis_label(char *axis_name)
+{
+   static Atom *atoms = NULL;
+   static char *names[] =
+     {
+        "Abs X", "Abs Y", "Abs Pressure",
+        "Abs Distance", "Abs Rotary Z",
+        "Abs Wheel", "Abs Tilt X", "Abs Tilt Y"
+     };
+   int n = sizeof(names) / sizeof(names[0]);
+   int i;
+
+   if (atoms == NULL)
+     {
+        atoms = calloc(n, sizeof(Atom));
+        if (!atoms) return 0;
+
+        if (!XInternAtoms(_ecore_x_disp, names, n, 1, atoms))
+          {
+             free(atoms);
+             atoms = NULL;
+             return 0;
+          }
+     }
+
+   for (i = 0; i < n; i++)
+     {
+        if (!strcmp(axis_name, names[i])) return atoms[i];
+     }
+
+   return 0;
+}
+#endif /* ifdef ECORE_XI2 */
+
 void
 _ecore_x_input_shutdown(void)
 {
@@ -208,15 +245,11 @@ _ecore_x_input_touch_info_get(XIDeviceInfo *dev)
 #endif
 
 void
-_ecore_x_input_handler(XEvent *xevent)
+_ecore_x_input_raw_handler(XEvent *xevent)
 {
 #ifdef ECORE_XI2
-   XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
-   /* XIRawEvent *evr = (XIRawEvent *)(xevent->xcookie.data); */
-   int devid = evd->deviceid;
-   int i;
+   if (xevent->type != GenericEvent) return;
 
-   /* No filter for this events */
    switch (xevent->xcookie.evtype)
      {
 #ifdef XI_RawButtonPress
@@ -235,24 +268,22 @@ _ecore_x_input_handler(XEvent *xevent)
          break;
 #endif
      }
+#endif /* ifdef ECORE_XI2 */
+}
 
-   if (_ecore_x_xi2_devs)
-     {
-        for (i = 0; i < _ecore_x_xi2_num; i++)
-          {
-             XIDeviceInfo *dev = &(_ecore_x_xi2_devs[i]);
+void
+_ecore_x_input_mouse_handler(XEvent *xevent)
+{
+#ifdef ECORE_XI2
+   if (xevent->type != GenericEvent) return;
+
+   XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
+   int devid = evd->deviceid;
 
-             if (devid == dev->deviceid)
-               {
-                  if (dev->use == XIMasterPointer) return;
-                  if ((dev->use == XISlavePointer) &&
-                      (evd->flags & XIPointerEmulated)) return;
-               }
-          }
-     }
    switch (xevent->xcookie.evtype)
      {
       case XI_Motion:
+        INF("Handling XI_Motion");
         _ecore_mouse_move
           (evd->time,
           0,   // state
@@ -290,7 +321,7 @@ _ecore_x_input_handler(XEvent *xevent)
         break;
 
       case XI_ButtonRelease:
-               INF("ButtonEvent:multi release time=%u x=%d y=%d devid=%d", 
(unsigned int)evd->time, (int)evd->event_x, (int)evd->event_y, devid);
+        INF("ButtonEvent:multi release time=%u x=%d y=%d devid=%d", (unsigned 
int)evd->time, (int)evd->event_x, (int)evd->event_y, devid);
         _ecore_mouse_button
           (ECORE_EVENT_MOUSE_BUTTON_UP,
           evd->time,
@@ -308,13 +339,27 @@ _ecore_x_input_handler(XEvent *xevent)
           evd->event_x, evd->event_y,
           evd->root_x, evd->root_y);
         break;
+      }
+#endif /* ifdef ECORE_XI2 */
+}
+
+void
+_ecore_x_input_multi_handler(XEvent *xevent)
+{
+#ifdef ECORE_XI2
+   if (xevent->type != GenericEvent) return;
+   XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
+   int devid = evd->deviceid;
 
+   switch (xevent->xcookie.evtype)
+      {
 #ifdef XI_TouchUpdate
       case XI_TouchUpdate:
 #ifdef ECORE_XI2_2
         i = _ecore_x_input_touch_index_get(devid, evd->detail, XI_TouchUpdate);
         if ((i == 0) && (evd->flags & XITouchEmulatingPointer)) return;
 #endif /* #ifdef ECORE_XI2_2 */
+        INF("Handling XI_TouchUpdate");
         _ecore_mouse_move
           (evd->time,
           0,   // state
@@ -342,6 +387,7 @@ _ecore_x_input_handler(XEvent *xevent)
         i = _ecore_x_input_touch_index_get(devid, evd->detail, XI_TouchBegin);
         if ((i == 0) && (evd->flags & XITouchEmulatingPointer)) return;
 #endif /* #ifdef ECORE_XI2_2 */
+       INF("Handling XI_TouchBegin");
         _ecore_mouse_button
           (ECORE_EVENT_MOUSE_BUTTON_DOWN,
           evd->time,
@@ -375,6 +421,7 @@ _ecore_x_input_handler(XEvent *xevent)
              return;
           }
 #endif /* #ifdef ECORE_XI2_2 */
+        INF("Handling XI_TouchEnd");
         _ecore_mouse_button
           (ECORE_EVENT_MOUSE_BUTTON_UP,
           evd->time,
@@ -400,7 +447,181 @@ _ecore_x_input_handler(XEvent *xevent)
 #endif /* #ifdef ECORE_XI2_2 */
         break;
 #endif
+      }
+#endif /* ifdef ECORE_XI2 */
+}
+
+static int
+count_bits(long n)
+{
+   unsigned int c; /* c accumulates the total bits set in v */
+   for (c = 0; n; c++) n &= n - 1; /* clear the least significant bit set */
+   return c;
+}
+
+void
+_ecore_x_input_axis_handler(XEvent *xevent, XIDeviceInfo *dev)
+{
+#ifdef ECORE_XI2
+   if (xevent->type != GenericEvent) return;
+   XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
+   int n = count_bits(*evd->valuators.mask);
+   int i;
+   int j = 0;
+   double tiltx = 0, tilty = 0;
+   Eina_Bool compute_tilt = EINA_FALSE;
+   Ecore_Axis *axis = calloc(n, sizeof(Ecore_Axis));
+   if (!axis) return;
+   Ecore_Axis *axis_ptr = axis;
+
+   for (i = 0; i < dev->num_classes; i++)
+     {
+        if (dev->classes[i]->type == XIValuatorClass)
+          {
+             XIValuatorClassInfo *inf = ((XIValuatorClassInfo 
*)dev->classes[i]);
+
+             if (*evd->valuators.mask & (1 << inf->number))
+               {
+                  if (inf->label == _ecore_x_input_get_axis_label("Abs X"))
+                    {
+                       axis_ptr->label = ECORE_AXIS_LABEL_X;
+                       axis_ptr->value = evd->valuators.values[j];
+                       axis_ptr++;
+                    }
+                  else if (inf->label == _ecore_x_input_get_axis_label("Abs 
Y"))
+                    {
+                       axis_ptr->label = ECORE_AXIS_LABEL_Y;
+                       axis_ptr->value = evd->valuators.values[j];
+                       axis_ptr++;
+                    }
+                  else if (inf->label == _ecore_x_input_get_axis_label("Abs 
Pressure"))
+                    {
+                       axis_ptr->label = ECORE_AXIS_LABEL_PRESSURE;
+                       axis_ptr->value = (evd->valuators.values[j] - inf->min) 
/ (inf->max - inf->min);
+                       axis_ptr++;
+                    }
+                  else if (inf->label == _ecore_x_input_get_axis_label("Abs 
Distance"))
+                    {
+                       axis_ptr->label = ECORE_AXIS_LABEL_DISTANCE;
+                       axis_ptr->value = (evd->valuators.values[j] - inf->min) 
/ (inf->max - inf->min);
+                       axis_ptr++;
+                    }
+                  else if ((inf->label == _ecore_x_input_get_axis_label("Abs 
Rotary Z")) ||
+                           (inf->label == _ecore_x_input_get_axis_label("Abs 
Wheel")))
+                    {
+                       axis_ptr->label = ECORE_AXIS_LABEL_TWIST;
+                       if (inf->resolution == 1)
+                         {
+                            /* some wacom drivers do not correctly report 
resolution, so pre-normalize */
+                            axis_ptr->value = 2*((evd->valuators.values[j] - 
inf->min) / (inf->max - inf->min)) - 1;
+                            axis_ptr->value *= M_PI;
+                         }
+                       else
+                         {
+                            axis_ptr->value = evd->valuators.values[j] / 
inf->resolution;
+                         }
+                       axis_ptr++;
+                    }
+                  else if (inf->label == _ecore_x_input_get_axis_label("Abs 
Tilt X"))
+                    {
+                       tiltx = evd->valuators.values[j] / inf->resolution;
+                       compute_tilt = EINA_TRUE;
+                       /* don't increment axis_ptr */
+                    }
+                  else if (inf->label == _ecore_x_input_get_axis_label("Abs 
Tilt Y"))
+                    {
+                       tilty = -evd->valuators.values[j] / inf->resolution;
+                       compute_tilt = EINA_TRUE;
+                       /* don't increment axis_ptr */
+                    }
+                  else
+                    {
+                       axis_ptr->label = ECORE_AXIS_LABEL_UNKNOWN;
+                       axis_ptr->value = evd->valuators.values[j];
+                       axis_ptr++;
+                    }
+                  j++;
+               }
+          }
+     }
+
+   if ((compute_tilt) && ((axis_ptr + 2) <= (axis + n)))
+     {
+        double x = sin(tiltx);
+        double y = sin(tilty);
+        axis_ptr->label = ECORE_AXIS_LABEL_TILT;
+        axis_ptr->value = asin(sqrt((x * x) + (y * y)));
+        axis_ptr++;
+
+        /* note: the value of atan2(0,0) is implementation-defined */
+        axis_ptr->label = ECORE_AXIS_LABEL_AZIMUTH;
+        axis_ptr->value = atan2(y, x);
+        axis_ptr++;
+     }
+
+   /* update n to reflect actual count and realloc array to free excess */
+   n = (axis_ptr - axis);
+   Ecore_Axis *shrunk_axis = realloc(axis, n * sizeof(Ecore_Axis));
+   if (shrunk_axis != NULL) axis = shrunk_axis;
+
+   if (n > 0)
+     _ecore_x_axis_update(evd->child ? evd->child : evd->event,
+                          evd->event, evd->root, evd->time, evd->deviceid,
+                          evd->detail, n, axis);
+#endif /* ifdef ECORE_XI2 */
+}
+
+static XIDeviceInfo *
+_ecore_x_input_device_lookup(int deviceid)
+{
+   XIDeviceInfo *dev;
+   int i;
+
+   if (_ecore_x_xi2_devs)
+     {
+        for (i = 0; i < _ecore_x_xi2_num; i++)
+          {
+             dev = &(_ecore_x_xi2_devs[i]);
+             if (deviceid == dev->deviceid) return dev;
+          }
+     }
+   return NULL;
+}
+
+void
+_ecore_x_input_handler(XEvent *xevent)
+{
+#ifdef ECORE_XI2
+   if (xevent->type != GenericEvent) return;
+
+   switch (xevent->xcookie.evtype)
+     {
+      case XI_RawMotion:
+      case XI_RawButtonPress:
+      case XI_RawButtonRelease:
+        _ecore_x_input_raw_handler(xevent);
+        break;
+
+      case XI_Motion:
+      case XI_ButtonPress:
+      case XI_ButtonRelease:
+      case XI_TouchUpdate:
+      case XI_TouchBegin:
+      case XI_TouchEnd:
+          {
+             XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data);
+             XIDeviceInfo *dev = _ecore_x_input_device_lookup(evd->deviceid);
 
+             if ((dev->use == XISlavePointer) &&
+                 !(evd->flags & XIPointerEmulated))
+               _ecore_x_input_multi_handler(xevent);
+             else if (dev->use == XIFloatingSlave)
+               _ecore_x_input_mouse_handler(xevent);
+
+             if (dev->use != XIMasterPointer)
+               _ecore_x_input_axis_handler(xevent, dev);
+          }
+        break;
       default:
         break;
      }
@@ -408,116 +629,64 @@ _ecore_x_input_handler(XEvent *xevent)
 }
 
 EAPI Eina_Bool
-ecore_x_input_multi_select(Ecore_X_Window win)
+ecore_x_input_select(Ecore_X_Window win)
 {
 #ifdef ECORE_XI2
    int i;
    Eina_Bool find = EINA_FALSE;
 
    if (!_ecore_x_xi2_devs)
-     return 0;
+     return EINA_FALSE;
 
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
    for (i = 0; i < _ecore_x_xi2_num; i++)
      {
         XIDeviceInfo *dev = &(_ecore_x_xi2_devs[i]);
+        XIEventMask eventmask;
+        unsigned char mask[4] = { 0 };
+        int update = 0;
 
-        if (dev->use == XIFloatingSlave)
-          {
-             XIEventMask eventmask;
-             unsigned char mask[4] = { 0 };
+        eventmask.deviceid = dev->deviceid;
+        eventmask.mask_len = sizeof(mask);
+        eventmask.mask = mask;
 
-             eventmask.deviceid = dev->deviceid;
-             eventmask.mask_len = sizeof(mask);
-             eventmask.mask = mask;
+        if ((dev->use == XIFloatingSlave) || (dev->use == XISlavePointer))
+          {
              XISetMask(mask, XI_ButtonPress);
              XISetMask(mask, XI_ButtonRelease);
              XISetMask(mask, XI_Motion);
-             XISelectEvents(_ecore_x_disp, win, &eventmask, 1);
-             if (_ecore_xlib_sync) ecore_x_sync();
-             find = EINA_TRUE;
-          }
-        else if (dev->use == XISlavePointer)
-          {
-             XIDeviceInfo *atdev = NULL;
-             int j;
 
-             for (j = 0; j < _ecore_x_xi2_num; j++)
-               {
-                  if (_ecore_x_xi2_devs[j].deviceid == dev->attachment)
-                    atdev = &(_ecore_x_xi2_devs[j]);
-               }
-             if (((atdev) && (atdev->use != XIMasterPointer)) ||
-                 (!atdev))
-               {
-                  XIEventMask eventmask;
-                  unsigned char mask[4] = { 0 };
-
-                  eventmask.deviceid = dev->deviceid;
-                  eventmask.mask_len = sizeof(mask);
-                  eventmask.mask = mask;
-                  XISetMask(mask, XI_ButtonPress);
-                  XISetMask(mask, XI_ButtonRelease);
-                  XISetMask(mask, XI_Motion);
 #ifdef ECORE_XI2_2
-                  Eina_Inlist *l = _ecore_x_xi2_touch_info_list;
-                  Ecore_X_Touch_Device_Info *info;
-                  info = _ecore_x_input_touch_info_get(dev);
-
-                  if (info)
-                    {
-                       XISetMask(mask, XI_TouchUpdate);
-                       XISetMask(mask, XI_TouchBegin);
-                       XISetMask(mask, XI_TouchEnd);
+             Eina_Inlist *l = _ecore_x_xi2_touch_info_list;
+             Ecore_X_Touch_Device_Info *info;
+             info = _ecore_x_input_touch_info_get(dev);
 
-                       l = eina_inlist_append(l, (Eina_Inlist *)info);
-                       _ecore_x_xi2_touch_info_list = l;
-                    }
-#else
-# ifdef XI_TouchUpdate
+             if (info)
+               {
                   XISetMask(mask, XI_TouchUpdate);
-# endif
-# ifdef XI_TouchBegin
                   XISetMask(mask, XI_TouchBegin);
-# endif
-# ifdef XI_TouchEnd
                   XISetMask(mask, XI_TouchEnd);
-# endif
-#endif /* #ifdef ECORE_XI2_2 */
+                  update = 1;
 
-                  XISelectEvents(_ecore_x_disp, win, &eventmask, 1);
-                  if (_ecore_xlib_sync) ecore_x_sync();
-                  find = EINA_TRUE;
+                  l = eina_inlist_append(l, (Eina_Inlist *)info);
+                  _ecore_x_xi2_touch_info_list = l;
                }
-#ifdef ECORE_XI2_2
-             else if ((atdev) && (atdev->use == XIMasterPointer))
-               {
-                  Eina_Inlist *l = _ecore_x_xi2_touch_info_list;
-                  Ecore_X_Touch_Device_Info *info;
-                  info = _ecore_x_input_touch_info_get(dev);
-
-                  if (info)
-                    {
-                       XIEventMask eventmask;
-                       unsigned char mask[4] = { 0 };
-
-                       eventmask.deviceid = dev->deviceid;
-                       eventmask.mask_len = sizeof(mask);
-                       eventmask.mask = mask;
+#endif /* #ifdef ECORE_XI2_2 */
 
-                       XISetMask(mask, XI_TouchUpdate);
-                       XISetMask(mask, XI_TouchBegin);
-                       XISetMask(mask, XI_TouchEnd);
-                       XISelectEvents(_ecore_x_disp, win, &eventmask, 1);
-                       if (_ecore_xlib_sync) ecore_x_sync();
+#if !defined (ECORE_XI2_2) && defined (XI_TouchUpdate) && defined 
(XI_TouchBegin) && defined (XI_TouchEnd)
+             XISetMask(mask, XI_TouchUpdate);
+             XISetMask(mask, XI_TouchBegin);
+             XISetMask(mask, XI_TouchEnd);
+#endif
 
-                       l = eina_inlist_append(l, (Eina_Inlist *)info);
-                       _ecore_x_xi2_touch_info_list = l;
+             update = 1;
+          }
 
-                       find = EINA_TRUE;
-                    }
-               }
-#endif /* #ifdef ECORE_XI2_2 */
+        if (update)
+          {
+             XISelectEvents(_ecore_x_disp, win, &eventmask, 1);
+             if (_ecore_xlib_sync) ecore_x_sync();
+             find = EINA_TRUE;
           }
      }
 
diff --git a/src/lib/evas/Evas_Common.h b/src/lib/evas/Evas_Common.h
index e3cdc94..94acba2 100644
--- a/src/lib/evas/Evas_Common.h
+++ b/src/lib/evas/Evas_Common.h
@@ -129,6 +129,8 @@ typedef enum _Evas_Callback_Type
 
    EVAS_CALLBACK_IMAGE_RESIZE, /**< Image size is changed @since 1.8 */
    EVAS_CALLBACK_DEVICE_CHANGED, /**< Devices added, removed or changed on 
canvas @since 1.8 */
+
+   EVAS_CALLBACK_AXIS_UPDATE, /**< Input device changed value on some axis 
@since 1.13 */
    EVAS_CALLBACK_LAST /**< kept as last element/sentinel -- not really an 
event */
 } Evas_Callback_Type; /**< The types of events triggering a callback */
 
@@ -420,6 +422,8 @@ typedef struct _Evas_Event_Key_Down      
Evas_Event_Key_Down; /**< Event structu
 typedef struct _Evas_Event_Key_Up        Evas_Event_Key_Up; /**< Event 
structure for #EVAS_CALLBACK_KEY_UP event callbacks */
 typedef struct _Evas_Event_Hold          Evas_Event_Hold; /**< Event structure 
for #EVAS_CALLBACK_HOLD event callbacks */
 typedef struct _Evas_Event_Render_Post   Evas_Event_Render_Post; /**< Event 
structure that may come with #EVAS_CALLBACK_RENDER_POST event callbacks @since 
1.8 */
+typedef struct _Evas_Axis                Evas_Axis; /**< Details for a single 
device axis state @since 1.13 */
+typedef struct _Evas_Event_Axis_Update   Evas_Event_Axis_Update; /**< Event 
structure for #EVAS_CALLBACK_AXIS_UPDATE event callbacks @since 1.13 */
 
 typedef enum _Evas_Alloc_Error
 {
@@ -842,6 +846,41 @@ struct _Evas_Event_Hold /** Hold change event */
    Evas_Device     *dev;
 };
 
+typedef enum _Evas_Axis_Label
+{
+   EVAS_AXIS_LABEL_UNKNOWN,       /**< Axis containing unknown (or not yet 
representable) data. Range: Unbounded. Unit: Undefined. @since 1.13 */
+   EVAS_AXIS_LABEL_X,             /**< Position along physical X axis; not 
window relative. Range: Unbounded. Unit: Undefined. @since 1.13 */
+   EVAS_AXIS_LABEL_Y,             /**< Position along physical Y axis; not 
window relative. Range: Unbounded. Unit: Undefined. @since 1.13 */
+   EVAS_AXIS_LABEL_PRESSURE,      /**< Force applied to tool tip. Range: [0.0, 
1.0]. Unit: Unitless. @since 1.13 */
+   EVAS_AXIS_LABEL_DISTANCE,      /**< Relative distance along physical Z 
axis. Range: [0.0, 1.0]. Unit: Unitless @since 1.13 */
+   EVAS_AXIS_LABEL_AZIMUTH,       /**< Angle of tool about the Z axis from 
positive X axis. Range: [-PI, PI]. Unit: Radians. @since 1.13 */
+   EVAS_AXIS_LABEL_TILT,          /**< Angle of tool about plane of sensor 
from positive Z axis. Range: [0.0, PI]. Unit: Radians. @since 1.13 */
+   EVAS_AXIS_LABEL_TWIST,         /**< Rotation of tool about its major axis 
from its "natural" position. Range: [-PI, PI] Unit: Radians. @since 1.13 */
+   EVAS_AXIS_LABEL_TOUCH_WIDTH_MAJOR,   /**< Length of contact ellipse along 
AZIMUTH. Range: Unbounded: Unit: Same as EVAS_AXIS_LABEL_{X,Y}. @since 1.13 */
+   EVAS_AXIS_LABEL_TOUCH_WIDTH_MINOR,   /**< Length of contact ellipse 
perpendicular to AZIMUTH. Range: Unbounded. Unit: Same as 
EVAS_AXIS_LABEL_{X,Y}. @since 1.13 */
+   EVAS_AXIS_LABEL_TOOL_WIDTH_MAJOR,    /**< Length of tool ellipse along 
AZIMUTH. Range: Unbounded. Unit: Same as EVAS_AXIS_LABEL_{X,Y}. @since 1.13 */
+   EVAS_AXIS_LABEL_TOOL_WIDTH_MINOR     /**< Length of tool ellipse 
perpendicular to AZIMUTH. Range: Unbounded. Unit: Same as 
EVAS_AXIS_LABEL_{X,Y}. @since 1.13 */
+} Evas_Axis_Label; /**< Types of recognized device axes @since 1.13 */
+
+struct _Evas_Axis
+{
+   Evas_Axis_Label label;
+   double value;
+};
+
+struct _Evas_Event_Axis_Update
+{
+   void             *data;
+
+   unsigned int timestamp;
+   int device;
+   int toolid;
+
+   int naxis;
+   Evas_Axis *axis;
+   Evas_Device *dev;
+};
+
 /**
  * How the mouse pointer should be handled by Evas.
  *
diff --git a/src/lib/evas/Evas_Eo.h b/src/lib/evas/Evas_Eo.h
index 4d4fba1..fd48f74 100644
--- a/src/lib/evas/Evas_Eo.h
+++ b/src/lib/evas/Evas_Eo.h
@@ -11,6 +11,7 @@ EAPI extern const Eo_Event_Description 
_EVAS_CANVAS_EVENT_OBJECT_FOCUS_OUT;
 EAPI extern const Eo_Event_Description _EVAS_CANVAS_EVENT_RENDER_PRE;
 EAPI extern const Eo_Event_Description _EVAS_CANVAS_EVENT_RENDER_POST;
 EAPI extern const Eo_Event_Description _EVAS_CANVAS_EVENT_DEVICE_CHANGED;
+EAPI extern const Eo_Event_Description _EVAS_CANVAS_EVENT_AXIS_UPDATE;
 
 // Callbacks events for use with Evas canvases
 #define EVAS_CANVAS_EVENT_FOCUS_IN (&(_EVAS_CANVAS_EVENT_FOCUS_IN))
@@ -22,6 +23,7 @@ EAPI extern const Eo_Event_Description 
_EVAS_CANVAS_EVENT_DEVICE_CHANGED;
 #define EVAS_CANVAS_EVENT_RENDER_PRE (&(_EVAS_CANVAS_EVENT_RENDER_PRE))
 #define EVAS_CANVAS_EVENT_RENDER_POST (&(_EVAS_CANVAS_EVENT_RENDER_POST))
 #define EVAS_CANVAS_EVENT_DEVICE_CHANGED (&(_EVAS_CANVAS_EVENT_DEVICE_CHANGED))
+#define EVAS_CANVAS_EVENT_AXIS_UPDATE (&(_EVAS_CANVAS_EVENT_AXIS_UPDATE))
 
 #include "canvas/evas_signal_interface.eo.h"
 #include "canvas/evas_draggable_interface.eo.h"
diff --git a/src/lib/evas/Evas_Legacy.h b/src/lib/evas/Evas_Legacy.h
index bc135c0..0a10fce 100644
--- a/src/lib/evas/Evas_Legacy.h
+++ b/src/lib/evas/Evas_Legacy.h
@@ -613,6 +613,7 @@ EAPI void             evas_object_hide(Evas_Object *obj) 
EINA_ARG_NONNULL(1);
  * #EVAS_CALLBACK_MOUSE_DOWN, #EVAS_CALLBACK_MOUSE_UP,
  * #EVAS_CALLBACK_MOUSE_MOVE, #EVAS_CALLBACK_MOUSE_WHEEL,
  * #EVAS_CALLBACK_MULTI_DOWN, #EVAS_CALLBACK_MULTI_UP,
+ * #EVAS_CALLBACK_AXIS_UPDATE,
  * #EVAS_CALLBACK_MULTI_MOVE, #EVAS_CALLBACK_FREE,
  * #EVAS_CALLBACK_KEY_DOWN, #EVAS_CALLBACK_KEY_UP,
  * #EVAS_CALLBACK_FOCUS_IN, #EVAS_CALLBACK_FOCUS_OUT,
@@ -687,6 +688,9 @@ EAPI void             evas_object_hide(Evas_Object *obj) 
EINA_ARG_NONNULL(1);
  * - #EVAS_CALLBACK_MULTI_MOVE: @p event_info is a pointer to an
  *   #Evas_Event_Multi_Move struct
  *
+ * - #EVAS_CALLBACK_AXIS_UPDATE: @p event_info is a pointer to an
+ *   #Evas_Event_Axis_Update struct
+ *
  * - #EVAS_CALLBACK_FREE: @p event_info is @c NULL \n\n
  *   This event is triggered just before Evas is about to free all
  *   memory used by an object and remove all references to it. This is
diff --git a/src/lib/evas/canvas/evas_callbacks.c 
b/src/lib/evas/canvas/evas_callbacks.c
index a1b8231..52bd014 100644
--- a/src/lib/evas/canvas/evas_callbacks.c
+++ b/src/lib/evas/canvas/evas_callbacks.c
@@ -12,6 +12,9 @@ EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_RENDER_PRE 
=
 EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_RENDER_POST =
    EO_EVENT_DESCRIPTION("Render Post", "Called just after rendering stops on 
the canvas target @since 1.2");
 
+EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_AXIS_UPDATE =
+   EO_EVENT_DESCRIPTION("Axis Update", "Device axis value changed");
+
 EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_FOCUS_IN =
    EO_HOT_EVENT_DESCRIPTION("Canvas Focus In", "Canvas got focus as a whole");
 EAPI const Eo_Event_Description _EVAS_CANVAS_EVENT_FOCUS_OUT =
@@ -66,7 +69,8 @@ static const Eo_Event_Description 
*_legacy_evas_callback_table[EVAS_CALLBACK_LAS
    EVAS_CANVAS_EVENT_RENDER_PRE,
    EVAS_CANVAS_EVENT_RENDER_POST,
    EVAS_OBJECT_EVENT_IMAGE_RESIZE,
-   EVAS_CANVAS_EVENT_DEVICE_CHANGED
+   EVAS_CANVAS_EVENT_DEVICE_CHANGED,
+   EVAS_CANVAS_EVENT_AXIS_UPDATE
 };
 
 typedef struct
diff --git a/src/lib/evas/canvas/evas_canvas.eo 
b/src/lib/evas/canvas/evas_canvas.eo
index 893850d..2ff4c03 100644
--- a/src/lib/evas/canvas/evas_canvas.eo
+++ b/src/lib/evas/canvas/evas_canvas.eo
@@ -1758,6 +1758,25 @@ class Evas.Canvas (Eo.Base, Evas.Common_Interface)
             @in uint keycode; /*@ Key scan code numeric value for canvas. */
          }
       }
+      event_feed_axis_update {
+         /*@
+         Input device axis update event feed.
+
+         This function will set some evas properties that is necessary when
+         an e.g. stylus axis is updated. It prepares information to be treated
+         by the callback function.
+
+         @since 1.13 */
+
+         params {
+            @in uint timestamp; /*@ Timestamp of the axis event */
+            @in int device; /*@ System-provided device identifier */
+            @in int toolid; /*@ Type of tool currently being used */
+            @in int naxes; /*@ Number of elements in the \p axis array */
+            @in const(Evas_Axis)* axis; /*@ Array containing the current value 
of all updated axes */
+            @in const(void)* data; /*@ Data for canvas. */
+         }
+      }
    }
    implements {
       Eo.Base.constructor;
diff --git a/src/lib/evas/canvas/evas_events.c 
b/src/lib/evas/canvas/evas_events.c
index f5f7ba7..8fdadd0 100644
--- a/src/lib/evas/canvas/evas_events.c
+++ b/src/lib/evas/canvas/evas_events.c
@@ -2717,6 +2717,55 @@ _evas_canvas_event_feed_hold(Eo *eo_e, Evas_Public_Data 
*e, int hold, unsigned i
    _evas_object_event_new();
 }
 
+void
+_canvas_event_feed_axis_update_internal(Evas *eo_e, Evas_Public_Data *e, 
unsigned int timestamp, int device, int toolid, int naxis, const Evas_Axis 
*axis, const void *data)
+{
+   Eina_List *l, *copy;
+   Evas_Event_Axis_Update ev;
+   Evas_Object *eo_obj;
+   int event_id = 0;
+
+   if (e->is_frozen) return;
+   e->last_timestamp = timestamp;
+
+   _evas_object_event_new();
+
+   event_id = _evas_event_counter;
+   ev.data = (void *)data;
+   ev.timestamp = timestamp;
+   ev.device = device;
+   ev.toolid = toolid;
+   ev.naxis = naxis;
+   ev.axis = (Evas_Axis *)axis;
+   ev.dev = _evas_device_top_get(eo_e);
+   if (ev.dev) _evas_device_ref(ev.dev);
+
+   _evas_walk(e);
+   copy = evas_event_list_copy(e->pointer.object.in);
+
+   EINA_LIST_FOREACH(copy, l, eo_obj)
+     {
+        Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, 
EVAS_OBJECT_CLASS);
+        if (!evas_event_freezes_through(eo_obj, obj))
+          {
+             evas_object_event_callback_call(eo_obj, obj,
+                                             EVAS_CALLBACK_AXIS_UPDATE, &ev,
+                                             event_id);
+             if (e->delete_me || e->is_frozen) break;
+          }
+     }
+   eina_list_free(copy);
+   _evas_post_event_callback_call(eo_e, e);
+
+   _evas_unwalk(e);
+}
+
+EOLIAN void
+_evas_canvas_event_feed_axis_update(Evas *eo_e, Evas_Public_Data *pd, unsigned 
int timestamp, int device, int toolid, int naxis, const Evas_Axis *axis, const 
void *data)
+{
+   _canvas_event_feed_axis_update_internal(eo_e, pd, timestamp, device, 
toolid, naxis, axis, data);
+}
+
 static void
 _feed_mouse_move_eval_internal(Eo *eo_obj, Evas_Object_Protected_Data *obj)
 {
@@ -2882,6 +2931,12 @@ _evas_canvas_event_refeed_event(Eo *eo_e, 
Evas_Public_Data *e EINA_UNUSED, void
              evas_event_feed_key_up(eo_e, ev->keyname, ev->key, ev->string, 
ev->compose, ev->timestamp, ev->data);
              break;
           }
+      case EVAS_CALLBACK_AXIS_UPDATE:
+          {
+             Evas_Event_Axis_Update *ev = event_copy;
+             evas_event_feed_axis_update(eo_e, ev->timestamp, ev->device, 
ev->toolid, ev->naxis, ev->axis, ev->data);
+             break;
+          }
       default: /* All non-input events are not handeled */
         break;
      }
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index 89ff628..aa9c852 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -1522,6 +1522,7 @@ void _canvas_event_feed_key_up(Eo *e, void *_pd, va_list 
*list);
 void _canvas_event_feed_key_down_with_keycode(Eo *e, void *_pd, va_list *list);
 void _canvas_event_feed_key_up_with_keycode(Eo *e, void *_pd, va_list *list);
 void _canvas_event_feed_hold(Eo *e, void *_pd, va_list *list);
+void _canvas_event_feed_axis_update(Eo *e, void *_pd, va_list *list);
 void _canvas_event_refeed_event(Eo *e, void *_pd, va_list *list);
 void _canvas_event_down_count_get(Eo *e, void *_pd, va_list *list);
 void _canvas_tree_objects_at_xy_get(Eo *e, void *_pd, va_list *list);
diff --git a/src/modules/ecore_evas/engines/x/ecore_evas_x.c 
b/src/modules/ecore_evas/engines/x/ecore_evas_x.c
index d725663..17dfadb 100644
--- a/src/modules/ecore_evas/engines/x/ecore_evas_x.c
+++ b/src/modules/ecore_evas/engines/x/ecore_evas_x.c
@@ -2529,7 +2529,7 @@ _alpha_do(Ecore_Evas *ee, int alpha)
      }
    evas_damage_rectangle_add(ee->evas, 0, 0, ee->req.w, ee->req.h);
    ecore_x_window_shape_mask_set(ee->prop.window, 0);
-   ecore_x_input_multi_select(ee->prop.window);
+   ecore_x_input_select(ee->prop.window);
    ecore_event_window_register(ee->prop.window, ee, ee->evas,
                                
(Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
                                
(Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
@@ -2683,7 +2683,7 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
           }
         evas_damage_rectangle_add(ee->evas, 0, 0, ee->req.w, ee->req.h);
 //        ecore_x_window_shape_mask_set(ee->prop.window, 0);
-        ecore_x_input_multi_select(ee->prop.window);
+        ecore_x_input_select(ee->prop.window);
         ecore_event_window_register(ee->prop.window, ee, ee->evas,
                                     
(Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
                                     
(Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
@@ -3988,7 +3988,7 @@ ecore_evas_software_x11_new_internal(const char 
*disp_name, Ecore_X_Window paren
 
    ee->engine.func->fn_render = _ecore_evas_x_render;
    _ecore_evas_register(ee);
-   ecore_x_input_multi_select(ee->prop.window);
+   ecore_x_input_select(ee->prop.window);
    ecore_event_window_register(ee->prop.window, ee, ee->evas,
                                
(Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
                                
(Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
@@ -4212,7 +4212,7 @@ ecore_evas_software_x11_pixmap_new_internal(const char 
*disp_name, Ecore_X_Windo
 
    ee->draw_ok = 1;
 
-   /* ecore_x_input_multi_select(ee->prop.window); */
+   /* ecore_x_input_select(ee->prop.window); */
    /* ecore_event_window_register(ee->prop.window, ee, ee->evas, */
    /*                             
(Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process, */
    /*                             
(Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process, */
@@ -4305,7 +4305,7 @@ 
_ecore_evas_software_x11_extra_event_window_add(Ecore_Evas *ee, Ecore_X_Window w
      {
         *winp = win;
         edata->win_extra = eina_list_append(edata->win_extra, winp);
-        ecore_x_input_multi_select(win);
+        ecore_x_input_select(win);
         ecore_event_window_register(win, ee, ee->evas,
                                     
(Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
                                     
(Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
@@ -4439,7 +4439,7 @@ ecore_evas_gl_x11_options_new_internal(const char 
*disp_name, Ecore_X_Window par
 
    ee->engine.func->fn_render = _ecore_evas_x_render;
    _ecore_evas_register(ee);
-   ecore_x_input_multi_select(ee->prop.window);
+   ecore_x_input_select(ee->prop.window);
    ecore_event_window_register(ee->prop.window, ee, ee->evas,
                                
(Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process,
                                
(Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process,
@@ -4637,7 +4637,7 @@ ecore_evas_gl_x11_pixmap_new_internal(const char 
*disp_name, Ecore_X_Window pare
    ee->engine.func->fn_render = _ecore_evas_x_render;
    _ecore_evas_register(ee);
 
-   /* ecore_x_input_multi_select(ee->prop.window); */
+   /* ecore_x_input_select(ee->prop.window); */
    /* ecore_event_window_register(ee->prop.window, ee, ee->evas, */
    /*                             
(Ecore_Event_Mouse_Move_Cb)_ecore_evas_mouse_move_process, */
    /*                             
(Ecore_Event_Multi_Move_Cb)_ecore_evas_mouse_multi_move_process, */

-- 


Reply via email to