Ecore_Evas: Add support for per-seat focus.
authorGuilherme Iscaro <iscaro@profusion.mobi>
Thu, 3 Nov 2016 14:07:40 +0000 (12:07 -0200)
committerBruno Dilly <bdilly@profusion.mobi>
Mon, 28 Nov 2016 15:57:55 +0000 (13:57 -0200)
17 files changed:
src/lib/ecore_evas/Ecore_Evas.h
src/lib/ecore_evas/Ecore_Evas_Types.h
src/lib/ecore_evas/ecore_evas.c
src/lib/ecore_evas/ecore_evas_buffer.c
src/lib/ecore_evas/ecore_evas_ews.c
src/lib/ecore_evas/ecore_evas_private.h
src/lib/evas/canvas/evas_canvas.eo
src/lib/evas/canvas/evas_main.c
src/modules/ecore_evas/engines/cocoa/ecore_evas_cocoa.c
src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
src/modules/ecore_evas/engines/extn/ecore_evas_extn.c
src/modules/ecore_evas/engines/fb/ecore_evas_fb.c
src/modules/ecore_evas/engines/psl1ght/ecore_evas_psl1ght.c
src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c
src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c
src/modules/ecore_evas/engines/win32/ecore_evas_win32.c
src/modules/ecore_evas/engines/x/ecore_evas_x.c

index 45dd047..096cb90 100644 (file)
@@ -314,7 +314,7 @@ EAPI void        ecore_evas_geometry_get(const Ecore_Evas *ee, int *x, int *y, i
  */
 EAPI void        ecore_evas_request_geometry_get(const Ecore_Evas *ee, int *x, int *y, int *w, int *h);
 /**
- * @brief Set the focus of an Ecore_Evas' window.
+ * @brief Set the Ecore_Evas window focus for the default seat.
  *
  * @param ee The Ecore_Evas
  * @param on @c EINA_TRUE for focus, @c EINA_FALSE to defocus.
@@ -323,17 +323,47 @@ EAPI void        ecore_evas_request_geometry_get(const Ecore_Evas *ee, int *x, i
  * @p on is @c EINA_FALSE.
  *
  * @warning Support for this depends on the underlying windowing system.
+ * @see ecore_evas_focus_device_set()
  */
 EAPI void        ecore_evas_focus_set(Ecore_Evas *ee, Eina_Bool on);
 /**
- * @brief Query whether an Ecore_Evas' window is focused or not.
+ * @brief Query whether the default seat has the Ecore_Evas focus.
  *
  * @param ee The Ecore_Evas to set
  * @return @c EINA_TRUE if @p ee if focused, @c EINA_FALSE if not.
  *
  * @see ecore_evas_focus_set()
+ * @see ecore_evas_focus_device_get()
  */
 EAPI Eina_Bool   ecore_evas_focus_get(const Ecore_Evas *ee);
+
+/**
+ * @brief Set the Ecore_Evas windows focus for a given seat.
+ *
+ * @param ee The Ecore_Evas
+ * @param seat An Efl_Input_Device that represents the seat or @c NULL for the default seat.
+ * @param on @c EINA_TRUE for focus, @c EINA_FALSE to defocus.
+ *
+ * This function focuses @p ee if @p on is @c EINA_TRUE, or unfocuses @p ee if
+ * @p on is @c EINA_FALSE.
+ *
+ * @warning Support for this depends on the underlying windowing system.
+ * @see ecore_evas_focus_device_get()
+ * @since 1.19
+ */
+EAPI void        ecore_evas_focus_device_set(Ecore_Evas *ee, Eo *seat,
+                                             Eina_Bool on);
+/**
+ * @brief Query whether an Ecore_Evas' window is focused or not.
+ *
+ * @param ee The Ecore_Evas to set
+ * @param seat An Efl_Input_Device that represents the seat or @c NULL for the default seat.
+ * @return @c EINA_TRUE if @p ee if focused, @c EINA_FALSE if not.
+ *
+ * @see ecore_evas_focus_device_set()
+ * @since 1.19
+ */
+EAPI Eina_Bool   ecore_evas_focus_device_get(const Ecore_Evas *ee, Eo *seat);
 /**
  * @brief Iconify or uniconify an Ecore_Evas' window.
  *
@@ -1751,6 +1781,8 @@ EAPI void        ecore_evas_callback_destroy_set(Ecore_Evas *ee, Ecore_Evas_Even
  *
  * @warning If and when this function is called depends on the underlying
  * windowing system.
+ * @note This function only reports focus in events for the default seat!
+ * @see ecore_evas_callback_focus_device_in_set()
  */
 EAPI void        ecore_evas_callback_focus_in_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
 /**
@@ -1763,9 +1795,39 @@ EAPI void        ecore_evas_callback_focus_in_set(Ecore_Evas *ee, Ecore_Evas_Eve
  *
  * @warning If and when this function is called depends on the underlying
  * windowing system.
+ * @note This function only reports focus in events for the default seat!
+ * @see ecore_evas_callback_focus_device_out_set()
  */
 EAPI void        ecore_evas_callback_focus_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func);
 /**
+ * @brief Set a callback for Ecore_Evas focus in events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever @p ee gets focus.
+ *
+ * @warning If and when this function is called depends on the underlying
+ * windowing system.
+ * @see ecore_evas_callback_focus_device_out_set()
+ * @since 1.19
+ */
+EAPI void        ecore_evas_callback_focus_device_in_set(Ecore_Evas *ee, Ecore_Evas_Focus_Device_Event_Cb func);
+/**
+ * @brief Set a callback for Ecore_Evas focus out events.
+ * @param ee The Ecore_Evas to set callbacks on
+ * @param func The function to call
+
+ * A call to this function will set a callback on an Ecore_Evas, causing
+ * @p func to be called whenever @p ee loses focus.
+ *
+ * @warning If and when this function is called depends on the underlying
+ * windowing system.
+ * @see ecore_evas_callback_focus_device_in_set()
+ * @since 1.19
+ */
+EAPI void        ecore_evas_callback_focus_device_out_set(Ecore_Evas *ee, Ecore_Evas_Focus_Device_Event_Cb func);
+/**
  * @brief Set a callback for Ecore_Evas sticky events.
  * @param ee The Ecore_Evas to set callbacks on
  * @param func The function to call
index eeff920..e84a674 100644 (file)
@@ -41,6 +41,7 @@ typedef struct _Ecore_Cocoa_Window Ecore_Cocoa_Window;
 /* basic data types */
 typedef struct _Ecore_Evas Ecore_Evas;
 typedef void   (*Ecore_Evas_Event_Cb) (Ecore_Evas *ee); /**< Callback used for several ecore evas events @since 1.2 */
