evas/elm: Fix bad propagation of ON_HOLD flag
authorJean-Philippe Andre <jp.andre@samsung.com>
Wed, 12 Apr 2017 09:30:22 +0000 (18:30 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Wed, 12 Apr 2017 09:43:15 +0000 (18:43 +0900)
Test scenario:
  elementary_test -to "ExtScroller"

Try and modify a slider's value with the mouse wheel. Bad things
were happenning, as the flag ON_HOLD was not properly propagated
from the slider to the scroller. This is because the legacy
event_info structure inside the eo event info was not updated
with the new flag value.

By introducing a new EO only API, which is meant to remain
internal, we can use a single legacy info structure, fixing
this issue.

Note: In the future this API needs to be internal, not protected.

@fix

src/lib/elementary/elm_widget.c
src/lib/evas/canvas/efl_input_event.eo
src/lib/evas/canvas/efl_input_hold.c
src/lib/evas/canvas/efl_input_hold.eo
src/lib/evas/canvas/efl_input_key.c
src/lib/evas/canvas/efl_input_key.eo
src/lib/evas/canvas/efl_input_pointer.c
src/lib/evas/canvas/efl_input_pointer.eo
src/lib/evas/canvas/evas_events_legacy.c

index 9243bee..7521ebd 100644 (file)
@@ -7,6 +7,7 @@
 #define ELM_WIDGET_PROTECTED
 #define ELM_WIDGET_ITEM_PROTECTED
 #define EFL_CANVAS_OBJECT_BETA
+#define EFL_INPUT_EVENT_PROTECTED
 
 #include <Elementary.h>
 
@@ -741,86 +742,46 @@ _propagate_event(void *data EINA_UNUSED, const Efl_Event *event)
    Eo *obj = event->object;
    INTERNAL_ENTRY;
    Evas_Callback_Type type;
-   Evas_Event_Flags *event_flags;
+   Evas_Event_Flags *event_flags, prev_flags;
    union {
-      Evas_Event_Key_Down down;
-      Evas_Event_Key_Up up;
-      Evas_Event_Mouse_Wheel wheel;
-   } event_info = {};
-   Eina_Bool was_hold;
+      Evas_Event_Key_Down    *down;
+      Evas_Event_Key_Up      *up;
+      Evas_Event_Mouse_Wheel *wheel;
+      void                   *any;
+   } event_info;
 
    if ((evas_focus_get(evas_object_evas_get(obj)) != elm_widget_top_get(obj)) &&
        efl_isa(obj, EFL_UI_WIN_CLASS))
      return;
 
-   /* FIXME: Avoid this translation to evas struct and use pointer/key events
-    * in all of elementary widgets
-    * See also: efl_input_key_legacy_info_fill().
-    */
    if (event->desc == EFL_EVENT_KEY_DOWN)
      {
-        Efl_Input_Key_Data *ev = efl_data_scope_get(event->info, EFL_INPUT_KEY_CLASS);
-        if (!ev) return;
-        event_info.down.timestamp = ev->timestamp;
-        event_info.down.keyname = (char*) ev->keyname;
-        event_info.down.key = ev->key;
-        event_info.down.string = ev->string;
-        event_info.down.compose = ev->compose;
-        event_info.down.keycode = ev->keycode;
-        event_info.down.data = ev->data;
-        event_info.down.modifiers = ev->modifiers;
-        event_info.down.locks = ev->locks;
-        event_info.down.event_flags = ev->event_flags;
-        event_info.down.dev = ev->device;
+        event_info.down = efl_input_legacy_info_get(event->info);
+        EINA_SAFETY_ON_NULL_RETURN(event_info.down);
         type = EVAS_CALLBACK_KEY_DOWN;
-        event_flags = &event_info.down.event_flags;
-        was_hold = (*event_flags & EVAS_EVENT_FLAG_ON_HOLD) != 0;
+        event_flags = &event_info.down->event_flags;
      }
    else if (event->desc == EFL_EVENT_KEY_UP)
      {
-        Efl_Input_Key_Data *ev = efl_data_scope_get(event->info, EFL_INPUT_KEY_CLASS);
-        if (!ev) return;
-        event_info.up.timestamp = ev->timestamp;
-        event_info.up.keyname = (char*) ev->keyname;
-        event_info.up.key = ev->key;
-        event_info.up.string = ev->string;
-        event_info.up.compose = ev->compose;
-        event_info.up.keycode = ev->keycode;
-        event_info.up.data = ev->data;
-        event_info.up.modifiers = ev->modifiers;
-        event_info.up.locks = ev->locks;
-        event_info.up.event_flags = ev->event_flags;
-        event_info.up.dev = ev->device;
+        event_info.up = efl_input_legacy_info_get(event->info);
+        EINA_SAFETY_ON_NULL_RETURN(event_info.up);
         type = EVAS_CALLBACK_KEY_UP;
-        event_flags = &event_info.up.event_flags;
-        was_hold = (*event_flags & EVAS_EVENT_FLAG_ON_HOLD) != 0;
+        event_flags = &event_info.up->event_flags;
      }
    else if (event->desc == EFL_EVENT_POINTER_WHEEL)
      {
-        Efl_Input_Pointer_Data *ev = efl_data_scope_get(event->info, EFL_INPUT_POINTER_CLASS);
-        if (!ev) return;
-        event_info.wheel.direction = (ev->wheel.dir != EFL_ORIENT_HORIZONTAL) ? 1 : 0;
-        event_info.wheel.z = ev->wheel.z;
-        event_info.wheel.output.x = ev->cur.x;
-        event_info.wheel.output.y = ev->cur.y;
-        event_info.wheel.canvas.x = ev->cur.x;
-        event_info.wheel.canvas.y = ev->cur.y;
-        event_info.wheel.data = ev->data;
-        event_info.wheel.modifiers = ev->modifiers;
-        event_info.wheel.locks = ev->locks;
-        event_info.wheel.timestamp = ev->timestamp;
-        event_info.wheel.event_flags = ev->event_flags;
-        event_info.wheel.dev = ev->device;
+        event_info.wheel = efl_input_legacy_info_get(event->info);
+        EINA_SAFETY_ON_NULL_RETURN(event_info.wheel);
         type = EVAS_CALLBACK_MOUSE_WHEEL;
-        event_flags = &event_info.wheel.event_flags;
-        was_hold = (*event_flags & EVAS_EVENT_FLAG_ON_HOLD) != 0;
+        event_flags = &event_info.wheel->event_flags;
      }
    else
      return;
 
