#include "cursor.h"
#include "config/keybind.h"
#include "config/rcxml.h"
-#include "ssd.h"
#if HAVE_NLS
#include <libintl.h>
#include <locale.h>
/* SSD state */
struct view *focused_view;
- struct ssd_hover_state ssd_hover_state;
+ struct ssd_hover_state *ssd_hover_state;
/* Tree for all non-layer xdg/xwayland-shell surfaces */
struct wlr_scene_tree *view_tree;
};
struct ssd {
+ struct view *view;
struct wlr_scene_tree *tree;
/*
struct wlr_scene_node *node;
};
-/* Public SSD API */
-void ssd_create(struct view *view, bool active);
-void ssd_set_active(struct view *view, bool active);
-void ssd_update_title(struct view *view);
-void ssd_update_geometry(struct view *view);
-void ssd_destroy(struct view *view);
+/*
+ * Public SSD API
+ *
+ * For convenience in dealing with non-SSD views, this API allows NULL
+ * ssd/button/node arguments and attempts to do something sensible in
+ * that case (e.g. no-op/return default values).
+ *
+ * NULL scene/view arguments are not allowed.
+ */
+struct ssd *ssd_create(struct view *view, bool active);
+struct border ssd_get_margin(const struct ssd *ssd);
+void ssd_set_active(struct ssd *ssd, bool active);
+void ssd_update_title(struct ssd *ssd);
+void ssd_update_geometry(struct ssd *ssd);
+void ssd_destroy(struct ssd *ssd);
+
+struct ssd_hover_state *ssd_hover_state_new(void);
void ssd_update_button_hover(struct wlr_scene_node *node,
struct ssd_hover_state *hover_state);
#include <stdint.h>
#include <wayland-util.h>
#include <wlr/util/box.h>
-#include "ssd.h"
/*
* In labwc, a view is a container for surfaces which can be moved around by
#endif
};
+struct view;
struct view_impl {
void (*configure)(struct view *view, struct wlr_box geo);
void (*close)(struct view *view);
uint32_t configure_serial;
} pending_move_resize;
- struct ssd ssd;
+ struct ssd *ssd;
struct wlr_foreign_toplevel_handle_v1 *toplevel_handle;
struct wl_listener toplevel_handle_request_maximize;
if (!view) {
return;
}
- enum ssd_part_type type = ssd_at(&view->ssd, server->scene,
+ enum ssd_part_type type = ssd_at(view->ssd, server->scene,
server->seat.cursor->x, server->seat.cursor->y);
if (type == LAB_SSD_BUTTON_WINDOW_MENU) {
force_menu_top_left = true;
struct seat *seat = &server->seat;
struct wlr_seat *wlr_seat = seat->seat;
- ssd_update_button_hover(ctx->node, &server->ssd_hover_state);
+ ssd_update_button_hover(ctx->node, server->ssd_hover_state);
if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
/*
return "view->scene_node";
}
if (view) {
- return ssd_debug_get_node_name(&view->ssd, node);
+ return ssd_debug_get_node_name(view->ssd, node);
}
return NULL;
}
if ((IGNORE_MENU && node == &server->menu_tree->node)
|| (IGNORE_SSD && view
- && ssd_debug_is_root_node(&view->ssd, node))) {
+ && ssd_debug_is_root_node(view->ssd, node))) {
printf("%*c%s\n", pos + 4 + INDENT_SIZE, ' ', "<skipping children>");
return;
}
case LAB_NODE_DESC_VIEW:
case LAB_NODE_DESC_XDG_POPUP:
ret.view = desc->data;
- ret.type = ssd_get_part_type(&ret.view->ssd, ret.node);
+ ret.type = ssd_get_part_type(ret.view->ssd, ret.node);
if (ret.type == LAB_SSD_CLIENT) {
ret.surface = lab_wlr_surface_from_node(ret.node);
}
struct wlr_box tgeom = {.x = *x, .y = *y, .width = view->w,
.height = view->h};
struct output *output;
- struct border border = view->ssd.margin;
+ struct border border = ssd_get_margin(view->ssd);
struct edges view_edges; /* The edges of the current view */
struct edges target_edges; /* The desired edges */
struct edges other_edges; /* The edges of the monitor/other view */
.height = view->h};
struct wlr_box tgeom = {.x = new_view_geo->x, .y = new_view_geo->y,
.width = new_view_geo->width, .height = new_view_geo->height};
- struct border border = view->ssd.margin;
+ struct border border = ssd_get_margin(view->ssd);
struct edges view_edges; /* The edges of the current view */
struct edges target_edges; /* The desired edges */
struct edges other_edges; /* The edges of the monitor/other view */
wl_list_init(&server->views);
wl_list_init(&server->unmanaged_surfaces);
+ server->ssd_hover_state = ssd_hover_state_new();
+
server->scene = wlr_scene_create();
if (!server->scene) {
wlr_log(WLR_ERROR, "unable to create scene");
*/
#include <assert.h>
+#include "common/mem.h"
#include "common/scene-helpers.h"
#include "labwc.h"
#include "ssd.h"
struct border
ssd_thickness(struct view *view)
{
+ assert(view);
/*
* Check preconditions for displaying SSD. Note that this
* needs to work even before ssd_create() has been called.
struct wlr_box
ssd_max_extents(struct view *view)
{
+ assert(view);
struct border border = ssd_thickness(view);
return (struct wlr_box){
.x = view->x - border.left,
} else if (node->type == WLR_SCENE_NODE_BUFFER
&& lab_wlr_surface_from_node(node)) {
return LAB_SSD_CLIENT;
- } else if (!ssd->tree) {
+ } else if (!ssd) {
return LAB_SSD_NONE;
}
enum ssd_part_type
ssd_at(const struct ssd *ssd, struct wlr_scene *scene, double lx, double ly)
{
+ assert(scene);
double sx, sy;
struct wlr_scene_node *node = wlr_scene_node_at(
&scene->tree.node, lx, ly, &sx, &sy);
}
}
-void
+struct ssd *
ssd_create(struct view *view, bool active)
{
- struct ssd *ssd = &view->ssd;
- assert(!ssd->tree);
+ assert(view);
+ struct ssd *ssd = znew(*ssd);
+ ssd->view = view;
ssd->tree = wlr_scene_tree_create(view->scene_tree);
wlr_scene_node_lower_to_bottom(&ssd->tree->node);
ssd_extents_create(ssd);
ssd_border_create(ssd);
ssd_titlebar_create(ssd);
ssd->margin = ssd_thickness(view);
- ssd_set_active(view, active);
+ ssd_set_active(ssd, active);
ssd->state.width = view->w;
ssd->state.height = view->h;
ssd->state.x = view->x;
ssd->state.y = view->y;
+
+ return ssd;
+}
+
+struct border
+ssd_get_margin(const struct ssd *ssd)
+{
+ return ssd ? ssd->margin : (struct border){ 0 };
}
void
-ssd_update_geometry(struct view *view)
+ssd_update_geometry(struct ssd *ssd)
{
- struct ssd *ssd = &view->ssd;
- if (!ssd->tree) {
+ if (!ssd) {
return;
}
+ struct view *view = ssd->view;
if (view->w == ssd->state.width && view->h == ssd->state.height) {
if (view->x != ssd->state.x || view->y != ssd->state.y) {
/* Dynamically resize extents based on position and usable_area */
}
void
-ssd_destroy(struct view *view)
+ssd_destroy(struct ssd *ssd)
{
- struct ssd *ssd = &view->ssd;
- if (!ssd->tree) {
+ if (!ssd) {
return;
}
/* Maybe reset hover view */
+ struct view *view = ssd->view;
struct ssd_hover_state *hover_state;
- hover_state = &view->server->ssd_hover_state;
+ hover_state = view->server->ssd_hover_state;
if (hover_state->view == view) {
hover_state->view = NULL;
hover_state->node = NULL;
ssd_border_destroy(ssd);
ssd_extents_destroy(ssd);
wlr_scene_node_destroy(&ssd->tree->node);
- ssd->tree = NULL;
- ssd->margin = (struct border){ 0 };
+
+ free(ssd);
}
bool
}
void
-ssd_set_active(struct view *view, bool active)
+ssd_set_active(struct ssd *ssd, bool active)
{
- struct ssd *ssd = &view->ssd;
- if (!ssd->tree) {
+ if (!ssd) {
return;
}
wlr_scene_node_set_enabled(&ssd->border.active.tree->node, active);
wlr_scene_node_set_enabled(&ssd->titlebar.inactive.tree->node, !active);
}
+struct ssd_hover_state *
+ssd_hover_state_new(void)
+{
+ return znew(struct ssd_hover_state);
+}
+
bool
ssd_debug_is_root_node(const struct ssd *ssd, struct wlr_scene_node *node)
{
- if (!ssd->tree || !node) {
+ if (!ssd || !node) {
return false;
}
return node == &ssd->tree->node;
const char *
ssd_debug_get_node_name(const struct ssd *ssd, struct wlr_scene_node *node)
{
- if (!ssd->tree || !node) {
+ if (!ssd || !node) {
return NULL;
}
if (node == &ssd->tree->node) {
void
ssd_border_create(struct ssd *ssd)
{
- struct view *view = wl_container_of(ssd, view, ssd);
+ struct view *view = ssd->view;
struct theme *theme = view->server->theme;
int width = view->w;
int height = view->h;
void
ssd_border_update(struct ssd *ssd)
{
- struct view *view = wl_container_of(ssd, view, ssd);
+ struct view *view = ssd->view;
struct theme *theme = view->server->theme;
int width = view->w;
void
ssd_extents_create(struct ssd *ssd)
{
- struct view *view = wl_container_of(ssd, view, ssd);
+ struct view *view = ssd->view;
struct theme *theme = view->server->theme;
struct wl_list *part_list = &ssd->extents.parts;
int extended_area = EXTENDED_AREA;
void
ssd_extents_update(struct ssd *ssd)
{
- struct view *view = wl_container_of(ssd, view, ssd);
+ struct view *view = ssd->view;
if (view->maximized || view->fullscreen) {
wlr_scene_node_set_enabled(&ssd->extents.tree->node, false);
return;
void
ssd_titlebar_create(struct ssd *ssd)
{
- struct view *view = wl_container_of(ssd, view, ssd);
+ struct view *view = ssd->view;
struct theme *theme = view->server->theme;
int width = view->w;
corner_top_right, close_button_unpressed,
width - BUTTON_WIDTH * 1, view);
} FOR_EACH_END
- ssd_update_title(view);
+ ssd_update_title(ssd);
}
static bool
void
ssd_titlebar_update(struct ssd *ssd)
{
- struct view *view = wl_container_of(ssd, view, ssd);
+ struct view *view = ssd->view;
int width = view->w;
if (width == ssd->state.width) {
return;
}
}
} FOR_EACH_END
- ssd_update_title(view);
+ ssd_update_title(ssd);
}
void
static void
ssd_update_title_positions(struct ssd *ssd)
{
- struct view *view = wl_container_of(ssd, view, ssd);
+ struct view *view = ssd->view;
struct theme *theme = view->server->theme;
int width = view->w;
int title_bg_width = width - BUTTON_WIDTH * BUTTON_COUNT;
}
void
-ssd_update_title(struct view *view)
+ssd_update_title(struct ssd *ssd)
{
- struct ssd *ssd = &view->ssd;
- if (!ssd->tree) {
+ if (!ssd) {
return;
}
+ struct view *view = ssd->view;
char *title = (char *)view_get_string_prop(view, "title");
if (!title || !*title) {
return;
break;
}
- struct border margin = view->ssd.margin;
+ struct border margin = ssd_get_margin(view->ssd);
struct wlr_box dst = {
.x = x_offset + usable.x + margin.left,
.y = y_offset + usable.y + margin.top,
static void
_view_set_activated(struct view *view, bool activated)
{
- if (view->ssd.tree) {
- ssd_set_active(view, activated);
- }
+ ssd_set_active(view->ssd, activated);
if (view->impl->set_activated) {
view->impl->set_activated(view, activated);
}
assert(view);
wlr_scene_node_set_position(&view->scene_tree->node, view->x, view->y);
view_discover_output(view);
- ssd_update_geometry(view);
+ ssd_update_geometry(view->ssd);
cursor_update_focus(view->server);
}
return false;
}
- struct border margin = view->ssd.margin;
+ struct border margin = ssd_get_margin(view->ssd);
struct wlr_box usable = output_usable_area_in_layout_coords(output);
int width = w + margin.left + margin.right;
int height = h + margin.top + margin.bottom;
}
}
+static void
+decorate(struct view *view)
+{
+ if (!view->ssd) {
+ view->ssd = ssd_create(view,
+ view == view->server->focused_view);
+ }
+}
+
+static void
+undecorate(struct view *view)
+{
+ ssd_destroy(view->ssd);
+ view->ssd = NULL;
+}
+
void
view_set_decorations(struct view *view, bool decorations)
{
*/
view->ssd_enabled = decorations;
if (decorations) {
- ssd_create(view, view == view->server->focused_view);
+ decorate(view);
} else {
- ssd_destroy(view);
+ undecorate(view);
}
if (view->maximized) {
view_apply_maximized_geometry(view);
}
/* Hide decorations when going fullscreen */
if (view->ssd_enabled) {
- ssd_destroy(view);
+ undecorate(view);
}
view->fullscreen = wlr_output;
view_apply_fullscreen_geometry(view, view->fullscreen);
}
/* Re-show decorations when no longer fullscreen */
if (view->ssd_enabled) {
- ssd_create(view, view == view->server->focused_view);
+ decorate(view);
}
}
return;
}
- struct border margin = view->ssd.margin;
+ struct border margin = ssd_get_margin(view->ssd);
struct wlr_box usable = output_usable_area_in_layout_coords(output);
if (usable.height == output->wlr_output->height
&& output->wlr_output->scale != 1) {
if (!view->toplevel_handle || !title) {
return;
}
- ssd_update_title(view);
+ ssd_update_title(view->ssd);
wlr_foreign_toplevel_handle_v1_set_title(view->toplevel_handle, title);
}
{
assert(view);
if (view->ssd_enabled && !view->fullscreen) {
- ssd_destroy(view);
- ssd_create(view, view == view->server->focused_view);
+ undecorate(view);
+ decorate(view);
}
}
}
osd_on_view_destroy(view);
+ undecorate(view);
if (view->scene_tree) {
- ssd_destroy(view);
wlr_scene_node_destroy(&view->scene_tree->node);
view->scene_tree = NULL;
}
view->x = center_x - xdg_surface->current.geometry.width / 2;
view->y = center_y - xdg_surface->current.geometry.height / 2;
}
- view->x += view->ssd.margin.left;
- view->y += view->ssd.margin.top;
+
+ struct border margin = ssd_get_margin(view->ssd);
+ view->x += margin.left;
+ view->y += margin.top;
}
static const char *