summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Blumenkrantz <zmike@osg.samsung.com>2015-07-06 15:46:02 -0400
committerMike Blumenkrantz <zmike@osg.samsung.com>2015-07-08 12:49:06 -0400
commit4f8af72fe3fe71d5811c6b955dd1c3e509002cc8 (patch)
tree77fc2f86fe25daff551212d9ce314740c9a43c27
parent2342a4d38fe19dbfab4964635abaf8e5e516ba7d (diff)
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
-rw-r--r--src/bin/e_comp_x.c53
-rw-r--r--src/bin/e_grabinput.c22
2 files changed, 56 insertions, 19 deletions
diff --git a/src/bin/e_comp_x.c b/src/bin/e_comp_x.c
index 07f4ae268..cb63be9d4 100644
--- a/src/bin/e_comp_x.c
+++ b/src/bin/e_comp_x.c
@@ -36,6 +36,8 @@ struct _E_Comp_X_Data
36}; 36};
37 37
38static unsigned int focus_time = 0; 38static unsigned int focus_time = 0;
39static Ecore_Timer *focus_timer;
40static E_Client *mouse_client;
39static Eina_List *handlers = NULL; 41static Eina_List *handlers = NULL;
40static Eina_Hash *clients_win_hash = NULL; 42static Eina_Hash *clients_win_hash = NULL;
41static Eina_Hash *damages_hash = NULL; 43static 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
2032 ec = _e_comp_x_client_find_by_window(ev->win); 2034 ec = _e_comp_x_client_find_by_window(ev->win);
2033 if (!ec) return ECORE_CALLBACK_RENEW; 2035 if (!ec) return ECORE_CALLBACK_RENEW;
2034 if (ec->comp_data->deleted) return ECORE_CALLBACK_RENEW; 2036 if (ec->comp_data->deleted) return ECORE_CALLBACK_RENEW;
2037 mouse_client = ec;
2035 if (ec->input_object) return ECORE_CALLBACK_RENEW; 2038 if (ec->input_object) return ECORE_CALLBACK_RENEW;
2036 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)); 2039 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));
2037 return ECORE_CALLBACK_RENEW; 2040 return ECORE_CALLBACK_RENEW;
@@ -2053,6 +2056,7 @@ _e_comp_x_mouse_out(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_
2053 ec = _e_comp_x_client_find_by_window(ev->win); 2056 ec = _e_comp_x_client_find_by_window(ev->win);
2054 if (!ec) return ECORE_CALLBACK_RENEW; 2057 if (!ec) return ECORE_CALLBACK_RENEW;
2055 if (ec->comp_data->deleted) return ECORE_CALLBACK_RENEW; 2058 if (ec->comp_data->deleted) return ECORE_CALLBACK_RENEW;
2059 if (mouse_client == ec) mouse_client = NULL;
2056 if (ec->input_object) return ECORE_CALLBACK_RENEW; 2060 if (ec->input_object) return ECORE_CALLBACK_RENEW;
2057 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)); 2061 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));
2058 return ECORE_CALLBACK_RENEW; 2062 return ECORE_CALLBACK_RENEW;
@@ -2451,6 +2455,50 @@ _e_comp_x_move_resize_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecor
2451} 2455}
2452 2456
2453static Eina_Bool 2457static Eina_Bool
2458_e_comp_x_focus_timer_cb(void *d EINA_UNUSED)
2459{
2460 E_Client *focused;
2461
2462 /* if mouse-based focus policy clients exist for [focused] and [mouse_client],
2463 * [mouse_client] should have focus here.
2464 * race conditions in x11 focus setting can result in a scenario such that:
2465 * -> set focus on A
2466 * -> set focus on B
2467 * -> receive focus event on A
2468 * -> re-set focus on A
2469 * -> receive focus event on B
2470 * -> receive focus event on A
2471 * ...
2472 * where the end state is that the cursor is over a client which does not have focus.
2473 * this timer is triggered only when such eventing occurs in order to adjust the focused
2474 * client as necessary
2475 */
2476 focused = e_client_focused_get();
2477 if (mouse_client && focused && (!e_client_focus_policy_click(focused)) && (mouse_client != focused))
2478 {
2479 int x, y;
2480
2481 ecore_evas_pointer_xy_get(e_comp_get(NULL)->ee, &x, &y);
2482 if (E_INSIDE(x, y, mouse_client->x, mouse_client->y, mouse_client->w, mouse_client->h))
2483 {
2484 if (!mouse_client->comp_data->deleted)
2485 e_client_mouse_in(mouse_client, x, y);
2486 }
2487 }
2488 focus_timer = NULL;
2489 return EINA_FALSE;
2490}
2491
2492static void
2493_e_comp_x_focus_timer(void)
2494{
2495 if (focus_timer)
2496 ecore_timer_reset(focus_timer);
2497 else /* focus has changed twice in .002 seconds; .01 seconds should be more than enough delay */
2498 focus_timer = ecore_timer_add(0.01, _e_comp_x_focus_timer_cb, NULL);
2499}
2500
2501static Eina_Bool
2454_e_comp_x_focus_in(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Focus_In *ev) 2502_e_comp_x_focus_in(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Focus_In *ev)
2455{ 2503{
2456 E_Client *ec, *focused; 2504 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
2493 /* should be equal, maybe some clients dont reply with the proper timestamp ? */ 2541 /* should be equal, maybe some clients dont reply with the proper timestamp ? */
2494 if (ev->time >= focus_time) 2542 if (ev->time >= focus_time)
2495 evas_object_focus_set(ec->frame, 1); 2543 evas_object_focus_set(ec->frame, 1);
2544 /* handle case of someone trying to benchmark focus handling */
2545 if ((!e_client_focus_policy_click(ec)) && (focused && (!e_client_focus_policy_click(focused))) &&
2546 (ev->time - focus_time <= 2))
2547 _e_comp_x_focus_timer();
2496 return ECORE_CALLBACK_PASS_ON; 2548 return ECORE_CALLBACK_PASS_ON;
2497} 2549}
2498 2550
@@ -4211,6 +4263,7 @@ _e_comp_x_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
4211 win = e_client_util_win_get(ec); 4263 win = e_client_util_win_get(ec);
4212 4264
4213 if ((!stopping) && (!ec->comp_data->deleted)) 4265 if ((!stopping) && (!ec->comp_data->deleted))
4266 if (mouse_client == ec) mouse_client = NULL;
4214 ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &visible, 1); 4267 ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &visible, 1);
4215 if ((!ec->already_unparented) && ec->comp_data->reparented) 4268 if ((!ec->already_unparented) && ec->comp_data->reparented)
4216 { 4269 {
diff --git a/src/bin/e_grabinput.c b/src/bin/e_grabinput.c
index 5f4b2e8dd..b40a74267 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;
13static double last_focus_time = 0.0; 13static double last_focus_time = 0.0;
14 14
15static Ecore_Window focus_fix_win = 0; 15static Ecore_Window focus_fix_win = 0;
16static Ecore_Timer *focus_fix_timer = NULL;
17static E_Focus_Method focus_fix_method = E_FOCUS_METHOD_NO_INPUT; 16static E_Focus_Method focus_fix_method = E_FOCUS_METHOD_NO_INPUT;
18 17
19/* externally accessible functions */ 18/* externally accessible functions */
@@ -26,11 +25,6 @@ e_grabinput_init(void)
26EINTERN int 25EINTERN int
27e_grabinput_shutdown(void) 26e_grabinput_shutdown(void)
28{ 27{
29 if (focus_fix_timer)
30 {
31 ecore_timer_del(focus_fix_timer);
32 focus_fix_timer = NULL;
33 }
34 return 1; 28 return 1;
35} 29}
36 30
@@ -149,18 +143,10 @@ e_grabinput_key_win_get(void)
149 return grab_key_win; 143 return grab_key_win;
150} 144}
151 145
152static Eina_Bool 146E_API Ecore_Window
153_e_grabinput_focus_check(void *data __UNUSED__) 147e_grabinput_mouse_win_get(void)
154{ 148{
155#ifndef HAVE_WAYLAND_ONLY 149 return grab_mouse_win;
156 if (ecore_x_window_focus_get() != focus_fix_win)
157 {
158 /* fprintf(stderr, "foc do 2\n"); */
159 _e_grabinput_focus_do(focus_fix_win, focus_fix_method);
160 }
161#endif
162 focus_fix_timer = NULL;
163 return EINA_FALSE;
164} 150}
165 151
166static void 152static void
@@ -204,7 +190,5 @@ _e_grabinput_focus(Ecore_Window win, E_Focus_Method method)
204 /* fprintf(stderr, "foc do 1\n"); */ 190 /* fprintf(stderr, "foc do 1\n"); */
205 _e_grabinput_focus_do(win, method); 191 _e_grabinput_focus_do(win, method);
206 last_focus_time = ecore_loop_time_get(); 192 last_focus_time = ecore_loop_time_get();
207 if (focus_fix_timer) ecore_timer_del(focus_fix_timer);
208 focus_fix_timer = ecore_timer_add(0.2, _e_grabinput_focus_check, NULL);
209} 193}
210 194