discomfitor pushed a commit to branch enlightenment-0.19.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=4f8af72fe3fe71d5811c6b955dd1c3e509002cc8

commit 4f8af72fe3fe71d5811c6b955dd1c3e509002cc8
Author: Mike Blumenkrantz <zm...@osg.samsung.com>
Date:   Mon Jul 6 15:46:02 2015 -0400

    move grabinput focus fix timer to x11 compositor and fix it to Work Better
    
    see inline comments about x11 focus eventing for details
    
    fix T2547
---
 src/bin/e_comp_x.c    | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/bin/e_grabinput.c | 22 +++------------------
 2 files changed, 56 insertions(+), 19 deletions(-)

diff --git a/src/bin/e_comp_x.c b/src/bin/e_comp_x.c
index 07f4ae2..cb63be9 100644
--- a/src/bin/e_comp_x.c
+++ b/src/bin/e_comp_x.c
@@ -36,6 +36,8 @@ struct _E_Comp_X_Data
 };
 
 static unsigned int focus_time = 0;
+static Ecore_Timer *focus_timer;
+static E_Client *mouse_client;
 static Eina_List *handlers = NULL;
 static Eina_Hash *clients_win_hash = NULL;
 static Eina_Hash *damages_hash = NULL;
@@ -2032,6 +2034,7 @@ _e_comp_x_mouse_in(void *data EINA_UNUSED, int type 
EINA_UNUSED, Ecore_X_Event_M
    ec = _e_comp_x_client_find_by_window(ev->win);
    if (!ec) return ECORE_CALLBACK_RENEW;
    if (ec->comp_data->deleted) return ECORE_CALLBACK_RENEW;
+   mouse_client = ec;
    if (ec->input_object) return ECORE_CALLBACK_RENEW;
    e_client_mouse_in(ec, e_comp_canvas_x_root_adjust(ec->comp, ev->root.x), 
e_comp_canvas_x_root_adjust(ec->comp, ev->root.y));
    return ECORE_CALLBACK_RENEW;
@@ -2053,6 +2056,7 @@ _e_comp_x_mouse_out(void *data EINA_UNUSED, int type 
EINA_UNUSED, Ecore_X_Event_
    ec = _e_comp_x_client_find_by_window(ev->win);
    if (!ec) return ECORE_CALLBACK_RENEW;
    if (ec->comp_data->deleted) return ECORE_CALLBACK_RENEW;
+   if (mouse_client == ec) mouse_client = NULL;
    if (ec->input_object) return ECORE_CALLBACK_RENEW;
    e_client_mouse_out(ec, e_comp_canvas_x_root_adjust(ec->comp, ev->root.x), 
e_comp_canvas_x_root_adjust(ec->comp, ev->root.y));
    return ECORE_CALLBACK_RENEW;
@@ -2451,6 +2455,50 @@ _e_comp_x_move_resize_request(void *data EINA_UNUSED, 
int type EINA_UNUSED, Ecor
 }
 
 static Eina_Bool
+_e_comp_x_focus_timer_cb(void *d EINA_UNUSED)
+{
+   E_Client *focused;
+
+   /* if mouse-based focus policy clients exist for [focused] and 
[mouse_client],
+    * [mouse_client] should have focus here.
+    * race conditions in x11 focus setting can result in a scenario such that:
+    * -> set focus on A
+    * -> set focus on B
+    * -> receive focus event on A
+    * -> re-set focus on A
+    * -> receive focus event on B
+    * -> receive focus event on A
+    * ...
+    * where the end state is that the cursor is over a client which does not 
have focus.
+    * this timer is triggered only when such eventing occurs in order to 
adjust the focused
+    * client as necessary
+    */
+   focused = e_client_focused_get();
+   if (mouse_client && focused && (!e_client_focus_policy_click(focused)) && 
(mouse_client != focused))
+     {
+        int x, y;
+
+        ecore_evas_pointer_xy_get(e_comp_get(NULL)->ee, &x, &y);
+        if (E_INSIDE(x, y, mouse_client->x, mouse_client->y, mouse_client->w, 
mouse_client->h))
+          {
+             if (!mouse_client->comp_data->deleted)
+               e_client_mouse_in(mouse_client, x, y);
+          }
+     }
+   focus_timer = NULL;
+   return EINA_FALSE;
+}
+
+static void
+_e_comp_x_focus_timer(void)
+{
+   if (focus_timer)
+     ecore_timer_reset(focus_timer);
+   else /* focus has changed twice in .002 seconds; .01 seconds should be more 
than enough delay */
+     focus_timer = ecore_timer_add(0.01, _e_comp_x_focus_timer_cb, NULL);
+}
+
+static Eina_Bool
 _e_comp_x_focus_in(void *data EINA_UNUSED, int type EINA_UNUSED, 
Ecore_X_Event_Window_Focus_In *ev)
 {
    E_Client *ec, *focused;
@@ -2493,6 +2541,10 @@ _e_comp_x_focus_in(void *data EINA_UNUSED, int type 
EINA_UNUSED, Ecore_X_Event_W
    /* should be equal, maybe some clients dont reply with the proper timestamp 
? */
    if (ev->time >= focus_time)
      evas_object_focus_set(ec->frame, 1);
+   /* handle case of someone trying to benchmark focus handling */
+   if ((!e_client_focus_policy_click(ec)) && (focused && 
(!e_client_focus_policy_click(focused))) &&
+       (ev->time - focus_time <= 2))
+     _e_comp_x_focus_timer();
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -4211,6 +4263,7 @@ _e_comp_x_hook_client_del(void *d EINA_UNUSED, E_Client 
*ec)
    win = e_client_util_win_get(ec);
 
    if ((!stopping) && (!ec->comp_data->deleted))
+   if (mouse_client == ec) mouse_client = NULL;
      ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &visible, 1);
    if ((!ec->already_unparented) && ec->comp_data->reparented)
      {
diff --git a/src/bin/e_grabinput.c b/src/bin/e_grabinput.c
index 5f4b2e8..b40a742 100644
--- a/src/bin/e_grabinput.c
+++ b/src/bin/e_grabinput.c
@@ -13,7 +13,6 @@ static E_Focus_Method focus_method = E_FOCUS_METHOD_NO_INPUT;
 static double last_focus_time = 0.0;
 
 static Ecore_Window focus_fix_win = 0;
-static Ecore_Timer *focus_fix_timer = NULL;
 static E_Focus_Method focus_fix_method = E_FOCUS_METHOD_NO_INPUT;
 
 /* externally accessible functions */
@@ -26,11 +25,6 @@ e_grabinput_init(void)
 EINTERN int
 e_grabinput_shutdown(void)
 {
-   if (focus_fix_timer)
-     {
-        ecore_timer_del(focus_fix_timer);
-        focus_fix_timer = NULL;
-     }
    return 1;
 }
 
@@ -149,18 +143,10 @@ e_grabinput_key_win_get(void)
    return grab_key_win;
 }
 
-static Eina_Bool
-_e_grabinput_focus_check(void *data __UNUSED__)
+E_API Ecore_Window
+e_grabinput_mouse_win_get(void)
 {
-#ifndef HAVE_WAYLAND_ONLY
-   if (ecore_x_window_focus_get() != focus_fix_win)
-     {
-        /* fprintf(stderr, "foc do 2\n"); */
-        _e_grabinput_focus_do(focus_fix_win, focus_fix_method);
-     }
-#endif
-   focus_fix_timer = NULL;
-   return EINA_FALSE;
+   return grab_mouse_win;
 }
 
 static void
@@ -204,7 +190,5 @@ _e_grabinput_focus(Ecore_Window win, E_Focus_Method method)
    /* fprintf(stderr, "foc do 1\n"); */
    _e_grabinput_focus_do(win, method);
    last_focus_time = ecore_loop_time_get();
-   if (focus_fix_timer) ecore_timer_del(focus_fix_timer);
-   focus_fix_timer = ecore_timer_add(0.2, _e_grabinput_focus_check, NULL);
 }
 

-- 


Reply via email to