-   elm_widget_event_propagate(obj, type, &event_info, event_flags);
-   if (!was_hold && (*event_flags & EVAS_EVENT_FLAG_ON_HOLD))
-     efl_input_processed_set(event->info, EINA_TRUE);
+   prev_flags = *event_flags;
+   elm_widget_event_propagate(obj, type, event_info.any, event_flags);
+   if (prev_flags != *event_flags)
+     efl_input_event_flags_set(event->info, *event_flags);
 }
 
 /**
index 420bf7a..718d203 100644 (file)
@@ -65,7 +65,16 @@ mixin Efl.Input.Event
             val: bool; [[$true if the event was not from real hardware, $false otherwise]]
          }
       }
-      instance_get @class @protected @pure_virtual {
+
+      /* FIXME: Internal functions should be marked as such, not as protected! */
+      @property legacy_info @protected @pure_virtual /* @internal */ {
+         [[Returns the legacy info structure. Internal API, do not use it!]]
+         get {}
+         values {
+            event_info: void_ptr; [[Should not be $null.]]
+         }
+      }
+      instance_get @class @protected @pure_virtual /* @internal */ {
         [[Get an instance of this input event]]
          params {
             @in owner: Efl.Object; [[Owner of this input event]]
index ac3dfbf..68a354f 100644 (file)
@@ -4,7 +4,8 @@
 
 #define EFL_INPUT_EVENT_PROTECTED
 
-#include <Evas.h>
+#include "evas_common_private.h"
+#include "evas_private.h"
 
 #define EFL_INTERNAL_UNSTABLE
 #include "interfaces/efl_common_internal.h"
@@ -116,4 +117,11 @@ _efl_input_hold_efl_input_event_dup(Eo *obj, Efl_Input_Hold_Data *pd)
    return evt;
 }
 
+EOLIAN static void *
+_efl_input_hold_efl_input_event_legacy_info_get(Eo *obj, Efl_Input_Hold_Data *pd)
+{
+   if (pd->legacy) return pd->legacy;
+   return efl_input_hold_legacy_info_fill(obj, NULL);
+}
+
 #include "efl_input_hold.eo.c"
index ed5d429..9a19931 100644 (file)
@@ -18,5 +18,6 @@ class Efl.Input.Hold (Efl.Object, Efl.Input.Event)
       Efl.Input.Event.timestamp { get; set; }
       Efl.Input.Event.event_flags { get; set; }
       Efl.Input.Event.device { get; set; }
+      Efl.Input.Event.legacy_info { get; }
    }
 }
index 984d82c..f017680 100644 (file)
@@ -4,7 +4,8 @@
 
 #define EFL_INPUT_EVENT_PROTECTED
 
-#include <Evas.h>
+#include "evas_common_private.h"
+#include "evas_private.h"
 
 #define EFL_INTERNAL_UNSTABLE
 #include "interfaces/efl_common_internal.h"
