mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
feat: add Shade/Unshade/ToggleShade actions
This builds on the work of @Consolatis in #1018. Co-authored-by: Consolatis <35009135+Consolatis@users.noreply.github.com> Co-authored-by: Andrew J. Hesford <ajh@sideband.org>
This commit is contained in:
parent
722a802de0
commit
e05bedb140
19 changed files with 218 additions and 47 deletions
|
|
@ -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.
|
||||
|
||||
*<action name="Shade" />*++
|
||||
*<action name="Unshade" />*++
|
||||
*<action name="ToggleShade" />*
|
||||
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.
|
||||
|
||||
*<action name="None" />*
|
||||
If used as the only action for a binding: clear an earlier defined
|
||||
binding.
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@
|
|||
<item label="Fullscreen">
|
||||
<action name="ToggleFullscreen" />
|
||||
</item>
|
||||
<item label="Roll up/down">
|
||||
<action name="ToggleShade" />
|
||||
</item>
|
||||
<item label="Decorations">
|
||||
<action name="ToggleDecorations" />
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -331,6 +331,14 @@
|
|||
<action name="Focus" />
|
||||
<action name="Raise" />
|
||||
</mousebind>
|
||||
<mousebind direction="Up" action="Scroll">
|
||||
<action name="Unshade" />
|
||||
<action name="Focus" />
|
||||
</mousebind>
|
||||
<mousebind direction="Down" action="Scroll">
|
||||
<action name="Unfocus" />
|
||||
<action name="Shade" />
|
||||
</mousebind>
|
||||
</context>
|
||||
|
||||
<context name="Title">
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
32
po/labwc.pot
32
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 <EMAIL@ADDRESS>, 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 <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\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 ""
|
||||
|
|
|
|||
22
src/action.c
22
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;
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
22
src/snap.c
22
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 {
|
||||
|
|
|
|||
|
|
@ -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 */);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
73
src/view.c
73
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)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue