mirror of
https://github.com/labwc/labwc.git
synced 2026-03-31 07:11:19 -04:00
Convert SSD to scene nodes
This commit is contained in:
parent
f2d40a8d69
commit
5862b65f89
23 changed files with 1134 additions and 557 deletions
|
|
@ -27,7 +27,7 @@
|
||||||
#define __LABWC_BUFFER_H
|
#define __LABWC_BUFFER_H
|
||||||
|
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include "labwc.h"
|
#include <wlr/types/wlr_buffer.h>
|
||||||
|
|
||||||
struct lab_data_buffer {
|
struct lab_data_buffer {
|
||||||
struct wlr_buffer base;
|
struct wlr_buffer base;
|
||||||
|
|
|
||||||
5
include/common/scene-helpers.h
Normal file
5
include/common/scene-helpers.h
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
|
||||||
|
struct wlr_scene_rect *lab_wlr_scene_get_rect(struct wlr_scene_node *node);
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
#ifndef __LABWC_MOUSEBIND_H
|
#ifndef __LABWC_MOUSEBIND_H
|
||||||
#define __LABWC_MOUSEBIND_H
|
#define __LABWC_MOUSEBIND_H
|
||||||
|
|
||||||
#include "ssd.h"
|
|
||||||
#include <wayland-util.h>
|
#include <wayland-util.h>
|
||||||
|
#include "ssd.h"
|
||||||
|
#include "config/keybind.h"
|
||||||
|
|
||||||
enum mouse_event {
|
enum mouse_event {
|
||||||
MOUSE_ACTION_NONE = 0,
|
MOUSE_ACTION_NONE = 0,
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,10 @@ struct server {
|
||||||
struct wlr_box grab_box;
|
struct wlr_box grab_box;
|
||||||
uint32_t resize_edges;
|
uint32_t resize_edges;
|
||||||
|
|
||||||
|
/* SSD state */
|
||||||
|
struct view *ssd_focused_view;
|
||||||
|
struct ssd_hover_state ssd_hover_state;
|
||||||
|
|
||||||
struct wlr_scene_tree *osd_tree;
|
struct wlr_scene_tree *osd_tree;
|
||||||
struct wlr_scene_tree *menu_tree;
|
struct wlr_scene_tree *menu_tree;
|
||||||
|
|
||||||
|
|
@ -272,17 +276,7 @@ struct view {
|
||||||
uint32_t configure_serial;
|
uint32_t configure_serial;
|
||||||
} pending_move_resize;
|
} pending_move_resize;
|
||||||
|
|
||||||
struct {
|
struct ssd ssd;
|
||||||
bool enabled;
|
|
||||||
struct wl_list parts;
|
|
||||||
struct wlr_box box; /* remember geo so we know when to update */
|
|
||||||
} ssd;
|
|
||||||
|
|
||||||
/* The title is unique to each view, so we store these here */
|
|
||||||
struct {
|
|
||||||
struct wlr_texture *active;
|
|
||||||
struct wlr_texture *inactive;
|
|
||||||
} title;
|
|
||||||
|
|
||||||
struct wlr_foreign_toplevel_handle_v1 *toplevel_handle;
|
struct wlr_foreign_toplevel_handle_v1 *toplevel_handle;
|
||||||
struct wl_listener toplevel_handle_request_maximize;
|
struct wl_listener toplevel_handle_request_maximize;
|
||||||
|
|
|
||||||
172
include/ssd.h
172
include/ssd.h
|
|
@ -2,6 +2,22 @@
|
||||||
#ifndef __LABWC_SSD_H
|
#ifndef __LABWC_SSD_H
|
||||||
#define __LABWC_SSD_H
|
#define __LABWC_SSD_H
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
#include <wlr/util/box.h>
|
||||||
|
|
||||||
|
#define SSD_HEIGHT 26 /* TODO: use theme->title_height */
|
||||||
|
#define BUTTON_COUNT 4
|
||||||
|
#define BUTTON_WIDTH 26
|
||||||
|
#define EXTENDED_AREA 20
|
||||||
|
|
||||||
|
#define FOR_EACH(tmp, ...) \
|
||||||
|
{ \
|
||||||
|
__typeof__(tmp) _x[] = { __VA_ARGS__, NULL }; \
|
||||||
|
size_t _i = 0; \
|
||||||
|
for ((tmp) = _x[_i]; _i < sizeof(_x) / sizeof(_x[0]) - 1; (tmp) = _x[++_i])
|
||||||
|
|
||||||
|
#define FOR_EACH_END }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sequence these according to the order they should be processed for
|
* Sequence these according to the order they should be processed for
|
||||||
* press and hover events. Bear in mind that some of their respective
|
* press and hover events. Bear in mind that some of their respective
|
||||||
|
|
@ -32,51 +48,139 @@ enum ssd_part_type {
|
||||||
LAB_SSD_END_MARKER
|
LAB_SSD_END_MARKER
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/* Forward declare arguments */
|
||||||
* Defer including labwc.h because it is using enum ssd_part_type.
|
struct view;
|
||||||
* This is an issue for headers like mousebind.h which only includes
|
struct wl_list;
|
||||||
* ssd.h but does not include labwc.h.
|
struct wlr_box;
|
||||||
*/
|
struct wlr_scene_tree;
|
||||||
#include "labwc.h"
|
|
||||||
|
struct ssd_sub_tree {
|
||||||
|
struct wlr_scene_tree *tree;
|
||||||
|
struct wl_list parts; /* ssd_part::link */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ssd_state_title_width {
|
||||||
|
int width;
|
||||||
|
bool truncated;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ssd_state_title {
|
||||||
|
char *text;
|
||||||
|
struct ssd_state_title_width active;
|
||||||
|
struct ssd_state_title_width inactive;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ssd {
|
||||||
|
bool enabled;
|
||||||
|
struct wlr_scene_tree *tree;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cache for current values.
|
||||||
|
* Used to detect actual changes so we
|
||||||
|
* don't update things we don't have to.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
struct ssd_state_title title;
|
||||||
|
} state;
|
||||||
|
|
||||||
|
/* An invisble area around the view which allows resizing */
|
||||||
|
struct ssd_sub_tree extents;
|
||||||
|
|
||||||
|
/* The top of the view, containing buttons, title, .. */
|
||||||
|
struct {
|
||||||
|
/* struct wlr_scene_tree *tree; unused for now */
|
||||||
|
struct ssd_sub_tree active;
|
||||||
|
struct ssd_sub_tree inactive;
|
||||||
|
} titlebar;
|
||||||
|
|
||||||
|
/* Borders allow resizing as well */
|
||||||
|
struct {
|
||||||
|
/* struct wlr_scene_tree *tree; unused for now */
|
||||||
|
struct ssd_sub_tree active;
|
||||||
|
struct ssd_sub_tree inactive;
|
||||||
|
} border;
|
||||||
|
};
|
||||||
|
|
||||||
struct ssd_part {
|
struct ssd_part {
|
||||||
struct wlr_box box;
|
|
||||||
enum ssd_part_type type;
|
enum ssd_part_type type;
|
||||||
|
|
||||||
/*
|
/* Buffer pointer. May be NULL */
|
||||||
* The texture pointers are often held in other places such as the
|
struct lab_data_buffer *buffer;
|
||||||
* theme struct, so here we use ** in order to keep the code
|
|
||||||
* simple and avoid updating pointers as textures change.
|
|
||||||
*/
|
|
||||||
struct {
|
|
||||||
struct wlr_texture **active;
|
|
||||||
struct wlr_texture **inactive;
|
|
||||||
} texture;
|
|
||||||
|
|
||||||
/*
|
/* This part represented in scene graph */
|
||||||
* If a part does not contain textures, it'll just be rendered as a
|
struct wlr_scene_node *node;
|
||||||
* rectangle with the following colors.
|
|
||||||
*/
|
|
||||||
struct {
|
|
||||||
float *active;
|
|
||||||
float *inactive;
|
|
||||||
} color;
|
|
||||||
|
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct view;
|
struct ssd_hover_state {
|
||||||
|
struct view *view;
|
||||||
|
enum ssd_part_type type;
|
||||||
|
struct wlr_scene_node *node;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Public SSD API */
|
||||||
|
void ssd_create(struct view *view);
|
||||||
|
void ssd_hide(struct view *view);
|
||||||
|
void ssd_set_active(struct view *view);
|
||||||
|
void ssd_update_title(struct view *view);
|
||||||
|
void ssd_update_geometry(struct view *view);
|
||||||
|
void ssd_reload(struct view *view);
|
||||||
|
void ssd_destroy(struct view *view);
|
||||||
|
/* Returns hover overlay node so it can be disabled later on */
|
||||||
|
struct wlr_scene_node *ssd_button_hover_enable(
|
||||||
|
struct view *view, enum ssd_part_type type);
|
||||||
|
|
||||||
|
/* Public SSD helpers */
|
||||||
|
enum ssd_part_type ssd_at(struct view *view, double lx, double ly);
|
||||||
|
enum ssd_part_type ssd_get_part_type(
|
||||||
|
struct view *view, struct wlr_scene_node *node);
|
||||||
|
uint32_t ssd_resize_edges(enum ssd_part_type type);
|
||||||
|
bool ssd_is_button(enum ssd_part_type type);
|
||||||
|
bool ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate);
|
||||||
|
|
||||||
|
/* SSD internal helpers to create various SSD elements */
|
||||||
|
/* TODO: Replace some common args with a struct */
|
||||||
|
struct ssd_part *add_scene_part(
|
||||||
|
struct wl_list *part_list, enum ssd_part_type type);
|
||||||
|
struct ssd_part *add_scene_rect(
|
||||||
|
struct wl_list *list, enum ssd_part_type type,
|
||||||
|
struct wlr_scene_node *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_node *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_node *parent, float *bg_color,
|
||||||
|
struct wlr_buffer *icon_buffer, int x);
|
||||||
|
struct ssd_part *add_scene_button_corner(
|
||||||
|
struct wl_list *part_list, enum ssd_part_type type,
|
||||||
|
struct wlr_scene_node *parent, struct wlr_buffer *corner_buffer,
|
||||||
|
struct wlr_buffer *icon_buffer, int x);
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
void ssd_titlebar_create(struct view *view);
|
||||||
|
void ssd_titlebar_update(struct view *view);
|
||||||
|
void ssd_titlebar_destroy(struct view *view);
|
||||||
|
|
||||||
|
void ssd_border_create(struct view *view);
|
||||||
|
void ssd_border_update(struct view *view);
|
||||||
|
void ssd_border_destroy(struct view *view);
|
||||||
|
|
||||||
|
void ssd_extents_create(struct view *view);
|
||||||
|
void ssd_extents_update(struct view *view);
|
||||||
|
void ssd_extents_destroy(struct view *view);
|
||||||
|
|
||||||
|
/* TODO: clean up / update */
|
||||||
struct border ssd_thickness(struct view *view);
|
struct border ssd_thickness(struct view *view);
|
||||||
struct wlr_box ssd_max_extents(struct view *view);
|
struct wlr_box ssd_max_extents(struct view *view);
|
||||||
struct wlr_box ssd_visible_box(struct view *view, enum ssd_part_type type);
|
|
||||||
enum ssd_part_type ssd_at(struct view *view, double lx, double ly);
|
|
||||||
uint32_t ssd_resize_edges(enum ssd_part_type type);
|
|
||||||
void ssd_update_title(struct view *view);
|
|
||||||
void ssd_create(struct view *view);
|
|
||||||
void ssd_destroy(struct view *view);
|
|
||||||
void ssd_update_geometry(struct view *view, bool force);
|
|
||||||
bool ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate);
|
|
||||||
bool ssd_is_button(enum ssd_part_type type);
|
|
||||||
|
|
||||||
#endif /* __LABWC_SSD_H */
|
#endif /* __LABWC_SSD_H */
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <drm_fourcc.h>
|
#include <drm_fourcc.h>
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ labwc_sources += files(
|
||||||
'font.c',
|
'font.c',
|
||||||
'grab-file.c',
|
'grab-file.c',
|
||||||
'nodename.c',
|
'nodename.c',
|
||||||
|
'scene-helpers.c',
|
||||||
'spawn.c',
|
'spawn.c',
|
||||||
'string-helpers.c',
|
'string-helpers.c',
|
||||||
'zfree.c',
|
'zfree.c',
|
||||||
|
|
|
||||||
11
src/common/scene-helpers.c
Normal file
11
src/common/scene-helpers.c
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <wlr/types/wlr_scene.h>
|
||||||
|
|
||||||
|
struct wlr_scene_rect *
|
||||||
|
lab_wlr_scene_get_rect(struct wlr_scene_node *node)
|
||||||
|
{
|
||||||
|
assert(node->type == WLR_SCENE_NODE_RECT);
|
||||||
|
return (struct wlr_scene_rect *)node;
|
||||||
|
}
|
||||||
24
src/cursor.c
24
src/cursor.c
|
|
@ -178,7 +178,6 @@ static void
|
||||||
process_cursor_motion(struct server *server, uint32_t time)
|
process_cursor_motion(struct server *server, uint32_t time)
|
||||||
{
|
{
|
||||||
static bool cursor_name_set_by_server;
|
static bool cursor_name_set_by_server;
|
||||||
static enum ssd_part_type last_button_hover = LAB_SSD_NONE;
|
|
||||||
|
|
||||||
/* If the mode is non-passthrough, delegate to those functions. */
|
/* If the mode is non-passthrough, delegate to those functions. */
|
||||||
if (server->input_mode == LAB_INPUT_STATE_MOVE) {
|
if (server->input_mode == LAB_INPUT_STATE_MOVE) {
|
||||||
|
|
@ -257,17 +256,24 @@ process_cursor_motion(struct server *server, uint32_t time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Required for iconify/maximize/close button mouse-over deco */
|
/* SSD button mouse-over */
|
||||||
|
struct ssd_hover_state *hover = &server->ssd_hover_state;
|
||||||
if (ssd_is_button(view_area)) {
|
if (ssd_is_button(view_area)) {
|
||||||
if (last_button_hover != view_area) {
|
/* Cursor entered new button area */
|
||||||
/* Cursor entered new button area */
|
if (hover->view != view || hover->type != view_area) {
|
||||||
//damage_whole_current_output(server);
|
if (hover->node) {
|
||||||
last_button_hover = view_area;
|
wlr_scene_node_set_enabled(hover->node, false);
|
||||||
|
}
|
||||||
|
hover->view = view;
|
||||||
|
hover->type = view_area;
|
||||||
|
hover->node = ssd_button_hover_enable(view, view_area);
|
||||||
}
|
}
|
||||||
} else if (last_button_hover != LAB_SSD_NONE) {
|
} else if (hover->node) {
|
||||||
/* Cursor left button area */
|
/* Cursor left button area */
|
||||||
//damage_whole_current_output(server);
|
wlr_scene_node_set_enabled(hover->node, false);
|
||||||
last_button_hover = LAB_SSD_NONE;
|
hover->view = NULL;
|
||||||
|
hover->type = LAB_SSD_NONE;
|
||||||
|
hover->node = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface &&
|
if (surface &&
|
||||||
|
|
|
||||||
|
|
@ -276,10 +276,6 @@ desktop_node_and_view_at(struct server *server, double lx, double ly,
|
||||||
*view_area = LAB_SSD_LAYER_SURFACE;
|
*view_area = LAB_SSD_LAYER_SURFACE;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*view_area = LAB_SSD_CLIENT;
|
|
||||||
} else {
|
|
||||||
/* TODO: remove */
|
|
||||||
*view_area = LAB_SSD_NONE;
|
|
||||||
}
|
}
|
||||||
struct wlr_scene_node *osd = &server->osd_tree->node;
|
struct wlr_scene_node *osd = &server->osd_tree->node;
|
||||||
struct wlr_scene_node *menu = &server->menu_tree->node;
|
struct wlr_scene_node *menu = &server->menu_tree->node;
|
||||||
|
|
@ -299,7 +295,7 @@ desktop_node_and_view_at(struct server *server, double lx, double ly,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
struct view *view = node->data;
|
struct view *view = node->data;
|
||||||
/* TODO: *view_area = ssd_get_type(view, node) */
|
*view_area = ssd_get_part_type(view, *scene_node);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ labwc_sources = files(
|
||||||
'resistance.c',
|
'resistance.c',
|
||||||
'seat.c',
|
'seat.c',
|
||||||
'server.c',
|
'server.c',
|
||||||
'ssd.c',
|
|
||||||
'theme.c',
|
'theme.c',
|
||||||
'view.c',
|
'view.c',
|
||||||
'view-impl.c',
|
'view-impl.c',
|
||||||
|
|
@ -37,3 +36,4 @@ subdir('common')
|
||||||
subdir('config')
|
subdir('config')
|
||||||
subdir('xbm')
|
subdir('xbm')
|
||||||
subdir('menu')
|
subdir('menu')
|
||||||
|
subdir('ssd')
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ reload_config_and_theme(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
view->margin = ssd_thickness(view);
|
view->margin = ssd_thickness(view);
|
||||||
ssd_update_geometry(view, true);
|
ssd_reload(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_reconfigure(g_server);
|
menu_reconfigure(g_server);
|
||||||
|
|
|
||||||
479
src/ssd.c
479
src/ssd.c
|
|
@ -1,479 +0,0 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
/*
|
|
||||||
* Helpers for view server side decorations
|
|
||||||
*
|
|
||||||
* Copyright (C) Johan Malm 2020-2021
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include "config/rcxml.h"
|
|
||||||
#include "common/font.h"
|
|
||||||
#include "labwc.h"
|
|
||||||
#include "theme.h"
|
|
||||||
#include "ssd.h"
|
|
||||||
|
|
||||||
#define INVISIBLE_MARGIN (16)
|
|
||||||
|
|
||||||
struct border
|
|
||||||
ssd_thickness(struct view *view)
|
|
||||||
{
|
|
||||||
struct theme *theme = view->server->theme;
|
|
||||||
struct border border = {
|
|
||||||
.top = theme->title_height + theme->border_width,
|
|
||||||
.bottom = theme->border_width,
|
|
||||||
.left = theme->border_width,
|
|
||||||
.right = theme->border_width,
|
|
||||||
};
|
|
||||||
return border;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_box
|
|
||||||
ssd_max_extents(struct view *view)
|
|
||||||
{
|
|
||||||
struct border border = ssd_thickness(view);
|
|
||||||
struct wlr_box box = {
|
|
||||||
.x = view->x - border.left,
|
|
||||||
.y = view->y - border.top,
|
|
||||||
.width = view->w + border.left + border.right,
|
|
||||||
.height = view->h + border.top + border.bottom,
|
|
||||||
};
|
|
||||||
return box;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NR_BUTTONS (4)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ssd_box - the 'full' decoration geometry which includes both visible
|
|
||||||
* and invisible parts. It typically includes an invisible margin outside
|
|
||||||
* the decoration.
|
|
||||||
*
|
|
||||||
* This function is used for determining decoration parts during user-
|
|
||||||
* interactive operations such as mouse hover or button press
|
|
||||||
*/
|
|
||||||
static struct wlr_box
|
|
||||||
ssd_box(struct view *view, enum ssd_part_type type)
|
|
||||||
{
|
|
||||||
struct theme *theme = view->server->theme;
|
|
||||||
struct wlr_box box = { 0 };
|
|
||||||
int16_t button_height = theme->title_height;
|
|
||||||
int16_t button_width = theme->title_height;
|
|
||||||
int16_t corner_square = theme->title_height + theme->border_width;
|
|
||||||
int16_t title_x_padding = (double)corner_square / 2;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case LAB_SSD_BUTTON_CLOSE:
|
|
||||||
box.x = view->x + view->w - button_width * 1;
|
|
||||||
box.y = view->y - button_height;
|
|
||||||
box.width = button_width;
|
|
||||||
box.height = button_height;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_BUTTON_MAXIMIZE:
|
|
||||||
box.x = view->x + view->w - button_width * 2;
|
|
||||||
box.y = view->y - button_height;
|
|
||||||
box.width = button_width;
|
|
||||||
box.height = button_height;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_BUTTON_ICONIFY:
|
|
||||||
box.x = view->x + view->w - button_width * 3;
|
|
||||||
box.y = view->y - button_height;
|
|
||||||
box.width = button_width;
|
|
||||||
box.height = button_height;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_BUTTON_WINDOW_MENU:
|
|
||||||
box.x = view->x;
|
|
||||||
box.y = view->y - button_height;
|
|
||||||
box.width = button_width;
|
|
||||||
box.height = button_height;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_TITLEBAR:
|
|
||||||
box.x = view->x;
|
|
||||||
box.y = view->y - theme->title_height;
|
|
||||||
box.width = view->w;
|
|
||||||
box.height = theme->title_height;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_TITLE:
|
|
||||||
box.x = view->x + button_width + title_x_padding;
|
|
||||||
box.y = view->y - theme->title_height;
|
|
||||||
box.width = view->w - title_x_padding * 2 - NR_BUTTONS * button_width;
|
|
||||||
box.height = theme->title_height;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_CORNER_TOP_LEFT:
|
|
||||||
box.x = view->x - theme->border_width - INVISIBLE_MARGIN;
|
|
||||||
box.y = view->y - corner_square - INVISIBLE_MARGIN;
|
|
||||||
box.width = corner_square + INVISIBLE_MARGIN;
|
|
||||||
box.height = corner_square + INVISIBLE_MARGIN;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_CORNER_TOP_RIGHT:
|
|
||||||
box.x = view->x + view->w - theme->title_height;
|
|
||||||
box.y = view->y - corner_square - INVISIBLE_MARGIN;
|
|
||||||
box.width = corner_square + INVISIBLE_MARGIN;
|
|
||||||
box.height = corner_square + INVISIBLE_MARGIN;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_CORNER_BOTTOM_RIGHT:
|
|
||||||
box.x = view->x + view->w - corner_square;
|
|
||||||
box.y = view->y + view->h - corner_square;
|
|
||||||
box.width = corner_square + INVISIBLE_MARGIN;
|
|
||||||
box.height = corner_square + INVISIBLE_MARGIN;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_CORNER_BOTTOM_LEFT:
|
|
||||||
box.x = view->x - theme->border_width - INVISIBLE_MARGIN;
|
|
||||||
box.y = view->y + view->h - corner_square;
|
|
||||||
box.width = corner_square + INVISIBLE_MARGIN;
|
|
||||||
box.height = corner_square + INVISIBLE_MARGIN;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_TOP:
|
|
||||||
box.x = view->x + theme->title_height;
|
|
||||||
box.y = view->y - corner_square - INVISIBLE_MARGIN;
|
|
||||||
box.width = view->w - 2 * theme->title_height;
|
|
||||||
box.height = theme->border_width + INVISIBLE_MARGIN;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_RIGHT:
|
|
||||||
box.x = view->x + view->w;
|
|
||||||
box.y = view->y;
|
|
||||||
box.width = theme->border_width + INVISIBLE_MARGIN;
|
|
||||||
box.height = view->h;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_BOTTOM:
|
|
||||||
box.x = view->x - theme->border_width;
|
|
||||||
box.y = view->y + view->h;
|
|
||||||
box.width = view->w + 2 * theme->border_width;
|
|
||||||
box.height = theme->border_width + INVISIBLE_MARGIN;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_LEFT:
|
|
||||||
box.x = view->x - theme->border_width - INVISIBLE_MARGIN;
|
|
||||||
box.y = view->y;
|
|
||||||
box.width = theme->border_width + INVISIBLE_MARGIN;
|
|
||||||
box.height = view->h;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_CLIENT:
|
|
||||||
box.x = view->x;
|
|
||||||
box.y = view->y;
|
|
||||||
box.width = view->w;
|
|
||||||
box.height = view->h;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return box;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
center_vertically(struct wlr_box *box, struct wlr_texture *texture)
|
|
||||||
{
|
|
||||||
if (!texture) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
box->y += (box->height - texture->height) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
center_horizontally(struct view *view, struct wlr_box *box,
|
|
||||||
struct wlr_texture *texture)
|
|
||||||
{
|
|
||||||
if (!texture) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
box->x = view->x + (view->w - texture->width) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
justify_right(struct view *view, struct wlr_box *box,
|
|
||||||
struct wlr_texture *texture)
|
|
||||||
{
|
|
||||||
if (!texture) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
box->x = view->x + (box->width - texture->width);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
ssd_is_button(enum ssd_part_type type)
|
|
||||||
{
|
|
||||||
return type == LAB_SSD_BUTTON_CLOSE ||
|
|
||||||
type == LAB_SSD_BUTTON_MAXIMIZE ||
|
|
||||||
type == LAB_SSD_BUTTON_ICONIFY ||
|
|
||||||
type == LAB_SSD_BUTTON_WINDOW_MENU;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_box
|
|
||||||
ssd_visible_box(struct view *view, enum ssd_part_type type)
|
|
||||||
{
|
|
||||||
struct theme *theme = view->server->theme;
|
|
||||||
struct wlr_box box = { 0 };
|
|
||||||
switch (type) {
|
|
||||||
case LAB_SSD_BUTTON_CLOSE:
|
|
||||||
box = ssd_box(view, type);
|
|
||||||
break;
|
|
||||||
case LAB_SSD_BUTTON_MAXIMIZE:
|
|
||||||
box = ssd_box(view, type);
|
|
||||||
break;
|
|
||||||
case LAB_SSD_BUTTON_ICONIFY:
|
|
||||||
box = ssd_box(view, type);
|
|
||||||
break;
|
|
||||||
case LAB_SSD_BUTTON_WINDOW_MENU:
|
|
||||||
box = ssd_box(view, type);
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_TITLEBAR:
|
|
||||||
box = ssd_box(view, type);
|
|
||||||
box.x += theme->title_height;
|
|
||||||
box.width -= 2 * theme->title_height;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_TITLE:
|
|
||||||
box = ssd_box(view, type);
|
|
||||||
center_vertically(&box, view->title.active);
|
|
||||||
if (theme->window_label_text_justify == LAB_JUSTIFY_CENTER) {
|
|
||||||
center_horizontally(view, &box, view->title.active);
|
|
||||||
} else if (theme->window_label_text_justify == LAB_JUSTIFY_RIGHT) {
|
|
||||||
justify_right(view, &box, view->title.active);
|
|
||||||
}
|
|
||||||
if (view->title.active) {
|
|
||||||
box.width = view->title.active->width;
|
|
||||||
box.height = view->title.active->height;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_CORNER_TOP_LEFT:
|
|
||||||
box = ssd_box(view, type);
|
|
||||||
box.x += INVISIBLE_MARGIN;
|
|
||||||
box.y += INVISIBLE_MARGIN;
|
|
||||||
box.width -= INVISIBLE_MARGIN;
|
|
||||||
box.height -= INVISIBLE_MARGIN;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_CORNER_TOP_RIGHT:
|
|
||||||
box = ssd_box(view, type);
|
|
||||||
box.y += INVISIBLE_MARGIN;
|
|
||||||
box.width -= INVISIBLE_MARGIN;
|
|
||||||
box.height -= INVISIBLE_MARGIN;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_TOP:
|
|
||||||
box = ssd_box(view, type);
|
|
||||||
box.y += INVISIBLE_MARGIN;
|
|
||||||
box.height -= INVISIBLE_MARGIN;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_RIGHT:
|
|
||||||
box = ssd_box(view, type);
|
|
||||||
box.width -= INVISIBLE_MARGIN;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_BOTTOM:
|
|
||||||
box = ssd_box(view, type);
|
|
||||||
box.height -= INVISIBLE_MARGIN;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_LEFT:
|
|
||||||
box = ssd_box(view, type);
|
|
||||||
box.x += INVISIBLE_MARGIN;
|
|
||||||
box.width -= INVISIBLE_MARGIN;
|
|
||||||
break;
|
|
||||||
case LAB_SSD_PART_CORNER_BOTTOM_RIGHT:
|
|
||||||
case LAB_SSD_PART_CORNER_BOTTOM_LEFT:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return box;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ssd_part_type
|
|
||||||
ssd_at(struct view *view, double lx, double ly)
|
|
||||||
{
|
|
||||||
enum ssd_part_type type;
|
|
||||||
for (type = 0; type < LAB_SSD_END_MARKER; ++type) {
|
|
||||||
struct wlr_box box = ssd_box(view, type);
|
|
||||||
if (wlr_box_contains_point(&box, lx, ly)) {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return LAB_SSD_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t
|
|
||||||
ssd_resize_edges(enum ssd_part_type type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case LAB_SSD_PART_TOP:
|
|
||||||
return WLR_EDGE_TOP;
|
|
||||||
case LAB_SSD_PART_RIGHT:
|
|
||||||
return WLR_EDGE_RIGHT;
|
|
||||||
case LAB_SSD_PART_BOTTOM:
|
|
||||||
return WLR_EDGE_BOTTOM;
|
|
||||||
case LAB_SSD_PART_LEFT:
|
|
||||||
return WLR_EDGE_LEFT;
|
|
||||||
case LAB_SSD_PART_CORNER_TOP_LEFT:
|
|
||||||
return WLR_EDGE_TOP | WLR_EDGE_LEFT;
|
|
||||||
case LAB_SSD_PART_CORNER_TOP_RIGHT:
|
|
||||||
return WLR_EDGE_RIGHT | WLR_EDGE_TOP;
|
|
||||||
case LAB_SSD_PART_CORNER_BOTTOM_RIGHT:
|
|
||||||
return WLR_EDGE_BOTTOM | WLR_EDGE_RIGHT;
|
|
||||||
case LAB_SSD_PART_CORNER_BOTTOM_LEFT:
|
|
||||||
return WLR_EDGE_BOTTOM | WLR_EDGE_LEFT;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct ssd_part *
|
|
||||||
add_part(struct view *view, enum ssd_part_type type)
|
|
||||||
{
|
|
||||||
struct ssd_part *part = calloc(1, sizeof(struct ssd_part));
|
|
||||||
part->type = type;
|
|
||||||
wl_list_insert(&view->ssd.parts, &part->link);
|
|
||||||
return part;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ssd_update_title(struct view *view)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* FIXME */
|
|
||||||
#if 0
|
|
||||||
struct theme *theme = view->server->theme;
|
|
||||||
|
|
||||||
struct font font = {
|
|
||||||
.name = rc.font_name_activewindow,
|
|
||||||
.size = rc.font_size_activewindow,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct ssd_part *part;
|
|
||||||
wl_list_for_each(part, &view->ssd.parts, link) {
|
|
||||||
if (part->type == LAB_SSD_PART_TITLE) {
|
|
||||||
part->box = ssd_box(view, part->type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (part->type != LAB_SSD_PART_TITLE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME */
|
|
||||||
#if 0
|
|
||||||
int max_width = part->box.width > 0 ? part->box.width : 1000;
|
|
||||||
|
|
||||||
font_texture_create(view->server, &view->title.active, max_width,
|
|
||||||
view_get_string_prop(view, "title"),
|
|
||||||
&font, theme->window_active_label_text_color);
|
|
||||||
|
|
||||||
font_texture_create(view->server, &view->title.inactive, max_width,
|
|
||||||
view_get_string_prop(view, "title"),
|
|
||||||
&font, theme->window_inactive_label_text_color);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
part->box = ssd_visible_box(view, part->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ssd_create(struct view *view)
|
|
||||||
{
|
|
||||||
struct theme *theme = view->server->theme;
|
|
||||||
struct ssd_part *part;
|
|
||||||
|
|
||||||
view->ssd.box.x = view->x;
|
|
||||||
view->ssd.box.y = view->y;
|
|
||||||
view->ssd.box.width = view->w;
|
|
||||||
view->ssd.box.height = view->h;
|
|
||||||
|
|
||||||
/* border */
|
|
||||||
enum ssd_part_type border[4] = {
|
|
||||||
LAB_SSD_PART_TOP,
|
|
||||||
LAB_SSD_PART_RIGHT,
|
|
||||||
LAB_SSD_PART_BOTTOM,
|
|
||||||
LAB_SSD_PART_LEFT,
|
|
||||||
};
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
part = add_part(view, border[i]);
|
|
||||||
part->box = ssd_visible_box(view, border[i]);
|
|
||||||
part->color.active = theme->window_active_border_color;
|
|
||||||
part->color.inactive = theme->window_inactive_border_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* titlebar */
|
|
||||||
part = add_part(view, LAB_SSD_PART_TITLEBAR);
|
|
||||||
part->box = ssd_visible_box(view, LAB_SSD_PART_TITLEBAR);
|
|
||||||
part->color.active = theme->window_active_title_bg_color;
|
|
||||||
part->color.inactive = theme->window_inactive_title_bg_color;
|
|
||||||
|
|
||||||
/* titlebar top-left corner */
|
|
||||||
part = add_part(view, LAB_SSD_PART_CORNER_TOP_LEFT);
|
|
||||||
part->box = ssd_visible_box(view, part->type);
|
|
||||||
/* FIXME */
|
|
||||||
#if 0
|
|
||||||
part->texture.active = &theme->corner_top_left_active_normal;
|
|
||||||
part->texture.inactive = &theme->corner_top_left_inactive_normal;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* titlebar top-right corner */
|
|
||||||
part = add_part(view, LAB_SSD_PART_CORNER_TOP_RIGHT);
|
|
||||||
part->box = ssd_visible_box(view, part->type);
|
|
||||||
/* FIXME */
|
|
||||||
#if 0
|
|
||||||
part->texture.active = &theme->corner_top_right_active_normal;
|
|
||||||
part->texture.inactive = &theme->corner_top_right_inactive_normal;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* title text */
|
|
||||||
part = add_part(view, LAB_SSD_PART_TITLE);
|
|
||||||
ssd_update_title(view);
|
|
||||||
part->texture.active = &view->title.active;
|
|
||||||
part->texture.inactive = &view->title.inactive;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ssd_destroy(struct view *view)
|
|
||||||
{
|
|
||||||
struct ssd_part *part, *next;
|
|
||||||
wl_list_for_each_safe(part, next, &view->ssd.parts, link) {
|
|
||||||
wl_list_remove(&part->link);
|
|
||||||
free(part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
geometry_changed(struct view *view)
|
|
||||||
{
|
|
||||||
return view->x != view->ssd.box.x || view->y != view->ssd.box.y ||
|
|
||||||
view->w != view->ssd.box.width ||
|
|
||||||
view->h != view->ssd.box.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ssd_update_geometry(struct view *view, bool force)
|
|
||||||
{
|
|
||||||
if (!geometry_changed(view) && !force) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct ssd_part *part;
|
|
||||||
wl_list_for_each(part, &view->ssd.parts, link) {
|
|
||||||
part->box = ssd_visible_box(view, part->type);
|
|
||||||
}
|
|
||||||
view->ssd.box.x = view->x;
|
|
||||||
view->ssd.box.y = view->y;
|
|
||||||
view->ssd.box.width = view->w;
|
|
||||||
view->ssd.box.height = view->h;
|
|
||||||
damage_all_outputs(view->server);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate)
|
|
||||||
{
|
|
||||||
if (whole == candidate) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (whole == LAB_SSD_PART_TITLEBAR) {
|
|
||||||
return candidate >= LAB_SSD_BUTTON_CLOSE && candidate <= LAB_SSD_PART_TITLE;
|
|
||||||
}
|
|
||||||
if (whole == LAB_SSD_FRAME) {
|
|
||||||
return candidate >= LAB_SSD_BUTTON_CLOSE && candidate <= LAB_SSD_CLIENT;
|
|
||||||
}
|
|
||||||
if (whole == LAB_SSD_PART_TOP) {
|
|
||||||
return candidate == LAB_SSD_PART_CORNER_TOP_LEFT || candidate == LAB_SSD_PART_CORNER_BOTTOM_LEFT;
|
|
||||||
}
|
|
||||||
if (whole == LAB_SSD_PART_RIGHT) {
|
|
||||||
return candidate == LAB_SSD_PART_CORNER_TOP_RIGHT || candidate == LAB_SSD_PART_CORNER_BOTTOM_RIGHT;
|
|
||||||
}
|
|
||||||
if (whole == LAB_SSD_PART_BOTTOM) {
|
|
||||||
return candidate == LAB_SSD_PART_CORNER_BOTTOM_RIGHT || candidate == LAB_SSD_PART_CORNER_BOTTOM_LEFT;
|
|
||||||
}
|
|
||||||
if (whole == LAB_SSD_PART_LEFT) {
|
|
||||||
return candidate == LAB_SSD_PART_CORNER_TOP_LEFT || candidate == LAB_SSD_PART_CORNER_BOTTOM_LEFT;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
7
src/ssd/meson.build
Normal file
7
src/ssd/meson.build
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
labwc_sources += files(
|
||||||
|
'ssd.c',
|
||||||
|
'ssd_part.c',
|
||||||
|
'ssd_titlebar.c',
|
||||||
|
'ssd_border.c',
|
||||||
|
'ssd_extents.c',
|
||||||
|
)
|
||||||
300
src/ssd/ssd.c
Normal file
300
src/ssd/ssd.c
Normal file
|
|
@ -0,0 +1,300 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helpers for view server side decorations
|
||||||
|
*
|
||||||
|
* Copyright (C) Johan Malm 2020-2021
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include "config/rcxml.h"
|
||||||
|
#include "common/font.h"
|
||||||
|
#include "labwc.h"
|
||||||
|
#include "theme.h"
|
||||||
|
#include "ssd.h"
|
||||||
|
|
||||||
|
/* TODO: use theme->title_height instead of SSD_HEIGHT */
|
||||||
|
struct border
|
||||||
|
ssd_thickness(struct view *view)
|
||||||
|
{
|
||||||
|
struct theme *theme = view->server->theme;
|
||||||
|
struct border border = {
|
||||||
|
.top = SSD_HEIGHT,
|
||||||
|
.bottom = theme->border_width,
|
||||||
|
.left = theme->border_width,
|
||||||
|
.right = theme->border_width,
|
||||||
|
};
|
||||||
|
return border;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_box
|
||||||
|
ssd_max_extents(struct view *view)
|
||||||
|
{
|
||||||
|
struct border border = ssd_thickness(view);
|
||||||
|
struct wlr_box box = {
|
||||||
|
.x = view->x - border.left,
|
||||||
|
.y = view->y - border.top,
|
||||||
|
.width = view->w + border.left + border.right,
|
||||||
|
.height = view->h + border.top + border.bottom,
|
||||||
|
};
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ssd_is_button(enum ssd_part_type type)
|
||||||
|
{
|
||||||
|
return type == LAB_SSD_BUTTON_CLOSE
|
||||||
|
|| type == LAB_SSD_BUTTON_MAXIMIZE
|
||||||
|
|| type == LAB_SSD_BUTTON_ICONIFY
|
||||||
|
|| type == LAB_SSD_BUTTON_WINDOW_MENU;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ssd_part_type
|
||||||
|
ssd_get_part_type(struct view *view, struct wlr_scene_node *node)
|
||||||
|
{
|
||||||
|
if (!node) {
|
||||||
|
return LAB_SSD_NONE;
|
||||||
|
} else if (node->type == WLR_SCENE_NODE_SURFACE) {
|
||||||
|
return LAB_SSD_CLIENT;
|
||||||
|
} else if (!view->ssd.tree) {
|
||||||
|
return LAB_SSD_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_list *part_list = NULL;
|
||||||
|
struct wlr_scene_node *grandparent =
|
||||||
|
node->parent ? node->parent->parent : NULL;
|
||||||
|
|
||||||
|
/* active titlebar */
|
||||||
|
if (node->parent == &view->ssd.titlebar.active.tree->node) {
|
||||||
|
part_list = &view->ssd.titlebar.active.parts;
|
||||||
|
} else if (grandparent == &view->ssd.titlebar.active.tree->node) {
|
||||||
|
part_list = &view->ssd.titlebar.active.parts;
|
||||||
|
|
||||||
|
/* extents */
|
||||||
|
} else if (node->parent == &view->ssd.extents.tree->node) {
|
||||||
|
part_list = &view->ssd.extents.parts;
|
||||||
|
|
||||||
|
/* active border */
|
||||||
|
} else if (node->parent == &view->ssd.border.active.tree->node) {
|
||||||
|
part_list = &view->ssd.border.active.parts;
|
||||||
|
|
||||||
|
/* inactive titlebar */
|
||||||
|
} else if (node->parent == &view->ssd.titlebar.inactive.tree->node) {
|
||||||
|
part_list = &view->ssd.titlebar.inactive.parts;
|
||||||
|
} else if (grandparent == &view->ssd.titlebar.inactive.tree->node) {
|
||||||
|
part_list = &view->ssd.titlebar.inactive.parts;
|
||||||
|
|
||||||
|
/* inactive border */
|
||||||
|
} else if (node->parent == &view->ssd.border.inactive.tree->node) {
|
||||||
|
part_list = &view->ssd.border.inactive.parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part_list) {
|
||||||
|
struct ssd_part *part;
|
||||||
|
wl_list_for_each(part, part_list, link) {
|
||||||
|
if (node == part->node) {
|
||||||
|
return part->type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LAB_SSD_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ssd_part_type
|
||||||
|
ssd_at(struct view *view, double lx, double ly)
|
||||||
|
{
|
||||||
|
double sx, sy;
|
||||||
|
struct wlr_scene_node *node = wlr_scene_node_at(
|
||||||
|
&view->server->scene->node, lx, ly, &sx, &sy);
|
||||||
|
return ssd_get_part_type(view, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
ssd_resize_edges(enum ssd_part_type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case LAB_SSD_PART_TOP:
|
||||||
|
return WLR_EDGE_TOP;
|
||||||
|
case LAB_SSD_PART_RIGHT:
|
||||||
|
return WLR_EDGE_RIGHT;
|
||||||
|
case LAB_SSD_PART_BOTTOM:
|
||||||
|
return WLR_EDGE_BOTTOM;
|
||||||
|
case LAB_SSD_PART_LEFT:
|
||||||
|
return WLR_EDGE_LEFT;
|
||||||
|
case LAB_SSD_PART_CORNER_TOP_LEFT:
|
||||||
|
return WLR_EDGE_TOP | WLR_EDGE_LEFT;
|
||||||
|
case LAB_SSD_PART_CORNER_TOP_RIGHT:
|
||||||
|
return WLR_EDGE_RIGHT | WLR_EDGE_TOP;
|
||||||
|
case LAB_SSD_PART_CORNER_BOTTOM_RIGHT:
|
||||||
|
return WLR_EDGE_BOTTOM | WLR_EDGE_RIGHT;
|
||||||
|
case LAB_SSD_PART_CORNER_BOTTOM_LEFT:
|
||||||
|
return WLR_EDGE_BOTTOM | WLR_EDGE_LEFT;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ssd_set_active(struct ssd *ssd, bool active)
|
||||||
|
{
|
||||||
|
wlr_scene_node_set_enabled(&ssd->border.active.tree->node, active);
|
||||||
|
wlr_scene_node_set_enabled(&ssd->titlebar.active.tree->node, active);
|
||||||
|
wlr_scene_node_set_enabled(&ssd->border.inactive.tree->node, !active);
|
||||||
|
wlr_scene_node_set_enabled(&ssd->titlebar.inactive.tree->node, !active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_create(struct view *view)
|
||||||
|
{
|
||||||
|
if (view->ssd.tree) {
|
||||||
|
/* SSD was hidden. Just enable it */
|
||||||
|
wlr_log(WLR_ERROR, "Unhiding SSD");
|
||||||
|
wlr_scene_node_set_enabled(&view->ssd.tree->node, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_log(WLR_ERROR, "Creating SSD");
|
||||||
|
view->ssd.tree = wlr_scene_tree_create(&view->scene_tree->node);
|
||||||
|
wlr_scene_node_lower_to_bottom(&view->ssd.tree->node);
|
||||||
|
ssd_extents_create(view);
|
||||||
|
ssd_border_create(view);
|
||||||
|
ssd_titlebar_create(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_update_geometry(struct view *view)
|
||||||
|
{
|
||||||
|
/* TODO: verify we are not called without reason. like in commit handlers */
|
||||||
|
if (!view->ssd.tree || !view->surface) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (view->ssd.enabled && !view->ssd.tree->node.state.enabled) {
|
||||||
|
wlr_scene_node_set_enabled(&view->ssd.tree->node, true);
|
||||||
|
}
|
||||||
|
if (!view->ssd.enabled && view->ssd.tree->node.state.enabled) {
|
||||||
|
wlr_scene_node_set_enabled(&view->ssd.tree->node, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = view->surface->current.width;
|
||||||
|
int height = view->surface->current.height;
|
||||||
|
if (width == view->ssd.state.width && height == view->ssd.state.height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ssd_extents_update(view);
|
||||||
|
ssd_border_update(view);
|
||||||
|
ssd_titlebar_update(view);
|
||||||
|
|
||||||
|
view->ssd.state.width = width;
|
||||||
|
view->ssd.state.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_hide(struct view *view)
|
||||||
|
{
|
||||||
|
if (!view->ssd.tree) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_log(WLR_ERROR, "Hiding SSD");
|
||||||
|
wlr_scene_node_set_enabled(&view->ssd.tree->node, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ssd_reload(struct view *view)
|
||||||
|
{
|
||||||
|
if (!view->ssd.tree) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool view_was_active = view->server->ssd_focused_view == view;
|
||||||
|
ssd_destroy(view);
|
||||||
|
ssd_create(view);
|
||||||
|
if (view_was_active) {
|
||||||
|
view->server->ssd_focused_view = view;
|
||||||
|
} else {
|
||||||
|
_ssd_set_active(&view->ssd, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_destroy(struct view *view)
|
||||||
|
{
|
||||||
|
if (!view->ssd.tree) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_log(WLR_ERROR, "Destroying SSD");
|
||||||
|
|
||||||
|
/* Maybe reset focused view */
|
||||||
|
if (view->server->ssd_focused_view == view) {
|
||||||
|
view->server->ssd_focused_view = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Maybe reset hover view */
|
||||||
|
struct ssd_hover_state *hover_state;
|
||||||
|
hover_state = &view->server->ssd_hover_state;
|
||||||
|
if (hover_state->view == view) {
|
||||||
|
hover_state->view = NULL;
|
||||||
|
hover_state->type = LAB_SSD_NONE;
|
||||||
|
hover_state->node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destroy subcomponents */
|
||||||
|
ssd_titlebar_destroy(view);
|
||||||
|
ssd_border_destroy(view);
|
||||||
|
ssd_extents_destroy(view);
|
||||||
|
wlr_scene_node_destroy(&view->ssd.tree->node);
|
||||||
|
view->ssd.tree = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate)
|
||||||
|
{
|
||||||
|
if (whole == candidate) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (whole == LAB_SSD_PART_TITLEBAR) {
|
||||||
|
return candidate >= LAB_SSD_BUTTON_CLOSE
|
||||||
|
&& candidate <= LAB_SSD_PART_TITLE;
|
||||||
|
}
|
||||||
|
if (whole == LAB_SSD_FRAME) {
|
||||||
|
return candidate >= LAB_SSD_BUTTON_CLOSE
|
||||||
|
&& candidate <= LAB_SSD_CLIENT;
|
||||||
|
}
|
||||||
|
if (whole == LAB_SSD_PART_TOP) {
|
||||||
|
return candidate == LAB_SSD_PART_CORNER_TOP_LEFT
|
||||||
|
|| candidate == LAB_SSD_PART_CORNER_BOTTOM_LEFT;
|
||||||
|
}
|
||||||
|
if (whole == LAB_SSD_PART_RIGHT) {
|
||||||
|
return candidate == LAB_SSD_PART_CORNER_TOP_RIGHT
|
||||||
|
|| candidate == LAB_SSD_PART_CORNER_BOTTOM_RIGHT;
|
||||||
|
}
|
||||||
|
if (whole == LAB_SSD_PART_BOTTOM) {
|
||||||
|
return candidate == LAB_SSD_PART_CORNER_BOTTOM_RIGHT
|
||||||
|
|| candidate == LAB_SSD_PART_CORNER_BOTTOM_LEFT;
|
||||||
|
}
|
||||||
|
if (whole == LAB_SSD_PART_LEFT) {
|
||||||
|
return candidate == LAB_SSD_PART_CORNER_TOP_LEFT
|
||||||
|
|| candidate == LAB_SSD_PART_CORNER_BOTTOM_LEFT;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_set_active(struct view *view)
|
||||||
|
{
|
||||||
|
if (!view->ssd.tree) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct view *last = view->server->ssd_focused_view;
|
||||||
|
if (last == view) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (last && last->ssd.tree) {
|
||||||
|
_ssd_set_active(&last->ssd, false);
|
||||||
|
}
|
||||||
|
_ssd_set_active(&view->ssd, true);
|
||||||
|
view->server->ssd_focused_view = view;
|
||||||
|
}
|
||||||
96
src/ssd/ssd_border.c
Normal file
96
src/ssd/ssd_border.c
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#include "labwc.h"
|
||||||
|
#include "ssd.h"
|
||||||
|
#include "theme.h"
|
||||||
|
#include "common/scene-helpers.h"
|
||||||
|
|
||||||
|
#define FOR_EACH_STATE(view, tmp) FOR_EACH(tmp, \
|
||||||
|
&(view)->ssd.border.active, \
|
||||||
|
&(view)->ssd.border.inactive)
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_border_create(struct view *view)
|
||||||
|
{
|
||||||
|
struct theme *theme = view->server->theme;
|
||||||
|
int width = view->surface->current.width;
|
||||||
|
int height = view->surface->current.height;
|
||||||
|
int full_width = width + 2 * theme->border_width;
|
||||||
|
|
||||||
|
float *color;
|
||||||
|
struct wlr_scene_node *parent;
|
||||||
|
struct ssd_sub_tree *subtree;
|
||||||
|
|
||||||
|
FOR_EACH_STATE(view, subtree) {
|
||||||
|
subtree->tree = wlr_scene_tree_create(&view->ssd.tree->node);
|
||||||
|
parent = &subtree->tree->node;
|
||||||
|
wlr_scene_node_set_position(parent, -theme->border_width, 0);
|
||||||
|
if (subtree == &view->ssd.border.active) {
|
||||||
|
color = theme->window_active_border_color;
|
||||||
|
} else {
|
||||||
|
color = theme->window_inactive_border_color;
|
||||||
|
wlr_scene_node_set_enabled(parent, false);
|
||||||
|
}
|
||||||
|
wl_list_init(&subtree->parts);
|
||||||
|
add_scene_rect(&subtree->parts, LAB_SSD_PART_LEFT, parent,
|
||||||
|
theme->border_width, height, 0, 0, color);
|
||||||
|
add_scene_rect(&subtree->parts, LAB_SSD_PART_RIGHT, parent,
|
||||||
|
theme->border_width, height,
|
||||||
|
theme->border_width + width, 0, color);
|
||||||
|
add_scene_rect(&subtree->parts, LAB_SSD_PART_BOTTOM, parent,
|
||||||
|
full_width, theme->border_width,
|
||||||
|
0, height, color);
|
||||||
|
} FOR_EACH_END
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_border_update(struct view *view)
|
||||||
|
{
|
||||||
|
struct theme *theme = view->server->theme;
|
||||||
|
|
||||||
|
int width = view->surface->current.width;
|
||||||
|
int height = view->surface->current.height;
|
||||||
|
int full_width = width + 2 * theme->border_width;
|
||||||
|
|
||||||
|
struct ssd_part *part;
|
||||||
|
struct wlr_scene_rect *rect;
|
||||||
|
struct ssd_sub_tree *subtree;
|
||||||
|
FOR_EACH_STATE(view, subtree) {
|
||||||
|
wl_list_for_each(part, &subtree->parts, link) {
|
||||||
|
rect = lab_wlr_scene_get_rect(part->node);
|
||||||
|
switch (part->type) {
|
||||||
|
case LAB_SSD_PART_LEFT:
|
||||||
|
wlr_scene_rect_set_size(rect, theme->border_width, height);
|
||||||
|
continue;
|
||||||
|
case LAB_SSD_PART_RIGHT:
|
||||||
|
wlr_scene_rect_set_size(rect, theme->border_width, height);
|
||||||
|
wlr_scene_node_set_position(
|
||||||
|
part->node, theme->border_width + width, 0);
|
||||||
|
continue;
|
||||||
|
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;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} FOR_EACH_END
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_border_destroy(struct view *view)
|
||||||
|
{
|
||||||
|
if (!view->ssd.border.active.tree) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssd_sub_tree *subtree;
|
||||||
|
FOR_EACH_STATE(view, subtree) {
|
||||||
|
ssd_destroy_parts(&subtree->parts);
|
||||||
|
wlr_scene_node_destroy(&subtree->tree->node);
|
||||||
|
subtree->tree = NULL;
|
||||||
|
} FOR_EACH_END
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef FOR_EACH_STATE
|
||||||
119
src/ssd/ssd_extents.c
Normal file
119
src/ssd/ssd_extents.c
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#include "labwc.h"
|
||||||
|
#include "ssd.h"
|
||||||
|
#include "theme.h"
|
||||||
|
#include "common/scene-helpers.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_extents_create(struct view *view)
|
||||||
|
{
|
||||||
|
struct theme *theme = view->server->theme;
|
||||||
|
float invisible[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
struct wl_list *part_list = &view->ssd.extents.parts;
|
||||||
|
int width = view->surface->current.width;
|
||||||
|
int height = view->surface->current.height;
|
||||||
|
int full_height = height + theme->border_width + SSD_HEIGHT;
|
||||||
|
int full_width = width + 2 * theme->border_width;
|
||||||
|
int extended_area = EXTENDED_AREA;
|
||||||
|
|
||||||
|
view->ssd.extents.tree = wlr_scene_tree_create(
|
||||||
|
&view->ssd.tree->node);
|
||||||
|
struct wlr_scene_node *parent =
|
||||||
|
&view->ssd.extents.tree->node;
|
||||||
|
wlr_scene_node_set_position(parent,
|
||||||
|
-(theme->border_width + extended_area), -(SSD_HEIGHT + extended_area));
|
||||||
|
wl_list_init(&view->ssd.extents.parts);
|
||||||
|
|
||||||
|
/* Top */
|
||||||
|
add_scene_rect(part_list, LAB_SSD_PART_CORNER_TOP_LEFT, parent,
|
||||||
|
extended_area, extended_area,
|
||||||
|
0, 0, invisible);
|
||||||
|
add_scene_rect(part_list, LAB_SSD_PART_TOP, parent,
|
||||||
|
full_width, extended_area,
|
||||||
|
extended_area, 0, invisible);
|
||||||
|
add_scene_rect(part_list, LAB_SSD_PART_CORNER_TOP_RIGHT, parent,
|
||||||
|
extended_area, extended_area,
|
||||||
|
extended_area + full_width, 0, invisible);
|
||||||
|
|
||||||
|
/* Sides */
|
||||||
|
add_scene_rect(part_list, LAB_SSD_PART_LEFT, parent,
|
||||||
|
extended_area, full_height,
|
||||||
|
0, extended_area, invisible);
|
||||||
|
add_scene_rect(part_list, LAB_SSD_PART_RIGHT, parent,
|
||||||
|
extended_area, full_height,
|
||||||
|
extended_area + full_width, extended_area, invisible);
|
||||||
|
|
||||||
|
/* Bottom */
|
||||||
|
add_scene_rect(part_list, LAB_SSD_PART_CORNER_BOTTOM_LEFT, parent,
|
||||||
|
extended_area, extended_area,
|
||||||
|
0, extended_area + full_height, invisible);
|
||||||
|
add_scene_rect(part_list, LAB_SSD_PART_BOTTOM, parent,
|
||||||
|
full_width, extended_area,
|
||||||
|
extended_area, extended_area + full_height, invisible);
|
||||||
|
add_scene_rect(part_list, LAB_SSD_PART_CORNER_BOTTOM_RIGHT, parent,
|
||||||
|
extended_area, extended_area,
|
||||||
|
extended_area + full_width, extended_area + full_height, invisible);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_extents_update(struct view *view)
|
||||||
|
{
|
||||||
|
struct theme *theme = view->server->theme;
|
||||||
|
|
||||||
|
int width = view->surface->current.width;
|
||||||
|
int height = view->surface->current.height;
|
||||||
|
int full_height = height + theme->border_width + SSD_HEIGHT;
|
||||||
|
int full_width = width + 2 * theme->border_width;
|
||||||
|
int extended_area = EXTENDED_AREA;
|
||||||
|
|
||||||
|
struct ssd_part *part;
|
||||||
|
struct wlr_scene_rect *rect;
|
||||||
|
wl_list_for_each(part, &view->ssd.extents.parts, link) {
|
||||||
|
rect = lab_wlr_scene_get_rect(part->node);
|
||||||
|
switch (part->type) {
|
||||||
|
case LAB_SSD_PART_TOP:
|
||||||
|
wlr_scene_rect_set_size(rect, full_width, extended_area);
|
||||||
|
continue;
|
||||||
|
case LAB_SSD_PART_CORNER_TOP_RIGHT:
|
||||||
|
wlr_scene_node_set_position(
|
||||||
|
part->node, extended_area + full_width, 0);
|
||||||
|
continue;
|
||||||
|
case LAB_SSD_PART_LEFT:
|
||||||
|
wlr_scene_rect_set_size(rect, extended_area, full_height);
|
||||||
|
continue;
|
||||||
|
case LAB_SSD_PART_RIGHT:
|
||||||
|
wlr_scene_rect_set_size(rect, extended_area, full_height);
|
||||||
|
wlr_scene_node_set_position(
|
||||||
|
part->node, extended_area + full_width, extended_area);
|
||||||
|
continue;
|
||||||
|
case LAB_SSD_PART_CORNER_BOTTOM_LEFT:
|
||||||
|
wlr_scene_node_set_position(
|
||||||
|
part->node, 0, extended_area + full_height);
|
||||||
|
continue;
|
||||||
|
case LAB_SSD_PART_BOTTOM:
|
||||||
|
wlr_scene_rect_set_size(rect, full_width, extended_area);
|
||||||
|
wlr_scene_node_set_position(
|
||||||
|
part->node, extended_area, extended_area + full_height);
|
||||||
|
continue;
|
||||||
|
case LAB_SSD_PART_CORNER_BOTTOM_RIGHT:
|
||||||
|
wlr_scene_node_set_position(part->node,
|
||||||
|
extended_area + full_width, extended_area + full_height);
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_extents_destroy(struct view *view)
|
||||||
|
{
|
||||||
|
if (!view->ssd.extents.tree) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssd_destroy_parts(&view->ssd.extents.parts);
|
||||||
|
wlr_scene_node_destroy(&view->ssd.extents.tree->node);
|
||||||
|
view->ssd.extents.tree = NULL;
|
||||||
|
}
|
||||||
109
src/ssd/ssd_part.c
Normal file
109
src/ssd/ssd_part.c
Normal file
|
|
@ -0,0 +1,109 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include "labwc.h"
|
||||||
|
#include "ssd.h"
|
||||||
|
|
||||||
|
struct ssd_part *
|
||||||
|
add_scene_part(struct wl_list *part_list, enum ssd_part_type type)
|
||||||
|
{
|
||||||
|
struct ssd_part *part = calloc(1, sizeof(struct ssd_part));
|
||||||
|
part->type = type;
|
||||||
|
wl_list_insert(part_list->prev, &part->link);
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssd_part *
|
||||||
|
add_scene_rect(struct wl_list *list, enum ssd_part_type type,
|
||||||
|
struct wlr_scene_node *parent, int width, int height,
|
||||||
|
int x, int y, float color[4])
|
||||||
|
{
|
||||||
|
struct ssd_part *part = add_scene_part(list, type);
|
||||||
|
part->node = &wlr_scene_rect_create(
|
||||||
|
parent, width, height, color)->node;
|
||||||
|
wlr_scene_node_set_position(part->node, x, y);
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssd_part *
|
||||||
|
add_scene_buffer(struct wl_list *list, enum ssd_part_type type,
|
||||||
|
struct wlr_scene_node *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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
finish_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
|
struct wlr_scene_node *parent, struct wlr_buffer *icon_buffer)
|
||||||
|
{
|
||||||
|
float hover_bg[4] = {0.15f, 0.15f, 0.15f, 0.3f};
|
||||||
|
|
||||||
|
/* Icon */
|
||||||
|
add_scene_buffer(part_list, type, parent, icon_buffer,
|
||||||
|
(BUTTON_WIDTH - icon_buffer->width) / 2,
|
||||||
|
(SSD_HEIGHT - icon_buffer->height) / 2);
|
||||||
|
|
||||||
|
/* Hover overlay */
|
||||||
|
struct ssd_part *hover_part;
|
||||||
|
hover_part = add_scene_rect(part_list, type, parent,
|
||||||
|
BUTTON_WIDTH, SSD_HEIGHT, 0, 0, hover_bg);
|
||||||
|
wlr_scene_node_set_enabled(hover_part->node, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssd_part *
|
||||||
|
add_scene_button_corner(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
|
struct wlr_scene_node *parent, struct wlr_buffer *corner_buffer,
|
||||||
|
struct wlr_buffer *icon_buffer, int x)
|
||||||
|
{
|
||||||
|
struct ssd_part *part;
|
||||||
|
/* Background */
|
||||||
|
part = add_scene_buffer(part_list, type, parent, corner_buffer, x, 0);
|
||||||
|
finish_scene_button(part_list, type, part->node, icon_buffer);
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssd_part *
|
||||||
|
add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
|
struct wlr_scene_node *parent, float *bg_color,
|
||||||
|
struct wlr_buffer *icon_buffer, int x)
|
||||||
|
{
|
||||||
|
struct ssd_part *part;
|
||||||
|
/* Background */
|
||||||
|
part = add_scene_rect(part_list, type, parent,
|
||||||
|
BUTTON_WIDTH, SSD_HEIGHT, x, 0, bg_color);
|
||||||
|
finish_scene_button(part_list, type, part->node, icon_buffer);
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssd_part *
|
||||||
|
ssd_get_part(struct wl_list *part_list, enum ssd_part_type type)
|
||||||
|
{
|
||||||
|
struct ssd_part *part;
|
||||||
|
wl_list_for_each(part, part_list, link) {
|
||||||
|
if (part->type == type) {
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
if (part->buffer) {
|
||||||
|
wlr_buffer_drop(&part->buffer->base);
|
||||||
|
}
|
||||||
|
wl_list_remove(&part->link);
|
||||||
|
free(part);
|
||||||
|
}
|
||||||
|
assert(wl_list_empty(list));
|
||||||
|
}
|
||||||
306
src/ssd/ssd_titlebar.c
Normal file
306
src/ssd/ssd_titlebar.c
Normal file
|
|
@ -0,0 +1,306 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "labwc.h"
|
||||||
|
#include "ssd.h"
|
||||||
|
#include "theme.h"
|
||||||
|
#include "common/font.h"
|
||||||
|
#include "common/scene-helpers.h"
|
||||||
|
|
||||||
|
#define FOR_EACH_STATE(view, tmp) FOR_EACH(tmp, \
|
||||||
|
&(view)->ssd.titlebar.active, \
|
||||||
|
&(view)->ssd.titlebar.inactive)
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_titlebar_create(struct view *view)
|
||||||
|
{
|
||||||
|
struct theme *theme = view->server->theme;
|
||||||
|
int width = view->surface->current.width;
|
||||||
|
int full_width = width + 2 * theme->border_width;
|
||||||
|
|
||||||
|
float *color;
|
||||||
|
struct wlr_scene_node *parent;
|
||||||
|
struct wlr_buffer *corner_top_left;
|
||||||
|
struct wlr_buffer *corner_top_right;
|
||||||
|
|
||||||
|
struct ssd_sub_tree *subtree;
|
||||||
|
FOR_EACH_STATE(view, subtree) {
|
||||||
|
subtree->tree = wlr_scene_tree_create(&view->ssd.tree->node);
|
||||||
|
parent = &subtree->tree->node;
|
||||||
|
wlr_scene_node_set_position(parent, -theme->border_width, -SSD_HEIGHT);
|
||||||
|
if (subtree == &view->ssd.titlebar.active) {
|
||||||
|
color = theme->window_active_title_bg_color;
|
||||||
|
corner_top_left = &theme->corner_top_left_active_normal->base;
|
||||||
|
corner_top_right = &theme->corner_top_right_active_normal->base;
|
||||||
|
} else {
|
||||||
|
color = theme->window_inactive_title_bg_color;
|
||||||
|
corner_top_left = &theme->corner_top_left_inactive_normal->base;
|
||||||
|
corner_top_right = &theme->corner_top_right_inactive_normal->base;
|
||||||
|
wlr_scene_node_set_enabled(parent, false);
|
||||||
|
}
|
||||||
|
wl_list_init(&subtree->parts);
|
||||||
|
|
||||||
|
/* Title */
|
||||||
|
add_scene_rect(&subtree->parts, LAB_SSD_PART_TITLEBAR, parent,
|
||||||
|
full_width - BUTTON_WIDTH * BUTTON_COUNT, SSD_HEIGHT,
|
||||||
|
BUTTON_WIDTH, 0, color);
|
||||||
|
/* Buttons */
|
||||||
|
add_scene_button_corner(&subtree->parts, LAB_SSD_BUTTON_WINDOW_MENU,
|
||||||
|
parent, corner_top_left,
|
||||||
|
&theme->xbm_menu_active_unpressed->base, 0);
|
||||||
|
add_scene_button(&subtree->parts, LAB_SSD_BUTTON_ICONIFY, parent,
|
||||||
|
color, &theme->xbm_iconify_active_unpressed->base,
|
||||||
|
full_width - BUTTON_WIDTH * 3);
|
||||||
|
add_scene_button(&subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, parent,
|
||||||
|
color, &theme->xbm_maximize_active_unpressed->base,
|
||||||
|
full_width - BUTTON_WIDTH * 2);
|
||||||
|
add_scene_button_corner(&subtree->parts, LAB_SSD_BUTTON_CLOSE, parent,
|
||||||
|
corner_top_right, &theme->xbm_close_active_unpressed->base,
|
||||||
|
full_width - BUTTON_WIDTH * 1);
|
||||||
|
} FOR_EACH_END
|
||||||
|
ssd_update_title(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_direct_child(struct wlr_scene_node *node, struct ssd_sub_tree *subtree)
|
||||||
|
{
|
||||||
|
return node->parent == &subtree->tree->node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_titlebar_update(struct view *view)
|
||||||
|
{
|
||||||
|
int width = view->surface->current.width;
|
||||||
|
if (width == view->ssd.state.width) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int full_width = width + 2 * view->server->theme->border_width;
|
||||||
|
|
||||||
|
struct ssd_part *part;
|
||||||
|
struct ssd_sub_tree *subtree;
|
||||||
|
FOR_EACH_STATE(view, subtree) {
|
||||||
|
wl_list_for_each(part, &subtree->parts, link) {
|
||||||
|
switch (part->type) {
|
||||||
|
case LAB_SSD_PART_TITLEBAR:
|
||||||
|
wlr_scene_rect_set_size(lab_wlr_scene_get_rect(part->node),
|
||||||
|
full_width - BUTTON_WIDTH * BUTTON_COUNT, SSD_HEIGHT);
|
||||||
|
continue;
|
||||||
|
case LAB_SSD_BUTTON_ICONIFY:
|
||||||
|
if (is_direct_child(part->node, subtree)) {
|
||||||
|
wlr_scene_node_set_position(part->node,
|
||||||
|
full_width - BUTTON_WIDTH * 3, 0);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case LAB_SSD_BUTTON_MAXIMIZE:
|
||||||
|
if (is_direct_child(part->node, subtree)) {
|
||||||
|
wlr_scene_node_set_position(part->node,
|
||||||
|
full_width - BUTTON_WIDTH * 2, 0);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case LAB_SSD_BUTTON_CLOSE:
|
||||||
|
if (is_direct_child(part->node, subtree)) {
|
||||||
|
wlr_scene_node_set_position(part->node,
|
||||||
|
full_width - BUTTON_WIDTH * 1, 0);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} FOR_EACH_END
|
||||||
|
ssd_update_title(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_titlebar_destroy(struct view *view)
|
||||||
|
{
|
||||||
|
if (!view->ssd.titlebar.active.tree) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ssd_sub_tree *subtree;
|
||||||
|
FOR_EACH_STATE(view, subtree) {
|
||||||
|
ssd_destroy_parts(&subtree->parts);
|
||||||
|
wlr_scene_node_destroy(&subtree->tree->node);
|
||||||
|
subtree->tree = NULL;
|
||||||
|
} FOR_EACH_END
|
||||||
|
|
||||||
|
if (view->ssd.state.title.text) {
|
||||||
|
free(view->ssd.state.title.text);
|
||||||
|
view->ssd.state.title.text = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For ssd_update_title* we do not early out because
|
||||||
|
* .active and .inactive may result in different sizes
|
||||||
|
* of the title (font family/size) or background of
|
||||||
|
* the title (different button/border width).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
ssd_update_title_positions(struct view *view)
|
||||||
|
{
|
||||||
|
struct theme *theme = view->server->theme;
|
||||||
|
int width = view->surface->current.width;
|
||||||
|
int full_width = width + 2 * view->server->theme->border_width;
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
struct wlr_scene_rect *rect;
|
||||||
|
struct ssd_part *part;
|
||||||
|
struct ssd_sub_tree *subtree;
|
||||||
|
FOR_EACH_STATE(view, subtree) {
|
||||||
|
part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLE);
|
||||||
|
if (!part) {
|
||||||
|
wlr_log(WLR_ERROR,
|
||||||
|
"Failed to position SSD title: title node not found");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
y = (SSD_HEIGHT - part->buffer->base.height) / 2;
|
||||||
|
rect = lab_wlr_scene_get_rect(part->node->parent);
|
||||||
|
if (rect->width <= 0) {
|
||||||
|
wlr_log(WLR_ERROR,
|
||||||
|
"Failed to position SSD title: not enough screen space");
|
||||||
|
wlr_scene_node_set_position(part->node, x, y);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (theme->window_label_text_justify == LAB_JUSTIFY_CENTER) {
|
||||||
|
if (part->buffer->base.width + BUTTON_WIDTH * 2 <= rect->width) {
|
||||||
|
/* Center based on the full width */
|
||||||
|
x = (full_width - part->buffer->base.width) / 2;
|
||||||
|
x -= BUTTON_WIDTH;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Center based on the width between the buttons.
|
||||||
|
* Title jumps around once this is hit but its still
|
||||||
|
* better than to hide behind the buttons on the right.
|
||||||
|
*/
|
||||||
|
x = (rect->width - part->buffer->base.width) / 2;
|
||||||
|
}
|
||||||
|
} else if (theme->window_label_text_justify == LAB_JUSTIFY_RIGHT) {
|
||||||
|
x = rect->width - part->buffer->base.width;
|
||||||
|
} else if (theme->window_label_text_justify == LAB_JUSTIFY_LEFT) {
|
||||||
|
/* TODO: maybe add some theme x padding here? */
|
||||||
|
}
|
||||||
|
wlr_scene_node_set_position(part->node, x, y);
|
||||||
|
} FOR_EACH_END
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssd_update_title(struct view *view)
|
||||||
|
{
|
||||||
|
if (!view->ssd.tree) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *title = (char *)view_get_string_prop(view, "title");
|
||||||
|
if (!title || !*title) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct theme *theme = view->server->theme;
|
||||||
|
struct ssd_state_title *state = &view->ssd.state.title;
|
||||||
|
bool title_unchanged = state->text && !strcmp(title, state->text);
|
||||||
|
|
||||||
|
/* TODO: Do we only have active window fonts? */
|
||||||
|
struct font font = {
|
||||||
|
.name = rc.font_name_activewindow,
|
||||||
|
.size = rc.font_size_activewindow,
|
||||||
|
};
|
||||||
|
|
||||||
|
float *text_color;
|
||||||
|
struct wlr_scene_rect *rect;
|
||||||
|
struct ssd_part *part;
|
||||||
|
struct ssd_part *parent_part;
|
||||||
|
struct ssd_sub_tree *subtree;
|
||||||
|
struct ssd_state_title_width *dstate;
|
||||||
|
FOR_EACH_STATE(view, subtree) {
|
||||||
|
parent_part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLEBAR);
|
||||||
|
if (!parent_part) {
|
||||||
|
wlr_log(WLR_ERROR,
|
||||||
|
"Failed to update SSD title: parent node not found");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rect = lab_wlr_scene_get_rect(parent_part->node);
|
||||||
|
if (rect->width <= 0) {
|
||||||
|
wlr_log(WLR_ERROR,
|
||||||
|
"Failed to update SSD title: not enough screen space");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (subtree == &view->ssd.titlebar.active) {
|
||||||
|
dstate = &state->active;
|
||||||
|
text_color = theme->window_active_label_text_color;
|
||||||
|
} else {
|
||||||
|
dstate = &state->inactive;
|
||||||
|
text_color = theme->window_inactive_label_text_color;
|
||||||
|
}
|
||||||
|
if (title_unchanged
|
||||||
|
&& !dstate->truncated && dstate->width < rect->width) {
|
||||||
|
/* title the same + we don't need to resize title */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
part = ssd_get_part(&subtree->parts, LAB_SSD_PART_TITLE);
|
||||||
|
if (!part) {
|
||||||
|
part = add_scene_part(&subtree->parts, LAB_SSD_PART_TITLE);
|
||||||
|
}
|
||||||
|
if (part->node) {
|
||||||
|
wlr_scene_node_destroy(part->node);
|
||||||
|
}
|
||||||
|
font_buffer_update(
|
||||||
|
&part->buffer, rect->width, title, &font, text_color);
|
||||||
|
part->node = &wlr_scene_buffer_create(
|
||||||
|
parent_part->node, &part->buffer->base)->node;
|
||||||
|
dstate->width = part->buffer->base.width;
|
||||||
|
dstate->truncated = rect->width <= dstate->width;
|
||||||
|
} FOR_EACH_END
|
||||||
|
|
||||||
|
if (state->text) {
|
||||||
|
free(state->text);
|
||||||
|
}
|
||||||
|
state->text = strdup(title);
|
||||||
|
ssd_update_title_positions(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the wlr_scene_node for hover effect.
|
||||||
|
* To disable the hover effect later on just call
|
||||||
|
* wlr_scene_node_set_enabled(node, false).
|
||||||
|
*/
|
||||||
|
struct wlr_scene_node *
|
||||||
|
ssd_button_hover_enable(struct view *view, enum ssd_part_type type)
|
||||||
|
{
|
||||||
|
if (!view->ssd.tree) {
|
||||||
|
wlr_log(WLR_ERROR, "%s() for destroyed view", __func__);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(ssd_is_button(type));
|
||||||
|
struct ssd_part *part;
|
||||||
|
struct ssd_sub_tree *subtree;
|
||||||
|
FOR_EACH_STATE(view, subtree) {
|
||||||
|
if (subtree->tree->node.state.enabled) {
|
||||||
|
part = ssd_get_part(&subtree->parts, type);
|
||||||
|
if (!part) {
|
||||||
|
wlr_log(WLR_ERROR, "hover enable failed to find button");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
struct wlr_scene_node *child;
|
||||||
|
wl_list_for_each(child, &part->node->state.children, state.link) {
|
||||||
|
if (child->type == WLR_SCENE_NODE_RECT) {
|
||||||
|
wlr_scene_node_set_enabled(child, true);
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} FOR_EACH_END
|
||||||
|
|
||||||
|
wlr_log(WLR_ERROR, "hover enable failed to find button");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef FOR_EACH_STATE
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "xbm/xbm.h"
|
#include "xbm/xbm.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "ssd.h"
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hex_to_dec(char c)
|
hex_to_dec(char c)
|
||||||
|
|
@ -417,12 +418,11 @@ rounded_rect(struct rounded_corner_ctx *ctx)
|
||||||
static void
|
static void
|
||||||
create_corners(struct theme *theme)
|
create_corners(struct theme *theme)
|
||||||
{
|
{
|
||||||
int corner_square = theme->title_height + theme->border_width;
|
|
||||||
struct wlr_box box = {
|
struct wlr_box box = {
|
||||||
.x = 0,
|
.x = 0,
|
||||||
.y = 0,
|
.y = 0,
|
||||||
.width = corner_square,
|
.width = BUTTON_WIDTH,
|
||||||
.height = corner_square,
|
.height = SSD_HEIGHT,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rounded_corner_ctx ctx = {
|
struct rounded_corner_ctx ctx = {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@
|
||||||
void
|
void
|
||||||
view_set_activated(struct view *view, bool activated)
|
view_set_activated(struct view *view, bool activated)
|
||||||
{
|
{
|
||||||
|
if (view->ssd.enabled) {
|
||||||
|
ssd_set_active(view);
|
||||||
|
}
|
||||||
if (view->impl->set_activated) {
|
if (view->impl->set_activated) {
|
||||||
view->impl->set_activated(view, activated);
|
view->impl->set_activated(view, activated);
|
||||||
}
|
}
|
||||||
|
|
@ -258,7 +261,7 @@ view_toggle_decorations(struct view *view)
|
||||||
{
|
{
|
||||||
if (!view->fullscreen) {
|
if (!view->fullscreen) {
|
||||||
view->ssd.enabled = !view->ssd.enabled;
|
view->ssd.enabled = !view->ssd.enabled;
|
||||||
ssd_update_geometry(view, true);
|
ssd_update_geometry(view);
|
||||||
if (view->maximized) {
|
if (view->maximized) {
|
||||||
view_apply_maximized_geometry(view);
|
view_apply_maximized_geometry(view);
|
||||||
}
|
}
|
||||||
|
|
@ -270,7 +273,7 @@ view_set_decorations(struct view *view, bool decorations)
|
||||||
{
|
{
|
||||||
if (view->ssd.enabled != decorations && !view->fullscreen) {
|
if (view->ssd.enabled != decorations && !view->fullscreen) {
|
||||||
view->ssd.enabled = decorations;
|
view->ssd.enabled = decorations;
|
||||||
ssd_update_geometry(view, true);
|
ssd_update_geometry(view);
|
||||||
if (view->maximized) {
|
if (view->maximized) {
|
||||||
view_apply_maximized_geometry(view);
|
view_apply_maximized_geometry(view);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
src/xdg.c
11
src/xdg.c
|
|
@ -58,7 +58,7 @@ handle_commit(struct wl_listener *listener, void *data)
|
||||||
view->pending_move_resize.configure_serial = 0;
|
view->pending_move_resize.configure_serial = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ssd_update_geometry(view, false);
|
ssd_update_geometry(view);
|
||||||
damage_view_part(view);
|
damage_view_part(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -187,8 +187,8 @@ xdg_toplevel_view_configure(struct view *view, struct wlr_box geo)
|
||||||
} else if (view->pending_move_resize.configure_serial == 0) {
|
} else if (view->pending_move_resize.configure_serial == 0) {
|
||||||
view->x = geo.x;
|
view->x = geo.x;
|
||||||
view->y = geo.y;
|
view->y = geo.y;
|
||||||
ssd_update_geometry(view, false);
|
ssd_update_geometry(view);
|
||||||
damage_all_outputs(view->server);
|
//damage_all_outputs(view->server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef MAX
|
#undef MAX
|
||||||
|
|
@ -198,8 +198,6 @@ xdg_toplevel_view_move(struct view *view, double x, double y)
|
||||||
{
|
{
|
||||||
view->x = x;
|
view->x = x;
|
||||||
view->y = y;
|
view->y = y;
|
||||||
ssd_update_geometry(view, false);
|
|
||||||
damage_all_outputs(view->server);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -344,6 +342,7 @@ xdg_toplevel_view_unmap(struct view *view)
|
||||||
view->mapped = false;
|
view->mapped = false;
|
||||||
damage_all_outputs(view->server);
|
damage_all_outputs(view->server);
|
||||||
wlr_scene_node_destroy(view->scene_node);
|
wlr_scene_node_destroy(view->scene_node);
|
||||||
|
ssd_hide(view);
|
||||||
wl_list_remove(&view->commit.link);
|
wl_list_remove(&view->commit.link);
|
||||||
desktop_focus_topmost_mapped_view(view->server);
|
desktop_focus_topmost_mapped_view(view->server);
|
||||||
}
|
}
|
||||||
|
|
@ -390,9 +389,9 @@ xdg_surface_new(struct wl_listener *listener, void *data)
|
||||||
view->type = LAB_XDG_SHELL_VIEW;
|
view->type = LAB_XDG_SHELL_VIEW;
|
||||||
view->impl = &xdg_toplevel_view_impl;
|
view->impl = &xdg_toplevel_view_impl;
|
||||||
view->xdg_surface = xdg_surface;
|
view->xdg_surface = xdg_surface;
|
||||||
wl_list_init(&view->ssd.parts);
|
|
||||||
|
|
||||||
view->scene_tree = wlr_scene_tree_create(&view->server->view_tree->node);
|
view->scene_tree = wlr_scene_tree_create(&view->server->view_tree->node);
|
||||||
|
|
||||||
view->scene_node = wlr_scene_xdg_surface_create(
|
view->scene_node = wlr_scene_xdg_surface_create(
|
||||||
&view->scene_tree->node, view->xdg_surface);
|
&view->scene_tree->node, view->xdg_surface);
|
||||||
if (!view->scene_node) {
|
if (!view->scene_node) {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ handle_commit(struct wl_listener *listener, void *data)
|
||||||
view->pending_move_resize.height - view->h;
|
view->pending_move_resize.height - view->h;
|
||||||
view->pending_move_resize.update_y = false;
|
view->pending_move_resize.update_y = false;
|
||||||
}
|
}
|
||||||
ssd_update_geometry(view, false);
|
ssd_update_geometry(view);
|
||||||
damage_view_whole(view);
|
damage_view_whole(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -188,8 +188,6 @@ move(struct view *view, double x, double y)
|
||||||
struct wlr_xwayland_surface *s = view->xwayland_surface;
|
struct wlr_xwayland_surface *s = view->xwayland_surface;
|
||||||
wlr_xwayland_surface_configure(s, (int16_t)x, (int16_t)y,
|
wlr_xwayland_surface_configure(s, (int16_t)x, (int16_t)y,
|
||||||
(uint16_t)s->width, (uint16_t)s->height);
|
(uint16_t)s->width, (uint16_t)s->height);
|
||||||
ssd_update_geometry(view, false);
|
|
||||||
damage_all_outputs(view->server);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -313,6 +311,7 @@ unmap(struct view *view)
|
||||||
view->mapped = false;
|
view->mapped = false;
|
||||||
damage_all_outputs(view->server);
|
damage_all_outputs(view->server);
|
||||||
wl_list_remove(&view->commit.link);
|
wl_list_remove(&view->commit.link);
|
||||||
|
ssd_hide(view);
|
||||||
desktop_focus_topmost_mapped_view(view->server);
|
desktop_focus_topmost_mapped_view(view->server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -376,7 +375,6 @@ xwayland_surface_new(struct wl_listener *listener, void *data)
|
||||||
view->type = LAB_XWAYLAND_VIEW;
|
view->type = LAB_XWAYLAND_VIEW;
|
||||||
view->impl = &xwl_view_impl;
|
view->impl = &xwl_view_impl;
|
||||||
view->xwayland_surface = xsurface;
|
view->xwayland_surface = xsurface;
|
||||||
wl_list_init(&view->ssd.parts);
|
|
||||||
|
|
||||||
xsurface->data = view;
|
xsurface->data = view;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue