mirror of
https://github.com/labwc/labwc.git
synced 2026-02-09 10:07:31 -05:00
ssd: clean up scene management
Our codebase for ssd scenes has grown with a lot of technical debts: - We needed to call `ssd_get_part()` everywhere to get the scene node of a ssd part. We then needed to cast it to `wlr_scene_rect` and `wlr_scene_buffer`. This bloated our codebase and even blocked duplicated button types in `<titlebar><layout>`. - `ssd_get_part_type()` was a dirty hack. It compared parent, grandparent and grandgrandparent of a node with each subtree in the ssd to get the part type of the node. To resolve this issues, this commit changes how ssd scenes are managed: - Access scene rects and scene buffers just as a member of `struct ssd`. - `ssd_part` is now a attachment to a scene node that can be accessed via node_descriptor->data, with a new node-descriptor type `LAB_NODE_DESC_SSD_PART`. `LAB_NODE_DESC_SSD_BUTTON` is unified into it. Now the scene graph under ssd->tree looks like below. The parentheses indicate the type of ssd_part attached to the node: ssd->tree (LAB_SSD_NONE) +--titlebar (LAB_SSD_PART_TITLEBAR) | +--inactive | | +--background bar | | +--left corner | | +--right corner | | +--title (LAB_SSD_PART_TITLE) | | +--iconify button (LAB_SSD_BUTTON_ICONIFY) | | | +--normal close icon image | | | +--hovered close icon image | | | +--... | | +--window icon (LAB_SSD_BUTTON_WINDOW_ICON) | | | +--window icon image | | +--... | +--active | +--... +--border | +--inactive | | +--top | | +--... | +--active | +--top | +--... +--shadow | +--inactive | | +--top | | +--... | +--active | +--top | +--... +--extents +--top +--... When hovering on SSD, `get_cursor_context()` traverses this scene node from the leaf. If it finds a `ssd_part` attached to the node, it returns `ssd_part_type` that represents the resizing direction, button types or `Title`/`Titlebar`.
This commit is contained in:
parent
aa3dbb4f85
commit
f347a818e3
13 changed files with 516 additions and 726 deletions
|
|
@ -7,7 +7,7 @@ struct view;
|
||||||
struct lab_layer_surface;
|
struct lab_layer_surface;
|
||||||
struct lab_layer_popup;
|
struct lab_layer_popup;
|
||||||
struct menuitem;
|
struct menuitem;
|
||||||
struct ssd_button;
|
struct ssd_part;
|
||||||
struct scaled_scene_buffer;
|
struct scaled_scene_buffer;
|
||||||
|
|
||||||
enum node_descriptor_type {
|
enum node_descriptor_type {
|
||||||
|
|
@ -21,7 +21,7 @@ enum node_descriptor_type {
|
||||||
LAB_NODE_DESC_MENUITEM,
|
LAB_NODE_DESC_MENUITEM,
|
||||||
LAB_NODE_DESC_TREE,
|
LAB_NODE_DESC_TREE,
|
||||||
LAB_NODE_DESC_SCALED_SCENE_BUFFER,
|
LAB_NODE_DESC_SCALED_SCENE_BUFFER,
|
||||||
LAB_NODE_DESC_SSD_BUTTON,
|
LAB_NODE_DESC_SSD_PART,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct node_descriptor {
|
struct node_descriptor {
|
||||||
|
|
@ -44,7 +44,7 @@ struct node_descriptor {
|
||||||
* - LAB_NODE_DESC_LAYER_SURFACE struct lab_layer_surface
|
* - LAB_NODE_DESC_LAYER_SURFACE struct lab_layer_surface
|
||||||
* - LAB_NODE_DESC_LAYER_POPUP struct lab_layer_popup
|
* - LAB_NODE_DESC_LAYER_POPUP struct lab_layer_popup
|
||||||
* - LAB_NODE_DESC_MENUITEM struct menuitem
|
* - LAB_NODE_DESC_MENUITEM struct menuitem
|
||||||
* - LAB_NODE_DESC_SSD_BUTTON struct ssd_button
|
* - LAB_NODE_DESC_SSD_PART struct ssd_part
|
||||||
*/
|
*/
|
||||||
void node_descriptor_create(struct wlr_scene_node *scene_node,
|
void node_descriptor_create(struct wlr_scene_node *scene_node,
|
||||||
enum node_descriptor_type type, void *data);
|
enum node_descriptor_type type, void *data);
|
||||||
|
|
@ -77,10 +77,10 @@ struct menuitem *node_menuitem_from_node(
|
||||||
struct wlr_scene_node *wlr_scene_node);
|
struct wlr_scene_node *wlr_scene_node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* node_ssd_button_from_node - return ssd_button struct from node
|
* node_ssd_part_from_node - return ssd_part struct from node
|
||||||
* @wlr_scene_node: wlr_scene_node from which to return data
|
* @wlr_scene_node: wlr_scene_node from which to return data
|
||||||
*/
|
*/
|
||||||
struct ssd_button *node_ssd_button_from_node(
|
struct ssd_part *node_ssd_part_from_node(
|
||||||
struct wlr_scene_node *wlr_scene_node);
|
struct wlr_scene_node *wlr_scene_node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -3,52 +3,53 @@
|
||||||
#define LABWC_SSD_INTERNAL_H
|
#define LABWC_SSD_INTERNAL_H
|
||||||
|
|
||||||
#include <wlr/util/box.h>
|
#include <wlr/util/box.h>
|
||||||
#include "common/macros.h"
|
|
||||||
#include "ssd.h"
|
#include "ssd.h"
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
|
||||||
#define FOR_EACH(tmp, ...) \
|
|
||||||
{ \
|
|
||||||
__typeof__(tmp) _x[] = { __VA_ARGS__, NULL }; \
|
|
||||||
size_t _i = 0; \
|
|
||||||
for ((tmp) = _x[_i]; _i < ARRAY_SIZE(_x) - 1; (tmp) = _x[++_i])
|
|
||||||
|
|
||||||
#define FOR_EACH_END }
|
|
||||||
|
|
||||||
struct ssd_button {
|
|
||||||
struct view *view;
|
|
||||||
enum ssd_part_type type;
|
|
||||||
/*
|
|
||||||
* Bitmap of lab_button_state that represents a combination of
|
|
||||||
* hover/toggled/rounded states.
|
|
||||||
*/
|
|
||||||
uint8_t state_set;
|
|
||||||
/*
|
|
||||||
* Image buffers for each combination of hover/toggled/rounded states.
|
|
||||||
* img_buffers[state_set] is displayed. Some of these can be NULL
|
|
||||||
* (e.g. img_buffers[LAB_BS_ROUNDED] is set only for corner buttons).
|
|
||||||
*
|
|
||||||
* When "type" is LAB_SSD_BUTTON_WINDOW_ICON, these are all NULL and
|
|
||||||
* window_icon is used instead.
|
|
||||||
*/
|
|
||||||
struct scaled_img_buffer *img_buffers[LAB_BS_ALL + 1];
|
|
||||||
|
|
||||||
struct scaled_icon_buffer *window_icon;
|
|
||||||
|
|
||||||
struct wl_listener destroy;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ssd_sub_tree {
|
|
||||||
struct wlr_scene_tree *tree;
|
|
||||||
struct wl_list parts; /* ssd_part.link */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ssd_state_title_width {
|
struct ssd_state_title_width {
|
||||||
int width;
|
int width;
|
||||||
bool truncated;
|
bool truncated;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The scene-graph of SSD looks like below. The parentheses indicate the type of
|
||||||
|
* ssd_part attached to the node.
|
||||||
|
*
|
||||||
|
* ssd->tree (LAB_SSD_NONE)
|
||||||
|
* +--titlebar (LAB_SSD_PART_TITLEBAR)
|
||||||
|
* | +--inactive
|
||||||
|
* | | +--background bar
|
||||||
|
* | | +--left corner
|
||||||
|
* | | +--right corner
|
||||||
|
* | | +--title (LAB_SSD_PART_TITLE)
|
||||||
|
* | | +--iconify button (LAB_SSD_BUTTON_ICONIFY)
|
||||||
|
* | | | +--normal close icon image
|
||||||
|
* | | | +--hovered close icon image
|
||||||
|
* | | | +--...
|
||||||
|
* | | +--window icon (LAB_SSD_BUTTON_WINDOW_ICON)
|
||||||
|
* | | | +--window icon image
|
||||||
|
* | | +--...
|
||||||
|
* | +--active
|
||||||
|
* | +--...
|
||||||
|
* +--border
|
||||||
|
* | +--inactive
|
||||||
|
* | | +--top
|
||||||
|
* | | +--...
|
||||||
|
* | +--active
|
||||||
|
* | +--top
|
||||||
|
* | +--...
|
||||||
|
* +--shadow
|
||||||
|
* | +--inactive
|
||||||
|
* | | +--top
|
||||||
|
* | | +--...
|
||||||
|
* | +--active
|
||||||
|
* | +--top
|
||||||
|
* | +--...
|
||||||
|
* +--extents
|
||||||
|
* +--top
|
||||||
|
* +--...
|
||||||
|
*/
|
||||||
struct ssd {
|
struct ssd {
|
||||||
struct view *view;
|
struct view *view;
|
||||||
struct wlr_scene_tree *tree;
|
struct wlr_scene_tree *tree;
|
||||||
|
|
@ -81,33 +82,49 @@ struct ssd {
|
||||||
struct wlr_box geometry;
|
struct wlr_box geometry;
|
||||||
struct ssd_state_title {
|
struct ssd_state_title {
|
||||||
char *text;
|
char *text;
|
||||||
struct ssd_state_title_width active;
|
/* indexed by enum ssd_active_state */
|
||||||
struct ssd_state_title_width inactive;
|
struct ssd_state_title_width dstates[2];
|
||||||
} title;
|
} title;
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
/* An invisible area around the view which allows resizing */
|
/* An invisible area around the view which allows resizing */
|
||||||
struct ssd_sub_tree extents;
|
struct ssd_extents_scene {
|
||||||
|
struct wlr_scene_tree *tree;
|
||||||
|
struct wlr_scene_rect *top, *bottom, *left, *right;
|
||||||
|
} extents;
|
||||||
|
|
||||||
/* The top of the view, containing buttons, title, .. */
|
/* The top of the view, containing buttons, title, .. */
|
||||||
struct {
|
struct ssd_titlebar_scene {
|
||||||
int height;
|
int height;
|
||||||
struct wlr_scene_tree *tree;
|
struct wlr_scene_tree *tree;
|
||||||
struct ssd_sub_tree active;
|
struct ssd_titlebar_subtree {
|
||||||
struct ssd_sub_tree inactive;
|
struct wlr_scene_tree *tree;
|
||||||
|
struct wlr_scene_buffer *corner_left;
|
||||||
|
struct wlr_scene_buffer *corner_right;
|
||||||
|
struct wlr_scene_buffer *bar;
|
||||||
|
struct scaled_font_buffer *title;
|
||||||
|
/* List of ssd_parts that represent buttons */
|
||||||
|
struct wl_list buttons_left;
|
||||||
|
struct wl_list buttons_right;
|
||||||
|
} subtrees[2]; /* indexed by enum ssd_active_state */
|
||||||
} titlebar;
|
} titlebar;
|
||||||
|
|
||||||
/* Borders allow resizing as well */
|
/* Borders allow resizing as well */
|
||||||
struct {
|
struct ssd_border_scene {
|
||||||
struct wlr_scene_tree *tree;
|
struct wlr_scene_tree *tree;
|
||||||
struct ssd_sub_tree active;
|
struct ssd_border_subtree {
|
||||||
struct ssd_sub_tree inactive;
|
struct wlr_scene_tree *tree;
|
||||||
|
struct wlr_scene_rect *top, *bottom, *left, *right;
|
||||||
|
} subtrees[2]; /* indexed by enum ssd_active_state */
|
||||||
} border;
|
} border;
|
||||||
|
|
||||||
struct {
|
struct ssd_shadow_scene {
|
||||||
struct wlr_scene_tree *tree;
|
struct wlr_scene_tree *tree;
|
||||||
struct ssd_sub_tree active;
|
struct ssd_shadow_subtree {
|
||||||
struct ssd_sub_tree inactive;
|
struct wlr_scene_tree *tree;
|
||||||
|
struct wlr_scene_buffer *top, *bottom, *left, *right,
|
||||||
|
*top_left, *top_right, *bottom_left, *bottom_right;
|
||||||
|
} subtrees[2]; /* indexed by enum ssd_active_state */
|
||||||
} shadow;
|
} shadow;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -118,46 +135,61 @@ struct ssd {
|
||||||
struct border margin;
|
struct border margin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ssd_part wraps a scene-node with ssd-specific information and can be
|
||||||
|
* accessed with node_ssd_part_from_node(wlr_scene_node *).
|
||||||
|
* This allows get_cursor_context() in desktop.c to see which SSD part is under
|
||||||
|
* the cursor.
|
||||||
|
*/
|
||||||
struct ssd_part {
|
struct ssd_part {
|
||||||
enum ssd_part_type type;
|
enum ssd_part_type type;
|
||||||
|
struct view *view;
|
||||||
/* Buffer pointer. May be NULL */
|
|
||||||
struct scaled_font_buffer *buffer;
|
|
||||||
|
|
||||||
/* This part represented in scene graph */
|
/* This part represented in scene graph */
|
||||||
struct wlr_scene_node *node;
|
struct wlr_scene_node *node;
|
||||||
|
struct wl_listener node_destroy;
|
||||||
struct wl_list link;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ssd_part_button {
|
||||||
|
struct ssd_part base;
|
||||||
|
/*
|
||||||
|
* Bitmap of lab_button_state that represents a combination of
|
||||||
|
* hover/toggled/rounded states.
|
||||||
|
*/
|
||||||
|
uint8_t state_set;
|
||||||
|
/*
|
||||||
|
* Image buffers for each combination of hover/toggled/rounded states.
|
||||||
|
* img_buffers[state_set] is displayed. Some of these can be NULL
|
||||||
|
* (e.g. img_buffers[LAB_BS_ROUNDED] is set only for corner buttons).
|
||||||
|
*
|
||||||
|
* When the type of ssd_part pointing to ssd_button is
|
||||||
|
* LAB_SSD_BUTTON_WINDOW_ICON, these are all NULL and window_icon is
|
||||||
|
* used instead.
|
||||||
|
*/
|
||||||
|
struct scaled_img_buffer *img_buffers[LAB_BS_ALL + 1];
|
||||||
|
|
||||||
|
struct scaled_icon_buffer *window_icon;
|
||||||
|
|
||||||
|
struct wl_list link; /* ssd_titlebar_subtree.buttons_{left,right} */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FIXME: This structure is redundant as ssd_part contains view */
|
||||||
struct ssd_hover_state {
|
struct ssd_hover_state {
|
||||||
struct view *view;
|
struct view *view;
|
||||||
struct ssd_button *button;
|
struct ssd_part_button *button;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_buffer;
|
struct wlr_buffer;
|
||||||
struct wlr_scene_tree;
|
struct wlr_scene_tree;
|
||||||
|
|
||||||
/* SSD internal helpers to create various SSD elements */
|
/* SSD internal helpers to create various SSD elements */
|
||||||
/* TODO: Replace some common args with a struct */
|
struct ssd_part *attach_ssd_part(enum ssd_part_type type, struct view *view,
|
||||||
struct ssd_part *add_scene_part(
|
struct wlr_scene_node *node);
|
||||||
struct wl_list *part_list, enum ssd_part_type type);
|
struct ssd_part_button *attach_ssd_part_button(struct wl_list *button_parts,
|
||||||
struct ssd_part *add_scene_rect(
|
|
||||||
struct wl_list *list, enum ssd_part_type type,
|
|
||||||
struct wlr_scene_tree *parent, int width, int height, int x, int y,
|
|
||||||
float color[4]);
|
|
||||||
struct ssd_part *add_scene_buffer(
|
|
||||||
struct wl_list *list, enum ssd_part_type type,
|
|
||||||
struct wlr_scene_tree *parent, struct wlr_buffer *buffer, int x, int y);
|
|
||||||
struct ssd_part *add_scene_button(struct wl_list *part_list,
|
|
||||||
enum ssd_part_type type, struct wlr_scene_tree *parent,
|
enum ssd_part_type type, struct wlr_scene_tree *parent,
|
||||||
struct lab_img *buffers[LAB_BS_ALL + 1], int x, int y,
|
struct lab_img *imgs[LAB_BS_ALL + 1], int x, int y,
|
||||||
struct view *view);
|
struct view *view);
|
||||||
|
struct ssd_part_button *button_try_from_ssd_part(struct ssd_part *part);
|
||||||
/* SSD internal helpers */
|
|
||||||
struct ssd_part *ssd_get_part(
|
|
||||||
struct wl_list *part_list, enum ssd_part_type type);
|
|
||||||
void ssd_destroy_parts(struct wl_list *list);
|
|
||||||
|
|
||||||
/* SSD internal */
|
/* SSD internal */
|
||||||
void ssd_titlebar_create(struct ssd *ssd);
|
void ssd_titlebar_create(struct ssd *ssd);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,13 @@
|
||||||
#include "common/edge.h"
|
#include "common/edge.h"
|
||||||
#include "config/types.h"
|
#include "config/types.h"
|
||||||
|
|
||||||
|
enum ssd_active_state {
|
||||||
|
SSD_INACTIVE = 0,
|
||||||
|
SSD_ACTIVE = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FOR_EACH_ACTIVE_STATE(active) for (active = SSD_INACTIVE; active <= SSD_ACTIVE; active++)
|
||||||
|
|
||||||
struct wlr_cursor;
|
struct wlr_cursor;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -36,11 +43,8 @@ enum ssd_part_type {
|
||||||
LAB_SSD_BUTTON,
|
LAB_SSD_BUTTON,
|
||||||
|
|
||||||
LAB_SSD_PART_TITLEBAR,
|
LAB_SSD_PART_TITLEBAR,
|
||||||
LAB_SSD_PART_TITLEBAR_CORNER_RIGHT,
|
|
||||||
LAB_SSD_PART_TITLEBAR_CORNER_LEFT,
|
|
||||||
LAB_SSD_PART_TITLE,
|
LAB_SSD_PART_TITLE,
|
||||||
|
|
||||||
/* shared by shadows, borders and extents */
|
|
||||||
LAB_SSD_PART_CORNER_TOP_LEFT,
|
LAB_SSD_PART_CORNER_TOP_LEFT,
|
||||||
LAB_SSD_PART_CORNER_TOP_RIGHT,
|
LAB_SSD_PART_CORNER_TOP_RIGHT,
|
||||||
LAB_SSD_PART_CORNER_BOTTOM_RIGHT,
|
LAB_SSD_PART_CORNER_BOTTOM_RIGHT,
|
||||||
|
|
@ -64,8 +68,8 @@ enum ssd_part_type {
|
||||||
|
|
||||||
/* Forward declare arguments */
|
/* Forward declare arguments */
|
||||||
struct ssd;
|
struct ssd;
|
||||||
struct ssd_button;
|
|
||||||
struct ssd_hover_state;
|
struct ssd_hover_state;
|
||||||
|
struct ssd_part;
|
||||||
struct view;
|
struct view;
|
||||||
struct wlr_scene;
|
struct wlr_scene;
|
||||||
struct wlr_scene_node;
|
struct wlr_scene_node;
|
||||||
|
|
@ -96,12 +100,17 @@ struct ssd_hover_state *ssd_hover_state_new(void);
|
||||||
void ssd_update_button_hover(struct wlr_scene_node *node,
|
void ssd_update_button_hover(struct wlr_scene_node *node,
|
||||||
struct ssd_hover_state *hover_state);
|
struct ssd_hover_state *hover_state);
|
||||||
|
|
||||||
enum ssd_part_type ssd_button_get_type(const struct ssd_button *button);
|
enum ssd_part_type ssd_part_get_type(const struct ssd_part *part);
|
||||||
struct view *ssd_button_get_view(const struct ssd_button *button);
|
struct view *ssd_part_get_view(const struct ssd_part *part);
|
||||||
|
|
||||||
/* Public SSD helpers */
|
/* Public SSD helpers */
|
||||||
enum ssd_part_type ssd_get_part_type(const struct ssd *ssd,
|
|
||||||
struct wlr_scene_node *node, struct wlr_cursor *cursor);
|
/*
|
||||||
|
* Returns a part type that represents a mouse context like "Top", "Left" and
|
||||||
|
* "TRCorner" when the cursor is on the window border or resizing handle.
|
||||||
|
*/
|
||||||
|
enum ssd_part_type ssd_get_resizing_type(const struct ssd *ssd,
|
||||||
|
struct wlr_cursor *cursor);
|
||||||
enum lab_edge ssd_resize_edges(enum ssd_part_type type);
|
enum lab_edge ssd_resize_edges(enum ssd_part_type type);
|
||||||
bool ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate);
|
bool ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate);
|
||||||
enum lab_ssd_mode ssd_mode_parse(const char *mode);
|
enum lab_ssd_mode ssd_mode_parse(const char *mode);
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,7 @@ struct theme {
|
||||||
int mag_border_width;
|
int mag_border_width;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* TODO: replace with enum ssd_active_state */
|
||||||
#define THEME_INACTIVE 0
|
#define THEME_INACTIVE 0
|
||||||
#define THEME_ACTIVE 1
|
#define THEME_ACTIVE 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,7 @@ fill_section(const char *content, struct wl_list *list, uint32_t *found_buttons)
|
||||||
|
|
||||||
assert(type != LAB_SSD_NONE);
|
assert(type != LAB_SSD_NONE);
|
||||||
|
|
||||||
|
/* We no longer need this check, but let's keep it just in case */
|
||||||
if (*found_buttons & (1 << type)) {
|
if (*found_buttons & (1 << type)) {
|
||||||
wlr_log(WLR_ERROR, "ignoring duplicated button type '%s'",
|
wlr_log(WLR_ERROR, "ignoring duplicated button type '%s'",
|
||||||
identifier);
|
identifier);
|
||||||
|
|
|
||||||
|
|
@ -302,22 +302,30 @@ get_cursor_context(struct server *server)
|
||||||
case LAB_NODE_DESC_VIEW:
|
case LAB_NODE_DESC_VIEW:
|
||||||
case LAB_NODE_DESC_XDG_POPUP:
|
case LAB_NODE_DESC_XDG_POPUP:
|
||||||
ret.view = desc->data;
|
ret.view = desc->data;
|
||||||
ret.type = ssd_get_part_type(
|
if (ret.node->type == WLR_SCENE_NODE_BUFFER
|
||||||
ret.view->ssd, ret.node, cursor);
|
&& lab_wlr_surface_from_node(ret.node)) {
|
||||||
if (ret.type == LAB_SSD_CLIENT) {
|
ret.type = LAB_SSD_CLIENT;
|
||||||
ret.surface = lab_wlr_surface_from_node(ret.node);
|
ret.surface = lab_wlr_surface_from_node(ret.node);
|
||||||
|
} else {
|
||||||
|
/* should never be reached */
|
||||||
|
wlr_log(WLR_ERROR, "cursor not on client or ssd");
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
case LAB_NODE_DESC_SSD_BUTTON: {
|
case LAB_NODE_DESC_SSD_PART: {
|
||||||
/*
|
struct ssd_part *part = node_ssd_part_from_node(node);
|
||||||
* Always return the top scene node for SSD
|
|
||||||
* buttons
|
|
||||||
*/
|
|
||||||
struct ssd_button *button =
|
|
||||||
node_ssd_button_from_node(node);
|
|
||||||
ret.node = node;
|
ret.node = node;
|
||||||
ret.type = ssd_button_get_type(button);
|
ret.view = ssd_part_get_view(part);
|
||||||
ret.view = ssd_button_get_view(button);
|
|
||||||
|
/* Detect mouse contexts like Top, Left and TRCorner */
|
||||||
|
ret.type = ssd_get_resizing_type(ret.view->ssd, cursor);
|
||||||
|
if (ret.type == LAB_SSD_NONE) {
|
||||||
|
/*
|
||||||
|
* Otherwise, detect mouse contexts like
|
||||||
|
* Title, Titlebar and Iconify
|
||||||
|
*/
|
||||||
|
ret.type = ssd_part_get_type(part);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
case LAB_NODE_DESC_LAYER_SURFACE:
|
case LAB_NODE_DESC_LAYER_SURFACE:
|
||||||
|
|
|
||||||
|
|
@ -71,13 +71,13 @@ node_menuitem_from_node(struct wlr_scene_node *wlr_scene_node)
|
||||||
return (struct menuitem *)node_descriptor->data;
|
return (struct menuitem *)node_descriptor->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ssd_button *
|
struct ssd_part *
|
||||||
node_ssd_button_from_node(struct wlr_scene_node *wlr_scene_node)
|
node_ssd_part_from_node(struct wlr_scene_node *wlr_scene_node)
|
||||||
{
|
{
|
||||||
assert(wlr_scene_node->data);
|
assert(wlr_scene_node->data);
|
||||||
struct node_descriptor *node_descriptor = wlr_scene_node->data;
|
struct node_descriptor *node_descriptor = wlr_scene_node->data;
|
||||||
assert(node_descriptor->type == LAB_NODE_DESC_SSD_BUTTON);
|
assert(node_descriptor->type == LAB_NODE_DESC_SSD_PART);
|
||||||
return (struct ssd_button *)node_descriptor->data;
|
return (struct ssd_part *)node_descriptor->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct scaled_scene_buffer *
|
struct scaled_scene_buffer *
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,13 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <wlr/types/wlr_scene.h>
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
#include "common/macros.h"
|
||||||
#include "common/scene-helpers.h"
|
#include "common/scene-helpers.h"
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
#include "ssd-internal.h"
|
#include "ssd-internal.h"
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
|
||||||
#define FOR_EACH_STATE(ssd, tmp) FOR_EACH(tmp, \
|
|
||||||
&(ssd)->border.active, \
|
|
||||||
&(ssd)->border.inactive)
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ssd_border_create(struct ssd *ssd)
|
ssd_border_create(struct ssd *ssd)
|
||||||
{
|
{
|
||||||
|
|
@ -25,35 +22,37 @@ ssd_border_create(struct ssd *ssd)
|
||||||
int full_width = width + 2 * theme->border_width;
|
int full_width = width + 2 * theme->border_width;
|
||||||
int corner_width = ssd_get_corner_width();
|
int corner_width = ssd_get_corner_width();
|
||||||
|
|
||||||
float *color;
|
|
||||||
struct wlr_scene_tree *parent;
|
|
||||||
struct ssd_sub_tree *subtree;
|
|
||||||
int active;
|
|
||||||
|
|
||||||
ssd->border.tree = wlr_scene_tree_create(ssd->tree);
|
ssd->border.tree = wlr_scene_tree_create(ssd->tree);
|
||||||
wlr_scene_node_set_position(&ssd->border.tree->node, -theme->border_width, 0);
|
wlr_scene_node_set_position(&ssd->border.tree->node, -theme->border_width, 0);
|
||||||
|
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
enum ssd_active_state active;
|
||||||
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
|
struct ssd_border_subtree *subtree = &ssd->border.subtrees[active];
|
||||||
subtree->tree = wlr_scene_tree_create(ssd->border.tree);
|
subtree->tree = wlr_scene_tree_create(ssd->border.tree);
|
||||||
parent = subtree->tree;
|
struct wlr_scene_tree *parent = subtree->tree;
|
||||||
active = (subtree == &ssd->border.active) ?
|
|
||||||
THEME_ACTIVE : THEME_INACTIVE;
|
|
||||||
wlr_scene_node_set_enabled(&parent->node, active);
|
wlr_scene_node_set_enabled(&parent->node, active);
|
||||||
color = theme->window[active].border_color;
|
float *color = theme->window[active].border_color;
|
||||||
|
|
||||||
wl_list_init(&subtree->parts);
|
subtree->left = wlr_scene_rect_create(parent,
|
||||||
add_scene_rect(&subtree->parts, LAB_SSD_PART_LEFT, parent,
|
theme->border_width, height, color);
|
||||||
theme->border_width, height, 0, 0, color);
|
wlr_scene_node_set_position(&subtree->left->node, 0, 0);
|
||||||
add_scene_rect(&subtree->parts, LAB_SSD_PART_RIGHT, parent,
|
|
||||||
theme->border_width, height,
|
subtree->right = wlr_scene_rect_create(parent,
|
||||||
theme->border_width + width, 0, color);
|
theme->border_width, height, color);
|
||||||
add_scene_rect(&subtree->parts, LAB_SSD_PART_BOTTOM, parent,
|
wlr_scene_node_set_position(&subtree->right->node,
|
||||||
full_width, theme->border_width, 0, height, color);
|
theme->border_width + width, 0);
|
||||||
add_scene_rect(&subtree->parts, LAB_SSD_PART_TOP, parent,
|
|
||||||
MAX(width - 2 * corner_width, 0), theme->border_width,
|
subtree->bottom = wlr_scene_rect_create(parent,
|
||||||
|
full_width, theme->border_width, color);
|
||||||
|
wlr_scene_node_set_position(&subtree->bottom->node,
|
||||||
|
0, height);
|
||||||
|
|
||||||
|
subtree->top = wlr_scene_rect_create(parent,
|
||||||
|
MAX(width - 2 * corner_width, 0), theme->border_width, color);
|
||||||
|
wlr_scene_node_set_position(&subtree->top->node,
|
||||||
theme->border_width + corner_width,
|
theme->border_width + corner_width,
|
||||||
-(ssd->titlebar.height + theme->border_width), color);
|
-(ssd->titlebar.height + theme->border_width));
|
||||||
} FOR_EACH_END
|
}
|
||||||
|
|
||||||
if (view->maximized == VIEW_AXIS_BOTH) {
|
if (view->maximized == VIEW_AXIS_BOTH) {
|
||||||
wlr_scene_node_set_enabled(&ssd->border.tree->node, false);
|
wlr_scene_node_set_enabled(&ssd->border.tree->node, false);
|
||||||
|
|
@ -129,50 +128,30 @@ ssd_border_update(struct ssd *ssd)
|
||||||
? 0
|
? 0
|
||||||
: theme->border_width + corner_width;
|
: theme->border_width + corner_width;
|
||||||
|
|
||||||
struct ssd_part *part;
|
enum ssd_active_state active;
|
||||||
struct wlr_scene_rect *rect;
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
struct ssd_sub_tree *subtree;
|
struct ssd_border_subtree *subtree = &ssd->border.subtrees[active];
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
|
||||||
wl_list_for_each(part, &subtree->parts, link) {
|
wlr_scene_rect_set_size(subtree->left,
|
||||||
rect = wlr_scene_rect_from_node(part->node);
|
theme->border_width, side_height);
|
||||||
switch (part->type) {
|
wlr_scene_node_set_position(&subtree->left->node,
|
||||||
case LAB_SSD_PART_LEFT:
|
0, side_y);
|
||||||
wlr_scene_rect_set_size(rect,
|
|
||||||
theme->border_width,
|
wlr_scene_rect_set_size(subtree->right,
|
||||||
side_height);
|
theme->border_width, side_height);
|
||||||
wlr_scene_node_set_position(part->node,
|
wlr_scene_node_set_position(&subtree->right->node,
|
||||||
0,
|
theme->border_width + width, side_y);
|
||||||
side_y);
|
|
||||||
continue;
|
wlr_scene_rect_set_size(subtree->bottom,
|
||||||
case LAB_SSD_PART_RIGHT:
|
full_width, theme->border_width);
|
||||||
wlr_scene_rect_set_size(rect,
|
wlr_scene_node_set_position(&subtree->bottom->node,
|
||||||
theme->border_width,
|
0, height);
|
||||||
side_height);
|
|
||||||
wlr_scene_node_set_position(part->node,
|
wlr_scene_rect_set_size(subtree->top,
|
||||||
theme->border_width + width,
|
top_width, theme->border_width);
|
||||||
side_y);
|
wlr_scene_node_set_position(&subtree->top->node,
|
||||||
continue;
|
top_x, -(ssd->titlebar.height + theme->border_width));
|
||||||
case LAB_SSD_PART_BOTTOM:
|
}
|
||||||
wlr_scene_rect_set_size(rect,
|
|
||||||
full_width,
|
|
||||||
theme->border_width);
|
|
||||||
wlr_scene_node_set_position(part->node,
|
|
||||||
0,
|
|
||||||
height);
|
|
||||||
continue;
|
|
||||||
case LAB_SSD_PART_TOP:
|
|
||||||
wlr_scene_rect_set_size(rect,
|
|
||||||
top_width,
|
|
||||||
theme->border_width);
|
|
||||||
wlr_scene_node_set_position(part->node,
|
|
||||||
top_x,
|
|
||||||
-(ssd->titlebar.height + theme->border_width));
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} FOR_EACH_END
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -181,15 +160,6 @@ ssd_border_destroy(struct ssd *ssd)
|
||||||
assert(ssd);
|
assert(ssd);
|
||||||
assert(ssd->border.tree);
|
assert(ssd->border.tree);
|
||||||
|
|
||||||
struct ssd_sub_tree *subtree;
|
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
|
||||||
ssd_destroy_parts(&subtree->parts);
|
|
||||||
wlr_scene_node_destroy(&subtree->tree->node);
|
|
||||||
subtree->tree = NULL;
|
|
||||||
} FOR_EACH_END
|
|
||||||
|
|
||||||
wlr_scene_node_destroy(&ssd->border.tree->node);
|
wlr_scene_node_destroy(&ssd->border.tree->node);
|
||||||
ssd->border.tree = NULL;
|
ssd->border = (struct ssd_border_scene){0};
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef FOR_EACH_STATE
|
|
||||||
|
|
|
||||||
|
|
@ -11,22 +11,11 @@
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
|
||||||
static struct ssd_part *
|
|
||||||
add_extent(struct wl_list *part_list, enum ssd_part_type type,
|
|
||||||
struct wlr_scene_tree *parent)
|
|
||||||
{
|
|
||||||
float invisible[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
||||||
struct ssd_part *part = add_scene_part(part_list, type);
|
|
||||||
part->node = &wlr_scene_rect_create(parent, 0, 0, invisible)->node;
|
|
||||||
return part;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ssd_extents_create(struct ssd *ssd)
|
ssd_extents_create(struct ssd *ssd)
|
||||||
{
|
{
|
||||||
struct view *view = ssd->view;
|
struct view *view = ssd->view;
|
||||||
struct theme *theme = view->server->theme;
|
struct theme *theme = view->server->theme;
|
||||||
struct wl_list *part_list = &ssd->extents.parts;
|
|
||||||
|
|
||||||
int border_width = MAX(0, MAX(rc.resize_minimum_area, theme->border_width));
|
int border_width = MAX(0, MAX(rc.resize_minimum_area, theme->border_width));
|
||||||
|
|
||||||
|
|
@ -35,14 +24,14 @@ ssd_extents_create(struct ssd *ssd)
|
||||||
if (view->fullscreen || view->maximized == VIEW_AXIS_BOTH) {
|
if (view->fullscreen || view->maximized == VIEW_AXIS_BOTH) {
|
||||||
wlr_scene_node_set_enabled(&parent->node, false);
|
wlr_scene_node_set_enabled(&parent->node, false);
|
||||||
}
|
}
|
||||||
wl_list_init(&ssd->extents.parts);
|
|
||||||
wlr_scene_node_set_position(&parent->node,
|
wlr_scene_node_set_position(&parent->node,
|
||||||
-border_width, -(ssd->titlebar.height + border_width));
|
-border_width, -(ssd->titlebar.height + border_width));
|
||||||
|
|
||||||
add_extent(part_list, LAB_SSD_PART_TOP, parent);
|
float invisible[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
add_extent(part_list, LAB_SSD_PART_LEFT, parent);
|
ssd->extents.top = wlr_scene_rect_create(parent, 0, 0, invisible);
|
||||||
add_extent(part_list, LAB_SSD_PART_RIGHT, parent);
|
ssd->extents.left = wlr_scene_rect_create(parent, 0, 0, invisible);
|
||||||
add_extent(part_list, LAB_SSD_PART_BOTTOM, parent);
|
ssd->extents.right = wlr_scene_rect_create(parent, 0, 0, invisible);
|
||||||
|
ssd->extents.bottom = wlr_scene_rect_create(parent, 0, 0, invisible);
|
||||||
|
|
||||||
/* Initial manual update to keep X11 applications happy */
|
/* Initial manual update to keep X11 applications happy */
|
||||||
ssd_extents_update(ssd);
|
ssd_extents_update(ssd);
|
||||||
|
|
@ -121,10 +110,6 @@ ssd_extents_update(struct ssd *ssd)
|
||||||
int border_width = MAX(rc.resize_minimum_area, theme->border_width);
|
int border_width = MAX(rc.resize_minimum_area, theme->border_width);
|
||||||
int extended_area = MAX(0, rc.resize_minimum_area - theme->border_width);
|
int extended_area = MAX(0, rc.resize_minimum_area - theme->border_width);
|
||||||
|
|
||||||
struct ssd_part *part;
|
|
||||||
struct wlr_scene_rect *rect;
|
|
||||||
struct wlr_box target;
|
|
||||||
|
|
||||||
/* Make sure we update the y offset based on titlebar shown / hidden */
|
/* Make sure we update the y offset based on titlebar shown / hidden */
|
||||||
wlr_scene_node_set_position(&ssd->extents.tree->node,
|
wlr_scene_node_set_position(&ssd->extents.tree->node,
|
||||||
-border_width, -(ssd->titlebar.height + border_width));
|
-border_width, -(ssd->titlebar.height + border_width));
|
||||||
|
|
@ -151,43 +136,19 @@ ssd_extents_update(struct ssd *ssd)
|
||||||
wlr_scene_node_coords(&ssd->extents.tree->node, &base_x, &base_y);
|
wlr_scene_node_coords(&ssd->extents.tree->node, &base_x, &base_y);
|
||||||
pixman_region32_translate(&usable, -base_x, -base_y);
|
pixman_region32_translate(&usable, -base_x, -base_y);
|
||||||
|
|
||||||
wl_list_for_each(part, &ssd->extents.parts, link) {
|
resize_extent_within_usable(ssd->extents.top, &usable,
|
||||||
rect = wlr_scene_rect_from_node(part->node);
|
0, 0,
|
||||||
switch (part->type) {
|
full_width + extended_area * 2, extended_area);
|
||||||
case LAB_SSD_PART_TOP:
|
resize_extent_within_usable(ssd->extents.left, &usable,
|
||||||
target.x = 0;
|
0, extended_area,
|
||||||
target.y = 0;
|
extended_area, full_height);
|
||||||
target.width = full_width + extended_area * 2;
|
resize_extent_within_usable(ssd->extents.right, &usable,
|
||||||
target.height = extended_area;
|
extended_area + full_width, extended_area,
|
||||||
break;
|
extended_area, full_height);
|
||||||
case LAB_SSD_PART_LEFT:
|
resize_extent_within_usable(ssd->extents.bottom, &usable,
|
||||||
target.x = 0;
|
0, extended_area + full_height,
|
||||||
target.y = extended_area;
|
full_width + extended_area * 2, extended_area);
|
||||||
target.width = extended_area;
|
|
||||||
target.height = full_height;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_RIGHT:
|
|
||||||
target.x = extended_area + full_width;
|
|
||||||
target.y = extended_area;
|
|
||||||
target.width = extended_area;
|
|
||||||
target.height = full_height;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_BOTTOM:
|
|
||||||
target.x = 0;
|
|
||||||
target.y = extended_area + full_height;
|
|
||||||
target.width = full_width + extended_area * 2;
|
|
||||||
target.height = extended_area;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* not reached */
|
|
||||||
assert(false);
|
|
||||||
/* suppress warnings with NDEBUG */
|
|
||||||
target = (struct wlr_box){0};
|
|
||||||
}
|
|
||||||
|
|
||||||
resize_extent_within_usable(rect, &usable,
|
|
||||||
target.x, target.y, target.width, target.height);
|
|
||||||
}
|
|
||||||
pixman_region32_fini(&usable);
|
pixman_region32_fini(&usable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -198,7 +159,6 @@ ssd_extents_destroy(struct ssd *ssd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssd_destroy_parts(&ssd->extents.parts);
|
|
||||||
wlr_scene_node_destroy(&ssd->extents.tree->node);
|
wlr_scene_node_destroy(&ssd->extents.tree->node);
|
||||||
ssd->extents.tree = NULL;
|
ssd->extents = (struct ssd_extents_scene){0};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,100 +1,77 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "buffer.h"
|
#include "config/rcxml.h"
|
||||||
#include "common/box.h"
|
|
||||||
#include "common/list.h"
|
#include "common/list.h"
|
||||||
#include "common/mem.h"
|
#include "common/mem.h"
|
||||||
#include "common/scaled-icon-buffer.h"
|
#include "common/scaled-icon-buffer.h"
|
||||||
#include "common/scaled-img-buffer.h"
|
#include "common/scaled-img-buffer.h"
|
||||||
#include "config/rcxml.h"
|
|
||||||
#include "labwc.h"
|
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "ssd-internal.h"
|
#include "ssd-internal.h"
|
||||||
|
|
||||||
/* Internal helpers */
|
/* Internal helpers */
|
||||||
static void
|
static void
|
||||||
handle_button_node_destroy(struct wl_listener *listener, void *data)
|
handle_node_destroy(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
struct ssd_button *button = wl_container_of(listener, button, destroy);
|
struct ssd_part *part = wl_container_of(listener, part, node_destroy);
|
||||||
wl_list_remove(&button->destroy.link);
|
wl_list_remove(&part->node_destroy.link);
|
||||||
free(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
struct ssd_part_button *button = button_try_from_ssd_part(part);
|
||||||
* Create a new node_descriptor containing a link to a new ssd_button struct.
|
if (button) {
|
||||||
* Both will be destroyed automatically once the scene_node they are attached
|
wl_list_remove(&button->link);
|
||||||
* to is destroyed.
|
}
|
||||||
*/
|
|
||||||
static struct ssd_button *
|
|
||||||
ssd_button_descriptor_create(struct wlr_scene_node *node)
|
|
||||||
{
|
|
||||||
/* Create new ssd_button */
|
|
||||||
struct ssd_button *button = znew(*button);
|
|
||||||
|
|
||||||
/* Let it destroy automatically when the scene node destroys */
|
free(part);
|
||||||
button->destroy.notify = handle_button_node_destroy;
|
|
||||||
wl_signal_add(&node->events.destroy, &button->destroy);
|
|
||||||
|
|
||||||
/* And finally attach the ssd_button to a node descriptor */
|
|
||||||
node_descriptor_create(node, LAB_NODE_DESC_SSD_BUTTON, button);
|
|
||||||
return button;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internal API */
|
/* Internal API */
|
||||||
struct ssd_part *
|
|
||||||
add_scene_part(struct wl_list *part_list, enum ssd_part_type type)
|
/*
|
||||||
|
* Create a new node_descriptor containing a link to a new ssd_part struct.
|
||||||
|
* Both will be destroyed automatically once the scene_node they are attached
|
||||||
|
* to is destroyed.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
init_ssd_part(struct ssd_part *part, enum ssd_part_type type,
|
||||||
|
struct view *view, struct wlr_scene_node *node)
|
||||||
{
|
{
|
||||||
struct ssd_part *part = znew(*part);
|
|
||||||
part->type = type;
|
part->type = type;
|
||||||
wl_list_append(part_list, &part->link);
|
part->node = node;
|
||||||
return part;
|
part->view = view;
|
||||||
|
|
||||||
|
node_descriptor_create(node, LAB_NODE_DESC_SSD_PART, part);
|
||||||
|
part->node_destroy.notify = handle_node_destroy;
|
||||||
|
wl_signal_add(&node->events.destroy, &part->node_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ssd_part *
|
struct ssd_part *
|
||||||
add_scene_rect(struct wl_list *list, enum ssd_part_type type,
|
attach_ssd_part(enum ssd_part_type type, struct view *view,
|
||||||
struct wlr_scene_tree *parent, int width, int height,
|
struct wlr_scene_node *node)
|
||||||
int x, int y, float color[4])
|
|
||||||
{
|
{
|
||||||
assert(width >= 0 && height >= 0);
|
assert(!ssd_part_contains(LAB_SSD_BUTTON, type));
|
||||||
struct ssd_part *part = add_scene_part(list, type);
|
struct ssd_part *part = znew(*part);
|
||||||
part->node = &wlr_scene_rect_create(
|
init_ssd_part(part, type, view, node);
|
||||||
parent, width, height, color)->node;
|
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
|
||||||
return part;
|
return part;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ssd_part *
|
struct ssd_part_button *
|
||||||
add_scene_buffer(struct wl_list *list, enum ssd_part_type type,
|
attach_ssd_part_button(struct wl_list *button_parts, enum ssd_part_type type,
|
||||||
struct wlr_scene_tree *parent, struct wlr_buffer *buffer,
|
|
||||||
int x, int y)
|
|
||||||
{
|
|
||||||
struct ssd_part *part = add_scene_part(list, type);
|
|
||||||
part->node = &wlr_scene_buffer_create(parent, buffer)->node;
|
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
|
||||||
return part;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ssd_part *
|
|
||||||
add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
|
||||||
struct wlr_scene_tree *parent,
|
struct wlr_scene_tree *parent,
|
||||||
struct lab_img *imgs[LAB_BS_ALL + 1],
|
struct lab_img *imgs[LAB_BS_ALL + 1],
|
||||||
int x, int y, struct view *view)
|
int x, int y, struct view *view)
|
||||||
{
|
{
|
||||||
struct ssd_part *button_root = add_scene_part(part_list, type);
|
struct wlr_scene_tree *root = wlr_scene_tree_create(parent);
|
||||||
parent = wlr_scene_tree_create(parent);
|
wlr_scene_node_set_position(&root->node, x, y);
|
||||||
button_root->node = &parent->node;
|
|
||||||
wlr_scene_node_set_position(button_root->node, x, y);
|
|
||||||
|
|
||||||
struct ssd_button *button = ssd_button_descriptor_create(button_root->node);
|
assert(ssd_part_contains(LAB_SSD_BUTTON, type));
|
||||||
button->type = type;
|
struct ssd_part_button *button = znew(*button);
|
||||||
button->view = view;
|
init_ssd_part(&button->base, type, view, &root->node);
|
||||||
|
wl_list_append(button_parts, &button->link);
|
||||||
|
|
||||||
/* Hitbox */
|
/* Hitbox */
|
||||||
float invisible[4] = { 0, 0, 0, 0 };
|
float invisible[4] = { 0, 0, 0, 0 };
|
||||||
add_scene_rect(part_list, type, parent,
|
wlr_scene_rect_create(root, rc.theme->window_button_width,
|
||||||
rc.theme->window_button_width, rc.theme->window_button_height, 0, 0,
|
rc.theme->window_button_height, invisible);
|
||||||
invisible);
|
|
||||||
|
|
||||||
/* Icons */
|
/* Icons */
|
||||||
int button_width = rc.theme->window_button_width;
|
int button_width = rc.theme->window_button_width;
|
||||||
|
|
@ -110,14 +87,13 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
int icon_padding = button_width / 10;
|
int icon_padding = button_width / 10;
|
||||||
|
|
||||||
if (type == LAB_SSD_BUTTON_WINDOW_ICON) {
|
if (type == LAB_SSD_BUTTON_WINDOW_ICON) {
|
||||||
struct ssd_part *icon_part = add_scene_part(part_list, type);
|
|
||||||
struct scaled_icon_buffer *icon_buffer =
|
struct scaled_icon_buffer *icon_buffer =
|
||||||
scaled_icon_buffer_create(parent, view->server,
|
scaled_icon_buffer_create(root, view->server,
|
||||||
button_width - 2 * icon_padding, button_height);
|
button_width - 2 * icon_padding, button_height);
|
||||||
scaled_icon_buffer_set_view(icon_buffer, view);
|
|
||||||
assert(icon_buffer);
|
assert(icon_buffer);
|
||||||
icon_part->node = &icon_buffer->scene_buffer->node;
|
struct wlr_scene_node *icon_node = &icon_buffer->scene_buffer->node;
|
||||||
wlr_scene_node_set_position(icon_part->node, icon_padding, 0);
|
scaled_icon_buffer_set_view(icon_buffer, view);
|
||||||
|
wlr_scene_node_set_position(icon_node, icon_padding, 0);
|
||||||
button->window_icon = icon_buffer;
|
button->window_icon = icon_buffer;
|
||||||
} else {
|
} else {
|
||||||
for (uint8_t state_set = LAB_BS_DEFAULT;
|
for (uint8_t state_set = LAB_BS_DEFAULT;
|
||||||
|
|
@ -125,13 +101,12 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
if (!imgs[state_set]) {
|
if (!imgs[state_set]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
struct ssd_part *icon_part = add_scene_part(part_list, type);
|
|
||||||
struct scaled_img_buffer *img_buffer = scaled_img_buffer_create(
|
struct scaled_img_buffer *img_buffer = scaled_img_buffer_create(
|
||||||
parent, imgs[state_set], rc.theme->window_button_width,
|
root, imgs[state_set], rc.theme->window_button_width,
|
||||||
rc.theme->window_button_height);
|
rc.theme->window_button_height);
|
||||||
assert(img_buffer);
|
assert(img_buffer);
|
||||||
icon_part->node = &img_buffer->scene_buffer->node;
|
struct wlr_scene_node *icon_node = &img_buffer->scene_buffer->node;
|
||||||
wlr_scene_node_set_enabled(icon_part->node, false);
|
wlr_scene_node_set_enabled(icon_node, false);
|
||||||
button->img_buffers[state_set] = img_buffer;
|
button->img_buffers[state_set] = img_buffer;
|
||||||
}
|
}
|
||||||
/* Initially show non-hover, non-toggled, unrounded variant */
|
/* Initially show non-hover, non-toggled, unrounded variant */
|
||||||
|
|
@ -139,34 +114,14 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
&button->img_buffers[LAB_BS_DEFAULT]->scene_buffer->node, true);
|
&button->img_buffers[LAB_BS_DEFAULT]->scene_buffer->node, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return button_root;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ssd_part *
|
struct ssd_part_button *
|
||||||
ssd_get_part(struct wl_list *part_list, enum ssd_part_type type)
|
button_try_from_ssd_part(struct ssd_part *part)
|
||||||
{
|
{
|
||||||
struct ssd_part *part;
|
if (ssd_part_contains(LAB_SSD_BUTTON, part->type)) {
|
||||||
wl_list_for_each(part, part_list, link) {
|
return (struct ssd_part_button *)part;
|
||||||
if (part->type == type) {
|
|
||||||
return part;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ssd_destroy_parts(struct wl_list *list)
|
|
||||||
{
|
|
||||||
struct ssd_part *part, *tmp;
|
|
||||||
wl_list_for_each_reverse_safe(part, tmp, list, link) {
|
|
||||||
if (part->node) {
|
|
||||||
wlr_scene_node_destroy(part->node);
|
|
||||||
part->node = NULL;
|
|
||||||
}
|
|
||||||
/* part->buffer will free itself along the scene_buffer node */
|
|
||||||
part->buffer = NULL;
|
|
||||||
wl_list_remove(&part->link);
|
|
||||||
free(part);
|
|
||||||
}
|
|
||||||
assert(wl_list_empty(list));
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,6 @@
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
|
||||||
#define FOR_EACH_STATE(ssd, tmp) FOR_EACH(tmp, \
|
|
||||||
&(ssd)->shadow.active, \
|
|
||||||
&(ssd)->shadow.inactive)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implements point_accepts_input for a buffer which never accepts input
|
* Implements point_accepts_input for a buffer which never accepts input
|
||||||
* because drop-shadows should never catch clicks!
|
* because drop-shadows should never catch clicks!
|
||||||
|
|
@ -50,12 +46,10 @@ corner_scale_crop(struct wlr_scene_buffer *buffer, int horizontal_overlap,
|
||||||
* drop-shadow.
|
* drop-shadow.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
set_shadow_part_geometry(struct ssd_part *part, int width, int height,
|
set_shadow_parts_geometry(struct ssd_shadow_subtree *subtree,
|
||||||
int titlebar_height, int corner_size, int inset,
|
int width, int height, int titlebar_height, int corner_size,
|
||||||
int visible_shadow_width)
|
int inset, int visible_shadow_width)
|
||||||
{
|
{
|
||||||
struct wlr_scene_buffer *scene_buf =
|
|
||||||
wlr_scene_buffer_from_node(part->node);
|
|
||||||
/*
|
/*
|
||||||
* If the shadow inset is greater than half the overall window height
|
* If the shadow inset is greater than half the overall window height
|
||||||
* or width (eg. because the window is shaded or because we have a
|
* or width (eg. because the window is shaded or because we have a
|
||||||
|
|
@ -81,83 +75,69 @@ set_shadow_part_geometry(struct ssd_part *part, int width, int height,
|
||||||
* the top-left and bottom-right corners one pixel wider (if the width
|
* the top-left and bottom-right corners one pixel wider (if the width
|
||||||
* is odd) or taller (if the height is odd).
|
* is odd) or taller (if the height is odd).
|
||||||
*/
|
*/
|
||||||
if (part->type == LAB_SSD_PART_CORNER_TOP_LEFT
|
int horizontal_overlap_downsized = horizontal_overlap;
|
||||||
|| part->type == LAB_SSD_PART_CORNER_BOTTOM_RIGHT) {
|
if (horizontal_overlap > 0) {
|
||||||
if (horizontal_overlap > 0) {
|
horizontal_overlap_downsized -= width % 2;
|
||||||
horizontal_overlap -= width % 2;
|
}
|
||||||
}
|
int vertical_overlap_downsized = vertical_overlap;
|
||||||
if (vertical_overlap > 0) {
|
if (vertical_overlap > 0) {
|
||||||
vertical_overlap -= height % 2;
|
vertical_overlap_downsized -= height % 2;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
switch (part->type) {
|
x = width - inset + horizontal_overlap_downsized;
|
||||||
case LAB_SSD_PART_CORNER_BOTTOM_RIGHT:
|
y = -titlebar_height + height - inset + vertical_overlap_downsized;
|
||||||
x = width - inset + horizontal_overlap;
|
wlr_scene_node_set_position(&subtree->bottom_right->node, x, y);
|
||||||
y = -titlebar_height + height - inset + vertical_overlap;
|
corner_scale_crop(subtree->bottom_right, horizontal_overlap_downsized,
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
vertical_overlap_downsized, corner_size);
|
||||||
corner_scale_crop(scene_buf, horizontal_overlap,
|
|
||||||
vertical_overlap, corner_size);
|
x = -visible_shadow_width;
|
||||||
break;
|
y = -titlebar_height + height - inset + vertical_overlap;
|
||||||
case LAB_SSD_PART_CORNER_BOTTOM_LEFT:
|
wlr_scene_node_set_position(&subtree->bottom_left->node, x, y);
|
||||||
x = -visible_shadow_width;
|
corner_scale_crop(subtree->bottom_left, horizontal_overlap,
|
||||||
y = -titlebar_height + height - inset + vertical_overlap;
|
vertical_overlap, corner_size);
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
|
||||||
corner_scale_crop(scene_buf, horizontal_overlap,
|
x = -visible_shadow_width;
|
||||||
vertical_overlap, corner_size);
|
y = -titlebar_height - visible_shadow_width;
|
||||||
break;
|
wlr_scene_node_set_position(&subtree->top_left->node, x, y);
|
||||||
case LAB_SSD_PART_CORNER_TOP_LEFT:
|
corner_scale_crop(subtree->top_left, horizontal_overlap_downsized,
|
||||||
x = -visible_shadow_width;
|
vertical_overlap_downsized, corner_size);
|
||||||
y = -titlebar_height - visible_shadow_width;
|
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
x = width - inset + horizontal_overlap;
|
||||||
corner_scale_crop(scene_buf, horizontal_overlap,
|
y = -titlebar_height - visible_shadow_width;
|
||||||
vertical_overlap, corner_size);
|
wlr_scene_node_set_position(&subtree->top_right->node, x, y);
|
||||||
break;
|
corner_scale_crop(subtree->top_right, horizontal_overlap,
|
||||||
case LAB_SSD_PART_CORNER_TOP_RIGHT:
|
vertical_overlap, corner_size);
|
||||||
x = width - inset + horizontal_overlap;
|
|
||||||
y = -titlebar_height - visible_shadow_width;
|
x = width;
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
y = -titlebar_height + inset;
|
||||||
corner_scale_crop(scene_buf, horizontal_overlap,
|
wlr_scene_node_set_position(&subtree->right->node, x, y);
|
||||||
vertical_overlap, corner_size);
|
wlr_scene_buffer_set_dest_size(subtree->right,
|
||||||
break;
|
visible_shadow_width, MAX(height - 2 * inset, 0));
|
||||||
case LAB_SSD_PART_RIGHT:
|
wlr_scene_node_set_enabled(&subtree->right->node, show_sides);
|
||||||
x = width;
|
|
||||||
y = -titlebar_height + inset;
|
x = inset;
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
y = -titlebar_height + height;
|
||||||
wlr_scene_buffer_set_dest_size(
|
wlr_scene_node_set_position(&subtree->bottom->node, x, y);
|
||||||
scene_buf, visible_shadow_width, MAX(height - 2 * inset, 0));
|
wlr_scene_buffer_set_dest_size(subtree->bottom,
|
||||||
wlr_scene_node_set_enabled(part->node, show_sides);
|
MAX(width - 2 * inset, 0), visible_shadow_width);
|
||||||
break;
|
wlr_scene_node_set_enabled(&subtree->bottom->node, show_topbottom);
|
||||||
case LAB_SSD_PART_BOTTOM:
|
|
||||||
x = inset;
|
x = -visible_shadow_width;
|
||||||
y = -titlebar_height + height;
|
y = -titlebar_height + inset;
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
wlr_scene_node_set_position(&subtree->left->node, x, y);
|
||||||
wlr_scene_buffer_set_dest_size(
|
wlr_scene_buffer_set_dest_size(subtree->left,
|
||||||
scene_buf, MAX(width - 2 * inset, 0), visible_shadow_width);
|
visible_shadow_width, MAX(height - 2 * inset, 0));
|
||||||
wlr_scene_node_set_enabled(part->node, show_topbottom);
|
wlr_scene_node_set_enabled(&subtree->left->node, show_sides);
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_LEFT:
|
x = inset;
|
||||||
x = -visible_shadow_width;
|
y = -titlebar_height - visible_shadow_width;
|
||||||
y = -titlebar_height + inset;
|
wlr_scene_node_set_position(&subtree->top->node, x, y);
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
wlr_scene_buffer_set_dest_size(subtree->top,
|
||||||
wlr_scene_buffer_set_dest_size(
|
MAX(width - 2 * inset, 0), visible_shadow_width);
|
||||||
scene_buf, visible_shadow_width, MAX(height - 2 * inset, 0));
|
wlr_scene_node_set_enabled(&subtree->top->node, show_topbottom);
|
||||||
wlr_scene_node_set_enabled(part->node, show_sides);
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_TOP:
|
|
||||||
x = inset;
|
|
||||||
y = -titlebar_height - visible_shadow_width;
|
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
|
||||||
wlr_scene_buffer_set_dest_size(
|
|
||||||
scene_buf, MAX(width - 2 * inset, 0), visible_shadow_width);
|
|
||||||
wlr_scene_node_set_enabled(part->node, show_topbottom);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -169,17 +149,14 @@ set_shadow_geometry(struct ssd *ssd)
|
||||||
int width = view->current.width;
|
int width = view->current.width;
|
||||||
int height = view_effective_height(view, false) + titlebar_height;
|
int height = view_effective_height(view, false) + titlebar_height;
|
||||||
|
|
||||||
struct ssd_part *part;
|
enum ssd_active_state active;
|
||||||
struct ssd_sub_tree *subtree;
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
|
struct ssd_shadow_subtree *subtree = &ssd->shadow.subtrees[active];
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
|
||||||
if (!subtree->tree) {
|
if (!subtree->tree) {
|
||||||
/* Looks like this type of shadow is disabled */
|
/* Looks like this type of shadow is disabled */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int active = (subtree == &ssd->shadow.active) ?
|
|
||||||
THEME_ACTIVE : THEME_INACTIVE;
|
|
||||||
int visible_shadow_width = theme->window[active].shadow_size;
|
int visible_shadow_width = theme->window[active].shadow_size;
|
||||||
/* inset as a proportion of shadow width */
|
/* inset as a proportion of shadow width */
|
||||||
double inset_proportion = SSD_SHADOW_INSET;
|
double inset_proportion = SSD_SHADOW_INSET;
|
||||||
|
|
@ -194,23 +171,19 @@ set_shadow_geometry(struct ssd *ssd)
|
||||||
int corner_size =
|
int corner_size =
|
||||||
theme->window[active].shadow_corner_top->logical_height;
|
theme->window[active].shadow_corner_top->logical_height;
|
||||||
|
|
||||||
wl_list_for_each(part, &subtree->parts, link) {
|
set_shadow_parts_geometry(subtree, width, height,
|
||||||
set_shadow_part_geometry(part, width, height,
|
titlebar_height, corner_size, inset,
|
||||||
titlebar_height, corner_size, inset,
|
visible_shadow_width);
|
||||||
visible_shadow_width);
|
}
|
||||||
}
|
|
||||||
} FOR_EACH_END
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static struct wlr_scene_buffer *
|
||||||
make_shadow(struct wl_list *parts, enum ssd_part_type type,
|
make_shadow(struct view *view,
|
||||||
struct wlr_scene_tree *parent, struct wlr_buffer *buf,
|
struct wlr_scene_tree *parent, struct wlr_buffer *buf,
|
||||||
enum wl_output_transform tx)
|
enum wl_output_transform tx)
|
||||||
{
|
{
|
||||||
struct ssd_part *part = add_scene_buffer(
|
|
||||||
parts, type, parent, buf, 0, 0);
|
|
||||||
struct wlr_scene_buffer *scene_buf =
|
struct wlr_scene_buffer *scene_buf =
|
||||||
wlr_scene_buffer_from_node(part->node);
|
wlr_scene_buffer_create(parent, buf);
|
||||||
wlr_scene_buffer_set_transform(scene_buf, tx);
|
wlr_scene_buffer_set_transform(scene_buf, tx);
|
||||||
scene_buf->point_accepts_input = never_accepts_input;
|
scene_buf->point_accepts_input = never_accepts_input;
|
||||||
/*
|
/*
|
||||||
|
|
@ -218,6 +191,7 @@ make_shadow(struct wl_list *parts, enum ssd_part_type type,
|
||||||
* pixel wide/tall. Use nearest-neighbour scaling to workaround.
|
* pixel wide/tall. Use nearest-neighbour scaling to workaround.
|
||||||
*/
|
*/
|
||||||
scene_buf->filter_mode = WLR_SCALE_FILTER_NEAREST;
|
scene_buf->filter_mode = WLR_SCALE_FILTER_NEAREST;
|
||||||
|
return scene_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -229,51 +203,47 @@ ssd_shadow_create(struct ssd *ssd)
|
||||||
ssd->shadow.tree = wlr_scene_tree_create(ssd->tree);
|
ssd->shadow.tree = wlr_scene_tree_create(ssd->tree);
|
||||||
|
|
||||||
struct theme *theme = ssd->view->server->theme;
|
struct theme *theme = ssd->view->server->theme;
|
||||||
struct wlr_buffer *corner_top_buffer;
|
struct view *view = ssd->view;
|
||||||
struct wlr_buffer *corner_bottom_buffer;
|
|
||||||
struct wlr_buffer *edge_buffer;
|
|
||||||
struct ssd_sub_tree *subtree;
|
|
||||||
struct wlr_scene_tree *parent;
|
|
||||||
int active;
|
|
||||||
|
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
enum ssd_active_state active;
|
||||||
wl_list_init(&subtree->parts);
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
|
struct ssd_shadow_subtree *subtree = &ssd->shadow.subtrees[active];
|
||||||
|
|
||||||
if (!rc.shadows_enabled) {
|
if (!rc.shadows_enabled) {
|
||||||
/* Shadows are globally disabled */
|
/* Shadows are globally disabled */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
active = (subtree == &ssd->shadow.active) ?
|
|
||||||
THEME_ACTIVE : THEME_INACTIVE;
|
|
||||||
if (theme->window[active].shadow_size == 0) {
|
if (theme->window[active].shadow_size == 0) {
|
||||||
/* Window shadows are disabled */
|
/* Window shadows are disabled */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
subtree->tree = wlr_scene_tree_create(ssd->shadow.tree);
|
subtree->tree = wlr_scene_tree_create(ssd->shadow.tree);
|
||||||
parent = subtree->tree;
|
struct wlr_scene_tree *parent = subtree->tree;
|
||||||
corner_top_buffer = &theme->window[active].shadow_corner_top->base;
|
struct wlr_buffer *corner_top_buffer =
|
||||||
corner_bottom_buffer = &theme->window[active].shadow_corner_bottom->base;
|
&theme->window[active].shadow_corner_top->base;
|
||||||
edge_buffer = &theme->window[active].shadow_edge->base;
|
struct wlr_buffer *corner_bottom_buffer =
|
||||||
|
&theme->window[active].shadow_corner_bottom->base;
|
||||||
|
struct wlr_buffer *edge_buffer =
|
||||||
|
&theme->window[active].shadow_edge->base;
|
||||||
|
|
||||||
make_shadow(&subtree->parts, LAB_SSD_PART_CORNER_BOTTOM_RIGHT,
|
subtree->bottom_right = make_shadow(view, parent,
|
||||||
parent, corner_bottom_buffer, WL_OUTPUT_TRANSFORM_NORMAL);
|
corner_bottom_buffer, WL_OUTPUT_TRANSFORM_NORMAL);
|
||||||
make_shadow(&subtree->parts, LAB_SSD_PART_CORNER_BOTTOM_LEFT,
|
subtree->bottom_left = make_shadow(view, parent,
|
||||||
parent, corner_bottom_buffer, WL_OUTPUT_TRANSFORM_FLIPPED);
|
corner_bottom_buffer, WL_OUTPUT_TRANSFORM_FLIPPED);
|
||||||
make_shadow(&subtree->parts, LAB_SSD_PART_CORNER_TOP_LEFT,
|
subtree->top_left = make_shadow(view, parent,
|
||||||
parent, corner_top_buffer, WL_OUTPUT_TRANSFORM_180);
|
corner_top_buffer, WL_OUTPUT_TRANSFORM_180);
|
||||||
make_shadow(&subtree->parts, LAB_SSD_PART_CORNER_TOP_RIGHT,
|
subtree->top_right = make_shadow(view, parent,
|
||||||
parent, corner_top_buffer, WL_OUTPUT_TRANSFORM_FLIPPED_180);
|
corner_top_buffer, WL_OUTPUT_TRANSFORM_FLIPPED_180);
|
||||||
make_shadow(&subtree->parts, LAB_SSD_PART_RIGHT, parent,
|
subtree->right = make_shadow(view, parent,
|
||||||
edge_buffer, WL_OUTPUT_TRANSFORM_NORMAL);
|
edge_buffer, WL_OUTPUT_TRANSFORM_NORMAL);
|
||||||
make_shadow(&subtree->parts, LAB_SSD_PART_BOTTOM, parent,
|
subtree->bottom = make_shadow(view, parent,
|
||||||
edge_buffer, WL_OUTPUT_TRANSFORM_90);
|
edge_buffer, WL_OUTPUT_TRANSFORM_90);
|
||||||
make_shadow(&subtree->parts, LAB_SSD_PART_LEFT, parent,
|
subtree->left = make_shadow(view, parent,
|
||||||
edge_buffer, WL_OUTPUT_TRANSFORM_180);
|
edge_buffer, WL_OUTPUT_TRANSFORM_180);
|
||||||
make_shadow(&subtree->parts, LAB_SSD_PART_TOP, parent,
|
subtree->top = make_shadow(view, parent,
|
||||||
edge_buffer, WL_OUTPUT_TRANSFORM_270);
|
edge_buffer, WL_OUTPUT_TRANSFORM_270);
|
||||||
|
}
|
||||||
} FOR_EACH_END
|
|
||||||
|
|
||||||
ssd_shadow_update(ssd);
|
ssd_shadow_update(ssd);
|
||||||
}
|
}
|
||||||
|
|
@ -310,16 +280,6 @@ ssd_shadow_destroy(struct ssd *ssd)
|
||||||
assert(ssd);
|
assert(ssd);
|
||||||
assert(ssd->shadow.tree);
|
assert(ssd->shadow.tree);
|
||||||
|
|
||||||
struct ssd_sub_tree *subtree;
|
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
|
||||||
ssd_destroy_parts(&subtree->parts);
|
|
||||||
/*
|
|
||||||
* subtree->tree will be destroyed when its
|
|
||||||
* parent (ssd->shadow.tree) is destroyed.
|
|
||||||
*/
|
|
||||||
subtree->tree = NULL;
|
|
||||||
} FOR_EACH_END
|
|
||||||
|
|
||||||
wlr_scene_node_destroy(&ssd->shadow.tree->node);
|
wlr_scene_node_destroy(&ssd->shadow.tree->node);
|
||||||
ssd->shadow.tree = NULL;
|
ssd->shadow = (struct ssd_shadow_scene){0};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,6 @@
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
|
||||||
#define FOR_EACH_STATE(ssd, tmp) FOR_EACH(tmp, \
|
|
||||||
&(ssd)->titlebar.active, \
|
|
||||||
&(ssd)->titlebar.inactive)
|
|
||||||
|
|
||||||
static void set_squared_corners(struct ssd *ssd, bool enable);
|
static void set_squared_corners(struct ssd *ssd, bool enable);
|
||||||
static void set_alt_button_icon(struct ssd *ssd, enum ssd_part_type type, bool enable);
|
static void set_alt_button_icon(struct ssd *ssd, enum ssd_part_type type, bool enable);
|
||||||
static void update_visible_buttons(struct ssd *ssd);
|
static void update_visible_buttons(struct ssd *ssd);
|
||||||
|
|
@ -36,30 +32,26 @@ ssd_titlebar_create(struct ssd *ssd)
|
||||||
int width = view->current.width;
|
int width = view->current.width;
|
||||||
int corner_width = ssd_get_corner_width();
|
int corner_width = ssd_get_corner_width();
|
||||||
|
|
||||||
struct wlr_scene_tree *parent;
|
|
||||||
struct wlr_buffer *titlebar_fill;
|
|
||||||
struct wlr_buffer *corner_top_left;
|
|
||||||
struct wlr_buffer *corner_top_right;
|
|
||||||
int active;
|
|
||||||
|
|
||||||
ssd->titlebar.tree = wlr_scene_tree_create(ssd->tree);
|
ssd->titlebar.tree = wlr_scene_tree_create(ssd->tree);
|
||||||
|
attach_ssd_part(LAB_SSD_PART_TITLEBAR, view, &ssd->tree->node);
|
||||||
|
|
||||||
struct ssd_sub_tree *subtree;
|
enum ssd_active_state active;
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
|
struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active];
|
||||||
subtree->tree = wlr_scene_tree_create(ssd->titlebar.tree);
|
subtree->tree = wlr_scene_tree_create(ssd->titlebar.tree);
|
||||||
parent = subtree->tree;
|
struct wlr_scene_tree *parent = subtree->tree;
|
||||||
active = (subtree == &ssd->titlebar.active) ?
|
|
||||||
THEME_ACTIVE : THEME_INACTIVE;
|
|
||||||
titlebar_fill = &theme->window[active].titlebar_fill->base;
|
|
||||||
corner_top_left = &theme->window[active].corner_top_left_normal->base;
|
|
||||||
corner_top_right = &theme->window[active].corner_top_right_normal->base;
|
|
||||||
wlr_scene_node_set_enabled(&parent->node, active);
|
wlr_scene_node_set_enabled(&parent->node, active);
|
||||||
wlr_scene_node_set_position(&parent->node, 0, -theme->titlebar_height);
|
wlr_scene_node_set_position(&parent->node, 0, -theme->titlebar_height);
|
||||||
wl_list_init(&subtree->parts);
|
|
||||||
|
struct wlr_buffer *titlebar_fill =
|
||||||
|
&theme->window[active].titlebar_fill->base;
|
||||||
|
struct wlr_buffer *corner_top_left =
|
||||||
|
&theme->window[active].corner_top_left_normal->base;
|
||||||
|
struct wlr_buffer *corner_top_right =
|
||||||
|
&theme->window[active].corner_top_right_normal->base;
|
||||||
|
|
||||||
/* Background */
|
/* Background */
|
||||||
struct wlr_scene_buffer *bg_scene_buffer =
|
subtree->bar = wlr_scene_buffer_create(parent, titlebar_fill);
|
||||||
wlr_scene_buffer_create(parent, titlebar_fill);
|
|
||||||
/*
|
/*
|
||||||
* Work around the wlroots/pixman bug that widened 1px buffer
|
* Work around the wlroots/pixman bug that widened 1px buffer
|
||||||
* becomes translucent when bilinear filtering is used.
|
* becomes translucent when bilinear filtering is used.
|
||||||
|
|
@ -68,27 +60,25 @@ ssd_titlebar_create(struct ssd *ssd)
|
||||||
*/
|
*/
|
||||||
if (wlr_renderer_is_pixman(view->server->renderer)) {
|
if (wlr_renderer_is_pixman(view->server->renderer)) {
|
||||||
wlr_scene_buffer_set_filter_mode(
|
wlr_scene_buffer_set_filter_mode(
|
||||||
bg_scene_buffer, WLR_SCALE_FILTER_NEAREST);
|
subtree->bar, WLR_SCALE_FILTER_NEAREST);
|
||||||
}
|
}
|
||||||
struct ssd_part *bg_part =
|
wlr_scene_node_set_position(&subtree->bar->node, corner_width, 0);
|
||||||
add_scene_part(&subtree->parts, LAB_SSD_PART_TITLEBAR);
|
|
||||||
bg_part->node = &bg_scene_buffer->node;
|
|
||||||
wlr_scene_node_set_position(bg_part->node, corner_width, 0);
|
|
||||||
|
|
||||||
add_scene_buffer(&subtree->parts, LAB_SSD_PART_TITLEBAR_CORNER_LEFT, parent,
|
subtree->corner_left = wlr_scene_buffer_create(parent, corner_top_left);
|
||||||
corner_top_left, -rc.theme->border_width, -rc.theme->border_width);
|
wlr_scene_node_set_position(&subtree->corner_left->node,
|
||||||
add_scene_buffer(&subtree->parts, LAB_SSD_PART_TITLEBAR_CORNER_RIGHT, parent,
|
-rc.theme->border_width, -rc.theme->border_width);
|
||||||
corner_top_right, width - corner_width,
|
|
||||||
-rc.theme->border_width);
|
subtree->corner_right = wlr_scene_buffer_create(parent, corner_top_right);
|
||||||
|
wlr_scene_node_set_position(&subtree->corner_right->node,
|
||||||
|
width - corner_width, -rc.theme->border_width);
|
||||||
|
|
||||||
/* Title */
|
/* Title */
|
||||||
struct ssd_part *title_part =
|
subtree->title = scaled_font_buffer_create_for_titlebar(
|
||||||
add_scene_part(&subtree->parts, LAB_SSD_PART_TITLE);
|
|
||||||
title_part->buffer = scaled_font_buffer_create_for_titlebar(
|
|
||||||
subtree->tree, theme->titlebar_height,
|
subtree->tree, theme->titlebar_height,
|
||||||
theme->window[active].titlebar_pattern);
|
theme->window[active].titlebar_pattern);
|
||||||
assert(title_part->buffer);
|
assert(subtree->title);
|
||||||
title_part->node = &title_part->buffer->scene_buffer->node;
|
attach_ssd_part(LAB_SSD_PART_TITLE,
|
||||||
|
view, &subtree->title->scene_buffer->node);
|
||||||
|
|
||||||
/* Buttons */
|
/* Buttons */
|
||||||
struct title_button *b;
|
struct title_button *b;
|
||||||
|
|
@ -97,10 +87,13 @@ ssd_titlebar_create(struct ssd *ssd)
|
||||||
/* Center vertically within titlebar */
|
/* Center vertically within titlebar */
|
||||||
int y = (theme->titlebar_height - theme->window_button_height) / 2;
|
int y = (theme->titlebar_height - theme->window_button_height) / 2;
|
||||||
|
|
||||||
|
wl_list_init(&subtree->buttons_left);
|
||||||
|
wl_list_init(&subtree->buttons_right);
|
||||||
|
|
||||||
wl_list_for_each(b, &rc.title_buttons_left, link) {
|
wl_list_for_each(b, &rc.title_buttons_left, link) {
|
||||||
struct lab_img **imgs =
|
struct lab_img **imgs =
|
||||||
theme->window[active].button_imgs[b->type];
|
theme->window[active].button_imgs[b->type];
|
||||||
add_scene_button(&subtree->parts, b->type, parent,
|
attach_ssd_part_button(&subtree->buttons_left, b->type, parent,
|
||||||
imgs, x, y, view);
|
imgs, x, y, view);
|
||||||
x += theme->window_button_width + theme->window_button_spacing;
|
x += theme->window_button_width + theme->window_button_spacing;
|
||||||
}
|
}
|
||||||
|
|
@ -110,10 +103,10 @@ ssd_titlebar_create(struct ssd *ssd)
|
||||||
x -= theme->window_button_width + theme->window_button_spacing;
|
x -= theme->window_button_width + theme->window_button_spacing;
|
||||||
struct lab_img **imgs =
|
struct lab_img **imgs =
|
||||||
theme->window[active].button_imgs[b->type];
|
theme->window[active].button_imgs[b->type];
|
||||||
add_scene_button(&subtree->parts, b->type, parent,
|
attach_ssd_part_button(&subtree->buttons_right, b->type, parent,
|
||||||
imgs, x, y, view);
|
imgs, x, y, view);
|
||||||
}
|
}
|
||||||
} FOR_EACH_END
|
}
|
||||||
|
|
||||||
update_visible_buttons(ssd);
|
update_visible_buttons(ssd);
|
||||||
|
|
||||||
|
|
@ -140,7 +133,7 @@ ssd_titlebar_create(struct ssd *ssd)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_button_state(struct ssd_button *button, enum lab_button_state state,
|
update_button_state(struct ssd_part_button *button, enum lab_button_state state,
|
||||||
bool enable)
|
bool enable)
|
||||||
{
|
{
|
||||||
if (enable) {
|
if (enable) {
|
||||||
|
|
@ -168,56 +161,54 @@ set_squared_corners(struct ssd *ssd, bool enable)
|
||||||
int corner_width = ssd_get_corner_width();
|
int corner_width = ssd_get_corner_width();
|
||||||
struct theme *theme = view->server->theme;
|
struct theme *theme = view->server->theme;
|
||||||
|
|
||||||
struct ssd_part *part;
|
|
||||||
struct ssd_sub_tree *subtree;
|
|
||||||
int x = enable ? 0 : corner_width;
|
int x = enable ? 0 : corner_width;
|
||||||
|
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
enum ssd_active_state active;
|
||||||
part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLEBAR);
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
wlr_scene_node_set_position(part->node, x, 0);
|
struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active];
|
||||||
wlr_scene_buffer_set_dest_size(
|
|
||||||
wlr_scene_buffer_from_node(part->node),
|
wlr_scene_node_set_position(&subtree->bar->node, x, 0);
|
||||||
|
wlr_scene_buffer_set_dest_size(subtree->bar,
|
||||||
MAX(width - 2 * x, 0), theme->titlebar_height);
|
MAX(width - 2 * x, 0), theme->titlebar_height);
|
||||||
|
|
||||||
part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLEBAR_CORNER_LEFT);
|
wlr_scene_node_set_enabled(&subtree->corner_left->node, !enable);
|
||||||
wlr_scene_node_set_enabled(part->node, !enable);
|
|
||||||
|
|
||||||
part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLEBAR_CORNER_RIGHT);
|
wlr_scene_node_set_enabled(&subtree->corner_right->node, !enable);
|
||||||
wlr_scene_node_set_enabled(part->node, !enable);
|
|
||||||
|
|
||||||
/* (Un)round the corner buttons */
|
/* (Un)round the corner buttons */
|
||||||
struct title_button *title_button;
|
struct ssd_part_button *button;
|
||||||
wl_list_for_each(title_button, &rc.title_buttons_left, link) {
|
wl_list_for_each(button, &subtree->buttons_left, link) {
|
||||||
part = ssd_get_part(&subtree->parts, title_button->type);
|
|
||||||
struct ssd_button *button = node_ssd_button_from_node(part->node);
|
|
||||||
update_button_state(button, LAB_BS_ROUNDED, !enable);
|
update_button_state(button, LAB_BS_ROUNDED, !enable);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wl_list_for_each_reverse(title_button, &rc.title_buttons_right, link) {
|
wl_list_for_each(button, &subtree->buttons_right, link) {
|
||||||
part = ssd_get_part(&subtree->parts, title_button->type);
|
|
||||||
struct ssd_button *button = node_ssd_button_from_node(part->node);
|
|
||||||
update_button_state(button, LAB_BS_ROUNDED, !enable);
|
update_button_state(button, LAB_BS_ROUNDED, !enable);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} FOR_EACH_END
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_alt_button_icon(struct ssd *ssd, enum ssd_part_type type, bool enable)
|
set_alt_button_icon(struct ssd *ssd, enum ssd_part_type type, bool enable)
|
||||||
{
|
{
|
||||||
struct ssd_part *part;
|
enum ssd_active_state active;
|
||||||
struct ssd_button *button;
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
struct ssd_sub_tree *subtree;
|
struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active];
|
||||||
|
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
struct ssd_part_button *button;
|
||||||
part = ssd_get_part(&subtree->parts, type);
|
wl_list_for_each(button, &subtree->buttons_left, link) {
|
||||||
if (!part) {
|
if (button->base.type == type) {
|
||||||
return;
|
update_button_state(button,
|
||||||
|
LAB_BS_TOGGLED, enable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
wl_list_for_each(button, &subtree->buttons_right, link) {
|
||||||
button = node_ssd_button_from_node(part->node);
|
if (button->base.type == type) {
|
||||||
update_button_state(button, LAB_BS_TOGGLED, enable);
|
update_button_state(button,
|
||||||
} FOR_EACH_END
|
LAB_BS_TOGGLED, enable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -254,27 +245,25 @@ update_visible_buttons(struct ssd *ssd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int button_count;
|
enum ssd_active_state active;
|
||||||
struct ssd_part *part;
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
struct ssd_sub_tree *subtree;
|
struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active];
|
||||||
struct title_button *b;
|
int button_count = 0;
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
|
||||||
button_count = 0;
|
struct ssd_part_button *button;
|
||||||
wl_list_for_each(b, &rc.title_buttons_left, link) {
|
wl_list_for_each(button, &subtree->buttons_left, link) {
|
||||||
part = ssd_get_part(&subtree->parts, b->type);
|
wlr_scene_node_set_enabled(button->base.node,
|
||||||
wlr_scene_node_set_enabled(part->node,
|
|
||||||
button_count < button_count_left);
|
button_count < button_count_left);
|
||||||
button_count++;
|
button_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
button_count = 0;
|
button_count = 0;
|
||||||
wl_list_for_each_reverse(b, &rc.title_buttons_right, link) {
|
wl_list_for_each(button, &subtree->buttons_right, link) {
|
||||||
part = ssd_get_part(&subtree->parts, b->type);
|
wlr_scene_node_set_enabled(button->base.node,
|
||||||
wlr_scene_node_set_enabled(part->node,
|
|
||||||
button_count < button_count_right);
|
button_count < button_count_right);
|
||||||
button_count++;
|
button_count++;
|
||||||
}
|
}
|
||||||
} FOR_EACH_END
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -318,34 +307,31 @@ ssd_titlebar_update(struct ssd *ssd)
|
||||||
/* Center buttons vertically within titlebar */
|
/* Center buttons vertically within titlebar */
|
||||||
int y = (theme->titlebar_height - theme->window_button_height) / 2;
|
int y = (theme->titlebar_height - theme->window_button_height) / 2;
|
||||||
int x;
|
int x;
|
||||||
struct ssd_part *part;
|
|
||||||
struct ssd_sub_tree *subtree;
|
|
||||||
struct title_button *b;
|
|
||||||
int bg_offset = maximized || squared ? 0 : corner_width;
|
int bg_offset = maximized || squared ? 0 : corner_width;
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
|
||||||
part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLEBAR);
|
enum ssd_active_state active;
|
||||||
wlr_scene_buffer_set_dest_size(
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
wlr_scene_buffer_from_node(part->node),
|
struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active];
|
||||||
|
wlr_scene_buffer_set_dest_size(subtree->bar,
|
||||||
MAX(width - bg_offset * 2, 0), theme->titlebar_height);
|
MAX(width - bg_offset * 2, 0), theme->titlebar_height);
|
||||||
|
|
||||||
x = theme->window_titlebar_padding_width;
|
x = theme->window_titlebar_padding_width;
|
||||||
wl_list_for_each(b, &rc.title_buttons_left, link) {
|
struct ssd_part_button *button;
|
||||||
part = ssd_get_part(&subtree->parts, b->type);
|
wl_list_for_each(button, &subtree->buttons_left, link) {
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
wlr_scene_node_set_position(button->base.node, x, y);
|
||||||
x += theme->window_button_width + theme->window_button_spacing;
|
x += theme->window_button_width + theme->window_button_spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
x = width - corner_width;
|
x = width - corner_width;
|
||||||
part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLEBAR_CORNER_RIGHT);
|
wlr_scene_node_set_position(&subtree->corner_right->node,
|
||||||
wlr_scene_node_set_position(part->node, x, -rc.theme->border_width);
|
x, -rc.theme->border_width);
|
||||||
|
|
||||||
x = width - theme->window_titlebar_padding_width + theme->window_button_spacing;
|
x = width - theme->window_titlebar_padding_width + theme->window_button_spacing;
|
||||||
wl_list_for_each_reverse(b, &rc.title_buttons_right, link) {
|
wl_list_for_each(button, &subtree->buttons_right, link) {
|
||||||
part = ssd_get_part(&subtree->parts, b->type);
|
|
||||||
x -= theme->window_button_width + theme->window_button_spacing;
|
x -= theme->window_button_width + theme->window_button_spacing;
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
wlr_scene_node_set_position(button->base.node, x, y);
|
||||||
}
|
}
|
||||||
} FOR_EACH_END
|
}
|
||||||
|
|
||||||
ssd_update_title(ssd);
|
ssd_update_title(ssd);
|
||||||
}
|
}
|
||||||
|
|
@ -357,19 +343,9 @@ ssd_titlebar_destroy(struct ssd *ssd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ssd_sub_tree *subtree;
|
zfree(ssd->state.title.text);
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
|
||||||
ssd_destroy_parts(&subtree->parts);
|
|
||||||
wlr_scene_node_destroy(&subtree->tree->node);
|
|
||||||
subtree->tree = NULL;
|
|
||||||
} FOR_EACH_END
|
|
||||||
|
|
||||||
if (ssd->state.title.text) {
|
|
||||||
zfree(ssd->state.title.text);
|
|
||||||
}
|
|
||||||
|
|
||||||
wlr_scene_node_destroy(&ssd->titlebar.tree->node);
|
wlr_scene_node_destroy(&ssd->titlebar.tree->node);
|
||||||
ssd->titlebar.tree = NULL;
|
ssd->titlebar = (struct ssd_titlebar_scene){0};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -392,43 +368,40 @@ ssd_update_title_positions(struct ssd *ssd, int offset_left, int offset_right)
|
||||||
int width = view->current.width;
|
int width = view->current.width;
|
||||||
int title_bg_width = width - offset_left - offset_right;
|
int title_bg_width = width - offset_left - offset_right;
|
||||||
|
|
||||||
int x, y;
|
enum ssd_active_state active;
|
||||||
int buffer_height, buffer_width;
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
struct ssd_part *part;
|
struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active];
|
||||||
struct ssd_sub_tree *subtree;
|
struct scaled_font_buffer *title = subtree->title;
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
int x, y;
|
||||||
part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLE);
|
|
||||||
|
|
||||||
buffer_width = part->buffer ? part->buffer->width : 0;
|
|
||||||
buffer_height = part->buffer ? part->buffer->height : 0;
|
|
||||||
x = offset_left;
|
x = offset_left;
|
||||||
y = (theme->titlebar_height - buffer_height) / 2;
|
y = (theme->titlebar_height - title->height) / 2;
|
||||||
|
|
||||||
if (title_bg_width <= 0) {
|
if (title_bg_width <= 0) {
|
||||||
wlr_scene_node_set_enabled(part->node, false);
|
wlr_scene_node_set_enabled(&title->scene_buffer->node, false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
wlr_scene_node_set_enabled(part->node, true);
|
wlr_scene_node_set_enabled(&title->scene_buffer->node, true);
|
||||||
|
|
||||||
if (theme->window_label_text_justify == LAB_JUSTIFY_CENTER) {
|
if (theme->window_label_text_justify == LAB_JUSTIFY_CENTER) {
|
||||||
if (buffer_width + MAX(offset_left, offset_right) * 2 <= width) {
|
if (title->width + MAX(offset_left, offset_right) * 2 <= width) {
|
||||||
/* Center based on the full width */
|
/* Center based on the full width */
|
||||||
x = (width - buffer_width) / 2;
|
x = (width - title->width) / 2;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Center based on the width between the buttons.
|
* Center based on the width between the buttons.
|
||||||
* Title jumps around once this is hit but its still
|
* Title jumps around once this is hit but its still
|
||||||
* better than to hide behind the buttons on the right.
|
* better than to hide behind the buttons on the right.
|
||||||
*/
|
*/
|
||||||
x += (title_bg_width - buffer_width) / 2;
|
x += (title_bg_width - title->width) / 2;
|
||||||
}
|
}
|
||||||
} else if (theme->window_label_text_justify == LAB_JUSTIFY_RIGHT) {
|
} else if (theme->window_label_text_justify == LAB_JUSTIFY_RIGHT) {
|
||||||
x += title_bg_width - buffer_width;
|
x += title_bg_width - title->width;
|
||||||
} else if (theme->window_label_text_justify == LAB_JUSTIFY_LEFT) {
|
} else if (theme->window_label_text_justify == LAB_JUSTIFY_LEFT) {
|
||||||
/* TODO: maybe add some theme x padding here? */
|
/* TODO: maybe add some theme x padding here? */
|
||||||
}
|
}
|
||||||
wlr_scene_node_set_position(part->node, x, y);
|
wlr_scene_node_set_position(&title->scene_buffer->node, x, y);
|
||||||
} FOR_EACH_END
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -438,23 +411,21 @@ ssd_update_title_positions(struct ssd *ssd, int offset_left, int offset_right)
|
||||||
static void
|
static void
|
||||||
get_title_offsets(struct ssd *ssd, int *offset_left, int *offset_right)
|
get_title_offsets(struct ssd *ssd, int *offset_left, int *offset_right)
|
||||||
{
|
{
|
||||||
struct ssd_sub_tree *subtree = &ssd->titlebar.active;
|
struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[SSD_ACTIVE];
|
||||||
int button_width = ssd->view->server->theme->window_button_width;
|
int button_width = ssd->view->server->theme->window_button_width;
|
||||||
int button_spacing = ssd->view->server->theme->window_button_spacing;
|
int button_spacing = ssd->view->server->theme->window_button_spacing;
|
||||||
int padding_width = ssd->view->server->theme->window_titlebar_padding_width;
|
int padding_width = ssd->view->server->theme->window_titlebar_padding_width;
|
||||||
*offset_left = padding_width;
|
*offset_left = padding_width;
|
||||||
*offset_right = padding_width;
|
*offset_right = padding_width;
|
||||||
|
|
||||||
struct title_button *b;
|
struct ssd_part_button *button;
|
||||||
wl_list_for_each(b, &rc.title_buttons_left, link) {
|
wl_list_for_each(button, &subtree->buttons_left, link) {
|
||||||
struct ssd_part *part = ssd_get_part(&subtree->parts, b->type);
|
if (button->base.node->enabled) {
|
||||||
if (part->node->enabled) {
|
|
||||||
*offset_left += button_width + button_spacing;
|
*offset_left += button_width + button_spacing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wl_list_for_each_reverse(b, &rc.title_buttons_right, link) {
|
wl_list_for_each(button, &subtree->buttons_right, link) {
|
||||||
struct ssd_part *part = ssd_get_part(&subtree->parts, b->type);
|
if (button->base.node->enabled) {
|
||||||
if (part->node->enabled) {
|
|
||||||
*offset_right += button_width + button_spacing;
|
*offset_right += button_width + button_spacing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -477,24 +448,17 @@ ssd_update_title(struct ssd *ssd)
|
||||||
struct ssd_state_title *state = &ssd->state.title;
|
struct ssd_state_title *state = &ssd->state.title;
|
||||||
bool title_unchanged = state->text && !strcmp(title, state->text);
|
bool title_unchanged = state->text && !strcmp(title, state->text);
|
||||||
|
|
||||||
const float *text_color;
|
|
||||||
const float bg_color[4] = {0, 0, 0, 0}; /* ignored */
|
|
||||||
struct font *font = NULL;
|
|
||||||
struct ssd_part *part;
|
|
||||||
struct ssd_sub_tree *subtree;
|
|
||||||
struct ssd_state_title_width *dstate;
|
|
||||||
int active;
|
|
||||||
|
|
||||||
int offset_left, offset_right;
|
int offset_left, offset_right;
|
||||||
get_title_offsets(ssd, &offset_left, &offset_right);
|
get_title_offsets(ssd, &offset_left, &offset_right);
|
||||||
int title_bg_width = view->current.width - offset_left - offset_right;
|
int title_bg_width = view->current.width - offset_left - offset_right;
|
||||||
|
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
enum ssd_active_state active;
|
||||||
active = (subtree == &ssd->titlebar.active) ?
|
FOR_EACH_ACTIVE_STATE(active) {
|
||||||
THEME_ACTIVE : THEME_INACTIVE;
|
struct ssd_titlebar_subtree *subtree = &ssd->titlebar.subtrees[active];
|
||||||
dstate = active ? &state->active : &state->inactive;
|
struct ssd_state_title_width *dstate = &state->dstates[active];
|
||||||
text_color = theme->window[active].label_text_color;
|
const float *text_color = theme->window[active].label_text_color;
|
||||||
font = active ? &rc.font_activewindow : &rc.font_inactivewindow;
|
struct font *font = active ?
|
||||||
|
&rc.font_activewindow : &rc.font_inactivewindow;
|
||||||
|
|
||||||
if (title_bg_width <= 0) {
|
if (title_bg_width <= 0) {
|
||||||
dstate->truncated = true;
|
dstate->truncated = true;
|
||||||
|
|
@ -507,15 +471,15 @@ ssd_update_title(struct ssd *ssd)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLE);
|
const float bg_color[4] = {0, 0, 0, 0}; /* ignored */
|
||||||
scaled_font_buffer_update(part->buffer, title, title_bg_width,
|
scaled_font_buffer_update(subtree->title, title,
|
||||||
font, text_color, bg_color);
|
title_bg_width, font,
|
||||||
|
text_color, bg_color);
|
||||||
|
|
||||||
/* And finally update the cache */
|
/* And finally update the cache */
|
||||||
dstate->width = part->buffer ? part->buffer->width : 0;
|
dstate->width = subtree->title->width;
|
||||||
dstate->truncated = title_bg_width <= dstate->width;
|
dstate->truncated = title_bg_width <= dstate->width;
|
||||||
|
}
|
||||||
} FOR_EACH_END
|
|
||||||
|
|
||||||
if (!title_unchanged) {
|
if (!title_unchanged) {
|
||||||
if (state->text) {
|
if (state->text) {
|
||||||
|
|
@ -530,12 +494,13 @@ void
|
||||||
ssd_update_button_hover(struct wlr_scene_node *node,
|
ssd_update_button_hover(struct wlr_scene_node *node,
|
||||||
struct ssd_hover_state *hover_state)
|
struct ssd_hover_state *hover_state)
|
||||||
{
|
{
|
||||||
struct ssd_button *button = NULL;
|
struct ssd_part_button *button = NULL;
|
||||||
|
|
||||||
if (node && node->data) {
|
if (node && node->data) {
|
||||||
struct node_descriptor *desc = node->data;
|
struct node_descriptor *desc = node->data;
|
||||||
if (desc->type == LAB_NODE_DESC_SSD_BUTTON) {
|
if (desc->type == LAB_NODE_DESC_SSD_PART) {
|
||||||
button = node_ssd_button_from_node(node);
|
button = button_try_from_ssd_part(
|
||||||
|
node_ssd_part_from_node(node));
|
||||||
if (button == hover_state->button) {
|
if (button == hover_state->button) {
|
||||||
/* Cursor is still on the same button */
|
/* Cursor is still on the same button */
|
||||||
return;
|
return;
|
||||||
|
|
@ -551,7 +516,7 @@ ssd_update_button_hover(struct wlr_scene_node *node,
|
||||||
}
|
}
|
||||||
if (button) {
|
if (button) {
|
||||||
update_button_state(button, LAB_BS_HOVERD, true);
|
update_button_state(button, LAB_BS_HOVERD, true);
|
||||||
hover_state->view = button->view;
|
hover_state->view = button->base.view;
|
||||||
hover_state->button = button;
|
hover_state->button = button;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -566,5 +531,3 @@ ssd_should_be_squared(struct ssd *ssd)
|
||||||
|| view->current.width < corner_width * 2)
|
|| view->current.width < corner_width * 2)
|
||||||
&& view->maximized != VIEW_AXIS_BOTH;
|
&& view->maximized != VIEW_AXIS_BOTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef FOR_EACH_STATE
|
|
||||||
|
|
|
||||||
115
src/ssd/ssd.c
115
src/ssd/ssd.c
|
|
@ -85,8 +85,8 @@ ssd_max_extents(struct view *view)
|
||||||
* (generally rc.resize_corner_range, but clipped to view size) of the view
|
* (generally rc.resize_corner_range, but clipped to view size) of the view
|
||||||
* bounds, so check the cursor against the view here.
|
* bounds, so check the cursor against the view here.
|
||||||
*/
|
*/
|
||||||
static enum ssd_part_type
|
enum ssd_part_type
|
||||||
get_resizing_type(const struct ssd *ssd, struct wlr_cursor *cursor)
|
ssd_get_resizing_type(const struct ssd *ssd, struct wlr_cursor *cursor)
|
||||||
{
|
{
|
||||||
struct view *view = ssd ? ssd->view : NULL;
|
struct view *view = ssd ? ssd->view : NULL;
|
||||||
if (!view || !cursor || !view->ssd_mode || view->fullscreen) {
|
if (!view || !cursor || !view->ssd_mode || view->fullscreen) {
|
||||||
|
|
@ -136,75 +136,6 @@ get_resizing_type(const struct ssd *ssd, struct wlr_cursor *cursor)
|
||||||
return LAB_SSD_NONE;
|
return LAB_SSD_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ssd_part_type
|
|
||||||
ssd_get_part_type(const struct ssd *ssd, struct wlr_scene_node *node,
|
|
||||||
struct wlr_cursor *cursor)
|
|
||||||
{
|
|
||||||
if (!node) {
|
|
||||||
return LAB_SSD_NONE;
|
|
||||||
} else if (node->type == WLR_SCENE_NODE_BUFFER
|
|
||||||
&& lab_wlr_surface_from_node(node)) {
|
|
||||||
return LAB_SSD_CLIENT;
|
|
||||||
} else if (!ssd) {
|
|
||||||
return LAB_SSD_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct wl_list *part_list = NULL;
|
|
||||||
struct wlr_scene_tree *grandparent =
|
|
||||||
node->parent ? node->parent->node.parent : NULL;
|
|
||||||
struct wlr_scene_tree *greatgrandparent =
|
|
||||||
grandparent ? grandparent->node.parent : NULL;
|
|
||||||
|
|
||||||
/* active titlebar */
|
|
||||||
if (node->parent == ssd->titlebar.active.tree) {
|
|
||||||
part_list = &ssd->titlebar.active.parts;
|
|
||||||
} else if (grandparent == ssd->titlebar.active.tree) {
|
|
||||||
part_list = &ssd->titlebar.active.parts;
|
|
||||||
} else if (greatgrandparent == ssd->titlebar.active.tree) {
|
|
||||||
part_list = &ssd->titlebar.active.parts;
|
|
||||||
|
|
||||||
/* extents */
|
|
||||||
} else if (node->parent == ssd->extents.tree) {
|
|
||||||
part_list = &ssd->extents.parts;
|
|
||||||
|
|
||||||
/* active border */
|
|
||||||
} else if (node->parent == ssd->border.active.tree) {
|
|
||||||
part_list = &ssd->border.active.parts;
|
|
||||||
|
|
||||||
/* inactive titlebar */
|
|
||||||
} else if (node->parent == ssd->titlebar.inactive.tree) {
|
|
||||||
part_list = &ssd->titlebar.inactive.parts;
|
|
||||||
} else if (grandparent == ssd->titlebar.inactive.tree) {
|
|
||||||
part_list = &ssd->titlebar.inactive.parts;
|
|
||||||
} else if (greatgrandparent == ssd->titlebar.inactive.tree) {
|
|
||||||
part_list = &ssd->titlebar.inactive.parts;
|
|
||||||
|
|
||||||
/* inactive border */
|
|
||||||
} else if (node->parent == ssd->border.inactive.tree) {
|
|
||||||
part_list = &ssd->border.inactive.parts;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ssd_part_type part_type = LAB_SSD_NONE;
|
|
||||||
|
|
||||||
if (part_list) {
|
|
||||||
struct ssd_part *part;
|
|
||||||
wl_list_for_each(part, part_list, link) {
|
|
||||||
if (node == part->node) {
|
|
||||||
part_type = part->type;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (part_type == LAB_SSD_NONE) {
|
|
||||||
return part_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Perform cursor-based context checks */
|
|
||||||
enum ssd_part_type resizing_type = get_resizing_type(ssd, cursor);
|
|
||||||
return resizing_type != LAB_SSD_NONE ? resizing_type : part_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum lab_edge
|
enum lab_edge
|
||||||
ssd_resize_edges(enum ssd_part_type type)
|
ssd_resize_edges(enum ssd_part_type type)
|
||||||
{
|
{
|
||||||
|
|
@ -238,6 +169,7 @@ ssd_create(struct view *view, bool active)
|
||||||
|
|
||||||
ssd->view = view;
|
ssd->view = view;
|
||||||
ssd->tree = wlr_scene_tree_create(view->scene_tree);
|
ssd->tree = wlr_scene_tree_create(view->scene_tree);
|
||||||
|
attach_ssd_part(LAB_SSD_NONE, view, &ssd->tree->node);
|
||||||
wlr_scene_node_lower_to_bottom(&ssd->tree->node);
|
wlr_scene_node_lower_to_bottom(&ssd->tree->node);
|
||||||
ssd->titlebar.height = view->server->theme->titlebar_height;
|
ssd->titlebar.height = view->server->theme->titlebar_height;
|
||||||
ssd_shadow_create(ssd);
|
ssd_shadow_create(ssd);
|
||||||
|
|
@ -438,17 +370,19 @@ ssd_set_active(struct ssd *ssd, bool active)
|
||||||
if (!ssd) {
|
if (!ssd) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wlr_scene_node_set_enabled(&ssd->border.active.tree->node, active);
|
enum ssd_active_state active_state;
|
||||||
wlr_scene_node_set_enabled(&ssd->titlebar.active.tree->node, active);
|
FOR_EACH_ACTIVE_STATE(active_state) {
|
||||||
if (ssd->shadow.active.tree) {
|
|
||||||
wlr_scene_node_set_enabled(
|
wlr_scene_node_set_enabled(
|
||||||
&ssd->shadow.active.tree->node, active);
|
&ssd->border.subtrees[active_state].tree->node,
|
||||||
}
|
active == active_state);
|
||||||
wlr_scene_node_set_enabled(&ssd->border.inactive.tree->node, !active);
|
|
||||||
wlr_scene_node_set_enabled(&ssd->titlebar.inactive.tree->node, !active);
|
|
||||||
if (ssd->shadow.inactive.tree) {
|
|
||||||
wlr_scene_node_set_enabled(
|
wlr_scene_node_set_enabled(
|
||||||
&ssd->shadow.inactive.tree->node, !active);
|
&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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -474,10 +408,7 @@ ssd_enable_keybind_inhibit_indicator(struct ssd *ssd, bool enable)
|
||||||
float *color = enable
|
float *color = enable
|
||||||
? rc.theme->window_toggled_keybinds_color
|
? rc.theme->window_toggled_keybinds_color
|
||||||
: rc.theme->window[THEME_ACTIVE].border_color;
|
: rc.theme->window[THEME_ACTIVE].border_color;
|
||||||
|
wlr_scene_rect_set_color(ssd->border.subtrees[SSD_ACTIVE].top, color);
|
||||||
struct ssd_part *part = ssd_get_part(&ssd->border.active.parts, LAB_SSD_PART_TOP);
|
|
||||||
struct wlr_scene_rect *rect = wlr_scene_rect_from_node(part->node);
|
|
||||||
wlr_scene_rect_set_color(rect, color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ssd_hover_state *
|
struct ssd_hover_state *
|
||||||
|
|
@ -487,15 +418,15 @@ ssd_hover_state_new(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ssd_part_type
|
enum ssd_part_type
|
||||||
ssd_button_get_type(const struct ssd_button *button)
|
ssd_part_get_type(const struct ssd_part *part)
|
||||||
{
|
{
|
||||||
return button ? button->type : LAB_SSD_NONE;
|
return part ? part->type : LAB_SSD_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct view *
|
struct view *
|
||||||
ssd_button_get_view(const struct ssd_button *button)
|
ssd_part_get_view(const struct ssd_part *part)
|
||||||
{
|
{
|
||||||
return button ? button->view : NULL;
|
return part ? part->view : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -516,16 +447,16 @@ ssd_debug_get_node_name(const struct ssd *ssd, struct wlr_scene_node *node)
|
||||||
if (node == &ssd->tree->node) {
|
if (node == &ssd->tree->node) {
|
||||||
return "view->ssd";
|
return "view->ssd";
|
||||||
}
|
}
|
||||||
if (node == &ssd->titlebar.active.tree->node) {
|
if (node == &ssd->titlebar.subtrees[SSD_ACTIVE].tree->node) {
|
||||||
return "titlebar.active";
|
return "titlebar.active";
|
||||||
}
|
}
|
||||||
if (node == &ssd->titlebar.inactive.tree->node) {
|
if (node == &ssd->titlebar.subtrees[SSD_INACTIVE].tree->node) {
|
||||||
return "titlebar.inactive";
|
return "titlebar.inactive";
|
||||||
}
|
}
|
||||||
if (node == &ssd->border.active.tree->node) {
|
if (node == &ssd->border.subtrees[SSD_ACTIVE].tree->node) {
|
||||||
return "border.active";
|
return "border.active";
|
||||||
}
|
}
|
||||||
if (node == &ssd->border.inactive.tree->node) {
|
if (node == &ssd->border.subtrees[SSD_INACTIVE].tree->node) {
|
||||||
return "border.inactive";
|
return "border.inactive";
|
||||||
}
|
}
|
||||||
if (node == &ssd->extents.tree->node) {
|
if (node == &ssd->extents.tree->node) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue