mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
workspaces: Wire up workspaces
This commit is contained in:
parent
ae2fa1571b
commit
8c5157a098
7 changed files with 134 additions and 68 deletions
|
|
@ -6,6 +6,7 @@
|
|||
#include "node.h"
|
||||
#include "ssd.h"
|
||||
#include "common/scene-helpers.h"
|
||||
#include "workspaces.h"
|
||||
|
||||
static void
|
||||
move_to_front(struct view *view)
|
||||
|
|
@ -162,73 +163,80 @@ isfocusable(struct view *view)
|
|||
return (view->mapped || view->minimized);
|
||||
}
|
||||
|
||||
static bool
|
||||
has_focusable_view(struct wl_list *wl_list)
|
||||
static struct wl_list *
|
||||
get_prev_item(struct wl_list *item)
|
||||
{
|
||||
struct view *view;
|
||||
wl_list_for_each (view, wl_list, link) {
|
||||
if (isfocusable(view)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return item->prev;
|
||||
}
|
||||
|
||||
static struct wl_list *
|
||||
get_next_item(struct wl_list *item)
|
||||
{
|
||||
return item->next;
|
||||
}
|
||||
|
||||
static struct view *
|
||||
first_view(struct server *server)
|
||||
{
|
||||
struct view *view;
|
||||
view = wl_container_of(server->views.next, view, link);
|
||||
return view;
|
||||
struct wlr_scene_node *node;
|
||||
struct wl_list *list_head =
|
||||
&server->workspace_current->tree->children;
|
||||
wl_list_for_each_reverse(node, list_head, link) {
|
||||
return node_view_from_node(node);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct view *
|
||||
desktop_cycle_view(struct server *server, struct view *current,
|
||||
desktop_cycle_view(struct server *server, struct view *start_view,
|
||||
enum lab_cycle_dir dir)
|
||||
{
|
||||
if (!has_focusable_view(&server->views)) {
|
||||
struct view *view = start_view ? start_view : first_view(server);
|
||||
if (!view) {
|
||||
return NULL;
|
||||
}
|
||||
start_view = view;
|
||||
struct wlr_scene_node *node = &view->scene_tree->node;
|
||||
|
||||
struct view *view = current ? current : first_view(server);
|
||||
if (dir == LAB_CYCLE_DIR_FORWARD) {
|
||||
/* Replacement for wl_list_for_each_from() */
|
||||
do {
|
||||
view = wl_container_of(view->link.next, view, link);
|
||||
} while (&view->link == &server->views || !isfocusable(view));
|
||||
} else if (dir == LAB_CYCLE_DIR_BACKWARD) {
|
||||
do {
|
||||
view = wl_container_of(view->link.prev, view, link);
|
||||
} while (&view->link == &server->views || !isfocusable(view));
|
||||
}
|
||||
return view;
|
||||
}
|
||||
assert(node->parent);
|
||||
struct wl_list *list_head = &node->parent->children;
|
||||
struct wl_list *list_item = &node->link;
|
||||
struct wl_list *(*iter)(struct wl_list *);
|
||||
|
||||
static bool
|
||||
has_mapped_view(struct wl_list *wl_list)
|
||||
{
|
||||
struct view *view;
|
||||
wl_list_for_each (view, wl_list, link) {
|
||||
if (view->mapped) {
|
||||
return true;
|
||||
/* Scene nodes are ordered like last node == displayed topmost */
|
||||
iter = dir == LAB_CYCLE_DIR_FORWARD ? get_prev_item : get_next_item;
|
||||
|
||||
do {
|
||||
list_item = iter(list_item);
|
||||
if (list_item == list_head) {
|
||||
/* Start / End of list reached. Roll over */
|
||||
list_item = iter(list_item);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
node = wl_container_of(list_item, node, link);
|
||||
view = node_view_from_node(node);
|
||||
if (isfocusable(view)) {
|
||||
return view;
|
||||
}
|
||||
} while (view != start_view);
|
||||
|
||||
/* No focusable views found, including the one we started with */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct view *
|
||||
topmost_mapped_view(struct server *server)
|
||||
{
|
||||
if (!has_mapped_view(&server->views)) {
|
||||
return NULL;
|
||||
struct view *view;
|
||||
struct wl_list *node_list;
|
||||
struct wlr_scene_node *node;
|
||||
node_list = &server->workspace_current->tree->children;
|
||||
wl_list_for_each_reverse(node, node_list, link) {
|
||||
view = node_view_from_node(node);
|
||||
if (view->mapped) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
/* start from tail of server->views */
|
||||
struct view *view = wl_container_of(server->views.prev, view, link);
|
||||
do {
|
||||
view = wl_container_of(view->link.next, view, link);
|
||||
} while (&view->link == &server->views || !view->mapped);
|
||||
return view;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct view *
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "buffer.h"
|
||||
#include "key-state.h"
|
||||
#include "labwc.h"
|
||||
#include "workspaces.h"
|
||||
|
||||
static void
|
||||
change_vt(struct server *server, unsigned int vt)
|
||||
|
|
@ -38,17 +39,23 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data)
|
|||
struct seat *seat = wl_container_of(listener, seat, keyboard_modifiers);
|
||||
struct server *server = seat->server;
|
||||
|
||||
if (server->cycle_view) {
|
||||
if (server->cycle_view || seat->workspace_osd_shown_by_modifier) {
|
||||
struct wlr_keyboard_key_event *event = data;
|
||||
struct wlr_keyboard *keyboard = &seat->keyboard_group->keyboard;
|
||||
|
||||
if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED
|
||||
&& !keyboard_any_modifiers_pressed(keyboard)) {
|
||||
/* end cycle */
|
||||
desktop_focus_and_activate_view(&server->seat,
|
||||
server->cycle_view);
|
||||
desktop_move_to_front(server->cycle_view);
|
||||
server->cycle_view = NULL;
|
||||
osd_finish(server);
|
||||
if (server->cycle_view) {
|
||||
/* end cycle */
|
||||
desktop_focus_and_activate_view(&server->seat,
|
||||
server->cycle_view);
|
||||
desktop_move_to_front(server->cycle_view);
|
||||
server->cycle_view = NULL;
|
||||
osd_finish(server);
|
||||
}
|
||||
if (seat->workspace_osd_shown_by_modifier) {
|
||||
workspaces_osd_hide(seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
61
src/osd.c
61
src/osd.c
|
|
@ -10,6 +10,8 @@
|
|||
#include "config/rcxml.h"
|
||||
#include "labwc.h"
|
||||
#include "theme.h"
|
||||
#include "node.h"
|
||||
#include "workspaces.h"
|
||||
|
||||
#define OSD_ITEM_HEIGHT (20)
|
||||
#define OSD_ITEM_WIDTH (600)
|
||||
|
|
@ -78,11 +80,13 @@ get_formatted_app_id(struct view *view)
|
|||
}
|
||||
|
||||
static int
|
||||
get_osd_height(struct wl_list *views)
|
||||
get_osd_height(struct wl_list *node_list)
|
||||
{
|
||||
int height = 0;
|
||||
struct view *view;
|
||||
wl_list_for_each(view, views, link) {
|
||||
struct wlr_scene_node *node;
|
||||
wl_list_for_each(node, node_list, link) {
|
||||
view = node_view_from_node(node);
|
||||
if (!isfocusable(view)) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -115,21 +119,32 @@ osd_finish(struct server *server)
|
|||
void
|
||||
osd_update(struct server *server)
|
||||
{
|
||||
if (wl_list_empty(&server->views)) {
|
||||
struct wl_list *node_list =
|
||||
&server->workspace_current->tree->children;
|
||||
|
||||
if (wl_list_empty(node_list)) {
|
||||
osd_finish(server);
|
||||
return;
|
||||
}
|
||||
|
||||
struct theme *theme = server->theme;
|
||||
bool show_workspace = wl_list_length(&rc.workspace_config.workspaces) > 1;
|
||||
|
||||
struct buf buf;
|
||||
buf_init(&buf);
|
||||
|
||||
struct view *view;
|
||||
struct output *output;
|
||||
struct wlr_scene_node *node;
|
||||
wl_list_for_each(output, &server->outputs, link) {
|
||||
destroy_osd_nodes(output);
|
||||
float scale = output->wlr_output->scale;
|
||||
int w = (OSD_ITEM_WIDTH + (2 * OSD_BORDER_WIDTH));
|
||||
int h = get_osd_height(&server->views);
|
||||
int w = OSD_ITEM_WIDTH + (2 * OSD_BORDER_WIDTH);
|
||||
int h = get_osd_height(node_list);
|
||||
if (show_workspace) {
|
||||
/* workspace indicator */
|
||||
h += OSD_ITEM_HEIGHT;
|
||||
}
|
||||
|
||||
if (output->osd_buffer) {
|
||||
wlr_buffer_drop(&output->osd_buffer->base);
|
||||
|
|
@ -148,10 +163,16 @@ osd_update(struct server *server)
|
|||
set_source(cairo, theme->osd_border_color);
|
||||
draw_border(cairo, w, h, theme->osd_border_width);
|
||||
|
||||
/* highlight current window */
|
||||
int y = OSD_BORDER_WIDTH;
|
||||
struct view *view;
|
||||
wl_list_for_each(view, &server->views, link) {
|
||||
|
||||
if (show_workspace) {
|
||||
/* workspace indicator */
|
||||
y += OSD_ITEM_HEIGHT;
|
||||
}
|
||||
|
||||
/* highlight current window */
|
||||
wl_list_for_each_reverse(node, node_list, link) {
|
||||
view = node_view_from_node(node);
|
||||
if (!isfocusable(view)) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -179,7 +200,6 @@ osd_update(struct server *server)
|
|||
pango_font_description_set_family(desc, font.name);
|
||||
pango_font_description_set_size(desc, font.size * PANGO_SCALE);
|
||||
pango_layout_set_font_description(layout, desc);
|
||||
pango_font_description_free(desc);
|
||||
|
||||
PangoTabArray *tabs = pango_tab_array_new_with_positions(2, TRUE,
|
||||
PANGO_TAB_LEFT, OSD_TAB1, PANGO_TAB_LEFT, OSD_TAB2);
|
||||
|
|
@ -189,9 +209,28 @@ osd_update(struct server *server)
|
|||
pango_cairo_update_layout(cairo, layout);
|
||||
|
||||
y = OSD_BORDER_WIDTH;
|
||||
y += (OSD_ITEM_HEIGHT - font_height(&font)) / 2;
|
||||
|
||||
wl_list_for_each(view, &server->views, link) {
|
||||
/* Center text entries on the y axis */
|
||||
int y_offset = (OSD_ITEM_HEIGHT - font_height(&font)) / 2;
|
||||
y += y_offset;
|
||||
|
||||
if (show_workspace) {
|
||||
/* Center workspace indicator on the x axis */
|
||||
int x = font_width(&font, server->workspace_current->name);
|
||||
x = (OSD_ITEM_WIDTH - x) / 2;
|
||||
cairo_move_to(cairo, x, y);
|
||||
pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
|
||||
pango_layout_set_font_description(layout, desc);
|
||||
pango_layout_set_text(layout, server->workspace_current->name, -1);
|
||||
pango_cairo_show_layout(cairo, layout);
|
||||
pango_font_description_set_weight(desc, PANGO_WEIGHT_NORMAL);
|
||||
pango_layout_set_font_description(layout, desc);
|
||||
y += OSD_ITEM_HEIGHT;
|
||||
}
|
||||
pango_font_description_free(desc);
|
||||
|
||||
wl_list_for_each_reverse(node, node_list, link) {
|
||||
view = node_view_from_node(node);
|
||||
if (!isfocusable(view)) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "menu/menu.h"
|
||||
#include "ssd.h"
|
||||
#include "theme.h"
|
||||
#include "workspaces.h"
|
||||
|
||||
#define LAB_XDG_SHELL_VERSION (2)
|
||||
|
||||
|
|
@ -181,6 +182,7 @@ server_init(struct server *server)
|
|||
event_loop, SIGINT, handle_sigterm, server->wl_display);
|
||||
sigterm_source = wl_event_loop_add_signal(
|
||||
event_loop, SIGTERM, handle_sigterm, server->wl_display);
|
||||
server->wl_event_loop = event_loop;
|
||||
|
||||
/*
|
||||
* The backend is a feature which abstracts the underlying input and
|
||||
|
|
@ -245,6 +247,8 @@ server_init(struct server *server)
|
|||
#endif
|
||||
server->menu_tree = wlr_scene_tree_create(&server->scene->tree);
|
||||
|
||||
workspaces_init(server);
|
||||
|
||||
output_init(server);
|
||||
|
||||
/*
|
||||
|
|
@ -452,7 +456,7 @@ server_start(struct server *server)
|
|||
void
|
||||
server_finish(struct server *server)
|
||||
{
|
||||
/* TODO: clean up various scene_tree nodes */
|
||||
|
||||
#if HAVE_XWAYLAND
|
||||
wlr_xwayland_destroy(server->xwayland);
|
||||
#endif
|
||||
|
|
@ -465,4 +469,7 @@ server_finish(struct server *server)
|
|||
wlr_output_layout_destroy(server->output_layout);
|
||||
|
||||
wl_display_destroy(server->wl_display);
|
||||
|
||||
/* TODO: clean up various scene_tree nodes */
|
||||
workspaces_destroy(server);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "labwc.h"
|
||||
#include "ssd.h"
|
||||
#include "menu/menu.h"
|
||||
#include "workspaces.h"
|
||||
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
|
|
@ -336,8 +337,8 @@ void
|
|||
view_toggle_always_on_top(struct view *view)
|
||||
{
|
||||
if (is_always_on_top(view)) {
|
||||
wlr_scene_node_reparent(&view->scene_tree->node,
|
||||
view->server->view_tree);
|
||||
view->workspace = view->server->workspace_current;
|
||||
wlr_scene_node_reparent(&view->scene_tree->node, view->workspace->tree);
|
||||
} else {
|
||||
wlr_scene_node_reparent(&view->scene_tree->node,
|
||||
view->server->view_tree_always_on_top);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "labwc.h"
|
||||
#include "node.h"
|
||||
#include "ssd.h"
|
||||
#include "workspaces.h"
|
||||
|
||||
static void
|
||||
handle_new_xdg_popup(struct wl_listener *listener, void *data)
|
||||
|
|
@ -374,7 +375,8 @@ xdg_surface_new(struct wl_listener *listener, void *data)
|
|||
view->impl = &xdg_toplevel_view_impl;
|
||||
view->xdg_surface = xdg_surface;
|
||||
|
||||
view->scene_tree = wlr_scene_tree_create(view->server->view_tree);
|
||||
view->workspace = server->workspace_current;
|
||||
view->scene_tree = wlr_scene_tree_create(view->workspace->tree);
|
||||
wlr_scene_node_set_enabled(&view->scene_tree->node, false);
|
||||
|
||||
struct wlr_scene_tree *tree = wlr_scene_xdg_surface_create(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "labwc.h"
|
||||
#include "node.h"
|
||||
#include "ssd.h"
|
||||
#include "workspaces.h"
|
||||
|
||||
static void
|
||||
handle_commit(struct wl_listener *listener, void *data)
|
||||
|
|
@ -434,7 +435,8 @@ xwayland_surface_new(struct wl_listener *listener, void *data)
|
|||
view->impl = &xwl_view_impl;
|
||||
view->xwayland_surface = xsurface;
|
||||
|
||||
view->scene_tree = wlr_scene_tree_create(view->server->view_tree);
|
||||
view->workspace = server->workspace_current;
|
||||
view->scene_tree = wlr_scene_tree_create(view->workspace->tree);
|
||||
node_descriptor_create(&view->scene_tree->node,
|
||||
LAB_NODE_DESC_VIEW, view);
|
||||
xsurface->data = view;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue