forked from enlightenment/enlightenment
simulate modal windows for badly behaved x11 clients
it seems that some clients, eg. libreoffice, don't set the modal window property on child dialogs. instead of fighting for focus, set up the child as a modal on the parent and then avoid the whole issue fix T2594
This commit is contained in:
parent
a951b88305
commit
a9db84f94e
|
@ -19,6 +19,9 @@
|
|||
*/
|
||||
#define MOVE_COUNTER_LIMIT 50
|
||||
|
||||
#define PARENT_ACTIVATE_TIME 200
|
||||
#define PARENT_ACTIVATE_LIMIT 2
|
||||
|
||||
EINTERN void _e_main_cb_x_fatal(void *data EINA_UNUSED);
|
||||
|
||||
typedef struct _Frame_Extents Frame_Extents;
|
||||
|
@ -115,6 +118,24 @@ _e_comp_x_focus_check(void)
|
|||
e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
|
||||
}
|
||||
|
||||
static void
|
||||
_e_comp_x_client_modal_setup(E_Client *ec)
|
||||
{
|
||||
E_Comp_X_Client_Data *pcd;
|
||||
|
||||
ec->parent->modal = ec;
|
||||
ec->parent->lock_close = 1;
|
||||
pcd = _e_comp_x_client_data_get(ec->parent);
|
||||
if (!pcd->lock_win)
|
||||
{
|
||||
eina_hash_add(clients_win_hash, &pcd->lock_win, ec->parent);
|
||||
pcd->lock_win = ecore_x_window_input_new(e_client_util_pwin_get(ec->parent), 0, 0, ec->parent->w, ec->parent->h);
|
||||
e_comp_ignore_win_add(E_PIXMAP_TYPE_X, pcd->lock_win);
|
||||
ecore_x_window_show(pcd->lock_win);
|
||||
ecore_x_icccm_name_class_set(pcd->lock_win, "comp_data->lock_win", "comp_data->lock_win");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_e_comp_x_client_frame_update(E_Client *ec, int l, int r, int t, int b)
|
||||
{
|
||||
|
@ -1980,7 +2001,31 @@ _e_comp_x_message(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Cl
|
|||
(!ec->desk->visible))
|
||||
e_client_urgent_set(ec, 1);
|
||||
else
|
||||
e_client_activate(ec, EINA_TRUE);
|
||||
{
|
||||
/* some apps, eg. libreoffice, create "modal" windows which
|
||||
* do not have the netwm modal state set. instead, attempting to
|
||||
* focus the parent window results in the app immediately trying to
|
||||
* activate the "modal" window, triggering an infinite loop.
|
||||
*
|
||||
* by treating this "modal" window as a genuine modal window,
|
||||
* we (eventually) can ignore this type of bad behavior and
|
||||
* give the application/user the expected behavior
|
||||
*/
|
||||
if (ec->parent && (!ec->parent->modal) && (e_client_focused_get() == ec->parent) &&
|
||||
(ev->time - focus_time < PARENT_ACTIVATE_TIME))
|
||||
{
|
||||
E_Comp_X_Client_Data *cd;
|
||||
|
||||
cd = _e_comp_x_client_data_get(ec);
|
||||
if (cd)
|
||||
{
|
||||
cd->parent_activate_count++;
|
||||
if (cd->parent_activate_count >= PARENT_ACTIVATE_LIMIT)
|
||||
_e_comp_x_client_modal_setup(ec);
|
||||
}
|
||||
}
|
||||
e_client_activate(ec, EINA_TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
evas_object_raise(ec->frame);
|
||||
|
@ -3525,21 +3570,7 @@ _e_comp_x_hook_client_fetch(void *d EINA_UNUSED, E_Client *ec)
|
|||
{
|
||||
evas_object_layer_set(ec->frame, ec->parent->layer);
|
||||
if (ec->netwm.state.modal)
|
||||
{
|
||||
E_Comp_X_Client_Data *pcd;
|
||||
|
||||
ec->parent->modal = ec;
|
||||
ec->parent->lock_close = 1;
|
||||
pcd = _e_comp_x_client_data_get(ec->parent);
|
||||
if (!pcd->lock_win)
|
||||
{
|
||||
eina_hash_add(clients_win_hash, &pcd->lock_win, ec->parent);
|
||||
pcd->lock_win = ecore_x_window_input_new(e_client_util_pwin_get(ec->parent), 0, 0, ec->parent->w, ec->parent->h);
|
||||
e_comp_ignore_win_add(E_PIXMAP_TYPE_X, pcd->lock_win);
|
||||
ecore_x_window_show(pcd->lock_win);
|
||||
ecore_x_icccm_name_class_set(pcd->lock_win, "comp_data->lock_win", "comp_data->lock_win");
|
||||
}
|
||||
}
|
||||
_e_comp_x_client_modal_setup(ec);
|
||||
|
||||
if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
|
||||
(ec->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
|
||||
|
|
|
@ -36,6 +36,8 @@ struct _E_Comp_X_Client_Data
|
|||
Ecore_Timer *first_draw_delay; //configurable placebo
|
||||
Eina_Bool first_damage : 1; //ignore first damage on non-re_manage clients
|
||||
|
||||
unsigned int parent_activate_count; //number of times a win has activated itself when parent was focused
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
|
|
Loading…
Reference in New Issue