+typedef void   (*Ecore_Evas_Focus_Device_Event_Cb) (Ecore_Evas *ee, Eo *seat); /** Callback used to report an focus in/out event originated from a seat. @since 1.19*/
 #endif
 
 #ifndef _ECORE_WAYLAND_H_
index 421345d..ae3fed8 100644 (file)
@@ -66,6 +66,23 @@ static int _ecore_evas_fps_debug = 0;
 static int _ecore_evas_render_sync = 1;
 
 static void
+_ecore_evas_focus_out_dispatch(Ecore_Evas *ee, Efl_Input_Device *seat)
+{
+   evas_canvas_seat_focus_out(ee->evas, seat);
+   if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
+   if (ee->func.fn_focus_device_out) ee->func.fn_focus_device_out(ee, seat);
+}
+
+static void
+_ecore_evas_device_del_cb(void *data, const Efl_Event *ev)
+{
+   Ecore_Evas *ee = data;
+
+   ee->prop.focused_by = eina_list_remove(ee->prop.focused_by, ev->object);
+   _ecore_evas_focus_out_dispatch(ee, ev->object);
+}
+
+static void
 _ecore_evas_animator(void *data, const Efl_Event *ev EINA_UNUSED)
 {
    Ecore_Evas *ee = data;
@@ -1005,6 +1022,16 @@ ecore_evas_callback_focus_in_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
 }
 
 EAPI void
+ecore_evas_callback_focus_device_in_set(Ecore_Evas *ee,
+                                        Ecore_Evas_Focus_Device_Event_Cb func)
+{
+   ECORE_EVAS_CHECK(ee);
+   IFC(ee, fn_callback_focus_device_in_set) (ee, func);
+   IFE;
+   ee->func.fn_focus_device_in = func;
+}
+
+EAPI void
 ecore_evas_callback_focus_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
 {
    ECORE_EVAS_CHECK(ee);
@@ -1014,6 +1041,16 @@ ecore_evas_callback_focus_out_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
 }
 
 EAPI void
+ecore_evas_callback_focus_device_out_set(Ecore_Evas *ee,
+                                         Ecore_Evas_Focus_Device_Event_Cb func)
+{
+   ECORE_EVAS_CHECK(ee);
+   IFC(ee, fn_callback_focus_device_out_set) (ee, func);
+   IFE;
+   ee->func.fn_focus_device_out = func;
+}
+
+EAPI void
 ecore_evas_callback_sticky_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func)
 {
    ECORE_EVAS_CHECK(ee);
@@ -1553,30 +1590,75 @@ ecore_evas_layer_get(const Ecore_Evas *ee)
    return ee->prop.layer;
 }
 
+EAPI Eina_Bool
+ecore_evas_focus_device_get(const Ecore_Evas *ee, Efl_Input_Device *seat)
+{
+   ECORE_EVAS_CHECK(ee, EINA_FALSE);
+   if (!seat)
+     seat = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_CLASS_SEAT);
+   return eina_list_data_find(ee->prop.focused_by, seat) ? EINA_TRUE : EINA_FALSE;
+}
+
 EAPI void
-ecore_evas_focus_set(Ecore_Evas *ee, Eina_Bool on)
+_ecore_evas_focus_device_set(Ecore_Evas *ee, Efl_Input_Device *seat,
+                             Eina_Bool on)
 {
-   ECORE_EVAS_CHECK(ee);
-   IFC(ee, fn_focus_set) (ee, on);
-   IFE;
+   Eina_Bool present;
+
+   if (!seat)
+     seat = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_CLASS_SEAT);
+   EINA_SAFETY_ON_NULL_RETURN(seat);
+
+   if (efl_input_device_type_get(seat) != EFL_INPUT_DEVICE_CLASS_SEAT)
+     {
+        ERR("The Input device must be an seat");
+        return;
+     }
+
+   present = ecore_evas_focus_device_get(ee, seat);
    if (on)
      {
-        evas_focus_in(ee->evas);
+        if (present) return;
+        ee->prop.focused_by = eina_list_append(ee->prop.focused_by, seat);
+        efl_event_callback_add(seat, EFL_EVENT_DEL,
+                               _ecore_evas_device_del_cb, ee);
+        evas_canvas_seat_focus_in(ee->evas, seat);
         if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+        if (ee->func.fn_focus_device_in) ee->func.fn_focus_device_in(ee, seat);
      }
    else
      {
-        evas_focus_out(ee->evas);
-        if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
+        if (!present) return;
+        ee->prop.focused_by = eina_list_remove(ee->prop.focused_by, seat);
+        efl_event_callback_del(seat, EFL_EVENT_DEL,
+                               _ecore_evas_device_del_cb, ee);
+        _ecore_evas_focus_out_dispatch(ee, seat);
      }
