#include "node.h"
#include "ssd.h"
#include "common/scene-helpers.h"
+#include "workspaces.h"
static void
move_to_front(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 *
#include "buffer.h"
#include "key-state.h"
#include "labwc.h"
+#include "workspaces.h"
static void
change_vt(struct server *server, unsigned int vt)
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);
+ }
}
}
#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)
}
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;
}
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);
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;
}
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);
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;
}
#include "menu/menu.h"
#include "ssd.h"
#include "theme.h"
+#include "workspaces.h"
#define LAB_XDG_SHELL_VERSION (2)
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
#endif
server->menu_tree = wlr_scene_tree_create(&server->scene->tree);
+ workspaces_init(server);
+
output_init(server);
/*
void
server_finish(struct server *server)
{
-/* TODO: clean up various scene_tree nodes */
+
#if HAVE_XWAYLAND
wlr_xwayland_destroy(server->xwayland);
#endif
wlr_output_layout_destroy(server->output_layout);
wl_display_destroy(server->wl_display);
+
+ /* TODO: clean up various scene_tree nodes */
+ workspaces_destroy(server);
}
#include "labwc.h"
#include "ssd.h"
#include "menu/menu.h"
+#include "workspaces.h"
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
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);
#include "labwc.h"
#include "node.h"
#include "ssd.h"
+#include "workspaces.h"
static void
handle_new_xdg_popup(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(
#include "labwc.h"
#include "node.h"
#include "ssd.h"
+#include "workspaces.h"
static void
handle_commit(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;