evas/elm: Fix bad propagation of ON_HOLD flag

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
This commit is contained in:
Jean-Philippe Andre 2017-04-12 18:30:22 +09:00
parent e139fda75b
commit 8ff2dffe7c
9 changed files with 66 additions and 66 deletions

View 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);
}
/**

View 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]]

View 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"

View 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; }
}
}

View 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"

View 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; }
}

View 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"

View 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; }
}

View 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)
{