-   ee->prop.focused = !!on;
+}
+
+EAPI void
+ecore_evas_focus_device_set(Ecore_Evas *ee, Efl_Input_Device *seat,
+                            Eina_Bool on)
+{
+   ECORE_EVAS_CHECK(ee);
+   IFC(ee, fn_focus_device_set) (ee, seat, on);
+   IFE;
+   _ecore_evas_focus_device_set(ee, seat, on);
+}
+
+EAPI void
+ecore_evas_focus_set(Ecore_Evas *ee, Eina_Bool on)
+{
+   ECORE_EVAS_CHECK(ee);
+   IFC(ee, fn_focus_set) (ee, on);
+   IFE;
+   ecore_evas_focus_device_set(ee, NULL, on);
 }
 
 EAPI Eina_Bool
 ecore_evas_focus_get(const Ecore_Evas *ee)
 {
-   ECORE_EVAS_CHECK(ee, EINA_FALSE);
-   return ee->prop.focused ? EINA_TRUE : EINA_FALSE;
+   return ecore_evas_focus_device_get(ee, NULL);
 }
 
 EAPI void
@@ -2672,6 +2754,7 @@ _ecore_evas_vnc_stop(Ecore_Evas *ee)
 EAPI void
 _ecore_evas_free(Ecore_Evas *ee)
 {
+   Efl_Input_Device *seat;
    Ecore_Evas_Interface *iface;
 
    ee->deleted = EINA_TRUE;
@@ -2695,6 +2778,11 @@ _ecore_evas_free(Ecore_Evas *ee)
      {
         _ecore_evas_free(ee->sub_ecore_evas->data);
      }
+   EINA_LIST_FREE(ee->prop.focused_by, seat)
+     {
+        efl_event_callback_del(seat, EFL_EVENT_DEL,
+                               _ecore_evas_device_del_cb, ee);
+     }
    if (ee->data) eina_hash_free(ee->data);
    ee->data = NULL;
    if (ee->name) free(ee->name);
index deb2387..ae9fb62 100644 (file)
@@ -105,12 +105,10 @@ _ecore_evas_show(Ecore_Evas *ee)
    Ecore_Evas_Engine_Buffer_Data *bdata = ee->engine.data;
 
    if (bdata->image) return;
-   if (ee->prop.focused) return;
-   ee->prop.focused = EINA_TRUE;
+   if (ecore_evas_focus_device_get(ee, NULL)) return;
    ee->prop.withdrawn = EINA_FALSE;
    if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
-   evas_focus_in(ee->evas);
-   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
 }
 
 static int
@@ -413,9 +411,7 @@ _ecore_evas_buffer_cb_focus_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj
    Ecore_Evas *ee;
 
    ee = data;
-   ee->prop.focused = EINA_TRUE;
-   evas_focus_in(ee->evas);
-   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
 }
 
 static void
@@ -424,9 +420,7 @@ _ecore_evas_buffer_cb_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *ob
    Ecore_Evas *ee;
 
    ee = data;
-   ee->prop.focused = EINA_FALSE;
-   evas_focus_out(ee->evas);
-   if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
+   _ecore_evas_focus_device_set(ee, NULL, EINA_FALSE);
 }
 
 static void
@@ -608,6 +602,9 @@ static Ecore_Evas_Engine_Func _ecore_buffer_engine_func =
      NULL, // fn_animator_unregister
 
      NULL, // fn_evas_changed
+     NULL, //fn_focus_device_set
+     NULL, //fn_callback_focus_device_in_set
+     NULL, //fn_callback_focus_device_out_set
 };
 
 static void *
