forked from enlightenment/enlightenment
client handling - add support for window stacks needed for views/manager
this adds core basic handling for window stacks where windows behave correctly as a single unified stack something like what naviframe does but out-of-window so you can including multiple processes. only on x11 right now as it's being supported/worked on. as we dont plan to kepe naviframe in future, this is the way to go. naviframe "pages" will be windows in a stack. the wm should do the nice thing. in e this will be very nice. for now elsewhere we use transient_for so a wm would treat this like a bunch of dialogs with a single parent window. i guess in a desktop thats probably what you might expect. e will be a little more "finesse" filled. need to make ibar, tasks,m win menu and winlist (alt-tab) respect this and only show the top member of a stack. need to send messages to clients when they are "top" or "middle" or "bottom" or "alone" in the stack or something so decorations can change. should add soem new border signals in theme (for both SSD and CSD) to make this look nice. will need some config additions for that and ability for e comp to do the right thing but this is a solid start
This commit is contained in:
parent
d83e885673
commit
5c38609e0e
|
@ -430,14 +430,34 @@ _e_client_revert_focus(E_Client *ec)
|
|||
E_Desk *desk;
|
||||
|
||||
if (stopping) return;
|
||||
|
||||
if (!ec->focused) return;
|
||||
if (!ec->zone) return;
|
||||
|
||||
desk = e_desk_current_get(ec->zone);
|
||||
if (ec->desk == desk)
|
||||
evas_object_focus_set(ec->frame, 0);
|
||||
|
||||
if ((ec->parent) &&
|
||||
(ec->parent->desk == desk) && (ec->parent->modal == ec))
|
||||
if (ec->stack.prev)
|
||||
{
|
||||
ec->stack.focus_skip = 1;
|
||||
pec = e_client_stack_active_adjust(ec);
|
||||
ec->stack.focus_skip = 0;
|
||||
if ((pec != ec) && (!pec->iconic))
|
||||
evas_object_focus_set(pec->frame, 1);
|
||||
else
|
||||
{
|
||||
if ((e_object_is_del(E_OBJECT(ec))) || (ec->iconic))
|
||||
{
|
||||
Eina_Bool unlock = ec->lock_focus_out;
|
||||
ec->lock_focus_out = 1;
|
||||
pec = e_desk_last_focused_focus(desk);
|
||||
ec->lock_focus_out = unlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((ec->parent) &&
|
||||
(ec->parent->desk == desk) && (ec->parent->modal == ec))
|
||||
{
|
||||
evas_object_focus_set(ec->parent->frame, 1);
|
||||
if (e_config->raise_on_revert_focus)
|
||||
|
@ -447,7 +467,7 @@ _e_client_revert_focus(E_Client *ec)
|
|||
{
|
||||
Eina_Bool unlock = ec->lock_focus_out;
|
||||
ec->lock_focus_out = 1;
|
||||
e_desk_last_focused_focus(desk);
|
||||
pec = e_desk_last_focused_focus(desk);
|
||||
ec->lock_focus_out = unlock;
|
||||
}
|
||||
else if (e_config->focus_policy == E_FOCUS_MOUSE)
|
||||
|
@ -567,6 +587,9 @@ _e_client_free(E_Client *ec)
|
|||
ec->e.state.profile.wait_desk_delfn = NULL;
|
||||
e_object_unref(E_OBJECT(ec->e.state.profile.wait_desk));
|
||||
}
|
||||
if (ec->stack.prev) ec->stack.prev->stack.next = ec->stack.next;
|
||||
if (ec->stack.next) ec->stack.next->stack.prev = ec->stack.prev;
|
||||
|
||||
ec->e.state.profile.wait_desk = NULL;
|
||||
evas_object_del(ec->frame);
|
||||
E_OBJECT(ec)->references--;
|
||||
|
@ -580,6 +603,8 @@ _e_client_del(E_Client *ec)
|
|||
E_Client *child;
|
||||
E_Client_Volume_Sink *sink;
|
||||
|
||||
for (child = ec->stack.next; child; child = child->stack.next)
|
||||
e_client_act_close_begin(child);
|
||||
ec->changed = 0;
|
||||
focus_stack = eina_list_remove(focus_stack, ec);
|
||||
raise_stack = eina_list_remove(raise_stack, ec);
|
||||
|
@ -1390,6 +1415,78 @@ _e_client_zone_update(E_Client *ec)
|
|||
|
||||
////////////////////////////////////////////////
|
||||
|
||||
E_API Eina_List *
|
||||
e_client_stack_list_prepare(E_Client *ec)
|
||||
{
|
||||
E_Client *ec2;
|
||||
Eina_List *list = NULL;
|
||||
|
||||
for (ec2 = ec->stack.prev; ec2; ec2 = ec2->stack.prev)
|
||||
{
|
||||
ec2->stack.ignore++;
|
||||
list = eina_list_prepend(list, ec2);
|
||||
}
|
||||
ec->stack.ignore++;
|
||||
list = eina_list_append(list, ec);
|
||||
for (ec2 = ec->stack.next; ec2; ec2 = ec2->stack.next)
|
||||
{
|
||||
ec2->stack.ignore++;
|
||||
list = eina_list_append(list, ec2);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
E_API void
|
||||
e_client_stack_list_finish(Eina_List *list)
|
||||
{
|
||||
E_Client *ec;
|
||||
|
||||
EINA_LIST_FREE(list, ec) ec->stack.ignore--;
|
||||
}
|
||||
|
||||
E_API E_Client *
|
||||
e_client_stack_top_get(E_Client *ec)
|
||||
{
|
||||
E_Client *ec2;
|
||||
|
||||
for (ec2 = ec; ec2; ec2 = ec2->stack.next)
|
||||
{
|
||||
if (!ec2->stack.next) return ec2;
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
|
||||
E_API E_Client *
|
||||
e_client_stack_bottom_get(E_Client *ec)
|
||||
{
|
||||
E_Client *ec2;
|
||||
|
||||
for (ec2 = ec; ec2; ec2 = ec2->stack.prev)
|
||||
{
|
||||
if (!ec2->stack.prev) return ec2;
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
|
||||
E_API E_Client *
|
||||
e_client_stack_active_adjust(E_Client *ec)
|
||||
{
|
||||
E_Client *pec = ec;
|
||||
if ((!ec->stack.prev) && (!ec->stack.next)) return ec;
|
||||
ec = e_client_stack_top_get(ec);
|
||||
for (; ec; ec = ec->stack.prev)
|
||||
{
|
||||
if (e_object_is_del(E_OBJECT(ec))) continue;
|
||||
if (ec->stack.focus_skip) continue;
|
||||
if (ec->iconic) continue;
|
||||
if (ec->visible) break;
|
||||
}
|
||||
if (!ec) ec = pec;
|
||||
return ec;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
|
||||
static void
|
||||
_e_client_cb_evas_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||
{
|
||||
|
@ -1444,16 +1541,44 @@ _e_client_cb_evas_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UN
|
|||
|
||||
_e_client_zone_update(ec);
|
||||
evas_object_geometry_get(ec->frame, &x, &y, NULL, NULL);
|
||||
if ((e_config->transient.move) && (ec->transients))
|
||||
if (ec->stack.prev || ec->stack.next)
|
||||
{
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
E_Client *child;
|
||||
|
||||
EINA_LIST_FREE(list, child)
|
||||
if (ec->stack.ignore == 0)
|
||||
{
|
||||
evas_object_move(child->frame,
|
||||
child->x + x - ec->pre_cb.x,
|
||||
child->y + y - ec->pre_cb.y);
|
||||
Eina_List *l, *list = e_client_stack_list_prepare(ec);
|
||||
E_Client *child;
|
||||
Evas_Coord bx, by, bw, bh, cw, ch, dx, dy;
|
||||
|
||||
child = e_client_stack_bottom_get(ec);
|
||||
dx = x - ec->pre_cb.x;
|
||||
dy = y - ec->pre_cb.y;
|
||||
if (child != ec)
|
||||
evas_object_move(child->frame, child->x + dx, child->y + dy);
|
||||
evas_object_geometry_get(child->frame, &bx, &by, &bw, &bh);
|
||||
EINA_LIST_FOREACH(list->next, l, child)
|
||||
{
|
||||
if (child == ec) continue;
|
||||
evas_object_geometry_get(child->frame, NULL, NULL, &cw, &ch);
|
||||
evas_object_move(child->frame,
|
||||
bx + ((bw - cw) / 2),
|
||||
by + ((bh - ch) / 2));
|
||||
}
|
||||
e_client_stack_list_finish(list);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((e_config->transient.move) && (ec->transients))
|
||||
{
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
E_Client *child;
|
||||
|
||||
EINA_LIST_FREE(list, child)
|
||||
{
|
||||
evas_object_move(child->frame,
|
||||
child->x + x - ec->pre_cb.x,
|
||||
child->y + y - ec->pre_cb.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ec->moving || (ecmove == ec))
|
||||
|
@ -1476,24 +1601,105 @@ _e_client_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_
|
|||
|
||||
_e_client_zone_update(ec);
|
||||
evas_object_geometry_get(ec->frame, &x, &y, &w, &h);
|
||||
if ((e_config->transient.resize) && (ec->transients))
|
||||
if (ec->stack.prev || ec->stack.next)
|
||||
{
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
E_Client *child;
|
||||
|
||||
EINA_LIST_FREE(list, child)
|
||||
if (ec->stack.ignore == 0)
|
||||
{
|
||||
Evas_Coord nx, ny, nw, nh;
|
||||
Eina_List *l, *list = e_client_stack_list_prepare(ec);
|
||||
E_Client *child;
|
||||
Evas_Coord bx, by, bw, bh, cw, ch;
|
||||
|
||||
if ((ec->pre_cb.w > 0) && (ec->pre_cb.h > 0))
|
||||
if (e_client_util_resizing_get(ec))
|
||||
{
|
||||
nx = x + (((child->x - x) * w) / ec->pre_cb.w);
|
||||
ny = y + (((child->y - y) * h) / ec->pre_cb.h);
|
||||
nw = (child->w * w) / ec->pre_cb.w;
|
||||
nh = (child->h * h) / ec->pre_cb.h;
|
||||
nx += ((nw - child->w) / 2);
|
||||
ny += ((nh - child->h) / 2);
|
||||
evas_object_move(child->frame, nx, ny);
|
||||
if (ec->dialog)
|
||||
{
|
||||
child = list->data;
|
||||
evas_object_geometry_get(child->frame, &bx, &by, &bw, &bh);
|
||||
EINA_LIST_FOREACH(list, l, child)
|
||||
{
|
||||
if (child == ec) continue;
|
||||
if (!ec->dialog)
|
||||
{
|
||||
evas_object_resize(child->frame, bw, bh);
|
||||
cw = bw;
|
||||
ch = bh;
|
||||
}
|
||||
else
|
||||
evas_object_geometry_get(child->frame, NULL, NULL, &cw, &ch);
|
||||
evas_object_move(child->frame,
|
||||
bx + ((bw - cw) / 2),
|
||||
by + ((bh - ch) / 2));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
child = e_client_stack_bottom_get(ec);
|
||||
evas_object_move(child->frame, x, y);
|
||||
evas_object_resize(child->frame, w, h);
|
||||
EINA_LIST_FOREACH(list->next, l, child)
|
||||
{
|
||||
if (child == ec) continue;
|
||||
if (!ec->dialog)
|
||||
{
|
||||
evas_object_move(child->frame, x, y);
|
||||
evas_object_resize(child->frame, w, h);
|
||||
cw = w;
|
||||
ch = h;
|
||||
}
|
||||
else
|
||||
evas_object_geometry_get(child->frame, NULL, NULL, &cw, &ch);
|
||||
evas_object_move(child->frame,
|
||||
x + ((w - cw) / 2),
|
||||
y + ((h - ch) / 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ec == e_client_stack_bottom_get(ec))
|
||||
{
|
||||
EINA_LIST_FOREACH(list->next, l, child)
|
||||
{
|
||||
if (child == ec) continue;
|
||||
if (!ec->dialog)
|
||||
{
|
||||
evas_object_move(child->frame, x, y);
|
||||
evas_object_resize(child->frame, w, h);
|
||||
cw = w;
|
||||
ch = h;
|
||||
}
|
||||
else
|
||||
evas_object_geometry_get(child->frame, NULL, NULL, &cw, &ch);
|
||||
evas_object_move(child->frame,
|
||||
x + ((w - cw) / 2),
|
||||
y + ((h - ch) / 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
e_client_stack_list_finish(list);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((e_config->transient.resize) && (ec->transients))
|
||||
{
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
E_Client *child;
|
||||
|
||||
EINA_LIST_FREE(list, child)
|
||||
{
|
||||
Evas_Coord nx, ny, nw, nh;
|
||||
|
||||
if ((ec->pre_cb.w > 0) && (ec->pre_cb.h > 0))
|
||||
{
|
||||
nx = x + (((child->x - x) * w) / ec->pre_cb.w);
|
||||
ny = y + (((child->y - y) * h) / ec->pre_cb.h);
|
||||
nw = (child->w * w) / ec->pre_cb.w;
|
||||
nh = (child->h * h) / ec->pre_cb.h;
|
||||
nx += ((nw - child->w) / 2);
|
||||
ny += ((nh - child->h) / 2);
|
||||
evas_object_move(child->frame, nx, ny);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1518,22 +1724,45 @@ _e_client_cb_evas_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA
|
|||
E_Client *ec = data;
|
||||
|
||||
if (ec->layer_block) return;
|
||||
if (e_config->transient.raise && ec->transients)
|
||||
if (ec->stack.prev || ec->stack.next)
|
||||
{
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
E_Client *child, *below = NULL;
|
||||
|
||||
E_LIST_REVERSE_FREE(list, child)
|
||||
if (ec->stack.ignore == 0)
|
||||
{
|
||||
/* Don't stack iconic transients. If the user wants these shown,
|
||||
* that's another option.
|
||||
*/
|
||||
if (child->iconic) continue;
|
||||
if (below)
|
||||
evas_object_stack_below(child->frame, below->frame);
|
||||
else
|
||||
evas_object_stack_above(child->frame, ec->frame);
|
||||
below = child;
|
||||
Eina_List *l, *list = e_client_stack_list_prepare(ec);
|
||||
E_Client *child;
|
||||
|
||||
EINA_LIST_FOREACH(list, l, child)
|
||||
{
|
||||
if (child == ec) break;
|
||||
evas_object_stack_below(child->frame, ec->frame);
|
||||
}
|
||||
EINA_LIST_REVERSE_FOREACH(list, l, child)
|
||||
{
|
||||
if (child == ec) break;
|
||||
evas_object_stack_above(child->frame, ec->frame);
|
||||
}
|
||||
e_client_stack_list_finish(list);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e_config->transient.raise && ec->transients)
|
||||
{
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
E_Client *child, *below = NULL;
|
||||
|
||||
E_LIST_REVERSE_FREE(list, child)
|
||||
{
|
||||
/* Don't stack iconic transients. If the user wants these shown,
|
||||
* that's another option.
|
||||
*/
|
||||
if (child->iconic) continue;
|
||||
if (below)
|
||||
evas_object_stack_below(child->frame, below->frame);
|
||||
else
|
||||
evas_object_stack_above(child->frame, ec->frame);
|
||||
below = child;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ec->unredirected_single) return;
|
||||
|
@ -1608,6 +1837,16 @@ _e_client_eval(E_Client *ec)
|
|||
ec->placed = 1;
|
||||
ec->pre_cb.x = ec->x; ec->pre_cb.y = ec->y;
|
||||
}
|
||||
|
||||
if ((ec->stack.prev) && (!ec->dialog))
|
||||
{
|
||||
E_Client *ec2 = e_client_stack_bottom_get(ec);
|
||||
|
||||
ec->stack.ignore++;
|
||||
evas_object_move(ec->frame, ec2->x, ec2->y);
|
||||
evas_object_resize(ec->frame, ec2->w, ec2->h);
|
||||
ec->stack.ignore--;
|
||||
}
|
||||
if (!ec->placed)
|
||||
{
|
||||
if (ec->parent)
|
||||
|
@ -2088,7 +2327,12 @@ _e_client_eval(E_Client *ec)
|
|||
((ec->take_focus) || (ec->want_focus)))
|
||||
{
|
||||
ec->take_focus = 0;
|
||||
if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (ec->want_focus))
|
||||
if ((ec->stack.prev) && (!ec->stack.next) &&
|
||||
(ec->stack.prev == e_client_focused_get()))
|
||||
{
|
||||
e_client_focus_set_with_pointer(ec);
|
||||
}
|
||||
else if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (ec->want_focus))
|
||||
{
|
||||
ec->want_focus = 0;
|
||||
e_client_focus_set_with_pointer(ec);
|
||||
|
@ -2580,6 +2824,8 @@ e_client_desk_set(E_Client *ec, E_Desk *desk)
|
|||
e_comp_object_effect_set(ec->frame, NULL);
|
||||
if (desk->visible || ec->sticky)
|
||||
{
|
||||
// force visibility if its a stack window going onto this desktop
|
||||
if (ec->stack.prev || ec->stack.next) ec->hidden = 0;
|
||||
if ((!ec->hidden) && (!ec->iconic))
|
||||
evas_object_show(ec->frame);
|
||||
}
|
||||
|
@ -2611,13 +2857,38 @@ e_client_desk_set(E_Client *ec, E_Desk *desk)
|
|||
}
|
||||
}
|
||||
|
||||
if (e_config->transient.desktop)
|
||||
if (ec->stack.prev || ec->stack.next)
|
||||
{
|
||||
E_Client *child;
|
||||
const Eina_List *l;
|
||||
if (ec->stack.ignore == 0)
|
||||
{
|
||||
Eina_List *l, *list = e_client_stack_list_prepare(ec);
|
||||
E_Client *child;
|
||||
|
||||
EINA_LIST_FOREACH(ec->transients, l, child)
|
||||
e_client_desk_set(child, ec->desk);
|
||||
EINA_LIST_FOREACH(list, l, child)
|
||||
{
|
||||
if (child == ec) break;
|
||||
e_client_desk_set(child, ec->desk);
|
||||
evas_object_stack_below(child->frame, ec->frame);
|
||||
}
|
||||
EINA_LIST_REVERSE_FOREACH(list, l, child)
|
||||
{
|
||||
if (child == ec) break;
|
||||
e_client_desk_set(child, ec->desk);
|
||||
evas_object_stack_above(child->frame, ec->frame);
|
||||
}
|
||||
e_client_stack_list_finish(list);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e_config->transient.desktop)
|
||||
{
|
||||
E_Client *child;
|
||||
const Eina_List *l;
|
||||
|
||||
EINA_LIST_FOREACH(ec->transients, l, child)
|
||||
e_client_desk_set(child, ec->desk);
|
||||
}
|
||||
}
|
||||
|
||||
e_remember_update(ec);
|
||||
|
@ -3344,6 +3615,7 @@ e_client_focus_set_with_pointer(E_Client *ec)
|
|||
if ((!ec->icccm.accepts_focus) &&
|
||||
(!ec->icccm.take_focus)) return;
|
||||
}
|
||||
ec = e_client_stack_active_adjust(ec);
|
||||
if (ec->lock_focus_out) return;
|
||||
if (ec == focused) return;
|
||||
evas_object_focus_set(ec->frame, 1);
|
||||
|
@ -3466,6 +3738,7 @@ e_client_activate(E_Client *ec, Eina_Bool just_do_it)
|
|||
{
|
||||
E_OBJECT_CHECK(ec);
|
||||
E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
|
||||
ec = e_client_stack_active_adjust(ec);
|
||||
if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
|
||||
((ec->parent) &&
|
||||
((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
|
||||
|
@ -4160,28 +4433,60 @@ e_client_iconify(E_Client *ec)
|
|||
E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
|
||||
if (!ec->zone) return;
|
||||
if (ec->shading || ec->iconic) return;
|
||||
if (((ec->stack.prev || ec->stack.next)) && (!ec->stack.ignore))
|
||||
{
|
||||
Eina_List *l, *list = e_client_stack_list_prepare(ec);
|
||||
E_Client *child;
|
||||
|
||||
EINA_LIST_FOREACH(list, l, child)
|
||||
{
|
||||
e_client_iconify(child);
|
||||
}
|
||||
e_client_stack_list_finish(list);
|
||||
E_Client *pec;
|
||||
E_Desk *desk;
|
||||
|
||||
desk = e_desk_current_get(ec->zone);
|
||||
pec = e_desk_last_focused_focus(desk);
|
||||
if (pec) evas_object_focus_set(pec->frame, 1);
|
||||
return;
|
||||
}
|
||||
ec->iconic = 1;
|
||||
ec->want_focus = ec->take_focus = 0;
|
||||
ec->changes.visible = 0;
|
||||
if (ec->fullscreen)
|
||||
ec->desk->fullscreen_clients = eina_list_remove(ec->desk->fullscreen_clients, ec);
|
||||
e_client_comp_hidden_set(ec, 1);
|
||||
if (!ec->new_client)
|
||||
if (!ec->stack.ignore)
|
||||
{
|
||||
_e_client_revert_focus(ec);
|
||||
evas_object_hide(ec->frame);
|
||||
if (!ec->new_client)
|
||||
{
|
||||
_e_client_revert_focus(ec);
|
||||
evas_object_hide(ec->frame);
|
||||
}
|
||||
e_client_urgent_set(ec, ec->icccm.urgent);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ec->new_client)
|
||||
evas_object_hide(ec->frame);
|
||||
e_client_urgent_set(ec, ec->icccm.urgent);
|
||||
if (ec->focused)
|
||||
evas_object_focus_set(ec->frame, 0);
|
||||
}
|
||||
e_client_urgent_set(ec, ec->icccm.urgent);
|
||||
|
||||
_e_client_event_simple(ec, E_EVENT_CLIENT_ICONIFY);
|
||||
|
||||
if (e_config->transient.iconify)
|
||||
if (!ec->stack.prev && !ec->stack.next)
|
||||
{
|
||||
E_Client *child;
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
if (e_config->transient.iconify)
|
||||
{
|
||||
E_Client *child;
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
|
||||
EINA_LIST_FREE(list, child)
|
||||
e_client_iconify(child);
|
||||
EINA_LIST_FREE(list, child)
|
||||
e_client_iconify(child);
|
||||
}
|
||||
}
|
||||
e_remember_update(ec);
|
||||
}
|
||||
|
@ -4195,23 +4500,44 @@ e_client_uniconify(E_Client *ec)
|
|||
E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
|
||||
if (!ec->zone) return;
|
||||
if (ec->shading || (!ec->iconic)) return;
|
||||
|
||||
if (((ec->stack.prev || ec->stack.next)) && (!ec->stack.ignore))
|
||||
{
|
||||
Eina_List *l, *list = e_client_stack_list_prepare(ec);
|
||||
E_Client *child, *ec_focus = NULL;
|
||||
|
||||
EINA_LIST_FOREACH(list, l, child)
|
||||
{
|
||||
e_client_uniconify(child);
|
||||
if (!l->next) ec_focus = child;
|
||||
}
|
||||
e_client_stack_list_finish(list);
|
||||
evas_object_raise(ec_focus->frame);
|
||||
evas_object_focus_set(ec_focus->frame, 1);
|
||||
return;
|
||||
}
|
||||
desk = e_desk_current_get(ec->desk->zone);
|
||||
e_client_desk_set(ec, desk);
|
||||
evas_object_raise(ec->frame);
|
||||
if (!ec->stack.ignore)
|
||||
evas_object_raise(ec->frame);
|
||||
evas_object_show(ec->frame);
|
||||
e_client_comp_hidden_set(ec, 0);
|
||||
ec->deskshow = ec->iconic = 0;
|
||||
evas_object_focus_set(ec->frame, 1);
|
||||
if (!ec->stack.ignore)
|
||||
evas_object_focus_set(ec->frame, 1);
|
||||
|
||||
_e_client_event_simple(ec, E_EVENT_CLIENT_UNICONIFY);
|
||||
|
||||
if (e_config->transient.iconify)
|
||||
if (!ec->stack.prev && !ec->stack.next)
|
||||
{
|
||||
E_Client *child;
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
if (e_config->transient.iconify)
|
||||
{
|
||||
E_Client *child;
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
|
||||
EINA_LIST_FREE(list, child)
|
||||
e_client_uniconify(child);
|
||||
EINA_LIST_FREE(list, child)
|
||||
e_client_uniconify(child);
|
||||
}
|
||||
}
|
||||
e_remember_update(ec);
|
||||
}
|
||||
|
@ -4267,16 +4593,36 @@ e_client_stick(E_Client *ec)
|
|||
e_client_desk_set(ec, desk);
|
||||
evas_object_smart_callback_call(ec->frame, "stick", NULL);
|
||||
|
||||
if (e_config->transient.desktop)
|
||||
if (ec->stack.prev || ec->stack.next)
|
||||
{
|
||||
E_Client *child;
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
|
||||
EINA_LIST_FREE(list, child)
|
||||
if (ec->stack.ignore == 0)
|
||||
{
|
||||
child->sticky = 1;
|
||||
e_hints_window_sticky_set(child, 1);
|
||||
evas_object_show(ec->frame);
|
||||
Eina_List *l, *list = e_client_stack_list_prepare(ec);
|
||||
E_Client *child;
|
||||
|
||||
EINA_LIST_FOREACH(list, l, child)
|
||||
{
|
||||
if (child == ec) continue;
|
||||
child->sticky = 1;
|
||||
e_hints_window_sticky_set(child, 1);
|
||||
evas_object_show(ec->frame);
|
||||
}
|
||||
e_client_stack_list_finish(list);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e_config->transient.desktop)
|
||||
{
|
||||
E_Client *child;
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
|
||||
EINA_LIST_FREE(list, child)
|
||||
{
|
||||
child->sticky = 1;
|
||||
e_hints_window_sticky_set(child, 1);
|
||||
evas_object_show(ec->frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4301,15 +4647,34 @@ e_client_unstick(E_Client *ec)
|
|||
e_client_desk_set(ec, desk);
|
||||
evas_object_smart_callback_call(ec->frame, "unstick", NULL);
|
||||
|
||||
if (e_config->transient.desktop)
|
||||
if (ec->stack.prev || ec->stack.next)
|
||||
{
|
||||
E_Client *child;
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
|
||||
EINA_LIST_FREE(list, child)
|
||||
if (ec->stack.ignore == 0)
|
||||
{
|
||||
child->sticky = 0;
|
||||
e_hints_window_sticky_set(child, 0);
|
||||
Eina_List *l, *list = e_client_stack_list_prepare(ec);
|
||||
E_Client *child;
|
||||
|
||||
EINA_LIST_FOREACH(list, l, child)
|
||||
{
|
||||
if (child == ec) continue;
|
||||
child->sticky = 1;
|
||||
e_hints_window_sticky_set(child, 0);
|
||||
}
|
||||
e_client_stack_list_finish(list);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e_config->transient.desktop)
|
||||
{
|
||||
E_Client *child;
|
||||
Eina_List *list = eina_list_clone(ec->transients);
|
||||
|
||||
EINA_LIST_FREE(list, child)
|
||||
{
|
||||
child->sticky = 0;
|
||||
e_hints_window_sticky_set(child, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5030,6 +5395,7 @@ e_client_pointer_warp_to_center(E_Client *ec)
|
|||
int x, y;
|
||||
E_Client *cec = NULL;
|
||||
|
||||
ec = e_client_stack_active_adjust(ec);
|
||||
if (!ec->zone) return 0;
|
||||
if (e_config->disable_all_pointer_warps) return 0;
|
||||
/* Only warp the pointer if it is not already in the area of
|
||||
|
@ -5039,6 +5405,7 @@ e_client_pointer_warp_to_center(E_Client *ec)
|
|||
(y >= ec->y) && (y <= (ec->y + ec->h)))
|
||||
{
|
||||
cec = _e_client_under_pointer_helper(ec->desk, ec, x, y);
|
||||
cec = e_client_stack_active_adjust(cec);
|
||||
if (cec == ec) return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -266,6 +266,13 @@ struct E_Client
|
|||
|
||||
E_Action *cur_mouse_action;
|
||||
|
||||
struct {
|
||||
E_Client *next;
|
||||
E_Client *prev;
|
||||
int ignore;
|
||||
Eina_Bool focus_skip : 1;
|
||||
} stack;
|
||||
|
||||
int border_size; //size of client's border
|
||||
|
||||
struct
|
||||
|
@ -518,8 +525,9 @@ struct E_Client
|
|||
unsigned char wait_for_done : 1;
|
||||
unsigned char use : 1;
|
||||
} profile;
|
||||
unsigned char centered : 1;
|
||||
unsigned char video : 1;
|
||||
Ecore_X_Stack_Type stack;
|
||||
unsigned char centered : 1;
|
||||
unsigned char video : 1;
|
||||
} state;
|
||||
|
||||
struct
|
||||
|
@ -528,6 +536,7 @@ struct E_Client
|
|||
unsigned char video_parent : 1;
|
||||
unsigned char video_position : 1;
|
||||
unsigned char profile : 1;
|
||||
unsigned char stack : 1;
|
||||
} fetch;
|
||||
} e;
|
||||
|
||||
|
@ -840,6 +849,11 @@ E_API Eina_Bool e_client_has_xwindow(const E_Client *ec);
|
|||
E_API Eina_Bool e_client_desk_window_profile_available_check(E_Client *ec, const char *profile);
|
||||
E_API void e_client_desk_window_profile_wait_desk_set(E_Client *ec, E_Desk *desk);
|
||||
E_API void e_client_layout_cb_set(E_Client_Layout_Cb cb);
|
||||
E_API Eina_List *e_client_stack_list_prepare(E_Client *ec);
|
||||
E_API void e_client_stack_list_finish(Eina_List *list);
|
||||
E_API E_Client *e_client_stack_top_get(E_Client *ec);
|
||||
E_API E_Client *e_client_stack_bottom_get(E_Client *ec);
|
||||
E_API E_Client *e_client_stack_active_adjust(E_Client *ec);
|
||||
|
||||
YOLO E_API void e_client_focus_stack_set(Eina_List *l);
|
||||
|
||||
|
|
|
@ -1318,6 +1318,7 @@ _e_comp_intercept_layer_set(void *data, Evas_Object *obj, int layer)
|
|||
E_Comp_Object *cw = data;
|
||||
unsigned int l = e_comp_canvas_layer_map(layer);
|
||||
int oldraise;
|
||||
E_Client *ec;
|
||||
|
||||
if (cw->ec->layer_block)
|
||||
{
|
||||
|
@ -1362,20 +1363,40 @@ _e_comp_intercept_layer_set(void *data, Evas_Object *obj, int layer)
|
|||
_e_comp_object_layers_remove(cw);
|
||||
/* clamp to valid client layer */
|
||||
layer = e_comp_canvas_client_layer_map_nearest(layer);
|
||||
cw->ec->layer = layer;
|
||||
if (e_config->transient.layer)
|
||||
ec = cw->ec;
|
||||
ec->layer = layer;
|
||||
if (ec->stack.prev || ec->stack.next)
|
||||
{
|
||||
E_Client *child;
|
||||
Eina_List *list = eina_list_clone(cw->ec->transients);
|
||||
if (ec->stack.ignore == 0)
|
||||
{
|
||||
Eina_List *l, *list = e_client_stack_list_prepare(ec);
|
||||
E_Client *child;
|
||||
|
||||
/* We need to set raise to one, else the child wont
|
||||
* follow to the new layer. It should be like this,
|
||||
* even if the user usually doesn't want to raise
|
||||
* the transients.
|
||||
*/
|
||||
e_config->transient.raise = 1;
|
||||
EINA_LIST_FREE(list, child)
|
||||
evas_object_layer_set(child->frame, layer);
|
||||
EINA_LIST_FOREACH(list, l, child)
|
||||
{
|
||||
if (child == ec) continue;
|
||||
evas_object_layer_set(child->frame, layer);
|
||||
}
|
||||
e_client_stack_list_finish(list);
|
||||
evas_object_raise(ec->frame);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e_config->transient.layer)
|
||||
{
|
||||
E_Client *child;
|
||||
Eina_List *list = eina_list_clone(cw->ec->transients);
|
||||
|
||||
/* We need to set raise to one, else the child wont
|
||||
* follow to the new layer. It should be like this,
|
||||
* even if the user usually doesn't want to raise
|
||||
* the transients.
|
||||
*/
|
||||
e_config->transient.raise = 1;
|
||||
EINA_LIST_FREE(list, child)
|
||||
evas_object_layer_set(child->frame, layer);
|
||||
}
|
||||
}
|
||||
if (!cw->ec->override)
|
||||
{
|
||||
|
@ -1780,9 +1801,14 @@ static void
|
|||
_e_comp_intercept_focus(void *data, Evas_Object *obj, Eina_Bool focus)
|
||||
{
|
||||
E_Comp_Object *cw = data;
|
||||
E_Client *ec;
|
||||
E_Client *ec = cw->ec;
|
||||
|
||||
ec = cw->ec;
|
||||
if (focus)
|
||||
{
|
||||
ec = e_client_stack_active_adjust(ec);
|
||||
obj = ec->frame;
|
||||
cw = evas_object_data_get(obj, "comp_obj");
|
||||
}
|
||||
/* note: this is here as it seems there are enough apps that do not even
|
||||
* expect us to emulate a look of focus but not actually set x input
|
||||
* focus as we do - so simply abort any focus set on such windows */
|
||||
|
|
|
@ -719,10 +719,29 @@ _e_comp_wl_evas_cb_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EIN
|
|||
|
||||
if (e_object_is_del(E_OBJECT(ec))) return;
|
||||
if (e_client_has_xwindow(ec)) return;
|
||||
EINA_LIST_FOREACH(ec->transients, l, sec)
|
||||
if (ec->stack.prev || ec->stack.next)
|
||||
{
|
||||
evas_object_layer_set(sec->frame, evas_object_layer_get(ec->frame));
|
||||
evas_object_stack_above(sec->frame, ec->frame);
|
||||
if (ec->stack.ignore == 0)
|
||||
{
|
||||
Eina_List *l, *list = e_client_stack_list_prepare(ec);
|
||||
E_Client *child;
|
||||
|
||||
EINA_LIST_FOREACH(list, l, child)
|
||||
{
|
||||
if (child == ec) continue;
|
||||
evas_object_layer_set(child->frame, layer);
|
||||
}
|
||||
e_client_stack_list_finish(list);
|
||||
evas_object_raise(ec->frame);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EINA_LIST_FOREACH(ec->transients, l, sec)
|
||||
{
|
||||
evas_object_layer_set(sec->frame, evas_object_layer_get(ec->frame));
|
||||
evas_object_stack_above(sec->frame, ec->frame);
|
||||
}
|
||||
}
|
||||
if (!ec->comp_data->sub.list) return;
|
||||
EINA_LIST_FOREACH(ec->comp_data->sub.list, l, sec)
|
||||
|
|
|
@ -519,6 +519,8 @@ _e_comp_x_client_new_helper(E_Client *ec)
|
|||
/* loop to check for window profile list atom */
|
||||
else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED)
|
||||
ec->e.fetch.profile = 1;
|
||||
else if (atoms[i] == ECORE_X_ATOM_E_STACK_TYPE)
|
||||
ec->e.fetch.stack = 1;
|
||||
else if (atoms[i] == ATM_GTK_FRAME_EXTENTS)
|
||||
ec->comp_data->fetch_gtk_frame_extents = 1;
|
||||
}
|
||||
|
@ -3406,6 +3408,11 @@ _e_comp_x_hook_client_fetch(void *d EINA_UNUSED, E_Client *ec)
|
|||
ec->e.fetch.state = 0;
|
||||
rem_change = 1;
|
||||
}
|
||||
if (ec->e.fetch.stack)
|
||||
{
|
||||
ec->e.state.stack = ecore_x_e_stack_type_get(win);
|
||||
ec->e.fetch.stack = 0;
|
||||
}
|
||||
if (ec->e.fetch.profile)
|
||||
{
|
||||
const char **list = NULL;
|
||||
|
@ -3847,6 +3854,16 @@ _e_comp_x_hook_client_fetch(void *d EINA_UNUSED, E_Client *ec)
|
|||
(ec->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
|
||||
ec->take_focus = 1;
|
||||
}
|
||||
if ((ec_parent) && (ec->e.state.stack != ECORE_X_STACK_NONE))
|
||||
{
|
||||
E_Client *ec2;
|
||||
|
||||
// find last one
|
||||
for (ec2 = ec_parent; ec2->stack.next; ec2 = ec2->stack.next);
|
||||
ec->stack.prev = ec2;
|
||||
ec->stack.next = NULL;
|
||||
ec->stack.prev->stack.next = ec;
|
||||
}
|
||||
ec->icccm.fetch.transient_for = 0;
|
||||
rem_change = 1;
|
||||
}
|
||||
|
|
|
@ -409,7 +409,8 @@ e_desk_last_focused_focus(E_Desk *desk)
|
|||
(ec->netwm.type != E_WINDOW_TYPE_TOOLBAR) &&
|
||||
(ec->netwm.type != E_WINDOW_TYPE_MENU) &&
|
||||
(ec->netwm.type != E_WINDOW_TYPE_SPLASH) &&
|
||||
(ec->netwm.type != E_WINDOW_TYPE_DESKTOP))
|
||||
(ec->netwm.type != E_WINDOW_TYPE_DESKTOP) &&
|
||||
(!e_object_is_del(E_OBJECT(ec))))
|
||||
{
|
||||
/* this was the window last focused in this desktop */
|
||||
if (!ec->lock_focus_out)
|
||||
|
|
Loading…
Reference in New Issue