@@ -266,4 +267,11 @@ _efl_input_key_efl_input_event_fake_get(Eo *obj EINA_UNUSED, Efl_Input_Key_Data
    return pd->fake;
 }
 
+EOLIAN static void *
+_efl_input_key_efl_input_event_legacy_info_get(Eo *obj, Efl_Input_Key_Data *pd)
+{
+   if (pd->legacy) return pd->legacy;
+   return efl_input_key_legacy_info_fill(obj, NULL);
+}
+
 #include "efl_input_key.eo.c"
index 895e795..1c45d21 100644 (file)
@@ -62,6 +62,7 @@ class Efl.Input.Key (Efl.Object, Efl.Input.Event, Efl.Input.State, Efl.Input.Eve
       Efl.Input.Event.fake { get; }
       Efl.Input.Event.event_flags { get; set; }
       Efl.Input.Event.device { get; set; }
+      Efl.Input.Event.legacy_info { get; }
       Efl.Input.State.modifier_enabled { get; }
       Efl.Input.State.lock_enabled { get; }
    }
index 89b8fc5..6f7c9ea 100644 (file)
@@ -4,7 +4,8 @@
 
 #define EFL_INPUT_EVENT_PROTECTED
 
-#include <Evas.h>
+#include "evas_common_private.h"
+#include "evas_private.h"
 
 #define EFL_INTERNAL_UNSTABLE
 #include "interfaces/efl_common_internal.h"
@@ -595,4 +596,11 @@ _efl_input_pointer_value_get(Eo *obj EINA_UNUSED, Efl_Input_Pointer_Data *pd, Ef
      }
 }
 
+EOLIAN static void *
+_efl_input_pointer_efl_input_event_legacy_info_get(Eo *obj, Efl_Input_Pointer_Data *pd)
+{
+   if (pd->legacy) return pd->legacy;
+   return efl_input_pointer_legacy_info_fill(NULL, obj, EVAS_CALLBACK_LAST, NULL);
+}
+
 #include "efl_input_pointer.eo.c"
index a83a2b0..5c1a646 100644 (file)
@@ -171,6 +171,7 @@ class Efl.Input.Pointer (Efl.Object, Efl.Input.Event, Efl.Input.State)
       Efl.Input.Event.fake { get; }
       Efl.Input.Event.event_flags { get; set; }
       Efl.Input.Event.device { get; set; }
+      Efl.Input.Event.legacy_info { get; }
       Efl.Input.State.modifier_enabled { get; }
       Efl.Input.State.lock_enabled { get; }
    }
index aa1e0eb..d4f4146 100644 (file)
@@ -36,10 +36,13 @@ void *
 efl_input_pointer_legacy_info_fill(Evas *eo_evas, Efl_Input_Key *eo_ev, Evas_Callback_Type type, Evas_Event_Flags **pflags)
 {
    Efl_Input_Pointer_Data *ev = efl_data_scope_get(eo_ev, EFL_INPUT_POINTER_CLASS);
-   Evas_Public_Data *evas = efl_data_scope_get(eo_evas, EVAS_CANVAS_CLASS);
+   Evas_Public_Data *evas;
    Evas_Pointer_Data *pdata;
 
-   if (!ev || !evas) return NULL;
+   if (!ev) return NULL;
+   if (!eo_evas) eo_evas = efl_provider_find(eo_ev, EVAS_CANVAS_CLASS);
+   evas = efl_data_scope_get(eo_evas, EVAS_CANVAS_CLASS);
+   if (!evas) return NULL;
 
    pdata = _evas_pointer_data_by_device_get(evas, ev->device);
    EINA_SAFETY_ON_NULL_RETURN_VAL(pdata, NULL);
@@ -47,7 +50,7 @@ efl_input_pointer_legacy_info_fill(Evas *eo_evas, Efl_Input_Key *eo_ev, Evas_Cal
 #define COORD_DUP(e) do { (e)->output.x = pdata->x; (e)->output.y = pdata->y; } while (0)
 #define COORD_DUP_CUR(e) do { (e)->cur.output.x = pdata->x; (e)->cur.output.y = pdata->y; } while (0)
 #define COORD_DUP_PREV(e) do { (e)->prev.output.x = pdata->prev.x; (e)->prev.output.y = pdata->prev.y; } while (0)
-#define TYPE_CHK(typ) do { if (type != EVAS_CALLBACK_ ## typ) return NULL; } while (0)
+#define TYPE_CHK(typ) do { if ((type != EVAS_CALLBACK_LAST) && (type != EVAS_CALLBACK_ ## typ)) return NULL; } while (0)
 
    switch (ev->action)
      {