@@ -672,7 +669,6 @@ ecore_evas_buffer_allocfunc_new(int w, int h,
    ee->prop.max.w = 0;
    ee->prop.max.h = 0;
    ee->prop.layer = 0;
-   ee->prop.focused = EINA_TRUE;
    ee->prop.borderless = EINA_TRUE;
    ee->prop.override = EINA_TRUE;
    ee->prop.maximized = EINA_TRUE;
@@ -727,7 +723,8 @@ ecore_evas_buffer_allocfunc_new(int w, int h,
    _ecore_evas_register(ee);
 
    evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
-   
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
+
    return ee;
 }
 
@@ -811,7 +808,6 @@ ecore_evas_object_image_new(Ecore_Evas *ee_target)
    ee->prop.max.w = 0;
    ee->prop.max.h = 0;
    ee->prop.layer = 0;
-   ee->prop.focused = EINA_FALSE;
    ee->prop.borderless = EINA_TRUE;
    ee->prop.override = EINA_TRUE;
    ee->prop.maximized = EINA_FALSE;
index 6f90654..c7dcb70 100644 (file)
@@ -465,19 +465,11 @@ static void
 _ecore_evas_ews_focus_set(Ecore_Evas *ee, Eina_Bool on)
 {
    evas_object_focus_set(ee->engine.ews.image, on);
-   ee->prop.focused = on;
+   _ecore_evas_focus_device_set(ee, NULL, on);
    if (on)
-     {
-        evas_focus_in(ee->evas);
-        if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
-        _ecore_evas_ews_event(ee, ECORE_EVAS_EWS_EVENT_FOCUS);
-     }
+     _ecore_evas_ews_event(ee, ECORE_EVAS_EWS_EVENT_FOCUS);
    else
-     {
-        evas_focus_out(ee->evas);
-        if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
-        _ecore_evas_ews_event(ee, ECORE_EVAS_EWS_EVENT_UNFOCUS);
-     }
+     _ecore_evas_ews_event(ee, ECORE_EVAS_EWS_EVENT_UNFOCUS);
 }
 
 static void
@@ -501,7 +493,8 @@ _ecore_evas_ews_override_set(Ecore_Evas *ee, Eina_Bool on)
 {
    if (ee->prop.override == on) return;
    if (ee->visible) evas_object_show(ee->engine.ews.image);
-   if (ee->prop.focused) evas_object_focus_set(ee->engine.ews.image, EINA_TRUE);
+   if (ecore_evas_focus_device_get(ee, NULL))
+     evas_object_focus_set(ee->engine.ews.image, EINA_TRUE);
    ee->prop.override = on;
    _ecore_evas_ews_event(ee, ECORE_EVAS_EWS_EVENT_CONFIG_CHANGE);
 }
@@ -721,6 +714,9 @@ static const Ecore_Evas_Engine_Func _ecore_ews_engine_func =
      NULL, // fn_animator_unregister
 
      NULL, // fn_evas_changed
+     NULL, //fn_focus_device_set
+     NULL, //fn_callback_focus_device_in_set
+     NULL, //fn_callback_focus_device_out_set
 };
 
 void
index 5184e94..af1c531 100644 (file)
@@ -158,6 +158,10 @@ struct _Ecore_Evas_Engine_Func
    void (*fn_animator_unregister)(Ecore_Evas *ee);
 
    void (*fn_evas_changed)(Ecore_Evas *ee, Eina_Bool changed);
+
+   void (*fn_focus_device_set) (Ecore_Evas *ee, Efl_Input_Device *seat, Eina_Bool on);
+   void (*fn_callback_focus_device_in_set) (Ecore_Evas *ee, Ecore_Evas_Focus_Device_Event_Cb func);
+   void (*fn_callback_focus_device_out_set) (Ecore_Evas *ee, Ecore_Evas_Focus_Device_Event_Cb func);
 };
 
 struct _Ecore_Evas_Interface
@@ -257,13 +261,13 @@ struct _Ecore_Evas
          Eina_List      *hints;
          int             id;
       } aux_hint;
+      Eina_List       *focused_by;
       int             layer;
       Ecore_Window    window;
       unsigned char   avoid_damage;
       Ecore_Evas     *group_ee;
       Ecore_Window    group_ee_win;
       double          aspect;
-      Eina_Bool       focused      : 1;
       Eina_Bool       iconified    : 1;
       Eina_Bool       borderless   : 1;
       Eina_Bool       override     : 1;
@@ -300,6 +304,8 @@ struct _Ecore_Evas
       void          (*fn_msg_handle) (Ecore_Evas *ee, int maj, int min, void *data, int size);
       void          (*fn_pointer_xy_get) (const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y);
       Eina_Bool     (*fn_pointer_warp) (const Ecore_Evas *ee, Evas_Coord x, Evas_Coord y);
+      void          (*fn_focus_device_in) (Ecore_Evas *ee, Efl_Input_Device *seat);
+      void          (*fn_focus_device_out) (Ecore_Evas *ee, Efl_Input_Device *seat);
    } func;
 
    Ecore_Evas_Engine engine;
