forked from enlightenment/enlightenment
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
This commit is contained in:
parent
409bc58131
commit
17f0ce3713
|
@ -40,6 +40,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;
|
||||
|
@ -2154,6 +2156,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 (_e_comp_x_client_data_get(ec)->deleted) return ECORE_CALLBACK_RENEW;
|
||||
mouse_client = ec;
|
||||
e_client_mouse_in(ec, e_comp_canvas_x_root_adjust(ev->root.x), e_comp_canvas_x_root_adjust(ev->root.y));
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
@ -2174,6 +2177,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 (_e_comp_x_client_data_get(ec)->deleted) return ECORE_CALLBACK_RENEW;
|
||||
if (mouse_client == ec) mouse_client = NULL;
|
||||
e_client_mouse_out(ec, e_comp_canvas_x_root_adjust(ev->root.x), e_comp_canvas_x_root_adjust(ev->root.y));
|
||||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
@ -2571,6 +2575,50 @@ _e_comp_x_move_resize_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecor
|
|||
return ECORE_CALLBACK_RENEW;
|
||||
}
|
||||
|
||||
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->ee, &x, &y);
|
||||
if (E_INSIDE(x, y, mouse_client->x, mouse_client->y, mouse_client->w, mouse_client->h))
|
||||
{
|
||||
if (!_e_comp_x_client_data_get(mouse_client)->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)
|
||||
{
|
||||
|
@ -2614,6 +2662,10 @@ _e_comp_x_focus_in(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_W
|
|||
/* should be equal, maybe some clients don't 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;
|
||||
}
|
||||
|
||||
|
@ -4325,6 +4377,7 @@ _e_comp_x_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
|
|||
pwin = _e_comp_x_client_util_pwin_get(ec);
|
||||
cd = _e_comp_x_client_data_get(ec);
|
||||
|
||||
if (mouse_client == ec) mouse_client = NULL;
|
||||
if ((!stopping) && cd && (!cd->deleted))
|
||||
ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &visible, 1);
|
||||
if ((!ec->already_unparented) && cd && cd->reparented)
|
||||
|
|
|
@ -12,9 +12,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;
|
||||
#ifndef HAVE_WAYLAND_ONLY
|
||||
static Ecore_Timer *focus_fix_timer = NULL;
|
||||
#endif
|
||||
static E_Focus_Method focus_fix_method = E_FOCUS_METHOD_NO_INPUT;
|
||||
|
||||
/* externally accessible functions */
|
||||
|
@ -27,9 +24,6 @@ e_grabinput_init(void)
|
|||
EINTERN int
|
||||
e_grabinput_shutdown(void)
|
||||
{
|
||||
#ifndef HAVE_WAYLAND_ONLY
|
||||
E_FREE_FUNC(focus_fix_timer, ecore_timer_del);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -194,26 +188,6 @@ e_grabinput_mouse_win_get(void)
|
|||
return grab_mouse_win;
|
||||
}
|
||||
|
||||
#ifndef HAVE_WAYLAND_ONLY
|
||||
static Eina_Bool
|
||||
_e_grabinput_focus_check(void *data EINA_UNUSED)
|
||||
{
|
||||
if (!e_comp->root)
|
||||
{
|
||||
focus_fix_timer = NULL;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
focus_fix_timer = NULL;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
_e_grabinput_focus_do(Ecore_Window win, E_Focus_Method method)
|
||||
{
|
||||
|
@ -289,8 +263,4 @@ _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();
|
||||
#ifndef HAVE_WAYLAND_ONLY
|
||||
if (focus_fix_timer) ecore_timer_del(focus_fix_timer);
|
||||
focus_fix_timer = ecore_timer_add(0.2, _e_grabinput_focus_check, NULL);
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue