- L: window label (aka. title)
- |: empty space (can be used instead of a title)
- W: window menu
- - S: shade
- I: iconify
- M: maximize
- C: close
+ - S: shade
+ - D: omnipresent
Example: WLIMC
buttons and the window title are shown.
- Title: The area of the titlebar (including blank space) between
the window buttons, where the window title is displayed.
- - WindowMenu: The button on the left.
- - Iconify: The button that looks like an underline.
- - Maximize: The button that looks like a box.
- - Shade: A button that looks like an overline.
- - Close: The button that looks like an X.
+ - WindowMenu: A button that, by default, displays a window menu.
+ - Iconify: A button that, by default, iconifies a window.
+ - Maximize: A button that, by default, toggles maximization of a window.
+ - Shade: A button that, by default, toggles window shading.
+ - Omnipresent: A button that, by default, toggles omnipresence of a window.
+ - Close: A button that, by default, closses a window.
- Top: The top edge of the window's border.
- Bottom: The bottom edge of the window's border.
- Left: The left edge of the window's border.
</mousebind>
</context>
+ <context name="Ominpresent">
+ <mousebind button="Left" action="Click">
+ <action name="ToggleOmnipresent" />
+ </mousebind>
+ </context>
+
<context name="Iconify">
<mousebind button="Left" action="Click">
<action name="Iconify" />
.button = "Left",
.event = "Click",
.action = "ToggleShade",
+ }, {
+ .context = "Omnipresent",
+ .button = "Left",
+ .event = "Click",
+ .action = "ToggleOmnipresent",
}, {
.context = "Maximize",
.button = "Right",
* don't update things we don't have to.
*/
struct {
- bool was_shaded; /* To toggle icon on shade */
- bool was_maximized; /* To un-round corner buttons and toggle icon on maximize */
- bool was_tiled_not_maximized; /* To un-round corner buttons */
+ /* Button icons need to be swapped on shade or omnipresent toggles */
+ bool was_shaded;
+ bool was_omnipresent;
+
+ /*
+ * Corners need to be (un)rounded when toggling tiling or
+ * maximization, and the button needs to be swapped on
+ * maximization toggles.
+ */
+ bool was_maximized;
+ bool was_tiled_not_maximized;
+
struct wlr_box geometry;
struct ssd_state_title {
char *text;
LAB_SSD_BUTTON_ICONIFY,
LAB_SSD_BUTTON_WINDOW_MENU,
LAB_SSD_BUTTON_SHADE,
+ LAB_SSD_BUTTON_OMNIPRESENT,
LAB_SSD_PART_TITLEBAR,
LAB_SSD_PART_TITLEBAR_CORNER_RIGHT,
LAB_SSD_PART_TITLEBAR_CORNER_LEFT,
float window_active_button_max_unpressed_image_color[4];
float window_active_button_close_unpressed_image_color[4];
float window_active_button_shade_unpressed_image_color[4];
+ float window_active_button_omnipresent_unpressed_image_color[4];
float window_inactive_button_menu_unpressed_image_color[4];
float window_inactive_button_iconify_unpressed_image_color[4];
float window_inactive_button_max_unpressed_image_color[4];
float window_inactive_button_close_unpressed_image_color[4];
float window_inactive_button_shade_unpressed_image_color[4];
+ float window_inactive_button_omnipresent_unpressed_image_color[4];
/* TODO: add pressed and hover colors for buttons */
int menu_item_padding_x;
struct lab_data_buffer *button_menu_active_unpressed;
struct lab_data_buffer *button_shade_active_unpressed;
struct lab_data_buffer *button_unshade_active_unpressed;
+ struct lab_data_buffer *button_omnipresent_active_unpressed;
+ struct lab_data_buffer *button_exclusive_active_unpressed;
struct lab_data_buffer *button_close_inactive_unpressed;
struct lab_data_buffer *button_maximize_inactive_unpressed;
struct lab_data_buffer *button_menu_inactive_unpressed;
struct lab_data_buffer *button_shade_inactive_unpressed;
struct lab_data_buffer *button_unshade_inactive_unpressed;
+ struct lab_data_buffer *button_omnipresent_inactive_unpressed;
+ struct lab_data_buffer *button_exclusive_inactive_unpressed;
/* hover variants are optional and may be NULL */
struct lab_data_buffer *button_close_active_hover;
struct lab_data_buffer *button_menu_active_hover;
struct lab_data_buffer *button_shade_active_hover;
struct lab_data_buffer *button_unshade_active_hover;
+ struct lab_data_buffer *button_omnipresent_active_hover;
+ struct lab_data_buffer *button_exclusive_active_hover;
struct lab_data_buffer *button_close_inactive_hover;
struct lab_data_buffer *button_maximize_inactive_hover;
struct lab_data_buffer *button_menu_inactive_hover;
struct lab_data_buffer *button_shade_inactive_hover;
struct lab_data_buffer *button_unshade_inactive_hover;
+ struct lab_data_buffer *button_omnipresent_inactive_hover;
+ struct lab_data_buffer *button_exclusive_inactive_hover;
struct lab_data_buffer *corner_top_left_active_normal;
struct lab_data_buffer *corner_top_right_active_normal;
return LAB_SSD_BUTTON_WINDOW_MENU;
} else if (!strcasecmp(str, "Shade")) {
return LAB_SSD_BUTTON_SHADE;
+ } else if (!strcasecmp(str, "Omnipresent")) {
+ return LAB_SSD_BUTTON_OMNIPRESENT;
} else if (!strcasecmp(str, "Titlebar")) {
return LAB_SSD_PART_TITLEBAR;
} else if (!strcasecmp(str, "Title")) {
case 'S':
type = LAB_SSD_BUTTON_SHADE;
break;
- /* case 'D': omnipresent */
+ case 'D':
+ type = LAB_SSD_BUTTON_OMNIPRESENT;
+ break;
default:
continue;
}
active ? &theme->button_unshade_active_hover->base
: &theme->button_unshade_inactive_hover->base);
break;
+ case LAB_SSD_BUTTON_OMNIPRESENT:
+ /* Omnipresent button has an alternate state when enabled */
+ btn_root = add_scene_button(&subtree->parts, type, parent,
+ active ? &theme->button_omnipresent_active_unpressed->base
+ : &theme->button_omnipresent_inactive_unpressed->base,
+ active ? &theme->button_omnipresent_active_hover->base
+ : &theme->button_omnipresent_inactive_hover->base,
+ x, view);
+ btn = node_ssd_button_from_node(btn_root->node);
+ add_toggled_icon(btn, &subtree->parts, LAB_SSD_BUTTON_OMNIPRESENT,
+ active ? &theme->button_exclusive_active_unpressed->base
+ : &theme->button_exclusive_inactive_unpressed->base,
+ active ? &theme->button_exclusive_active_hover->base
+ : &theme->button_exclusive_inactive_hover->base);
+ break;
case LAB_SSD_BUTTON_CLOSE:
add_scene_button(&subtree->parts, type, parent,
active ? &theme->button_close_active_unpressed->base
set_alt_button_icon(ssd, LAB_SSD_BUTTON_SHADE, true);
}
+ if (view->visible_on_all_workspaces) {
+ set_alt_button_icon(ssd, LAB_SSD_BUTTON_OMNIPRESENT, true);
+ }
+
if (view_is_tiled_and_notify_tiled(view) && !maximized) {
set_squared_corners(ssd, true);
ssd->state.was_tiled_not_maximized = true;
struct theme *theme = view->server->theme;
bool maximized = view->maximized == VIEW_AXIS_BOTH;
- bool tiled_not_maximized = view_is_tiled_and_notify_tiled(ssd->view)
- && !maximized;
+ bool tiled_not_maximized =
+ view_is_tiled_and_notify_tiled(ssd->view) && !maximized;
if (ssd->state.was_maximized != maximized
- || ssd->state.was_shaded != view->shaded
|| ssd->state.was_tiled_not_maximized != tiled_not_maximized) {
set_squared_corners(ssd, maximized || tiled_not_maximized);
if (ssd->state.was_maximized != maximized) {
set_alt_button_icon(ssd, LAB_SSD_BUTTON_MAXIMIZE, maximized);
}
- if (ssd->state.was_shaded != view->shaded) {
- set_alt_button_icon(ssd, LAB_SSD_BUTTON_SHADE, view->shaded);
- }
ssd->state.was_maximized = maximized;
- ssd->state.was_shaded = view->shaded;
ssd->state.was_tiled_not_maximized = tiled_not_maximized;
}
+ if (ssd->state.was_shaded != view->shaded) {
+ set_alt_button_icon(ssd, LAB_SSD_BUTTON_SHADE, view->shaded);
+ ssd->state.was_shaded = view->shaded;
+ }
+
+ if (ssd->state.was_omnipresent != view->visible_on_all_workspaces) {
+ set_alt_button_icon(ssd, LAB_SSD_BUTTON_OMNIPRESENT,
+ view->visible_on_all_workspaces);
+ ssd->state.was_omnipresent = view->visible_on_all_workspaces;
+ }
+
if (width == ssd->state.geometry.width) {
return;
}
return;
}
+ struct view *view = ssd->view;
+ assert(view);
+
struct wlr_box cached = ssd->state.geometry;
- struct wlr_box current = ssd->view->current;
+ struct wlr_box current = view->current;
int min_view_width = rc.theme->window_button_width * (
wl_list_length(&rc.title_buttons_left) + wl_list_length(&rc.title_buttons_right));
int eff_width = current.width;
- int eff_height = view_effective_height(ssd->view, /* use_pending */ false);
+ int eff_height = view_effective_height(view, /* use_pending */ false);
if (eff_width > 0 && eff_width < min_view_width) {
/*
return;
}
- 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);
- ssd->state.geometry = current;
- }
- bool maximized = ssd->view->maximized == VIEW_AXIS_BOTH;
- if (ssd->state.was_maximized != maximized
- || ssd->state.was_shaded != ssd->view->shaded) {
- ssd_titlebar_update(ssd);
- ssd_border_update(ssd);
- ssd_shadow_update(ssd);
- /*
- * Not strictly necessary as ssd_titlebar_update()
- * already sets these values, but set here to be safe.
- */
- ssd->state.was_maximized = maximized;
- ssd->state.was_shaded = ssd->view->shaded;
- }
- bool tiled_and_not_maximized = view_is_tiled(ssd->view) && !maximized;
- if (ssd->state.was_tiled_not_maximized != tiled_and_not_maximized) {
- ssd_titlebar_update(ssd);
- ssd_border_update(ssd);
- /* see above about being future proof */
- ssd->state.was_tiled_not_maximized = tiled_and_not_maximized;
- }
- return;
+ 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;
+ bool tiled_not_maximized = view_is_tiled(view) && !maximized;
+
+ bool state_changed = ssd->state.was_maximized != maximized
+ || ssd->state.was_shaded != view->shaded
+ || ssd->state.was_tiled_not_maximized != tiled_not_maximized
+ || ssd->state.was_omnipresent != view->visible_on_all_workspaces;
+
+ 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;
}
- ssd_extents_update(ssd);
- ssd_titlebar_update(ssd);
- ssd_border_update(ssd);
- ssd_shadow_update(ssd);
- ssd->state.geometry = current;
}
void
|| (b->type == LAB_SSD_BUTTON_ICONIFY && !strcmp(icon_name, "iconify"))
|| (b->type == LAB_SSD_BUTTON_CLOSE && !strcmp(icon_name, "close"))
|| (b->type == LAB_SSD_BUTTON_SHADE && !strcmp(icon_name, "shade"))
- || (b->type == LAB_SSD_BUTTON_SHADE && !strcmp(icon_name, "shade_toggled"));
+ || (b->type == LAB_SSD_BUTTON_SHADE && !strcmp(icon_name, "shade_toggled"))
+ || (b->type == LAB_SSD_BUTTON_OMNIPRESENT && !strcmp(icon_name, "desk"))
+ || (b->type == LAB_SSD_BUTTON_OMNIPRESENT && !strcmp(icon_name, "desk_toggled"));
}
static enum corner
.active.rgba = theme->window_active_button_shade_unpressed_image_color,
.inactive.buffer = &theme->button_unshade_inactive_unpressed,
.inactive.rgba = theme->window_inactive_button_shade_unpressed_image_color,
+ }, {
+ .name = "desk",
+ .fallback_button = (const char[]){ 0x33, 0x33, 0x00, 0x00, 0x33, 0x33 },
+ .active.buffer = &theme->button_omnipresent_active_unpressed,
+ .active.rgba = theme->window_active_button_omnipresent_unpressed_image_color,
+ .inactive.buffer = &theme->button_omnipresent_inactive_unpressed,
+ .inactive.rgba = theme->window_inactive_button_omnipresent_unpressed_image_color,
+ }, {
+ .name = "desk_toggled",
+ .fallback_button = (const char[]){ 0x00, 0x1e, 0x1a, 0x16, 0x1e, 0x00 },
+ .active.buffer = &theme->button_exclusive_active_unpressed,
+ .active.rgba = theme->window_active_button_omnipresent_unpressed_image_color,
+ .inactive.buffer = &theme->button_exclusive_inactive_unpressed,
+ .inactive.rgba = theme->window_inactive_button_omnipresent_unpressed_image_color,
}, {
.name = "close",
.fallback_button = (const char[]){ 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 },
.active.rgba = theme->window_active_button_shade_unpressed_image_color,
.inactive.buffer = &theme->button_unshade_inactive_hover,
.inactive.rgba = theme->window_inactive_button_shade_unpressed_image_color,
+ }, {
+ .name = "desk_hover",
+ /* no fallback (non-hover variant is used instead) */
+ .active.buffer = &theme->button_omnipresent_active_hover,
+ .active.rgba = theme->window_active_button_omnipresent_unpressed_image_color,
+ .inactive.buffer = &theme->button_omnipresent_inactive_hover,
+ .inactive.rgba = theme->window_inactive_button_omnipresent_unpressed_image_color,
+ }, {
+ .name = "desk_toggled_hover",
+ .alt_name = "desk_hover_toggled",
+ /* no fallback (non-hover variant is used instead) */
+ .active.buffer = &theme->button_exclusive_active_hover,
+ .active.rgba = theme->window_active_button_omnipresent_unpressed_image_color,
+ .inactive.buffer = &theme->button_exclusive_inactive_hover,
+ .inactive.rgba = theme->window_inactive_button_omnipresent_unpressed_image_color,
}, {
.name = "close_hover",
/* no fallback (non-hover variant is used instead) */
theme->window_active_button_max_unpressed_image_color);
parse_hexstr("#000000",
theme->window_active_button_shade_unpressed_image_color);
+ parse_hexstr("#000000",
+ theme->window_active_button_omnipresent_unpressed_image_color);
parse_hexstr("#000000",
theme->window_active_button_close_unpressed_image_color);
parse_hexstr("#000000",
theme->window_inactive_button_max_unpressed_image_color);
parse_hexstr("#000000",
theme->window_inactive_button_shade_unpressed_image_color);
+ parse_hexstr("#000000",
+ theme->window_inactive_button_omnipresent_unpressed_image_color);
parse_hexstr("#000000",
theme->window_inactive_button_close_unpressed_image_color);
theme->window_active_button_max_unpressed_image_color);
parse_hexstr(value,
theme->window_active_button_shade_unpressed_image_color);
+ parse_hexstr(value,
+ theme->window_active_button_omnipresent_unpressed_image_color);
parse_hexstr(value,
theme->window_active_button_close_unpressed_image_color);
}
theme->window_inactive_button_max_unpressed_image_color);
parse_hexstr(value,
theme->window_inactive_button_shade_unpressed_image_color);
+ parse_hexstr(value,
+ theme->window_inactive_button_omnipresent_unpressed_image_color);
parse_hexstr(value,
theme->window_inactive_button_close_unpressed_image_color);
}
parse_hexstr(value,
theme->window_active_button_shade_unpressed_image_color);
}
+ if (match_glob(key, "window.active.button.omnipresent.unpressed.image.color")) {
+ parse_hexstr(value,
+ theme->window_active_button_omnipresent_unpressed_image_color);
+ }
if (match_glob(key, "window.active.button.close.unpressed.image.color")) {
parse_hexstr(value,
theme->window_active_button_close_unpressed_image_color);
parse_hexstr(value,
theme->window_inactive_button_shade_unpressed_image_color);
}
+ if (match_glob(key, "window.inactive.button.omnipresent.unpressed.image.color")) {
+ parse_hexstr(value,
+ theme->window_inactive_button_omnipresent_unpressed_image_color);
+ }
if (match_glob(key, "window.inactive.button.close.unpressed.image.color")) {
parse_hexstr(value,
theme->window_inactive_button_close_unpressed_image_color);
zdrop(&theme->button_restore_active_unpressed);
zdrop(&theme->button_shade_active_unpressed);
zdrop(&theme->button_unshade_active_unpressed);
+ zdrop(&theme->button_omnipresent_active_unpressed);
+ zdrop(&theme->button_exclusive_active_unpressed);
zdrop(&theme->button_iconify_active_unpressed);
zdrop(&theme->button_menu_active_unpressed);
zdrop(&theme->button_restore_inactive_unpressed);
zdrop(&theme->button_shade_inactive_unpressed);
zdrop(&theme->button_unshade_inactive_unpressed);
+ zdrop(&theme->button_omnipresent_inactive_unpressed);
+ zdrop(&theme->button_exclusive_inactive_unpressed);
zdrop(&theme->button_iconify_inactive_unpressed);
zdrop(&theme->button_menu_inactive_unpressed);
zdrop(&theme->button_restore_active_hover);
zdrop(&theme->button_shade_active_hover);
zdrop(&theme->button_unshade_active_hover);
+ zdrop(&theme->button_omnipresent_active_hover);
+ zdrop(&theme->button_exclusive_active_hover);
zdrop(&theme->button_iconify_active_hover);
zdrop(&theme->button_menu_active_hover);
zdrop(&theme->button_restore_inactive_hover);
zdrop(&theme->button_shade_inactive_hover);
zdrop(&theme->button_unshade_inactive_hover);
+ zdrop(&theme->button_omnipresent_inactive_hover);
+ zdrop(&theme->button_exclusive_inactive_hover);
zdrop(&theme->button_iconify_inactive_hover);
zdrop(&theme->button_menu_inactive_hover);
{
assert(view);
view->visible_on_all_workspaces = !view->visible_on_all_workspaces;
+ ssd_update_geometry(view->ssd);
}
void