@@ -445,6 +451,10 @@ EAPI void ecore_evas_animator_tick(Ecore_Evas *ee, Eina_Rectangle *viewport, dou
 
 Eina_Module *_ecore_evas_vnc_server_module_load(void);
 
+
+EAPI void _ecore_evas_focus_device_set(Ecore_Evas *ee, Efl_Input_Device *seat,
+                                       Eina_Bool on);
+
 #undef EAPI
 #define EAPI
 
index 8f0c9ae..d4bbfac 100644 (file)
@@ -954,6 +954,20 @@ class Evas.Canvas (Efl.Object, Efl.Canvas, Efl.Animator, Efl.Input.Interface)
       focus_in {
          [[Inform to the evas that it got the focus from the default seat.]]
       }
+      seat_focus_in {
+         [[Inform to the evas that it got the focus from a given seat. @since 1.19]]
+         legacy: null;
+         params {
+            @in seat: Efl.Input.Device; [[The seat or $null for the default seat.]]
+         }
+      }
+      seat_focus_out {
+         [[Inform to the evas that it lost the focus from a given seat. @since 1.19]]
+         legacy: null;
+         params {
+            @in seat: Efl.Input.Device; [[The seat or $null for the default seat.]]
+         }
+      }
       obscured_rectangle_add {
          [[Add an "obscured region" to an Evas canvas.
 
index 0c58d83..22f4fa3 100644 (file)
@@ -539,7 +539,8 @@ _evas_canvas_data_attach_get(Eo *eo_e EINA_UNUSED, Evas_Public_Data *e)
 }
 
 static void
-_evas_canvas_focus_inout_dispatch(Eo *eo_e, Evas_Public_Data *e, Eina_Bool in)
+_evas_canvas_focus_inout_dispatch(Eo *eo_e, Efl_Input_Device *seat,
+                                  Eina_Bool in)
 {
    Efl_Input_Focus_Data *ev_data;
    Efl_Input_Focus *evt;
@@ -547,7 +548,7 @@ _evas_canvas_focus_inout_dispatch(Eo *eo_e, Evas_Public_Data *e, Eina_Bool in)
    evt = efl_input_instance_get(EFL_INPUT_FOCUS_CLASS, eo_e, (void **) &ev_data);
    if (!evt) return;
 
-   ev_data->device = efl_ref(e->default_seat);
+   ev_data->device = efl_ref(seat);
    ev_data->timestamp = time(NULL);
    efl_event_callback_call(eo_e,
                            in ? EFL_EVENT_FOCUS_IN : EFL_EVENT_FOCUS_OUT,
@@ -556,15 +557,33 @@ _evas_canvas_focus_inout_dispatch(Eo *eo_e, Evas_Public_Data *e, Eina_Bool in)
 }
 
 EOLIAN static void
+_evas_canvas_seat_focus_in(Eo *eo_e, Evas_Public_Data *e,
+                           Efl_Input_Device *seat)
+{
+   if (!seat) seat = e->default_seat;
+   if (!seat || efl_input_device_type_get(seat) != EFL_INPUT_DEVICE_CLASS_SEAT) return;
+   _evas_canvas_focus_inout_dispatch(eo_e, seat, EINA_TRUE);
+}
+
+EOLIAN static void
+_evas_canvas_seat_focus_out(Eo *eo_e, Evas_Public_Data *e,
+                            Efl_Input_Device *seat)
+{
+   if (!seat) seat = e->default_seat;
+   if (!seat || efl_input_device_type_get(seat) != EFL_INPUT_DEVICE_CLASS_SEAT) return;
+   _evas_canvas_focus_inout_dispatch(eo_e, seat, EINA_FALSE);
+}
+
+EOLIAN static void
 _evas_canvas_focus_in(Eo *eo_e, Evas_Public_Data *e)
 {
-   _evas_canvas_focus_inout_dispatch(eo_e, e, EINA_TRUE);
+   _evas_canvas_seat_focus_in(eo_e, e, NULL);
 }
 
 EOLIAN static void
 _evas_canvas_focus_out(Eo *eo_e, Evas_Public_Data *e)
 {
-   _evas_canvas_focus_inout_dispatch(eo_e, e, EINA_FALSE);
+   _evas_canvas_seat_focus_out(eo_e, e, NULL);
 }
 
 EOLIAN static Eina_Bool
index 1bfb085..9271d5b 100644 (file)
@@ -186,10 +186,7 @@ _ecore_evas_cocoa_event_got_focus(void *data EINA_UNUSED, int type EINA_UNUSED,
    ee = _ecore_evas_cocoa_match(e->cocoa_window);
    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
 
-   ee->prop.focused = EINA_TRUE;
-   evas_focus_in(ee->evas);
-   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
-
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -202,10 +199,7 @@ _ecore_evas_cocoa_event_lost_focus(void *data EINA_UNUSED, int type EINA_UNUSED,
    ee = _ecore_evas_cocoa_match(e->cocoa_window);
    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
 
-   evas_focus_out(ee->evas);
-   ee->prop.focused = EINA_FALSE;
-   if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
-
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -676,6 +670,9 @@ static Ecore_Evas_Engine_Func _ecore_cocoa_engine_func =
     NULL, // fn_animator_unregister
 
     NULL, // fn_evas_changed
+    NULL, //fn_focus_device_set
+    NULL, //fn_callback_focus_device_in_set
+    NULL, //fn_callback_focus_device_out_set
   };
 
 static Ecore_Cocoa_Window *
index d0f730a..917f1de 100644 (file)
@@ -793,6 +793,9 @@ static Ecore_Evas_Engine_Func _ecore_evas_drm_engine_func =
    _drm_animator_unregister, // animator_unregister
 
    _drm_evas_changed, // evas_changed
+   NULL, //fn_focus_device_set
+   NULL, //fn_callback_focus_device_in_set
+   NULL, //fn_callback_focus_device_out_set
 };
 
 static Ecore_Evas *
index 785f9cd..ff392bf 100644 (file)
@@ -750,8 +750,11 @@ _ecore_evas_extn_cb_focus_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj E
    Ecore_Evas *ee = data;
    Ecore_Evas_Engine_Buffer_Data *bdata = ee->engine.data;
    Extn *extn;
+   Evas_Device *dev;
 
-   ee->prop.focused = EINA_TRUE;
+   dev = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_CLASS_SEAT);
+   if (ecore_evas_focus_device_get(ee, dev)) return;
+   ee->prop.focused_by = eina_list_append(ee->prop.focused_by, dev);
    extn = bdata->data;
    if (!extn) return;
    if (!extn->ipc.server) return;
@@ -765,7 +768,8 @@ _ecore_evas_extn_cb_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj
    Ecore_Evas_Engine_Buffer_Data *bdata = ee->engine.data;
    Extn *extn;
 
-   ee->prop.focused = EINA_FALSE;
+   ee->prop.focused_by = eina_list_remove(ee->prop.focused_by,
+                                          evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_CLASS_SEAT));
    extn = bdata->data;
    if (!extn) return;
    if (!extn->ipc.server) return;
@@ -916,6 +920,9 @@ static const Ecore_Evas_Engine_Func _ecore_extn_plug_engine_func =
    NULL, // fn_animator_unregister
 
    NULL, // fn_evas_changed
+   NULL, //fn_focus_device_set
+   NULL, //fn_callback_focus_device_in_set
+   NULL, //fn_callback_focus_device_out_set
 };
 
 static Eina_Bool
@@ -1199,7 +1206,6 @@ ecore_evas_extn_plug_new_internal(Ecore_Evas *ee_target)
    ee->prop.max.w = 0;
    ee->prop.max.h = 0;
    ee->prop.layer = 0;
-   ee->prop.focused = EINA_FALSE;
    ee->prop.borderless = EINA_TRUE;
    ee->prop.override = EINA_TRUE;
    ee->prop.maximized = EINA_FALSE;
@@ -1660,20 +1666,10 @@ _ipc_client_data(void *data, int type EINA_UNUSED, void *event)
            }
          break;
       case OP_FOCUS:
