diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd
index 38bad8a2..52beef42 100644
--- a/docs/labwc-actions.5.scd
+++ b/docs/labwc-actions.5.scd
@@ -229,6 +229,15 @@ Actions are used in menus and keyboard/mouse bindings.
Use the automatic placement policy to move the active window to a
position on its output that will minimize overlap with other windows.
+**++
+**++
+**
+ Set, unset, or toggle, respectively, the "shaded" state of the active
+ window. When shaded, window contents are hidden, leaving only the
+ titlebar visible. Full-screen windows or those without server-side
+ decorations (including those for which the server-side titlebar has been
+ hidden) are not eligible for shading.
+
**
If used as the only action for a binding: clear an earlier defined
binding.
diff --git a/docs/menu.xml b/docs/menu.xml
index d03f8e71..521d80a9 100644
--- a/docs/menu.xml
+++ b/docs/menu.xml
@@ -12,6 +12,9 @@
-
+ -
+
+
-
diff --git a/docs/rc.xml.all b/docs/rc.xml.all
index 012818c2..350a5be1 100644
--- a/docs/rc.xml.all
+++ b/docs/rc.xml.all
@@ -331,6 +331,14 @@
+
+
+
+
+
+
+
+
diff --git a/include/ssd.h b/include/ssd.h
index f1b27516..5d0a32ee 100644
--- a/include/ssd.h
+++ b/include/ssd.h
@@ -68,6 +68,7 @@ void ssd_destroy(struct ssd *ssd);
void ssd_titlebar_hide(struct ssd *ssd);
void ssd_enable_keybind_inhibit_indicator(struct ssd *ssd, bool enable);
+void ssd_enable_shade(struct ssd *ssd, bool enable);
struct ssd_hover_state *ssd_hover_state_new(void);
void ssd_update_button_hover(struct wlr_scene_node *node,
diff --git a/include/view.h b/include/view.h
index c446df8b..f18904fc 100644
--- a/include/view.h
+++ b/include/view.h
@@ -148,6 +148,7 @@ struct view {
bool ssd_enabled;
bool ssd_titlebar_hidden;
enum ssd_preference ssd_preference;
+ bool shaded;
bool minimized;
enum view_axis maximized;
bool fullscreen;
@@ -394,6 +395,13 @@ bool view_compute_centered_position(struct view *view,
bool view_adjust_floating_geometry(struct view *view, struct wlr_box *geometry);
void view_store_natural_geometry(struct view *view);
+/**
+ * view_effective_height - effective height of view, with respect to shaded state
+ * @view: view for which effective height is desired
+ * @use_pending: if false, report current height; otherwise, report pending height
+ */
+int view_effective_height(struct view *view, bool use_pending);
+
/**
* view_center - center view within some region
* @view: view to be centered
@@ -463,6 +471,8 @@ void view_update_title(struct view *view);
void view_update_app_id(struct view *view);
void view_reload_ssd(struct view *view);
+void view_set_shade(struct view *view, bool shaded);
+
struct view_size_hints view_get_size_hints(struct view *view);
void view_adjust_size(struct view *view, int *w, int *h);
diff --git a/po/labwc.pot b/po/labwc.pot
index eff1d14e..51508ea5 100644
--- a/po/labwc.pot
+++ b/po/labwc.pot
@@ -1,5 +1,5 @@
# Labwc pot file
-# Copyright (C) 2023
+# Copyright (C) 2024
# This file is distributed under the same license as the labwc package.
# FIRST AUTHOR , YEAR.
#
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: labwc\n"
"Report-Msgid-Bugs-To: https://github.com/labwc/labwc/issues\n"
-"POT-Creation-Date: 2023-01-02 11:22+1000\n"
+"POT-Creation-Date: 2024-01-15 16:00-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -17,50 +17,54 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-#: src/menu/menu.c:698
+#: src/menu/menu.c:697
msgid "Reconfigure"
msgstr ""
-#: src/menu/menu.c:700
+#: src/menu/menu.c:699
msgid "Exit"
msgstr ""
-#: src/menu/menu.c:716
+#: src/menu/menu.c:715
msgid "Minimize"
msgstr ""
-#: src/menu/menu.c:718
+#: src/menu/menu.c:717
msgid "Maximize"
msgstr ""
-#: src/menu/menu.c:720
+#: src/menu/menu.c:719
msgid "Fullscreen"
msgstr ""
-#: src/menu/menu.c:722
+#: src/menu/menu.c:721
+msgid "Roll up/down"
+msgstr ""
+
+#: src/menu/menu.c:723
msgid "Decorations"
msgstr ""
-#: src/menu/menu.c:724
+#: src/menu/menu.c:725
msgid "Always on Top"
msgstr ""
-#: src/menu/menu.c:729
+#: src/menu/menu.c:730
msgid "Move left"
msgstr ""
-#: src/menu/menu.c:736
+#: src/menu/menu.c:737
msgid "Move right"
msgstr ""
-#: src/menu/menu.c:741
+#: src/menu/menu.c:742
msgid "Always on Visible Workspace"
msgstr ""
-#: src/menu/menu.c:744
+#: src/menu/menu.c:745
msgid "Workspace"
msgstr ""
-#: src/menu/menu.c:747
+#: src/menu/menu.c:748
msgid "Close"
msgstr ""
diff --git a/src/action.c b/src/action.c
index 46bc8c9e..d9b46866 100644
--- a/src/action.c
+++ b/src/action.c
@@ -103,6 +103,9 @@ enum action_type {
ACTION_TYPE_VIRTUAL_OUTPUT_REMOVE,
ACTION_TYPE_AUTO_PLACE,
ACTION_TYPE_TOGGLE_TEARING,
+ ACTION_TYPE_SHADE,
+ ACTION_TYPE_UNSHADE,
+ ACTION_TYPE_TOGGLE_SHADE,
};
const char *action_names[] = {
@@ -151,6 +154,9 @@ const char *action_names[] = {
"VirtualOutputRemove",
"AutoPlace",
"ToggleTearing",
+ "Shade",
+ "Unshade",
+ "ToggleShade",
NULL
};
@@ -841,6 +847,7 @@ actions_run(struct view *activator, struct server *server,
.width = width ? : view->pending.width,
.height = height ? : view->pending.height,
};
+ view_set_shade(view, false);
view_move_resize(view, box);
}
break;
@@ -960,6 +967,21 @@ actions_run(struct view *activator, struct server *server,
view->tearing_hint ? "en" : "dis");
}
break;
+ case ACTION_TYPE_TOGGLE_SHADE:
+ if (view) {
+ view_set_shade(view, !view->shaded);
+ }
+ break;
+ case ACTION_TYPE_SHADE:
+ if (view) {
+ view_set_shade(view, true);
+ }
+ break;
+ case ACTION_TYPE_UNSHADE:
+ if (view) {
+ view_set_shade(view, false);
+ }
+ break;
case ACTION_TYPE_INVALID:
wlr_log(WLR_ERROR, "Not executing unknown action");
break;
diff --git a/src/config/rcxml.c b/src/config/rcxml.c
index 4547422a..bc21a458 100644
--- a/src/config/rcxml.c
+++ b/src/config/rcxml.c
@@ -1166,6 +1166,10 @@ static struct mouse_combos {
{ "Frame", "A-Right", "Drag", "Resize", NULL, NULL},
{ "Titlebar", "Left", "Press", "Focus", NULL, NULL},
{ "Titlebar", "Left", "Press", "Raise", NULL, NULL},
+ { "Titlebar", "Up", "Scroll", "Unfocus", NULL, NULL},
+ { "Titlebar", "Up", "Scroll", "Shade", NULL, NULL},
+ { "Titlebar", "Down", "Scroll", "Unshade", NULL, NULL},
+ { "Titlebar", "Down", "Scroll", "Focus", NULL, NULL},
{ "Title", "Left", "Drag", "Move", NULL, NULL },
{ "Title", "Left", "DoubleClick", "ToggleMaximize", NULL, NULL },
{ "TitleBar", "Right", "Click", "Focus", NULL, NULL},
diff --git a/src/input/cursor.c b/src/input/cursor.c
index 309bb6cd..38bf250c 100644
--- a/src/input/cursor.c
+++ b/src/input/cursor.c
@@ -471,7 +471,12 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
*/
wlr_seat_pointer_notify_clear_focus(wlr_seat);
if (!seat->drag.active) {
- cursor_set(seat, cursor_get_from_ssd(ctx->type));
+ enum lab_cursors cursor = cursor_get_from_ssd(ctx->type);
+ if (ctx->view && ctx->view->shaded && cursor > LAB_CURSOR_GRAB) {
+ /* Prevent resize cursor on borders for shaded SSD */
+ cursor = LAB_CURSOR_DEFAULT;
+ }
+ cursor_set(seat, cursor);
}
}
}
diff --git a/src/interactive.c b/src/interactive.c
index f92ab8c1..0a4e1818 100644
--- a/src/interactive.c
+++ b/src/interactive.c
@@ -55,7 +55,8 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
}
if (!view_is_floating(view)) {
/*
- * Un-maximize and restore natural width/height.
+ * Un-maximize, unshade and restore natural
+ * width/height.
* Don't reset tiled state yet since we may want
* to keep it (in the snap-to-maximize case).
*/
@@ -66,6 +67,8 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
geometry.y = max_move_scale(seat->cursor->y,
view->current.y, view->current.height,
geometry.height);
+
+ view_set_shade(view, false);
view_restore_to(view, geometry);
} else {
/* Store natural geometry at start of move */
@@ -80,10 +83,11 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
cursor_set(seat, LAB_CURSOR_GRAB);
break;
case LAB_INPUT_STATE_RESIZE:
- if (view->fullscreen || view->maximized == VIEW_AXIS_BOTH) {
+ if (view->shaded || view->fullscreen ||
+ view->maximized == VIEW_AXIS_BOTH) {
/*
- * We don't allow resizing while fullscreen or
- * maximized in both directions.
+ * We don't allow resizing while shaded,
+ * fullscreen or maximized in both directions.
*/
return;
}
diff --git a/src/menu/menu.c b/src/menu/menu.c
index 236ab26d..5790caf5 100644
--- a/src/menu/menu.c
+++ b/src/menu/menu.c
@@ -718,6 +718,8 @@ init_windowmenu(struct server *server)
fill_item("name.action", "ToggleMaximize");
current_item = item_create(menu, _("Fullscreen"), false);
fill_item("name.action", "ToggleFullscreen");
+ current_item = item_create(menu, _("Roll up/down"), false);
+ fill_item("name.action", "ToggleShade");
current_item = item_create(menu, _("Decorations"), false);
fill_item("name.action", "ToggleDecorations");
current_item = item_create(menu, _("Always on Top"), false);
diff --git a/src/placement.c b/src/placement.c
index c2a724af..560b5e54 100644
--- a/src/placement.c
+++ b/src/placement.c
@@ -168,8 +168,9 @@ build_grid(struct overlap_bitmap *bmp, struct view *view)
bmp->rows[nr_rows++] = y;
}
- x = v->pending.x + v->pending.width + margin.right;
- y = v->pending.y + v->pending.height + margin.bottom;
+ x = v->pending.x + margin.right + v->pending.width;
+ y = v->pending.y + margin.bottom
+ + view_effective_height(v, /* use_pending */ true);
/* Add a column if the right view edge is in the usable region */
if (x > usable.x && x < usable_right) {
@@ -259,8 +260,9 @@ build_overlap(struct overlap_bitmap *bmp, struct view *view)
struct border margin = ssd_get_margin(v->ssd);
int lx = v->pending.x - margin.left;
int ly = v->pending.y - margin.top;
- int hx = v->pending.x + v->pending.width + margin.right;
- int hy = v->pending.y + v->pending.height + margin.bottom;
+ int hx = v->pending.x + margin.right + v->pending.width;
+ int hy = v->pending.y + margin.bottom
+ + view_effective_height(v, /* use_pending */ true);
/*
* Find the first and last row and column intervals spanned by
diff --git a/src/resistance.c b/src/resistance.c
index 26ee84e6..a03080a9 100644
--- a/src/resistance.c
+++ b/src/resistance.c
@@ -47,15 +47,18 @@ resistance_move_apply(struct view *view, double *x, double *y)
struct edges other_edges; /* The edges of the monitor/other view */
struct edges flags = { 0 };
+ /* Use the effective height to properly snap shaded views */
+ int eff_height = view_effective_height(view, /* use_pending */ false);
+
view_edges.left = vgeom.x - border.left + 1;
view_edges.top = vgeom.y - border.top + 1;
view_edges.right = vgeom.x + vgeom.width + border.right;
- view_edges.bottom = vgeom.y + vgeom.height + border.bottom;
+ view_edges.bottom = vgeom.y + eff_height + border.bottom;
target_edges.left = *x - border.left;
target_edges.top = *y - border.top;
target_edges.right = *x + vgeom.width + border.right;
- target_edges.bottom = *y + vgeom.height + border.bottom;
+ target_edges.bottom = *y + eff_height + border.bottom;
if (!rc.screen_edge_strength) {
return;
@@ -91,7 +94,7 @@ resistance_move_apply(struct view *view, double *x, double *y)
if (flags.top == 1) {
*y = other_edges.top + border.top;
} else if (flags.bottom == 1) {
- *y = other_edges.bottom - vgeom.height - border.bottom;
+ *y = other_edges.bottom - eff_height - border.bottom;
}
/* reset the flags */
diff --git a/src/snap.c b/src/snap.c
index 7128f167..fd60cad0 100644
--- a/src/snap.c
+++ b/src/snap.c
@@ -37,8 +37,9 @@ snap_get_view_edge(struct view *view)
struct border edge = {
.left = view->pending.x - margin.left,
.top = view->pending.y - margin.top,
- .right = view->pending.x + view->pending.width + margin.right,
- .bottom = view->pending.y + view->pending.height + margin.bottom
+ .right = view->pending.x + margin.right + view->pending.width,
+ .bottom = view->pending.y + margin.bottom
+ + view_effective_height(view, /* use_pending */ true)
};
return edge;
}
@@ -52,9 +53,10 @@ snap_get_max_distance(struct view *view)
struct border distance = {
.left = usable.x + margin.left + rc.gap - view->pending.x,
.top = usable.y + margin.top + rc.gap - view->pending.y,
- .right = usable.x + usable.width - view->pending.width
+ .right = usable.x + usable.width - view->pending.width
- margin.right - rc.gap - view->pending.x,
- .bottom = usable.y + usable.height - view->pending.height
+ .bottom = usable.y + usable.height
+ - view_effective_height(view, /* use_pending */ true)
- margin.bottom - rc.gap - view->pending.y
};
return distance;
@@ -115,7 +117,8 @@ _snap_next_edge(struct view *view, int start_pos, const struct snap_search def,
vp += def.add_view_x * v->pending.x;
vp += def.add_view_y * v->pending.y;
vp += def.add_view_width * v->pending.width;
- vp += def.add_view_height * v->pending.height;
+ vp += def.add_view_height
+ * view_effective_height(v, /* use_pending */ true);
vp += gap;
if (def.search_dir * vp > 0 && def.search_dir * (vp - p) < 0) {
@@ -131,12 +134,15 @@ _snap_move_resize_to_edge(struct view *view, enum view_edge direction, enum snap
{
struct border edge = snap_get_view_edge(view);
struct border dmax;
+
if (mode == SNAP_MODE_SHRINK) {
/* limit to half of current size */
- int width_max_dx = max(view->pending.width - LAB_MIN_VIEW_WIDTH, 0);
- int height_max_dy = max(view->pending.height - LAB_MIN_VIEW_HEIGHT, 0);
+ int eff_height =
+ view_effective_height(view, /* use_pending */ true);
+ int width_max_dx = max(view->pending.width - LAB_MIN_VIEW_WIDTH, 0);
+ int height_max_dy = max(eff_height - LAB_MIN_VIEW_HEIGHT, 0);
dmax.right = min(width_max_dx, view->pending.width / 2);
- dmax.bottom = min(height_max_dy, view->pending.height / 2);
+ dmax.bottom = min(height_max_dy, eff_height / 2);
dmax.left = -dmax.right;
dmax.top = -dmax.bottom;
} else {
diff --git a/src/ssd/resize_indicator.c b/src/ssd/resize_indicator.c
index 5360f1c0..e140886d 100644
--- a/src/ssd/resize_indicator.c
+++ b/src/ssd/resize_indicator.c
@@ -159,14 +159,17 @@ resize_indicator_update(struct view *view)
char text[32]; /* 12345 x 12345 would be 13 chars + 1 null byte */
+ int eff_height = view_effective_height(view, /* use_pending */ false);
+ int eff_width = view->current.width;
+
switch (view->server->input_mode) {
case LAB_INPUT_STATE_RESIZE:
; /* works around "a label can only be part of a statement" */
struct view_size_hints hints = view_get_size_hints(view);
snprintf(text, sizeof(text), "%d x %d",
- MAX(0, view->current.width - hints.base_width)
+ MAX(0, eff_width - hints.base_width)
/ MAX(1, hints.width_inc),
- MAX(0, view->current.height - hints.base_height)
+ MAX(0, eff_height - hints.base_height)
/ MAX(1, hints.height_inc));
break;
case LAB_INPUT_STATE_MOVE:
@@ -192,8 +195,8 @@ resize_indicator_update(struct view *view)
/* Center the indicator in the window */
wlr_scene_node_set_position(&indicator->tree->node,
- (view->current.width - indicator->width) / 2,
- (view->current.height - indicator->height) / 2);
+ (eff_width - indicator->width) / 2,
+ (eff_height - indicator->height) / 2);
scaled_font_buffer_update(indicator->text, text, width, &rc.font_osd,
rc.theme->osd_label_text_color, NULL /* const char *arrow */);
diff --git a/src/ssd/ssd.c b/src/ssd/ssd.c
index df18f1e5..dd7f1b60 100644
--- a/src/ssd/ssd.c
+++ b/src/ssd/ssd.c
@@ -61,11 +61,15 @@ ssd_max_extents(struct view *view)
{
assert(view);
struct border border = ssd_thickness(view);
+
+ int eff_width = view->current.width;
+ int eff_height = view_effective_height(view, /* use_pending */ false);
+
return (struct wlr_box){
.x = view->current.x - border.left,
.y = view->current.y - border.top,
- .width = view->current.width + border.left + border.right,
- .height = view->current.height + border.top + border.bottom,
+ .width = eff_width + border.left + border.right,
+ .height = eff_height + border.top + border.bottom,
};
}
@@ -220,7 +224,11 @@ ssd_update_geometry(struct ssd *ssd)
struct wlr_box cached = ssd->state.geometry;
struct wlr_box current = ssd->view->current;
- if (current.width == cached.width && current.height == cached.height) {
+
+ int eff_width = current.width;
+ int eff_height = view_effective_height(ssd->view, /* use_pending */ false);
+
+ if (eff_width == cached.width && eff_height == cached.height) {
if (current.x != cached.x || current.y != cached.y) {
/* Dynamically resize extents based on position and usable_area */
ssd_extents_update(ssd);
@@ -333,6 +341,16 @@ ssd_set_active(struct ssd *ssd, bool active)
wlr_scene_node_set_enabled(&ssd->titlebar.inactive.tree->node, !active);
}
+void
+ssd_enable_shade(struct ssd *ssd, bool enable)
+{
+ if (!ssd) {
+ return;
+ }
+ ssd_border_update(ssd);
+ wlr_scene_node_set_enabled(&ssd->extents.tree->node, !enable);
+}
+
void
ssd_enable_keybind_inhibit_indicator(struct ssd *ssd, bool enable)
{
diff --git a/src/ssd/ssd_border.c b/src/ssd/ssd_border.c
index c12b07b2..74f29ffa 100644
--- a/src/ssd/ssd_border.c
+++ b/src/ssd/ssd_border.c
@@ -20,7 +20,7 @@ ssd_border_create(struct ssd *ssd)
struct view *view = ssd->view;
struct theme *theme = view->server->theme;
int width = view->current.width;
- int height = view->current.height;
+ int height = view_effective_height(view, /* use_pending */ false);
int full_width = width + 2 * theme->border_width;
float *color;
@@ -83,7 +83,7 @@ ssd_border_update(struct ssd *ssd)
struct theme *theme = view->server->theme;
int width = view->current.width;
- int height = view->current.height;
+ int height = view_effective_height(view, /* use_pending */ false);
int full_width = width + 2 * theme->border_width;
struct ssd_part *part;
diff --git a/src/ssd/ssd_extents.c b/src/ssd/ssd_extents.c
index 22bfa579..9a926a2b 100644
--- a/src/ssd/ssd_extents.c
+++ b/src/ssd/ssd_extents.c
@@ -109,7 +109,7 @@ ssd_extents_update(struct ssd *ssd)
struct theme *theme = view->server->theme;
int width = view->current.width;
- int height = view->current.height;
+ int height = view_effective_height(view, /* use_pending */ false);
int full_height = height + theme->border_width * 2 + ssd->titlebar.height;
int full_width = width + 2 * theme->border_width;
int extended_area = SSD_EXTENDED_AREA;
diff --git a/src/view.c b/src/view.c
index 7ab09e2d..eac7893d 100644
--- a/src/view.c
+++ b/src/view.c
@@ -384,6 +384,7 @@ view_resize_relative(struct view *view, int left, int right, int top, int bottom
if (view->fullscreen || view->maximized != VIEW_AXIS_NONE) {
return;
}
+ view_set_shade(view, false);
struct wlr_box newgeo = view->pending;
newgeo.x -= left;
newgeo.width += left + right;
@@ -703,6 +704,18 @@ view_store_natural_geometry(struct view *view)
}
}
+int
+view_effective_height(struct view *view, bool use_pending)
+{
+ assert(view);
+
+ if (view->shaded) {
+ return 0;
+ }
+
+ return use_pending ? view->pending.height : view->current.height;
+}
+
void
view_center(struct view *view, const struct wlr_box *ref)
{
@@ -1032,12 +1045,17 @@ view_maximize(struct view *view, enum view_axis axis,
bool store_natural_geometry)
{
assert(view);
+
if (view->maximized == axis) {
return;
}
+
if (view->fullscreen) {
return;
}
+
+ view_set_shade(view, false);
+
if (axis != VIEW_AXIS_NONE) {
/*
* Maximize via keybind or client request cancels
@@ -1087,6 +1105,12 @@ void
view_toggle_decorations(struct view *view)
{
assert(view);
+
+ /* Reject decoration toggles when shaded */
+ if (view->shaded) {
+ return;
+ }
+
if (rc.ssd_keep_border && view->ssd_enabled && view->ssd
&& !view->ssd_titlebar_hidden) {
/*
@@ -1209,6 +1233,7 @@ void
view_toggle_fullscreen(struct view *view)
{
assert(view);
+
view_set_fullscreen(view, !view->fullscreen);
}
@@ -1216,6 +1241,11 @@ view_toggle_fullscreen(struct view *view)
static void
set_fullscreen(struct view *view, bool fullscreen)
{
+ /* When going fullscreen, unshade the window */
+ if (fullscreen) {
+ view_set_shade(view, false);
+ }
+
/* Hide decorations when going fullscreen */
if (fullscreen && view->ssd_enabled) {
undecorate(view);
@@ -1561,7 +1591,8 @@ view_move_to_edge(struct view *view, enum view_edge direction, bool snap_to_wind
destination_y = top;
break;
case VIEW_EDGE_DOWN:
- destination_y = bottom - view->pending.height;
+ destination_y = bottom
+ - view_effective_height(view, /* use_pending */ true);
break;
default:
return;
@@ -1578,9 +1609,11 @@ view_move_to_edge(struct view *view, enum view_edge direction, bool snap_to_wind
destination_x = MAX(destination_x, left);
/* If more than half the view is below usable region, align to bottom */
- midpoint = destination_y + view->pending.height / 2;
+ midpoint = destination_y
+ + view_effective_height(view, /* use_pending */ true) / 2;
if (destination_y >= top && midpoint > usable.y + usable.height) {
- destination_y = bottom - view->pending.height;
+ destination_y = bottom
+ - view_effective_height(view, /* use_pending */ true);
}
/* Never allow the window to start above the usable edge */
@@ -1599,11 +1632,14 @@ view_grow_to_edge(struct view *view, enum view_edge direction)
if (view->fullscreen || view->maximized != VIEW_AXIS_NONE) {
return;
}
+
if (!output_is_usable(view->output)) {
wlr_log(WLR_ERROR, "view has no output, not growing view");
return;
}
+ view_set_shade(view, false);
+
struct wlr_box geo = view->pending;
snap_grow_to_next_edge(view, direction, &geo);
view_move_resize(view, geo);
@@ -1613,15 +1649,19 @@ void
view_shrink_to_edge(struct view *view, enum view_edge direction)
{
assert(view);
+
/* TODO: allow shrink to edge if maximized along the other axis */
if (view->fullscreen || view->maximized != VIEW_AXIS_NONE) {
return;
}
+
if (!output_is_usable(view->output)) {
wlr_log(WLR_ERROR, "view has no output, not shrinking view");
return;
}
+ view_set_shade(view, false);
+
struct wlr_box geo = view->pending;
snap_shrink_to_next_edge(view, direction, &geo);
view_move_resize(view, geo);
@@ -1670,15 +1710,19 @@ view_snap_to_edge(struct view *view, enum view_edge edge,
bool across_outputs, bool store_natural_geometry)
{
assert(view);
+
if (view->fullscreen) {
return;
}
+
struct output *output = view->output;
if (!output_is_usable(output)) {
wlr_log(WLR_ERROR, "view has no output, not snapping to edge");
return;
}
+ view_set_shade(view, false);
+
if (across_outputs && view->tiled == edge && view->maximized == VIEW_AXIS_NONE) {
/* We are already tiled for this edge; try to switch outputs */
output = view_get_adjacent_output(view, edge);
@@ -1721,15 +1765,19 @@ view_snap_to_region(struct view *view, struct region *region,
{
assert(view);
assert(region);
+
if (view->fullscreen) {
return;
}
+
/* view_apply_region_geometry() needs a usable output */
if (!output_is_usable(view->output)) {
wlr_log(WLR_ERROR, "view has no output, not snapping to region");
return;
}
+ view_set_shade(view, false);
+
if (view->maximized != VIEW_AXIS_NONE) {
/* Unmaximize + keep using existing natural_geometry */
view_maximize(view, VIEW_AXIS_NONE,
@@ -1974,6 +2022,25 @@ view_connect_map(struct view *view, struct wlr_surface *surface)
mappable_connect(&view->mappable, surface, handle_map, handle_unmap);
}
+void
+view_set_shade(struct view *view, bool shaded)
+{
+ assert(view);
+
+ if (view->shaded == shaded) {
+ return;
+ }
+
+ /* Views without a title-bar or SSD cannot be shaded */
+ if (shaded && (!view->ssd || view->ssd_titlebar_hidden)) {
+ return;
+ }
+
+ view->shaded = shaded;
+ ssd_enable_shade(view->ssd, view->shaded);
+ wlr_scene_node_set_enabled(view->scene_node, !view->shaded);
+}
+
void
view_destroy(struct view *view)
{