mirror of
https://github.com/brl/mutter.git
synced 2025-02-19 14:44:10 +00:00
stack: Delegate layer calculation to a window vfunc
While most of the code to compute a window's layer isn't explicitly windowing backend specific, it is in practice: On wayland there are no DESKTOP windows(*), docks(*) or groups. Reflect that by introducing a calculate_layer() vfunc that computes (and sets) a window's layer. (*) they shall burn in hell, amen! https://gitlab.gnome.org/GNOME/mutter/merge_requests/949
This commit is contained in:
parent
b753213f9b
commit
c843102eec
128
src/core/stack.c
128
src/core/stack.c
@ -441,132 +441,6 @@ meta_stack_update_window_tile_matches (MetaStack *stack,
|
|||||||
g_list_free (windows);
|
g_list_free (windows);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get layer ignoring any transient or group relationships */
|
|
||||||
static MetaStackLayer
|
|
||||||
get_standalone_layer (MetaWindow *window)
|
|
||||||
{
|
|
||||||
MetaStackLayer layer;
|
|
||||||
|
|
||||||
switch (window->type)
|
|
||||||
{
|
|
||||||
case META_WINDOW_DESKTOP:
|
|
||||||
layer = META_LAYER_DESKTOP;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case META_WINDOW_DOCK:
|
|
||||||
if (window->wm_state_below ||
|
|
||||||
(window->monitor && window->monitor->in_fullscreen))
|
|
||||||
layer = META_LAYER_BOTTOM;
|
|
||||||
else
|
|
||||||
layer = META_LAYER_DOCK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case META_WINDOW_DROPDOWN_MENU:
|
|
||||||
case META_WINDOW_POPUP_MENU:
|
|
||||||
case META_WINDOW_TOOLTIP:
|
|
||||||
case META_WINDOW_NOTIFICATION:
|
|
||||||
case META_WINDOW_COMBO:
|
|
||||||
case META_WINDOW_OVERRIDE_OTHER:
|
|
||||||
switch (window->client_type)
|
|
||||||
{
|
|
||||||
case META_WINDOW_CLIENT_TYPE_X11:
|
|
||||||
layer = META_LAYER_OVERRIDE_REDIRECT;
|
|
||||||
break;
|
|
||||||
case META_WINDOW_CLIENT_TYPE_WAYLAND:
|
|
||||||
layer = META_LAYER_NORMAL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
layer = meta_window_get_default_layer (window);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note that this function can never use window->layer only
|
|
||||||
* get_standalone_layer, or we'd have issues.
|
|
||||||
*/
|
|
||||||
static MetaStackLayer
|
|
||||||
get_maximum_layer_in_group (MetaWindow *window)
|
|
||||||
{
|
|
||||||
GSList *members;
|
|
||||||
MetaGroup *group;
|
|
||||||
GSList *tmp;
|
|
||||||
MetaStackLayer max;
|
|
||||||
MetaStackLayer layer;
|
|
||||||
|
|
||||||
max = META_LAYER_DESKTOP;
|
|
||||||
|
|
||||||
group = meta_window_get_group (window);
|
|
||||||
|
|
||||||
if (group != NULL)
|
|
||||||
members = meta_group_list_windows (group);
|
|
||||||
else
|
|
||||||
members = NULL;
|
|
||||||
|
|
||||||
tmp = members;
|
|
||||||
while (tmp != NULL)
|
|
||||||
{
|
|
||||||
MetaWindow *w = tmp->data;
|
|
||||||
|
|
||||||
if (!w->override_redirect)
|
|
||||||
{
|
|
||||||
layer = get_standalone_layer (w);
|
|
||||||
if (layer > max)
|
|
||||||
max = layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_slist_free (members);
|
|
||||||
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
compute_layer (MetaWindow *window)
|
|
||||||
{
|
|
||||||
window->layer = get_standalone_layer (window);
|
|
||||||
|
|
||||||
/* We can only do promotion-due-to-group for dialogs and other
|
|
||||||
* transients, or weird stuff happens like the desktop window and
|
|
||||||
* nautilus windows getting in the same layer, or all gnome-terminal
|
|
||||||
* windows getting in fullscreen layer if any terminal is
|
|
||||||
* fullscreen.
|
|
||||||
*/
|
|
||||||
if (window->layer != META_LAYER_DESKTOP &&
|
|
||||||
meta_window_has_transient_type (window) &&
|
|
||||||
window->transient_for == NULL)
|
|
||||||
{
|
|
||||||
/* We only do the group thing if the dialog is NOT transient for
|
|
||||||
* a particular window. Imagine a group with a normal window, a dock,
|
|
||||||
* and a dialog transient for the normal window; you don't want the dialog
|
|
||||||
* above the dock if it wouldn't normally be.
|
|
||||||
*/
|
|
||||||
|
|
||||||
MetaStackLayer group_max;
|
|
||||||
|
|
||||||
group_max = get_maximum_layer_in_group (window);
|
|
||||||
|
|
||||||
if (group_max > window->layer)
|
|
||||||
{
|
|
||||||
meta_topic (META_DEBUG_STACK,
|
|
||||||
"Promoting window %s from layer %u to %u due to group membership\n",
|
|
||||||
window->desc, window->layer, group_max);
|
|
||||||
window->layer = group_max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
meta_topic (META_DEBUG_STACK, "Window %s on layer %u type = %u has_focus = %d\n",
|
|
||||||
window->desc, window->layer,
|
|
||||||
window->type, window->has_focus);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Front of the layer list is the topmost window,
|
/* Front of the layer list is the topmost window,
|
||||||
* so the lower stack position is later in the list
|
* so the lower stack position is later in the list
|
||||||
*/
|
*/
|
||||||
@ -957,7 +831,7 @@ stack_do_relayer (MetaStack *stack)
|
|||||||
w = tmp->data;
|
w = tmp->data;
|
||||||
old_layer = w->layer;
|
old_layer = w->layer;
|
||||||
|
|
||||||
compute_layer (w);
|
w->layer = meta_window_calculate_layer (w);
|
||||||
|
|
||||||
if (w->layer != old_layer)
|
if (w->layer != old_layer)
|
||||||
{
|
{
|
||||||
|
@ -589,6 +589,8 @@ struct _MetaWindowClass
|
|||||||
gboolean (*can_ping) (MetaWindow *window);
|
gboolean (*can_ping) (MetaWindow *window);
|
||||||
gboolean (*are_updates_frozen) (MetaWindow *window);
|
gboolean (*are_updates_frozen) (MetaWindow *window);
|
||||||
|
|
||||||
|
MetaStackLayer (*calculate_layer) (MetaWindow *window);
|
||||||
|
|
||||||
void (* map) (MetaWindow *window);
|
void (* map) (MetaWindow *window);
|
||||||
void (* unmap) (MetaWindow *window);
|
void (* unmap) (MetaWindow *window);
|
||||||
};
|
};
|
||||||
@ -693,6 +695,8 @@ gboolean meta_window_is_focusable (MetaWindow *window);
|
|||||||
|
|
||||||
gboolean meta_window_can_ping (MetaWindow *window);
|
gboolean meta_window_can_ping (MetaWindow *window);
|
||||||
|
|
||||||
|
MetaStackLayer meta_window_calculate_layer (MetaWindow *window);
|
||||||
|
|
||||||
void meta_window_current_workspace_changed (MetaWindow *window);
|
void meta_window_current_workspace_changed (MetaWindow *window);
|
||||||
|
|
||||||
void meta_window_show_menu (MetaWindow *window,
|
void meta_window_show_menu (MetaWindow *window,
|
||||||
|
@ -8582,6 +8582,12 @@ meta_window_is_stackable (MetaWindow *window)
|
|||||||
return META_WINDOW_GET_CLASS (window)->is_stackable (window);
|
return META_WINDOW_GET_CLASS (window)->is_stackable (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaStackLayer
|
||||||
|
meta_window_calculate_layer (MetaWindow *window)
|
||||||
|
{
|
||||||
|
return META_WINDOW_GET_CLASS (window)->calculate_layer (window);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_window_get_id:
|
* meta_window_get_id:
|
||||||
* @window: a #MetaWindow
|
* @window: a #MetaWindow
|
||||||
|
@ -634,6 +634,12 @@ meta_window_wayland_are_updates_frozen (MetaWindow *window)
|
|||||||
return !wl_window->has_been_shown;
|
return !wl_window->has_been_shown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MetaStackLayer
|
||||||
|
meta_window_wayland_calculate_layer (MetaWindow *window)
|
||||||
|
{
|
||||||
|
return meta_window_get_default_layer (window);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_wayland_map (MetaWindow *window)
|
meta_window_wayland_map (MetaWindow *window)
|
||||||
{
|
{
|
||||||
@ -667,6 +673,7 @@ meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
|
|||||||
window_class->is_stackable = meta_window_wayland_is_stackable;
|
window_class->is_stackable = meta_window_wayland_is_stackable;
|
||||||
window_class->can_ping = meta_window_wayland_can_ping;
|
window_class->can_ping = meta_window_wayland_can_ping;
|
||||||
window_class->are_updates_frozen = meta_window_wayland_are_updates_frozen;
|
window_class->are_updates_frozen = meta_window_wayland_are_updates_frozen;
|
||||||
|
window_class->calculate_layer = meta_window_wayland_calculate_layer;
|
||||||
window_class->map = meta_window_wayland_map;
|
window_class->map = meta_window_wayland_map;
|
||||||
window_class->unmap = meta_window_wayland_unmap;
|
window_class->unmap = meta_window_wayland_unmap;
|
||||||
}
|
}
|
||||||
|
@ -1855,6 +1855,124 @@ meta_window_x11_are_updates_frozen (MetaWindow *window)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get layer ignoring any transient or group relationships */
|
||||||
|
static MetaStackLayer
|
||||||
|
get_standalone_layer (MetaWindow *window)
|
||||||
|
{
|
||||||
|
MetaStackLayer layer;
|
||||||
|
|
||||||
|
switch (window->type)
|
||||||
|
{
|
||||||
|
case META_WINDOW_DESKTOP:
|
||||||
|
layer = META_LAYER_DESKTOP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case META_WINDOW_DOCK:
|
||||||
|
if (window->wm_state_below ||
|
||||||
|
(window->monitor && window->monitor->in_fullscreen))
|
||||||
|
layer = META_LAYER_BOTTOM;
|
||||||
|
else
|
||||||
|
layer = META_LAYER_DOCK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case META_WINDOW_DROPDOWN_MENU:
|
||||||
|
case META_WINDOW_POPUP_MENU:
|
||||||
|
case META_WINDOW_TOOLTIP:
|
||||||
|
case META_WINDOW_NOTIFICATION:
|
||||||
|
case META_WINDOW_COMBO:
|
||||||
|
case META_WINDOW_OVERRIDE_OTHER:
|
||||||
|
layer = META_LAYER_OVERRIDE_REDIRECT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
layer = meta_window_get_default_layer (window);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note that this function can never use window->layer only
|
||||||
|
* get_standalone_layer, or we'd have issues.
|
||||||
|
*/
|
||||||
|
static MetaStackLayer
|
||||||
|
get_maximum_layer_in_group (MetaWindow *window)
|
||||||
|
{
|
||||||
|
GSList *members;
|
||||||
|
MetaGroup *group;
|
||||||
|
GSList *tmp;
|
||||||
|
MetaStackLayer max;
|
||||||
|
MetaStackLayer layer;
|
||||||
|
|
||||||
|
max = META_LAYER_DESKTOP;
|
||||||
|
|
||||||
|
group = meta_window_get_group (window);
|
||||||
|
|
||||||
|
if (group != NULL)
|
||||||
|
members = meta_group_list_windows (group);
|
||||||
|
else
|
||||||
|
members = NULL;
|
||||||
|
|
||||||
|
tmp = members;
|
||||||
|
while (tmp != NULL)
|
||||||
|
{
|
||||||
|
MetaWindow *w = tmp->data;
|
||||||
|
|
||||||
|
if (!w->override_redirect)
|
||||||
|
{
|
||||||
|
layer = get_standalone_layer (w);
|
||||||
|
if (layer > max)
|
||||||
|
max = layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_slist_free (members);
|
||||||
|
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaStackLayer
|
||||||
|
meta_window_x11_calculate_layer (MetaWindow *window)
|
||||||
|
{
|
||||||
|
MetaStackLayer layer = get_standalone_layer (window);
|
||||||
|
|
||||||
|
/* We can only do promotion-due-to-group for dialogs and other
|
||||||
|
* transients, or weird stuff happens like the desktop window and
|
||||||
|
* nautilus windows getting in the same layer, or all gnome-terminal
|
||||||
|
* windows getting in fullscreen layer if any terminal is
|
||||||
|
* fullscreen.
|
||||||
|
*/
|
||||||
|
if (layer != META_LAYER_DESKTOP &&
|
||||||
|
meta_window_has_transient_type (window) &&
|
||||||
|
window->transient_for == NULL)
|
||||||
|
{
|
||||||
|
/* We only do the group thing if the dialog is NOT transient for
|
||||||
|
* a particular window. Imagine a group with a normal window, a dock,
|
||||||
|
* and a dialog transient for the normal window; you don't want the dialog
|
||||||
|
* above the dock if it wouldn't normally be.
|
||||||
|
*/
|
||||||
|
|
||||||
|
MetaStackLayer group_max;
|
||||||
|
|
||||||
|
group_max = get_maximum_layer_in_group (window);
|
||||||
|
|
||||||
|
if (group_max > layer)
|
||||||
|
{
|
||||||
|
meta_topic (META_DEBUG_STACK,
|
||||||
|
"Promoting window %s from layer %u to %u due to group membership\n",
|
||||||
|
window->desc, layer, group_max);
|
||||||
|
layer = group_max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_topic (META_DEBUG_STACK, "Window %s on layer %u type = %u has_focus = %d\n",
|
||||||
|
window->desc, layer,
|
||||||
|
window->type, window->has_focus);
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_x11_map (MetaWindow *window)
|
meta_window_x11_map (MetaWindow *window)
|
||||||
{
|
{
|
||||||
@ -1903,6 +2021,7 @@ meta_window_x11_class_init (MetaWindowX11Class *klass)
|
|||||||
window_class->is_stackable = meta_window_x11_is_stackable;
|
window_class->is_stackable = meta_window_x11_is_stackable;
|
||||||
window_class->can_ping = meta_window_x11_can_ping;
|
window_class->can_ping = meta_window_x11_can_ping;
|
||||||
window_class->are_updates_frozen = meta_window_x11_are_updates_frozen;
|
window_class->are_updates_frozen = meta_window_x11_are_updates_frozen;
|
||||||
|
window_class->calculate_layer = meta_window_x11_calculate_layer;
|
||||||
window_class->map = meta_window_x11_map;
|
window_class->map = meta_window_x11_map;
|
||||||
window_class->unmap = meta_window_x11_unmap;
|
window_class->unmap = meta_window_x11_unmap;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user