-         if (!ee->prop.focused)
-           {
-              ee->prop.focused = EINA_TRUE;
-              evas_focus_in(ee->evas);
-              if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
-           }
+         if (!ecore_evas_focus_device_get(ee, NULL)) _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
          break;
       case OP_UNFOCUS:
-         if (ee->prop.focused)
-           {
-              ee->prop.focused = EINA_FALSE;
-              evas_focus_out(ee->evas);
-              if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
-           }
+         if (ecore_evas_focus_device_get(ee, NULL)) _ecore_evas_focus_device_set(ee, NULL, EINA_FALSE);
          break;
       case OP_EV_MOUSE_IN:
          if (ee->events_block) break;
@@ -2125,7 +2121,6 @@ ecore_evas_extn_socket_new_internal(int w, int h)
    ee->prop.max.w = 0;
    ee->prop.max.h = 0;
    ee->prop.layer = 0;
-   ee->prop.focused = EINA_FALSE;
    ee->prop.borderless = EINA_TRUE;
    ee->prop.override = EINA_TRUE;
    ee->prop.maximized = EINA_FALSE;
index 558f82f..adc74b1 100644 (file)
@@ -416,12 +416,10 @@ _ecore_evas_rotation_set(Ecore_Evas *ee, int rotation, int resize EINA_UNUSED)
 static void
 _ecore_evas_show(Ecore_Evas *ee)
 {
-   if (ee->prop.focused) return;
+   if (ecore_evas_focus_device_get(ee, NULL)) return;
    ee->prop.withdrawn = EINA_FALSE;
    if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
-   ee->prop.focused = EINA_TRUE;
-   evas_focus_in(ee->evas);
-   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
 }
 
 static void
@@ -429,12 +427,7 @@ _ecore_evas_hide(Ecore_Evas *ee)
 {
    ee->prop.withdrawn = EINA_TRUE;
    if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
-   if (ee->prop.focused)
-     {
-        ee->prop.focused = EINA_FALSE;
-        evas_focus_out(ee->evas);
-        if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
-     }
+   _ecore_evas_focus_device_set(ee, NULL, EINA_FALSE);
 }
 
 static void
@@ -644,6 +637,9 @@ static Ecore_Evas_Engine_Func _ecore_fb_engine_func =
      NULL, // fn_animator_unregister
 
      NULL, // fn_evas_changed
+     NULL, //fn_focus_device_set
+     NULL, //fn_callback_focus_device_in_set
+     NULL, //fn_callback_focus_device_out_set
 };
 
 EAPI Ecore_Evas *
@@ -692,7 +688,6 @@ ecore_evas_fb_new_internal(const char *disp_name, int rotation, int w, int h)
    ee->prop.max.w = 0;
    ee->prop.max.h = 0;
    ee->prop.layer = 0;
-   ee->prop.focused = EINA_FALSE;
    ee->prop.borderless = EINA_TRUE;
    ee->prop.override = EINA_TRUE;
    ee->prop.maximized = EINA_TRUE;
