2022-02-21 03:18:38 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Helpers for view server side decorations
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) Johan Malm 2020-2021
|
|
|
|
|
*/
|
|
|
|
|
|
2025-09-03 05:08:52 -04:00
|
|
|
#include "ssd.h"
|
2022-02-21 03:18:38 +01:00
|
|
|
#include <assert.h>
|
2024-04-20 06:29:51 +02:00
|
|
|
#include <strings.h>
|
2025-09-06 20:06:32 -04:00
|
|
|
#include <wlr/types/wlr_cursor.h>
|
2025-07-28 01:22:10 -04:00
|
|
|
#include <wlr/types/wlr_scene.h>
|
2022-11-26 16:46:28 -05:00
|
|
|
#include "common/mem.h"
|
2026-02-23 16:34:36 -05:00
|
|
|
#include "common/scene-helpers.h"
|
2025-08-17 16:01:50 -04:00
|
|
|
#include "config/rcxml.h"
|
2022-11-21 10:10:39 -05:00
|
|
|
#include "labwc.h"
|
2025-09-03 05:32:44 -04:00
|
|
|
#include "node.h"
|
2022-11-26 16:53:35 -05:00
|
|
|
#include "ssd-internal.h"
|
2022-11-21 10:10:39 -05:00
|
|
|
#include "theme.h"
|
|
|
|
|
#include "view.h"
|
2022-02-21 03:18:38 +01:00
|
|
|
|
|
|
|
|
struct border
|
|
|
|
|
ssd_thickness(struct view *view)
|
|
|
|
|
{
|
2022-11-26 16:46:28 -05:00
|
|
|
assert(view);
|
2022-11-26 02:25:02 -05:00
|
|
|
/*
|
|
|
|
|
* Check preconditions for displaying SSD. Note that this
|
|
|
|
|
* needs to work even before ssd_create() has been called.
|
2023-09-17 22:41:46 +02:00
|
|
|
*
|
|
|
|
|
* For that reason we are not using the .enabled state of
|
|
|
|
|
* the titlebar node here but rather check for the view
|
|
|
|
|
* boolean. If we were to use the .enabled state this would
|
|
|
|
|
* cause issues on Reconfigure events with views which were
|
|
|
|
|
* in border-only deco mode as view->ssd would only be set
|
|
|
|
|
* after ssd_create() returns.
|
2022-11-26 02:25:02 -05:00
|
|
|
*/
|
2025-08-21 13:45:58 +09:00
|
|
|
if (!view->ssd_mode || view->fullscreen) {
|
2022-11-26 02:22:03 -05:00
|
|
|
return (struct border){ 0 };
|
2022-06-28 19:42:40 +02:00
|
|
|
}
|
2023-04-14 09:01:13 +02:00
|
|
|
|
2026-03-21 22:47:22 -04:00
|
|
|
struct theme *theme = rc.theme;
|
2023-08-23 01:04:40 +02:00
|
|
|
|
view: implement separate horizontal/vertical maximize
This is a useful (if lesser-known) feature of at least a few popular X11
window managers, for example Openbox and XFWM4. Typically right-click on
the maximize button toggles horizontal maximize, while middle-click
toggles vertical maximize.
Support in labwc uses the same configuration syntax as Openbox, where the
Maximize/ToggleMaximize actions have an optional "direction" argument:
horizontal, vertical, or both (default). The default mouse bindings match
the XFWM4 defaults (not sure what Openbox has by default).
Most of the external protocols still assume "maximized" is a Boolean,
which is no longer true internally. For the sake of the outside world,
a view is only "maximized" if maximized in both directions.
Internally, I've taken the following approach:
- SSD code decorates the view as "maximized" (i.e. hiding borders) only
if maximized in both directions.
- Layout code (interactive move/resize, tiling, etc.) generally treats
the view as "maximized" (with the restrictions that entails) if
maximized in either direction. For example, moving a vertically-
maximized view first restores the natural geometry (this differs from
Openbox, which instead allows the view to move only horizontally.)
v2: use enum view_axis for view->maximized
v3:
- update docs
- allow resizing if partly maximized
- add TODOs & corrections noted by Consolatis
2023-10-26 00:38:29 -04:00
|
|
|
if (view->maximized == VIEW_AXIS_BOTH) {
|
2023-08-23 01:04:40 +02:00
|
|
|
struct border thickness = { 0 };
|
2025-08-21 13:45:58 +09:00
|
|
|
if (view_titlebar_visible(view)) {
|
2024-11-12 12:37:26 +09:00
|
|
|
thickness.top += theme->titlebar_height;
|
2023-08-23 01:04:40 +02:00
|
|
|
}
|
|
|
|
|
return thickness;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-14 09:01:13 +02:00
|
|
|
struct border thickness = {
|
2024-11-12 12:37:26 +09:00
|
|
|
.top = theme->titlebar_height + theme->border_width,
|
2025-07-04 00:40:15 -04:00
|
|
|
.right = theme->border_width,
|
2022-02-21 03:18:38 +01:00
|
|
|
.bottom = theme->border_width,
|
|
|
|
|
.left = theme->border_width,
|
|
|
|
|
};
|
2023-04-14 09:01:13 +02:00
|
|
|
|
2025-08-21 13:45:58 +09:00
|
|
|
if (!view_titlebar_visible(view)) {
|
2024-11-12 12:37:26 +09:00
|
|
|
thickness.top -= theme->titlebar_height;
|
2023-04-14 09:01:13 +02:00
|
|
|
}
|
|
|
|
|
return thickness;
|
2022-02-21 03:18:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct wlr_box
|
|
|
|
|
ssd_max_extents(struct view *view)
|
|
|
|
|
{
|
2022-11-26 16:46:28 -05:00
|
|
|
assert(view);
|
2022-02-21 03:18:38 +01:00
|
|
|
struct border border = ssd_thickness(view);
|
2023-08-08 03:39:35 +02:00
|
|
|
|
|
|
|
|
int eff_width = view->current.width;
|
|
|
|
|
int eff_height = view_effective_height(view, /* use_pending */ false);
|
|
|
|
|
|
2022-11-26 02:22:03 -05:00
|
|
|
return (struct wlr_box){
|
2023-02-08 23:19:14 -05:00
|
|
|
.x = view->current.x - border.left,
|
|
|
|
|
.y = view->current.y - border.top,
|
2023-08-08 03:39:35 +02:00
|
|
|
.width = eff_width + border.left + border.right,
|
|
|
|
|
.height = eff_height + border.top + border.bottom,
|
2022-02-21 03:18:38 +01:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-01 14:51:47 +09:00
|
|
|
/*
|
|
|
|
|
* Resizing and mouse contexts like 'Left', 'TLCorner', etc. in the vicinity of
|
|
|
|
|
* SSD borders, titlebars and extents can have effective "corner regions" that
|
|
|
|
|
* behave differently from single-edge contexts.
|
|
|
|
|
*
|
|
|
|
|
* Corner regions are active whenever the cursor is within a prescribed size
|
|
|
|
|
* (generally rc.resize_corner_range, but clipped to view size) of the view
|
|
|
|
|
* bounds, so check the cursor against the view here.
|
|
|
|
|
*/
|
2025-09-03 05:08:52 -04:00
|
|
|
enum lab_node_type
|
2025-08-13 21:00:11 +09:00
|
|
|
ssd_get_resizing_type(const struct ssd *ssd, struct wlr_cursor *cursor)
|
2025-02-01 14:51:47 +09:00
|
|
|
{
|
|
|
|
|
struct view *view = ssd ? ssd->view : NULL;
|
2025-08-21 13:45:58 +09:00
|
|
|
if (!view || !cursor || !view->ssd_mode || view->fullscreen) {
|
2025-09-03 05:08:52 -04:00
|
|
|
return LAB_NODE_NONE;
|
2025-02-01 14:51:47 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct wlr_box view_box = view->current;
|
|
|
|
|
view_box.height = view_effective_height(view, /* use_pending */ false);
|
|
|
|
|
|
2025-08-21 13:45:58 +09:00
|
|
|
if (view_titlebar_visible(view)) {
|
2025-02-01 14:51:47 +09:00
|
|
|
/* If the titlebar is visible, consider it part of the view */
|
2026-03-21 22:47:22 -04:00
|
|
|
int titlebar_height = rc.theme->titlebar_height;
|
2025-02-01 14:51:47 +09:00
|
|
|
view_box.y -= titlebar_height;
|
|
|
|
|
view_box.height += titlebar_height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (wlr_box_contains_point(&view_box, cursor->x, cursor->y)) {
|
|
|
|
|
/* A cursor in bounds of the view is never in an SSD context */
|
2025-09-03 05:08:52 -04:00
|
|
|
return LAB_NODE_NONE;
|
2025-02-01 14:51:47 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int corner_height = MAX(0, MIN(rc.resize_corner_range, view_box.height / 2));
|
|
|
|
|
int corner_width = MAX(0, MIN(rc.resize_corner_range, view_box.width / 2));
|
|
|
|
|
bool left = cursor->x < view_box.x + corner_width;
|
|
|
|
|
bool right = cursor->x > view_box.x + view_box.width - corner_width;
|
|
|
|
|
bool top = cursor->y < view_box.y + corner_height;
|
|
|
|
|
bool bottom = cursor->y > view_box.y + view_box.height - corner_height;
|
|
|
|
|
|
|
|
|
|
if (top && left) {
|
2025-09-03 05:08:52 -04:00
|
|
|
return LAB_NODE_CORNER_TOP_LEFT;
|
2025-02-01 14:51:47 +09:00
|
|
|
} else if (top && right) {
|
2025-09-03 05:08:52 -04:00
|
|
|
return LAB_NODE_CORNER_TOP_RIGHT;
|
2025-02-01 14:51:47 +09:00
|
|
|
} else if (bottom && left) {
|
2025-09-03 05:08:52 -04:00
|
|
|
return LAB_NODE_CORNER_BOTTOM_LEFT;
|
2025-02-01 14:51:47 +09:00
|
|
|
} else if (bottom && right) {
|
2025-09-03 05:08:52 -04:00
|
|
|
return LAB_NODE_CORNER_BOTTOM_RIGHT;
|
2025-02-01 14:51:47 +09:00
|
|
|
} else if (top) {
|
2025-09-03 05:08:52 -04:00
|
|
|
return LAB_NODE_BORDER_TOP;
|
2025-02-01 14:51:47 +09:00
|
|
|
} else if (bottom) {
|
2025-09-03 05:08:52 -04:00
|
|
|
return LAB_NODE_BORDER_BOTTOM;
|
2025-02-01 14:51:47 +09:00
|
|
|
} else if (left) {
|
2025-09-03 05:08:52 -04:00
|
|
|
return LAB_NODE_BORDER_LEFT;
|
2025-02-01 14:51:47 +09:00
|
|
|
} else if (right) {
|
2025-09-03 05:08:52 -04:00
|
|
|
return LAB_NODE_BORDER_RIGHT;
|
2025-02-01 14:51:47 +09:00
|
|
|
}
|
|
|
|
|
|
2025-09-03 05:08:52 -04:00
|
|
|
return LAB_NODE_NONE;
|
2022-02-21 03:18:38 +01:00
|
|
|
}
|
|
|
|
|
|
2022-11-26 16:46:28 -05:00
|
|
|
struct ssd *
|
2022-11-26 02:17:04 -05:00
|
|
|
ssd_create(struct view *view, bool active)
|
2022-02-21 03:18:38 +01:00
|
|
|
{
|
2022-11-26 16:46:28 -05:00
|
|
|
assert(view);
|
|
|
|
|
struct ssd *ssd = znew(*ssd);
|
2022-02-21 03:18:38 +01:00
|
|
|
|
2022-11-26 16:46:28 -05:00
|
|
|
ssd->view = view;
|
2026-02-23 16:34:36 -05:00
|
|
|
ssd->tree = lab_wlr_scene_tree_create(view->scene_tree);
|
2025-09-07 21:48:51 +09:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Attach node_descriptor to the root node so that get_cursor_context()
|
|
|
|
|
* detect cursor hovering on borders and extents.
|
|
|
|
|
*/
|
2025-09-03 05:32:44 -04:00
|
|
|
node_descriptor_create(&ssd->tree->node,
|
2025-09-07 21:48:51 +09:00
|
|
|
LAB_NODE_SSD_ROOT, view, /*data*/ NULL);
|
|
|
|
|
|
2022-11-26 16:06:22 -05:00
|
|
|
wlr_scene_node_lower_to_bottom(&ssd->tree->node);
|
2026-03-21 22:47:22 -04:00
|
|
|
ssd->titlebar.height = rc.theme->titlebar_height;
|
2024-04-22 19:27:53 +01:00
|
|
|
ssd_shadow_create(ssd);
|
2022-11-26 16:06:22 -05:00
|
|
|
ssd_extents_create(ssd);
|
2024-07-19 21:45:24 +02:00
|
|
|
/*
|
|
|
|
|
* We need to create the borders after the titlebar because it sets
|
2024-08-25 16:33:41 +09:00
|
|
|
* ssd->state.squared which ssd_border_create() reacts to.
|
|
|
|
|
* TODO: Set the state here instead so the order does not matter
|
|
|
|
|
* anymore.
|
2024-07-19 21:45:24 +02:00
|
|
|
*/
|
2022-11-26 16:06:22 -05:00
|
|
|
ssd_titlebar_create(ssd);
|
2024-07-19 21:45:24 +02:00
|
|
|
ssd_border_create(ssd);
|
2025-08-21 13:45:58 +09:00
|
|
|
if (!view_titlebar_visible(view)) {
|
2023-09-17 22:41:46 +02:00
|
|
|
/* Ensure we keep the old state on Reconfigure or when exiting fullscreen */
|
2024-04-18 09:46:36 +02:00
|
|
|
ssd_set_titlebar(ssd, false);
|
2023-04-14 09:01:13 +02:00
|
|
|
}
|
2022-11-26 16:06:22 -05:00
|
|
|
ssd->margin = ssd_thickness(view);
|
2022-11-26 16:46:28 -05:00
|
|
|
ssd_set_active(ssd, active);
|
2023-03-05 10:35:56 +01:00
|
|
|
ssd_enable_keybind_inhibit_indicator(ssd, view->inhibits_keybinds);
|
2023-02-08 23:19:14 -05:00
|
|
|
ssd->state.geometry = view->current;
|
2022-11-26 16:46:28 -05:00
|
|
|
|
|
|
|
|
return ssd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct border
|
|
|
|
|
ssd_get_margin(const struct ssd *ssd)
|
|
|
|
|
{
|
|
|
|
|
return ssd ? ssd->margin : (struct border){ 0 };
|
2022-02-21 03:18:38 +01:00
|
|
|
}
|
|
|
|
|
|
2024-09-09 17:43:38 +02:00
|
|
|
int
|
|
|
|
|
ssd_get_corner_width(void)
|
|
|
|
|
{
|
|
|
|
|
/* ensure a minimum corner width */
|
|
|
|
|
return MAX(rc.corner_radius, 5);
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-25 13:22:23 +02:00
|
|
|
void
|
|
|
|
|
ssd_update_margin(struct ssd *ssd)
|
|
|
|
|
{
|
|
|
|
|
if (!ssd) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ssd->margin = ssd_thickness(ssd->view);
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 03:18:38 +01:00
|
|
|
void
|
2022-11-26 16:46:28 -05:00
|
|
|
ssd_update_geometry(struct ssd *ssd)
|
2022-02-21 03:18:38 +01:00
|
|
|
{
|
2022-11-26 16:46:28 -05:00
|
|
|
if (!ssd) {
|
2022-02-21 03:18:38 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-23 12:45:14 -04:00
|
|
|
struct view *view = ssd->view;
|
|
|
|
|
assert(view);
|
|
|
|
|
|
2023-02-08 23:19:14 -05:00
|
|
|
struct wlr_box cached = ssd->state.geometry;
|
2024-08-23 12:45:14 -04:00
|
|
|
struct wlr_box current = view->current;
|
2023-08-08 03:39:35 +02:00
|
|
|
|
|
|
|
|
int eff_width = current.width;
|
2024-08-23 12:45:14 -04:00
|
|
|
int eff_height = view_effective_height(view, /* use_pending */ false);
|
2023-08-08 03:39:35 +02:00
|
|
|
|
2024-08-23 12:45:14 -04:00
|
|
|
bool update_area = eff_width != cached.width || eff_height != cached.height;
|
|
|
|
|
bool update_extents = update_area
|
|
|
|
|
|| current.x != cached.x || current.y != cached.y;
|
|
|
|
|
|
|
|
|
|
bool maximized = view->maximized == VIEW_AXIS_BOTH;
|
2024-08-25 16:33:41 +09:00
|
|
|
bool squared = ssd_should_be_squared(ssd);
|
2024-08-23 12:45:14 -04:00
|
|
|
|
|
|
|
|
bool state_changed = ssd->state.was_maximized != maximized
|
|
|
|
|
|| ssd->state.was_shaded != view->shaded
|
2024-08-25 16:33:41 +09:00
|
|
|
|| ssd->state.was_squared != squared
|
2024-08-23 12:45:14 -04:00
|
|
|
|| ssd->state.was_omnipresent != view->visible_on_all_workspaces;
|
|
|
|
|
|
2025-08-21 13:56:37 +09:00
|
|
|
/*
|
|
|
|
|
* (Un)maximization updates titlebar visibility with
|
|
|
|
|
* maximizedDecoration=none
|
|
|
|
|
*/
|
|
|
|
|
ssd_set_titlebar(ssd, view_titlebar_visible(view));
|
|
|
|
|
|
2024-08-23 12:45:14 -04:00
|
|
|
if (update_extents) {
|
|
|
|
|
ssd_extents_update(ssd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (update_area || state_changed) {
|
|
|
|
|
ssd_titlebar_update(ssd);
|
|
|
|
|
ssd_border_update(ssd);
|
|
|
|
|
ssd_shadow_update(ssd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (update_extents) {
|
|
|
|
|
ssd->state.geometry = current;
|
2022-02-21 03:18:38 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-14 09:01:13 +02:00
|
|
|
void
|
2024-04-18 09:46:36 +02:00
|
|
|
ssd_set_titlebar(struct ssd *ssd, bool enabled)
|
2023-04-14 09:01:13 +02:00
|
|
|
{
|
2024-04-18 09:46:36 +02:00
|
|
|
if (!ssd || ssd->titlebar.tree->node.enabled == enabled) {
|
2023-04-14 09:01:13 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2024-04-18 09:46:36 +02:00
|
|
|
wlr_scene_node_set_enabled(&ssd->titlebar.tree->node, enabled);
|
2026-03-21 22:47:22 -04:00
|
|
|
ssd->titlebar.height = enabled ? rc.theme->titlebar_height : 0;
|
2023-04-14 09:01:13 +02:00
|
|
|
ssd_border_update(ssd);
|
|
|
|
|
ssd_extents_update(ssd);
|
2024-04-22 19:27:53 +01:00
|
|
|
ssd_shadow_update(ssd);
|
2023-04-14 09:01:13 +02:00
|
|
|
ssd->margin = ssd_thickness(ssd->view);
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 03:18:38 +01:00
|
|
|
void
|
2022-11-26 16:46:28 -05:00
|
|
|
ssd_destroy(struct ssd *ssd)
|
2022-02-21 03:18:38 +01:00
|
|
|
{
|
2022-11-26 16:46:28 -05:00
|
|
|
if (!ssd) {
|
2022-02-21 03:18:38 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Maybe reset hover view */
|
2022-11-26 16:46:28 -05:00
|
|
|
struct view *view = ssd->view;
|
2026-03-19 12:05:43 -04:00
|
|
|
if (server.hovered_button && node_view_from_node(
|
|
|
|
|
server.hovered_button->node) == view) {
|
|
|
|
|
server.hovered_button = NULL;
|
2022-02-21 03:18:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Destroy subcomponents */
|
2022-11-26 16:06:22 -05:00
|
|
|
ssd_titlebar_destroy(ssd);
|
|
|
|
|
ssd_border_destroy(ssd);
|
|
|
|
|
ssd_extents_destroy(ssd);
|
2024-04-22 19:27:53 +01:00
|
|
|
ssd_shadow_destroy(ssd);
|
2022-11-26 16:06:22 -05:00
|
|
|
wlr_scene_node_destroy(&ssd->tree->node);
|
2022-11-26 16:46:28 -05:00
|
|
|
|
|
|
|
|
free(ssd);
|
2022-02-21 03:18:38 +01:00
|
|
|
}
|
|
|
|
|
|
2025-08-17 16:01:50 -04:00
|
|
|
enum lab_ssd_mode
|
2024-04-20 06:29:51 +02:00
|
|
|
ssd_mode_parse(const char *mode)
|
|
|
|
|
{
|
|
|
|
|
if (!mode) {
|
2024-10-18 02:07:52 +03:00
|
|
|
return LAB_SSD_MODE_INVALID;
|
2024-04-20 06:29:51 +02:00
|
|
|
}
|
|
|
|
|
if (!strcasecmp(mode, "none")) {
|
|
|
|
|
return LAB_SSD_MODE_NONE;
|
|
|
|
|
} else if (!strcasecmp(mode, "border")) {
|
|
|
|
|
return LAB_SSD_MODE_BORDER;
|
2024-10-18 02:07:52 +03:00
|
|
|
} else if (!strcasecmp(mode, "full")) {
|
2024-04-20 06:29:51 +02:00
|
|
|
return LAB_SSD_MODE_FULL;
|
2024-10-18 02:07:52 +03:00
|
|
|
} else {
|
|
|
|
|
return LAB_SSD_MODE_INVALID;
|
2024-04-20 06:29:51 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 03:18:38 +01:00
|
|
|
void
|
2022-11-26 16:46:28 -05:00
|
|
|
ssd_set_active(struct ssd *ssd, bool active)
|
2022-02-21 03:18:38 +01:00
|
|
|
{
|
2022-11-26 16:46:28 -05:00
|
|
|
if (!ssd) {
|
2022-02-21 03:18:38 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2025-08-13 21:00:11 +09:00
|
|
|
enum ssd_active_state active_state;
|
|
|
|
|
FOR_EACH_ACTIVE_STATE(active_state) {
|
2024-04-22 19:27:53 +01:00
|
|
|
wlr_scene_node_set_enabled(
|
2025-08-13 21:00:11 +09:00
|
|
|
&ssd->border.subtrees[active_state].tree->node,
|
|
|
|
|
active == active_state);
|
2024-04-22 19:27:53 +01:00
|
|
|
wlr_scene_node_set_enabled(
|
2025-08-13 21:00:11 +09:00
|
|
|
&ssd->titlebar.subtrees[active_state].tree->node,
|
|
|
|
|
active == active_state);
|
|
|
|
|
if (ssd->shadow.subtrees[active_state].tree) {
|
|
|
|
|
wlr_scene_node_set_enabled(
|
|
|
|
|
&ssd->shadow.subtrees[active_state].tree->node,
|
|
|
|
|
active == active_state);
|
|
|
|
|
}
|
2024-04-22 19:27:53 +01:00
|
|
|
}
|
2022-02-21 03:18:38 +01:00
|
|
|
}
|
2022-11-26 16:13:09 -05:00
|
|
|
|
2023-08-08 03:39:35 +02:00
|
|
|
void
|
|
|
|
|
ssd_enable_shade(struct ssd *ssd, bool enable)
|
|
|
|
|
{
|
|
|
|
|
if (!ssd) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-08-22 16:27:24 -04:00
|
|
|
ssd_titlebar_update(ssd);
|
2023-08-08 03:39:35 +02:00
|
|
|
ssd_border_update(ssd);
|
|
|
|
|
wlr_scene_node_set_enabled(&ssd->extents.tree->node, !enable);
|
2024-04-22 19:27:53 +01:00
|
|
|
ssd_shadow_update(ssd);
|
2023-08-08 03:39:35 +02:00
|
|
|
}
|
|
|
|
|
|
2023-03-05 10:35:56 +01:00
|
|
|
void
|
|
|
|
|
ssd_enable_keybind_inhibit_indicator(struct ssd *ssd, bool enable)
|
|
|
|
|
{
|
|
|
|
|
if (!ssd) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float *color = enable
|
|
|
|
|
? rc.theme->window_toggled_keybinds_color
|
2025-10-14 13:44:44 +09:00
|
|
|
: rc.theme->window[SSD_ACTIVE].border_color;
|
2025-08-13 21:00:11 +09:00
|
|
|
wlr_scene_rect_set_color(ssd->border.subtrees[SSD_ACTIVE].top, color);
|
2022-11-26 16:46:28 -05:00
|
|
|
}
|
|
|
|
|
|
2022-11-26 16:13:09 -05:00
|
|
|
bool
|
|
|
|
|
ssd_debug_is_root_node(const struct ssd *ssd, struct wlr_scene_node *node)
|
|
|
|
|
{
|
2022-11-26 16:46:28 -05:00
|
|
|
if (!ssd || !node) {
|
2022-11-26 16:13:09 -05:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return node == &ssd->tree->node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *
|
|
|
|
|
ssd_debug_get_node_name(const struct ssd *ssd, struct wlr_scene_node *node)
|
|
|
|
|
{
|
2022-11-26 16:46:28 -05:00
|
|
|
if (!ssd || !node) {
|
2022-11-26 16:13:09 -05:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
if (node == &ssd->tree->node) {
|
|
|
|
|
return "view->ssd";
|
|
|
|
|
}
|
2025-08-13 21:00:11 +09:00
|
|
|
if (node == &ssd->titlebar.subtrees[SSD_ACTIVE].tree->node) {
|
2022-11-26 16:13:09 -05:00
|
|
|
return "titlebar.active";
|
|
|
|
|
}
|
2025-08-13 21:00:11 +09:00
|
|
|
if (node == &ssd->titlebar.subtrees[SSD_INACTIVE].tree->node) {
|
2022-11-26 16:13:09 -05:00
|
|
|
return "titlebar.inactive";
|
|
|
|
|
}
|
2025-08-13 21:00:11 +09:00
|
|
|
if (node == &ssd->border.subtrees[SSD_ACTIVE].tree->node) {
|
2022-11-26 16:13:09 -05:00
|
|
|
return "border.active";
|
|
|
|
|
}
|
2025-08-13 21:00:11 +09:00
|
|
|
if (node == &ssd->border.subtrees[SSD_INACTIVE].tree->node) {
|
2022-11-26 16:13:09 -05:00
|
|
|
return "border.inactive";
|
|
|
|
|
}
|
|
|
|
|
if (node == &ssd->extents.tree->node) {
|
|
|
|
|
return "extents";
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|