void (*set_activated)(struct view *view, bool activated);
void (*set_fullscreen)(struct view *view, bool fullscreen);
void (*notify_tiled)(struct view *view);
- /*
- * client_request is true if the client unmapped its own
- * surface; false if we are just minimizing the view. The two
- * cases are similar but have subtle differences (e.g., when
- * minimizing we don't destroy the foreign toplevel handle).
- */
- void (*unmap)(struct view *view, bool client_request);
+ void (*unmap)(struct view *view);
void (*maximize)(struct view *view, enum view_axis maximized);
void (*minimize)(struct view *view, bool minimize);
struct view *(*get_parent)(struct view *self);
void view_evacuate_region(struct view *view);
void view_on_output_destroy(struct view *view);
void view_connect_map(struct view *view, struct wlr_surface *surface);
+void view_update_visibility(struct view *view);
void view_init(struct view *view);
void view_destroy(struct view *view);
continue;
}
view = node_view_from_node(node);
- if (view->mapped && view_is_focusable(view)) {
+ if (view_is_focusable(view) && !view->minimized) {
return view;
}
}
#include "view-impl-common.h"
#include "foreign-toplevel/foreign.h"
#include "labwc.h"
-#include "output.h"
#include "view.h"
#include "window-rules.h"
void
view_impl_map(struct view *view)
{
- /* Leave minimized, if minimized before map */
- if (!view->minimized) {
- desktop_focus_view(view, /*raise*/ true);
- }
+ view_update_visibility(view);
+
if (!view->been_mapped) {
window_rules_apply(view, LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP);
}
}
}
- /*
- * Some clients (e.g. Steam's Big Picture Mode window) request
- * fullscreen before mapping.
- */
- desktop_update_top_layer_visibility(view->server);
-
wlr_log(WLR_DEBUG, "[map] identifier=%s, title=%s",
view->app_id, view->title);
}
void
view_impl_unmap(struct view *view)
{
- struct server *server = view->server;
- /*
- * When exiting an xwayland application with multiple views
- * mapped, a race condition can occur: after the topmost view
- * is unmapped, the next view under it is offered focus, but is
- * also unmapped before accepting focus (so server->active_view
- * remains NULL). To avoid being left with no active view at
- * all, check for that case also.
- */
- if (view == server->active_view || !server->active_view) {
- desktop_focus_topmost_view(server);
- }
-
- desktop_update_top_layer_visibility(view->server);
+ view_update_visibility(view);
/*
- * We may need to disable adaptive sync if view was fullscreen.
- *
- * FIXME: this logic doesn't account for multiple fullscreen
- * views. It should probably be combined with the existing
- * logic in desktop_update_top_layer_visibility().
+ * Destroy the foreign toplevel handle so the unmapped view
+ * doesn't show up in panels and the like.
*/
- if (view->fullscreen) {
- output_set_has_fullscreen_view(view->output, false);
+ if (view->foreign_toplevel) {
+ foreign_toplevel_destroy(view->foreign_toplevel);
+ view->foreign_toplevel = NULL;
}
}
switch (view_wants_focus(view)) {
case VIEW_WANTS_FOCUS_ALWAYS:
case VIEW_WANTS_FOCUS_LIKELY:
- return (view->mapped || view->minimized);
+ return view->mapped;
default:
return false;
}
view->minimized = minimized;
wl_signal_emit_mutable(&view->events.minimized, NULL);
- if (minimized) {
- view->impl->unmap(view, /* client_request */ false);
- } else {
- view->impl->map(view);
- }
+ view_update_visibility(view);
}
static void
struct view *root = view_get_root(view);
_minimize(root, minimized);
minimize_sub_views(root, minimized);
-
- /* Enable top-layer when full-screen views are minimized */
- if (view->fullscreen && view->output) {
- desktop_update_top_layer_visibility(view->server);
- }
}
bool
handle_unmap(struct wl_listener *listener, void *data)
{
struct view *view = wl_container_of(listener, view, mappable.unmap);
- view->impl->unmap(view, /* client_request */ true);
+ view->impl->unmap(view);
}
void
mappable_connect(&view->mappable, surface, handle_map, handle_unmap);
}
+/* Used in both (un)map and (un)minimize */
+void
+view_update_visibility(struct view *view)
+{
+ bool visible = view->mapped && !view->minimized;
+ if (visible == view->scene_tree->node.enabled) {
+ return;
+ }
+
+ wlr_scene_node_set_enabled(&view->scene_tree->node, visible);
+ struct server *server = view->server;
+
+ if (visible) {
+ desktop_focus_view(view, /*raise*/ true);
+ } else {
+ /*
+ * When exiting an xwayland application with multiple
+ * views mapped, a race condition can occur: after the
+ * topmost view is unmapped, the next view under it is
+ * offered focus, but is also unmapped before accepting
+ * focus (so server->active_view remains NULL). To avoid
+ * being left with no active view at all, check for that
+ * case also.
+ */
+ if (view == server->active_view || !server->active_view) {
+ desktop_focus_topmost_view(server);
+ }
+ }
+
+ /*
+ * Show top layer when a fullscreen view is hidden.
+ * Hide it if a fullscreen view is shown (or uncovered).
+ */
+ desktop_update_top_layer_visibility(server);
+
+ /*
+ * We may need to disable adaptive sync if view was fullscreen.
+ *
+ * FIXME: this logic doesn't account for multiple fullscreen
+ * views. It should probably be combined with the existing
+ * logic in desktop_update_top_layer_visibility().
+ */
+ if (view->fullscreen && !visible) {
+ output_set_has_fullscreen_view(view->output, false);
+ }
+
+ /* Update usable area to account for XWayland "struts" (panels) */
+ if (view_has_strut_partial(view)) {
+ output_update_all_usable_areas(server, false);
+ }
+}
+
void
view_set_shade(struct view *view, bool shaded)
{
if (view->type != LAB_XDG_SHELL_VIEW) {
continue;
}
- if (!view->mapped && !view->minimized) {
+ if (!view->mapped) {
continue;
}
if (top_parent_of(view) != toplevel) {
view_set_output(view, output_nearest_to_cursor(view->server));
}
- /*
- * For initially minimized views, we do not set view->mapped
- * nor enable the scene node. All other map logic (positioning,
- * creating foreign toplevel, etc.) happens as normal.
- */
- if (!view->minimized) {
- view->mapped = true;
- wlr_scene_node_set_enabled(&view->scene_tree->node, true);
- }
+ view->mapped = true;
if (!view->foreign_toplevel) {
view_impl_init_foreign_toplevel(view);
}
static void
-xdg_toplevel_view_unmap(struct view *view, bool client_request)
+xdg_toplevel_view_unmap(struct view *view)
{
if (view->mapped) {
view->mapped = false;
- wlr_scene_node_set_enabled(&view->scene_tree->node, false);
view_impl_unmap(view);
}
-
- /*
- * If the view was explicitly unmapped by the client (rather
- * than just minimized), destroy the foreign toplevel handle so
- * the unmapped view doesn't show up in panels and the like.
- */
- if (client_request && view->foreign_toplevel) {
- foreign_toplevel_destroy(view->foreign_toplevel);
- view->foreign_toplevel = NULL;
- }
}
static pid_t
static xcb_atom_t atoms[ATOM_COUNT] = {0};
static void set_surface(struct view *view, struct wlr_surface *surface);
-static void xwayland_view_unmap(struct view *view, bool client_request);
+static void xwayland_view_unmap(struct view *view);
static struct xwayland_view *
xwayland_view_from_view(struct view *view)
struct server *server = view->server;
bool mapped = xsurface->surface && xsurface->surface->mapped;
if (mapped) {
- xwayland_view_unmap(view, /* client_request */ true);
+ xwayland_view_unmap(view);
}
handle_destroy(&view->destroy, xsurface);
/* view is invalid after this point */
*/
handle_map_request(&xwayland_view->map_request, NULL);
- /*
- * For initially minimized views, we do not set view->mapped
- * nor enable the scene node. All other map logic (positioning,
- * creating foreign toplevel, etc.) happens as normal.
- */
- if (!view->minimized) {
- view->mapped = true;
- wlr_scene_node_set_enabled(&view->scene_tree->node, true);
- }
+ view->mapped = true;
if (view->surface != xwayland_surface->surface) {
set_surface(view, xwayland_surface->surface);
view_impl_map(view);
view->been_mapped = true;
-
- /* Update usable area to account for XWayland "struts" (panels) */
- if (xwayland_surface->strut_partial) {
- output_update_all_usable_areas(view->server, false);
- }
}
static void
-xwayland_view_unmap(struct view *view, bool client_request)
+xwayland_view_unmap(struct view *view)
{
if (!view->mapped) {
- goto out;
+ return;
}
view->mapped = false;
- wlr_scene_node_set_enabled(&view->scene_tree->node, false);
view_impl_unmap(view);
-
- /* Update usable area to account for XWayland "struts" (panels) */
- if (xwayland_surface_from_view(view)->strut_partial) {
- output_update_all_usable_areas(view->server, false);
- }
-
- /*
- * If the view was explicitly unmapped by the client (rather
- * than just minimized), destroy the foreign toplevel handle so
- * the unmapped view doesn't show up in panels and the like.
- */
-out:
- if (client_request && view->foreign_toplevel) {
- foreign_toplevel_destroy(view->foreign_toplevel);
- view->foreign_toplevel = NULL;
- }
}
static void
if (!view->surface) {
continue;
}
- if (!view->mapped && !view->minimized) {
+ if (!view->mapped) {
continue;
}
if (top_parent_of(view) != surface) {