index 7938dce..7eaf88e 100644 (file)
@@ -67,10 +67,7 @@ _ecore_evas_psl1ght_event_got_focus(void *data EINA_UNUSED, int type EINA_UNUSED
 
    if (!ee) return ECORE_CALLBACK_PASS_ON;
    /* pass on event */
-   ee->prop.focused = EINA_TRUE;
-   evas_focus_in(ee->evas);
-   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
-
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -83,10 +80,7 @@ _ecore_evas_psl1ght_event_lost_focus(void *data EINA_UNUSED, int type EINA_UNUSE
 
    if (!ee) return ECORE_CALLBACK_PASS_ON;
    /* pass on event */
-   evas_focus_out(ee->evas);
-   ee->prop.focused = EINA_FALSE;
-   if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
-
+   _ecore_evas_focus_device_set(ee, NULL, EINA_FALSE);
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -313,10 +307,8 @@ _ecore_evas_show(Ecore_Evas *ee)
 {
    ee->prop.withdrawn = EINA_FALSE;
    if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
-   if (ee->prop.focused) return;
-   ee->prop.focused = EINA_TRUE;
-   evas_focus_in(ee->evas);
-   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+   if (ecore_evas_focus_device_get(ee, NULL)) return;
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
 }
 
 static void
@@ -466,6 +458,9 @@ static Ecore_Evas_Engine_Func _ecore_psl1ght_engine_func =
    NULL, // fn_animator_unregister
 
    NULL, // fn_evas_changed
+   NULL, //fn_focus_device_set
+   NULL, //fn_callback_focus_device_in_set
+   NULL, //fn_callback_focus_device_out_set
 };
 
 EAPI Ecore_Evas *
@@ -496,7 +491,6 @@ ecore_evas_psl1ght_new_internal(const char *name, int w, int h)
    ee->prop.max.w = 0;
    ee->prop.max.h = 0;
    ee->prop.layer = 0;
-   ee->prop.focused = EINA_TRUE;
    ee->prop.borderless = EINA_TRUE;
    ee->prop.override = EINA_TRUE;
    ee->prop.maximized = EINA_TRUE;
@@ -558,6 +552,7 @@ ecore_evas_psl1ght_new_internal(const char *name, int w, int h)
    if (getenv("ECORE_EVAS_PSL1GHT_CURSOR_PATH"))
      ecore_evas_cursor_set(ee, getenv("ECORE_EVAS_PSL1GHT_CURSOR_PATH"), EVAS_LAYER_MAX, 0, 0);
 
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
    evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
    
    return ee;
index 2382fda..e45dd0f 100644 (file)
@@ -103,12 +103,9 @@ _ecore_evas_sdl_event_got_focus(void *data EINA_UNUSED, int type EINA_UNUSED, vo
    Ecore_Evas *ee;
 
    ee = _ecore_evas_sdl_match(ev->windowID);
-
-   if (!ee) return ECORE_CALLBACK_PASS_ON;
    /* pass on event */
-   ee->prop.focused = EINA_TRUE;
-   evas_focus_in(ee->evas);
-   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+   if (!ee) return ECORE_CALLBACK_PASS_ON;
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -122,9 +119,7 @@ _ecore_evas_sdl_event_lost_focus(void *data EINA_UNUSED, int type EINA_UNUSED, v
 
    if (!ee) return ECORE_CALLBACK_PASS_ON;
    /* pass on event */
-   ee->prop.focused = EINA_FALSE;
-   evas_focus_out(ee->evas);
-   if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
+   _ecore_evas_focus_device_set(ee, NULL, EINA_FALSE);
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -411,8 +406,8 @@ _ecore_evas_show(Ecore_Evas *ee)
 {
    ee->prop.withdrawn = EINA_FALSE;
    if (ee->func.fn_state_change) ee->func.fn_state_change(ee);
-   if (ee->prop.focused) return;
-   ee->prop.focused = EINA_TRUE;
+   if (ecore_evas_focus_device_get(ee, NULL)) return;
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
    evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL);
 }
 
@@ -555,6 +550,9 @@ static Ecore_Evas_Engine_Func _ecore_sdl_engine_func =
    NULL, // fn_animator_unregister
 
    NULL, // fn_evas_changed
+   NULL, //fn_focus_device_set
+   NULL, //fn_callback_focus_device_in_set
+   NULL, //fn_callback_focus_device_out_set
 };
 
 static Ecore_Evas*
@@ -599,7 +597,6 @@ _ecore_evas_internal_sdl_new(int rmethod, const char* name, int w, int h, int fu
    ee->prop.max.w = 0;
    ee->prop.max.h = 0;
    ee->prop.layer = 0;
-   ee->prop.focused = EINA_TRUE;
    ee->prop.borderless = EINA_TRUE;
    ee->prop.override = EINA_TRUE;
    ee->prop.maximized = EINA_TRUE;
@@ -725,6 +722,7 @@ _ecore_evas_internal_sdl_new(int rmethod, const char* name, int w, int h, int fu
    ee->engine.func->fn_render = _ecore_evas_sdl_render;
    _ecore_evas_register(ee);
 
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
    ecore_evas_sdl_count++;
    return ee;
 
index 232d96b..0ebff5b 100644 (file)
@@ -85,6 +85,9 @@ static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
    NULL, // fn_animator_unregister
 
    NULL, // fn_evas_changed
+   NULL, //fn_focus_device_set
+   NULL, //fn_callback_focus_device_in_set
+   NULL, //fn_callback_focus_device_out_set
 };
 
 #define _smart_frame_type "ecore_evas_wl_frame"
@@ -207,10 +210,7 @@ _ecore_evas_wl_common_cb_focus_in(void *data EINA_UNUSED, int type EINA_UNUSED,
    ee = ecore_event_window_match(ev->window);
    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
    if (ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
-   if (ee->prop.focused) return ECORE_CALLBACK_PASS_ON;
-   ee->prop.focused = EINA_TRUE;
-   evas_focus_in(ee->evas);
-   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+   _ecore_evas_focus_device_set(ee, ev->dev, EINA_TRUE);
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -226,10 +226,7 @@ _ecore_evas_wl_common_cb_focus_out(void *data EINA_UNUSED, int type EINA_UNUSED,
    ee = ecore_event_window_match(ev->window);
    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
    if (ev->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
-   if (!ee->prop.focused) return ECORE_CALLBACK_PASS_ON;
-   evas_focus_out(ee->evas);
-   ee->prop.focused = EINA_FALSE;
-   if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
+   _ecore_evas_focus_device_set(ee, ev->dev, EINA_FALSE);
    return ECORE_CALLBACK_PASS_ON;
 }
 
index 1187d5d..d5107a0 100644 (file)
@@ -237,9 +237,7 @@ _ecore_evas_win32_event_window_focus_in(void *data EINA_UNUSED, int type EINA_UN
    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
    if ((Ecore_Window)e->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
 
-   ee->prop.focused = EINA_TRUE;
-   evas_focus_in(ee->evas);
-   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -254,9 +252,7 @@ _ecore_evas_win32_event_window_focus_out(void *data EINA_UNUSED, int type EINA_U
    if ((!ee) || (ee->ignore_events)) return ECORE_CALLBACK_PASS_ON;
    if ((Ecore_Window)e->window != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
 
-   evas_focus_out(ee->evas);
-   ee->prop.focused = EINA_FALSE;
-   if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
+   _ecore_evas_focus_device_set(ee, NULL, EINA_FALSE);
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -958,7 +954,7 @@ _ecore_evas_win32_override_set(Ecore_Evas *ee, Eina_Bool on)
    /* FIXME: use borderless_set for now */
    ecore_win32_window_borderless_set(window, on);
    if (ee->should_be_visible) ecore_win32_window_show(window);
-   if (ee->prop.focused) ecore_win32_window_focus(window);
+   if (ecore_evas_focus_device_get(ee, NULL)) ecore_win32_window_focus(window);
    ee->prop.override = on;
 }
 
@@ -1077,7 +1073,7 @@ _ecore_evas_win32_alpha_set(Ecore_Evas *ee, int alpha)
         if (ee->prop.borderless)
           ecore_win32_window_borderless_set((struct _Ecore_Win32_Window *)ee->prop.window, ee->prop.borderless);
         if (ee->visible) ecore_win32_window_show((struct _Ecore_Win32_Window *)ee->prop.window);
-        if (ee->prop.focused) ecore_win32_window_focus((struct _Ecore_Win32_Window *)ee->prop.window);
+        if (ecore_evas_focus_device_get(ee, NULL)) ecore_win32_window_focus((struct _Ecore_Win32_Window *)ee->prop.window);
         if (ee->prop.title)
           {
              ecore_win32_window_title_set((struct _Ecore_Win32_Window *)ee->prop.window, ee->prop.title);
@@ -1206,6 +1202,9 @@ static Ecore_Evas_Engine_Func _ecore_win32_engine_func =
      NULL, // fn_animator_unregister
 
      NULL, // fn_evas_changed
+     NULL, //fn_focus_device_set
+     NULL, //fn_callback_focus_device_in_set
+     NULL, //fn_callback_focus_device_out_set
 };
 
 #endif /* BUILD_ECORE_EVAS_WIN32 */
index 2a71070..b86fca8 100644 (file)
@@ -1500,9 +1500,7 @@ _ecore_evas_x_event_window_focus_in(void *data EINA_UNUSED, int type EINA_UNUSED
    if (e->win != ee->prop.window) return ECORE_CALLBACK_PASS_ON;
 //xx// filtering with these doesnt help   
 //xx//   if (e->mode == ECORE_X_EVENT_MODE_UNGRAB) return ECORE_CALLBACK_PASS_ON;
-   ee->prop.focused = EINA_TRUE;
-   evas_focus_in(ee->evas);
-   if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee);
+   _ecore_evas_focus_device_set(ee, NULL, EINA_TRUE);
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -1521,9 +1519,7 @@ _ecore_evas_x_event_window_focus_out(void *data EINA_UNUSED, int type EINA_UNUSE
 
 //   if (ee->prop.fullscreen)
 //     ecore_x_window_focus(ee->prop.window);
-   evas_focus_out(ee->evas);
-   ee->prop.focused = EINA_FALSE;
-   if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee);
+   _ecore_evas_focus_device_set(ee, NULL, EINA_FALSE);
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -2721,7 +2717,7 @@ _alpha_do(Ecore_Evas *ee, int alpha)
      ecore_x_mwm_borderless_set(ee->prop.window, ee->prop.borderless);
    if (ee->visible || ee->should_be_visible)
      ecore_x_window_show(ee->prop.window);
-   if (ee->prop.focused) ecore_x_window_focus(ee->prop.window);
+   if (ecore_evas_focus_device_get(ee, NULL)) ecore_x_window_focus(ee->prop.window);
    if (ee->prop.title)
      {
         ecore_x_icccm_title_set(ee->prop.window, ee->prop.title);
@@ -2877,7 +2873,7 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
           ecore_x_mwm_borderless_set(ee->prop.window, ee->prop.borderless);
         if (ee->visible || ee->should_be_visible)
           ecore_x_window_show(ee->prop.window);
-        if (ee->prop.focused) ecore_x_window_focus(ee->prop.window);
+        if (ecore_evas_focus_device_get(ee, NULL)) ecore_x_window_focus(ee->prop.window);
         if (ee->prop.title)
           {
              ecore_x_icccm_title_set(ee->prop.window, ee->prop.title);
@@ -3359,7 +3355,7 @@ _ecore_evas_x_override_set(Ecore_Evas *ee, Eina_Bool on)
    if (ee->should_be_visible) ecore_x_window_hide(ee->prop.window);
    ecore_x_window_override_set(ee->prop.window, on);
    if (ee->should_be_visible) ecore_x_window_show(ee->prop.window);
-   if (ee->prop.focused) ecore_x_window_focus(ee->prop.window);
+   if (ecore_evas_focus_device_get(ee, NULL)) ecore_x_window_focus(ee->prop.window);
    ee->prop.override = on;
 }
 
@@ -3788,6 +3784,9 @@ static Ecore_Evas_Engine_Func _ecore_x_engine_func =
    NULL, // fn_animator_unregister
 
    NULL, // fn_evas_changed
+   NULL, //fn_focus_device_set
+   NULL, //fn_callback_focus_device_in_set
+   NULL, //fn_callback_focus_device_out_set
 };
 
 /*