hikari/src/workspace.c

1033 lines
34 KiB
C

#include <hikari/workspace.h>
#include <stdbool.h>
#include <stdlib.h>
#include <wlr/backend.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/render/wlr_texture.h>
#include <wlr/types/wlr_matrix.h>
#ifdef HAVE_XWAYLAND
#include <wlr/xwayland.h>
#endif
#include <hikari/color.h>
#include <hikari/configuration.h>
#include <hikari/group_assign_mode.h>
#include <hikari/indicator.h>
#include <hikari/indicator_frame.h>
#include <hikari/input_grab_mode.h>
#include <hikari/layout.h>
#include <hikari/mark_assign_mode.h>
#include <hikari/mark_select_mode.h>
#include <hikari/normal_mode.h>
#include <hikari/render_data.h>
#include <hikari/server.h>
#include <hikari/sheet.h>
#include <hikari/xdg_view.h>
#ifdef HAVE_XWAYLAND
#include <hikari/xwayland_view.h>
#endif
#define FOCUS_GUARD(workspace, view) \
struct hikari_view *view = workspace->focus_view; \
\
if (focus_view == NULL) { \
return; \
}
void
hikari_workspace_init(
struct hikari_workspace *workspace, struct hikari_output *output)
{
wl_list_init(&workspace->views);
wl_list_init(&hikari_server.visible_groups);
workspace->output = output;
workspace->focus_view = NULL;
workspace->sheets =
hikari_calloc(HIKARI_NR_OF_SHEETS, sizeof(struct hikari_sheet));
for (int i = 0; i < HIKARI_NR_OF_SHEETS; i++) {
hikari_sheet_init(&workspace->sheets[i], i, workspace);
}
workspace->alternate_sheet = &workspace->sheets[0];
workspace->sheet = &workspace->sheets[1];
#ifdef HAVE_LAYERSHELL
workspace->focus_layer = NULL;
#endif
wl_list_insert(hikari_server.workspaces.prev, &workspace->server_workspaces);
}
void
hikari_workspace_fini(struct hikari_workspace *workspace)
{
hikari_free(workspace->sheets);
wl_list_remove(&workspace->server_workspaces);
}
#define CYCLE_WORKSPACE(name) \
struct hikari_workspace *hikari_workspace_##name( \
struct hikari_workspace *workspace) \
{ \
struct wl_list *name = workspace->server_workspaces.name; \
\
if (name == &hikari_server.workspaces) { \
name = hikari_server.workspaces.name; \
} \
\
struct hikari_workspace *name##_workspace = \
wl_container_of(name, name##_workspace, server_workspaces); \
\
return name##_workspace; \
}
CYCLE_WORKSPACE(next)
CYCLE_WORKSPACE(prev)
#undef CYCLE_WORKSPACE
void
hikari_workspace_merge(
struct hikari_workspace *workspace, struct hikari_workspace *into)
{
assert(workspace != NULL);
assert(into != NULL);
for (int i = 0; i < HIKARI_NR_OF_SHEETS; i++) {
struct hikari_sheet *from = &workspace->sheets[i];
struct hikari_sheet *to = &into->sheets[i];
struct hikari_view *view, *view_temp;
wl_list_for_each_reverse_safe (view, view_temp, &from->views, sheet_views) {
hikari_view_evacuate(view, to);
}
}
}
void
hikari_workspace_quit_view(struct hikari_workspace *workspace)
{
struct hikari_view *focus_view = workspace->focus_view;
#ifdef HAVE_LAYERSHELL
struct hikari_layer *focus_layer = workspace->focus_layer;
if (focus_layer != NULL) {
assert(focus_view == NULL);
wlr_layer_surface_v1_close(focus_layer->surface);
return;
}
#endif
if (focus_view != NULL) {
#ifdef HAVE_LAYERSHELL
assert(focus_layer == NULL);
#endif
hikari_view_quit(focus_view);
hikari_server_cursor_focus();
}
}
void
hikari_workspace_clear(struct hikari_workspace *workspace)
{
struct hikari_view *view = NULL, *view_tmp = NULL;
wl_list_for_each_reverse_safe (
view, view_tmp, &(workspace->views), workspace_views) {
hikari_view_hide(view);
}
hikari_server_cursor_focus();
}
static void
display_sheet(struct hikari_workspace *workspace, struct hikari_sheet *sheet)
{
hikari_workspace_clear(workspace);
if (sheet != workspace->sheet) {
workspace->alternate_sheet = workspace->sheet;
workspace->sheet = sheet;
}
hikari_sheet_show(&workspace->sheets[0]);
if (sheet->nr != 0) {
hikari_sheet_show(sheet);
}
hikari_server_cursor_focus();
}
#define DISPLAY_SHEET(name, sheet) \
void hikari_workspace_display_sheet_##name( \
struct hikari_workspace *workspace) \
{ \
display_sheet(workspace, sheet); \
}
DISPLAY_SHEET(0, &workspace->sheets[0])
DISPLAY_SHEET(1, &workspace->sheets[1])
DISPLAY_SHEET(2, &workspace->sheets[2])
DISPLAY_SHEET(3, &workspace->sheets[3])
DISPLAY_SHEET(4, &workspace->sheets[4])
DISPLAY_SHEET(5, &workspace->sheets[5])
DISPLAY_SHEET(6, &workspace->sheets[6])
DISPLAY_SHEET(7, &workspace->sheets[7])
DISPLAY_SHEET(8, &workspace->sheets[8])
DISPLAY_SHEET(9, &workspace->sheets[9])
DISPLAY_SHEET(alternate, workspace->alternate_sheet)
DISPLAY_SHEET(current, workspace->sheet)
DISPLAY_SHEET(next, hikari_sheet_next(workspace->sheet))
DISPLAY_SHEET(prev, hikari_sheet_prev(workspace->sheet))
#undef DISPLAY_SHEET
void
hikari_workspace_switch_sheet(
struct hikari_workspace *workspace, struct hikari_sheet *sheet)
{
assert(workspace == sheet->workspace);
display_sheet(workspace, sheet);
}
void
hikari_workspace_switch_to_next_sheet(struct hikari_workspace *workspace)
{
if (workspace->sheet->nr == 0) {
return;
}
uint8_t nr = workspace->sheet->nr == 9 ? 1 : workspace->sheet->nr + 1;
display_sheet(workspace, &workspace->sheets[nr]);
}
void
hikari_workspace_switch_to_prev_sheet(struct hikari_workspace *workspace)
{
if (workspace->sheet->nr == 0) {
return;
}
uint8_t nr = workspace->sheet->nr == 1 ? 9 : workspace->sheet->nr - 1;
display_sheet(workspace, &workspace->sheets[nr]);
}
void
hikari_workspace_switch_to_next_inhabited_sheet(
struct hikari_workspace *workspace)
{
struct hikari_sheet *sheet = hikari_sheet_next_inhabited(workspace->sheet);
if (sheet == workspace->sheet) {
return;
}
display_sheet(workspace, sheet);
}
void
hikari_workspace_switch_to_prev_inhabited_sheet(
struct hikari_workspace *workspace)
{
struct hikari_sheet *sheet = hikari_sheet_prev_inhabited(workspace->sheet);
if (sheet == workspace->sheet) {
return;
}
display_sheet(workspace, sheet);
}
#define CYCLE_LAYOUT_VIEW(fallback, link) \
\
struct hikari_view *hikari_workspace_##fallback##_layout_view( \
struct hikari_workspace *workspace) \
{ \
struct hikari_layout *layout = workspace->sheet->layout; \
\
if (layout == NULL) { \
return NULL; \
} \
\
return hikari_layout_##fallback##_view(layout); \
} \
\
struct hikari_view *hikari_workspace_##link##_layout_view( \
struct hikari_workspace *workspace) \
{ \
struct hikari_layout *layout = workspace->sheet->layout; \
\
if (layout == NULL) { \
return NULL; \
} \
\
struct hikari_view *focus_view = workspace->focus_view; \
\
if (focus_view == NULL || !hikari_view_is_tiled(focus_view) || \
focus_view->sheet->layout != layout) { \
return hikari_layout_##fallback##_view(layout); \
} else { \
return hikari_tile_##link##_view(focus_view->tile); \
} \
}
CYCLE_LAYOUT_VIEW(first, next)
CYCLE_LAYOUT_VIEW(last, prev)
#undef CYCLE_LAYOUT_VIEW
#define CYCLE_GROUP_VIEW(link) \
struct hikari_view *hikari_workspace_##link##_group_view( \
struct hikari_workspace *workspace) \
{ \
struct hikari_view *focus_view = workspace->focus_view; \
if (focus_view == NULL) { \
return NULL; \
} \
\
return hikari_group_##link##_view(focus_view->group); \
}
CYCLE_GROUP_VIEW(first)
CYCLE_GROUP_VIEW(last)
#undef CYCLE_GROUP_VIEW
#define CYCLE_GROUP_VIEW(name, link) \
struct hikari_view *hikari_workspace_##name##_group_view( \
struct hikari_workspace *workspace) \
{ \
struct hikari_view *focus_view = workspace->focus_view; \
if (focus_view == NULL) { \
return NULL; \
} \
\
struct hikari_view *view; \
struct hikari_group *group = focus_view->group; \
struct wl_list *link = focus_view->visible_group_views.link; \
\
if (link != &group->visible_views) { \
view = wl_container_of( \
focus_view->visible_group_views.link, view, visible_group_views); \
} else { \
view = wl_container_of( \
group->visible_views.link, view, visible_group_views); \
} \
\
return view; \
}
CYCLE_GROUP_VIEW(next, prev)
CYCLE_GROUP_VIEW(prev, next)
#undef CYCLE_GROUP_VIEW
#define CYCLE_GROUP(name, link) \
struct hikari_view *hikari_workspace_##name##_group( \
struct hikari_workspace *workspace) \
{ \
if (wl_list_empty(&hikari_server.visible_groups)) { \
return NULL; \
} \
\
struct hikari_view *focus_view = workspace->focus_view; \
\
struct hikari_group *group; \
if (focus_view == NULL) { \
group = wl_container_of( \
hikari_server.visible_groups.link, group, visible_server_groups); \
} else { \
struct wl_list *link = focus_view->group->visible_server_groups.link; \
\
if (link != &hikari_server.visible_groups) { \
group = wl_container_of(link, group, visible_server_groups); \
} else { \
group = wl_container_of( \
hikari_server.visible_groups.link, group, visible_server_groups); \
} \
\
if (group == focus_view->group) { \
return focus_view; \
} \
} \
\
struct hikari_view *view = \
wl_container_of(group->visible_views.next, view, visible_group_views); \
\
return view; \
}
CYCLE_GROUP(next, prev)
CYCLE_GROUP(prev, next)
#undef CYCLE_GROUP
void
hikari_workspace_focus_view(
struct hikari_workspace *workspace, struct hikari_view *view)
{
#ifdef HAVE_LAYERSHELL
assert(workspace->focus_layer == NULL);
#endif
struct wlr_seat *seat = hikari_server.seat;
if (!hikari_server_in_normal_mode()) {
hikari_server_enter_normal_mode(NULL);
}
struct hikari_workspace *current_workspace = hikari_server.workspace;
struct hikari_view *focus_view = current_workspace->focus_view;
if (focus_view != NULL) {
if (hikari_server_is_indicating()) {
hikari_group_damage(focus_view->group);
hikari_indicator_damage(&hikari_server.indicator, focus_view);
} else {
hikari_view_damage_border(focus_view);
}
hikari_view_activate(focus_view, false);
}
wlr_seat_keyboard_end_grab(seat);
if (view != NULL) {
assert(!hikari_view_is_hidden(view));
struct wlr_keyboard *wlr_keyboard = wlr_seat_get_keyboard(seat);
hikari_view_activate(view, true);
if (wlr_keyboard != NULL) {
wlr_seat_keyboard_notify_enter(seat,
view->surface,
wlr_keyboard->keycodes,
wlr_keyboard->num_keycodes,
&wlr_keyboard->modifiers);
}
if (hikari_server_is_indicating()) {
if (focus_view == NULL || focus_view->group != view->group) {
hikari_group_damage(view->group);
}
} else {
hikari_view_damage_border(view);
}
hikari_indicator_update(&hikari_server.indicator,
view,
hikari_configuration->indicator_selected);
} else {
wlr_seat_keyboard_clear_focus(seat);
wlr_seat_pointer_clear_focus(seat);
hikari_cursor_reset_image(&hikari_server.cursor);
}
hikari_server.workspace = workspace;
workspace->focus_view = view;
}
void
hikari_workspace_raise_view(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
struct hikari_group *group = focus_view->group;
struct hikari_view *first = hikari_group_first_view(group);
hikari_view_raise(focus_view);
hikari_view_damage_border(first);
hikari_indicator_damage(&hikari_server.indicator, focus_view);
}
void
hikari_workspace_raise_group(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
hikari_group_raise(focus_view->group, focus_view);
hikari_indicator_damage(&hikari_server.indicator, focus_view);
}
void
hikari_workspace_lower_view(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
hikari_view_lower(focus_view);
struct hikari_group *group = focus_view->group;
struct hikari_view *first = hikari_group_first_view(group);
hikari_view_damage_border(first);
hikari_server_cursor_focus();
}
void
hikari_workspace_lower_group(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
hikari_group_lower(focus_view->group, focus_view);
hikari_indicator_damage(&hikari_server.indicator, focus_view);
hikari_server_cursor_focus();
}
void
hikari_workspace_hide_view(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
hikari_view_hide(focus_view);
hikari_server_cursor_focus();
}
void
hikari_workspace_only_view(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
struct hikari_view *view = NULL;
struct hikari_view *view_tmp;
wl_list_for_each_safe (view, view_tmp, &workspace->views, workspace_views) {
if (view != focus_view) {
hikari_view_hide(view);
}
}
hikari_server_cursor_focus();
}
void
hikari_workspace_move_resize_view(
struct hikari_workspace *workspace, int dx, int dy, int dwidth, int dheight)
{
FOCUS_GUARD(workspace, focus_view);
hikari_server_set_cycling();
hikari_view_move_resize(focus_view, dx, dy, dwidth, dheight);
}
void
hikari_workspace_snap_view_up(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
hikari_server_set_cycling();
struct wlr_box *view_geometry = hikari_view_geometry(focus_view);
int border = hikari_configuration->border;
int gap = hikari_configuration->gap;
int lookahead = view_geometry->y - border - gap;
int view_right = view_geometry->x + view_geometry->width;
int y;
bool found = false;
struct hikari_view *view = NULL;
struct wlr_box *geometry = NULL;
wl_list_for_each (view, &workspace->views, workspace_views) {
if (view == focus_view) {
continue;
}
geometry = hikari_view_geometry(view);
int right = geometry->x + geometry->width;
if (geometry->y + geometry->height + border < lookahead &&
((view_right >= geometry->x && geometry->x >= view_geometry->x) ||
(right >= view_geometry->x && view_geometry->x >= geometry->x))) {
found = true;
y = geometry->y + gap + geometry->height + border;
break;
}
}
if (!found) {
struct hikari_output *output = focus_view->output;
y = border + output->usable_area.y;
}
hikari_view_move_absolute(focus_view, view_geometry->x, y);
}
void
hikari_workspace_snap_view_down(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
hikari_server_set_cycling();
struct wlr_box *view_geometry = hikari_view_geometry(focus_view);
int border = hikari_configuration->border;
int gap = hikari_configuration->gap;
int lookahead = view_geometry->y + view_geometry->height + border + gap;
int view_right = view_geometry->x + view_geometry->width;
int y;
bool found = false;
struct hikari_view *view = NULL;
struct wlr_box *geometry = NULL;
wl_list_for_each (view, &workspace->views, workspace_views) {
if (view == focus_view) {
continue;
}
geometry = hikari_view_geometry(view);
int right = geometry->x + geometry->width;
if (geometry->y > lookahead &&
((view_right >= geometry->x && geometry->x >= view_geometry->x) ||
(right >= view_geometry->x && view_geometry->x >= geometry->x))) {
found = true;
y = geometry->y - gap - border - view_geometry->height;
break;
}
}
if (!found) {
struct hikari_output *output = focus_view->output;
y = output->usable_area.y + output->usable_area.height -
view_geometry->height - border;
}
hikari_view_move_absolute(focus_view, view_geometry->x, y);
}
void
hikari_workspace_snap_view_left(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
hikari_server_set_cycling();
struct wlr_box *view_geometry = hikari_view_geometry(focus_view);
int border = hikari_configuration->border;
int gap = hikari_configuration->gap;
int lookahead = view_geometry->x - gap - border;
int view_bottom = view_geometry->y + view_geometry->height;
int x;
bool found = false;
struct hikari_view *view = NULL;
struct wlr_box *geometry = NULL;
wl_list_for_each (view, &workspace->views, workspace_views) {
if (view == focus_view) {
continue;
}
geometry = hikari_view_geometry(view);
int bottom = geometry->y + geometry->height;
if (geometry->x + geometry->width + border < lookahead &&
((view_bottom >= geometry->y && geometry->y >= view_geometry->y) ||
(bottom >= view_geometry->y && view_geometry->y >= geometry->y))) {
found = true;
x = geometry->x + geometry->width + gap + border;
break;
}
}
if (!found) {
struct hikari_output *output = focus_view->output;
x = border + output->usable_area.x;
}
hikari_view_move_absolute(focus_view, x, view_geometry->y);
}
void
hikari_workspace_snap_view_right(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
hikari_server_set_cycling();
struct wlr_box *view_geometry = hikari_view_geometry(focus_view);
int border = hikari_configuration->border;
int gap = hikari_configuration->gap;
int lookahead = view_geometry->x + view_geometry->width + gap + border;
int view_bottom = view_geometry->y + view_geometry->height;
int x;
bool found = false;
struct hikari_view *view = NULL;
struct wlr_box *geometry = NULL;
wl_list_for_each (view, &workspace->views, workspace_views) {
if (view == focus_view) {
continue;
}
geometry = hikari_view_geometry(view);
int bottom = geometry->y + geometry->height;
if (geometry->x > lookahead &&
((view_bottom >= geometry->y && geometry->y >= view_geometry->y) ||
(bottom >= view_geometry->y && view_geometry->y >= geometry->y))) {
found = true;
x = geometry->x - gap - view_geometry->width - border;
break;
}
}
if (!found) {
struct hikari_output *output = focus_view->output;
x = output->usable_area.x + output->usable_area.width -
view_geometry->width - border;
}
hikari_view_move_absolute(focus_view, x, view_geometry->y);
}
static void
pin_to_sheet(struct hikari_workspace *workspace, struct hikari_sheet *sheet)
{
FOCUS_GUARD(workspace, focus_view);
hikari_view_pin_to_sheet(focus_view, sheet);
if (!hikari_view_is_hidden(focus_view)) {
struct hikari_output *output = workspace->output;
hikari_indicator_update_sheet(&hikari_server.indicator,
output,
focus_view->sheet,
focus_view->flags,
hikari_configuration->indicator_selected);
}
}
#define PIN_TO_SHEET(name, sheet) \
void hikari_workspace_pin_view_to_sheet_##name( \
struct hikari_workspace *workspace) \
{ \
pin_to_sheet(workspace, sheet); \
}
PIN_TO_SHEET(0, &workspace->sheets[0])
PIN_TO_SHEET(1, &workspace->sheets[1])
PIN_TO_SHEET(2, &workspace->sheets[2])
PIN_TO_SHEET(3, &workspace->sheets[3])
PIN_TO_SHEET(4, &workspace->sheets[4])
PIN_TO_SHEET(5, &workspace->sheets[5])
PIN_TO_SHEET(6, &workspace->sheets[6])
PIN_TO_SHEET(7, &workspace->sheets[7])
PIN_TO_SHEET(8, &workspace->sheets[8])
PIN_TO_SHEET(9, &workspace->sheets[9])
PIN_TO_SHEET(alternate, workspace->alternate_sheet)
PIN_TO_SHEET(current, workspace->sheet)
PIN_TO_SHEET(next, hikari_sheet_next(workspace->sheet))
PIN_TO_SHEET(prev, hikari_sheet_prev(workspace->sheet))
#undef PIN_TO_SHEET
#define MAXIMIZE(n) \
void hikari_workspace_toggle_view_##n##_maximize( \
struct hikari_workspace *workspace) \
{ \
FOCUS_GUARD(workspace, focus_view); \
\
hikari_view_toggle_##n##_maximize(focus_view); \
}
MAXIMIZE(full)
MAXIMIZE(vertical)
MAXIMIZE(horizontal)
#undef MAXIMIZE
void
hikari_workspace_toggle_view_invisible(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
hikari_view_toggle_invisible(focus_view);
struct hikari_output *output = workspace->output;
struct hikari_indicator *indicator = &hikari_server.indicator;
struct wlr_box *geometry = hikari_view_border_geometry(focus_view);
if (hikari_server_is_indicating()) {
hikari_indicator_damage_sheet(indicator, output, geometry);
}
hikari_indicator_update_sheet(indicator,
output,
focus_view->sheet,
focus_view->flags,
hikari_configuration->indicator_selected);
if (hikari_server_is_indicating()) {
hikari_indicator_damage_sheet(indicator, output, geometry);
}
}
void
hikari_workspace_toggle_view_public(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
hikari_view_toggle_public(focus_view);
struct hikari_output *output = workspace->output;
struct hikari_indicator *indicator = &hikari_server.indicator;
struct wlr_box *geometry = hikari_view_border_geometry(focus_view);
if (hikari_server_is_indicating()) {
hikari_indicator_damage_sheet(indicator, output, geometry);
}
hikari_indicator_update_sheet(indicator,
output,
focus_view->sheet,
focus_view->flags,
hikari_configuration->indicator_selected);
if (hikari_server_is_indicating()) {
hikari_indicator_damage_sheet(indicator, output, geometry);
}
}
void
hikari_workspace_toggle_view_floating(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
hikari_view_toggle_floating(focus_view);
struct hikari_output *output = workspace->output;
struct hikari_indicator *indicator = &hikari_server.indicator;
struct wlr_box *geometry = hikari_view_border_geometry(focus_view);
if (hikari_server_is_indicating()) {
hikari_indicator_damage_sheet(indicator, output, geometry);
}
hikari_indicator_update_sheet(indicator,
output,
focus_view->sheet,
focus_view->flags,
hikari_configuration->indicator_selected);
if (hikari_server_is_indicating()) {
hikari_indicator_damage_sheet(indicator, output, geometry);
}
}
void
hikari_workspace_show_invisible_sheet_views(struct hikari_workspace *workspace)
{
hikari_workspace_clear(workspace);
hikari_sheet_show_invisible(workspace->sheet);
hikari_server_cursor_focus();
}
void
hikari_workspace_reset_view_geometry(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
hikari_view_reset_geometry(focus_view);
}
#define VIEW_EXCHANGE(link) \
void hikari_workspace_exchange_##link##_view( \
struct hikari_workspace *workspace) \
{ \
struct hikari_view *focus_view = workspace->focus_view; \
struct hikari_layout *layout = workspace->sheet->layout; \
\
if (focus_view == NULL || layout == NULL || \
!hikari_view_is_tiled(focus_view)) { \
return; \
} \
\
struct hikari_view *link = hikari_tile_##link##_view(focus_view->tile); \
\
assert(!hikari_view_is_hidden(link)); \
\
if (focus_view == link) { \
return; \
} \
\
hikari_view_exchange(focus_view, link); \
}
VIEW_EXCHANGE(prev)
VIEW_EXCHANGE(next)
#undef VIEW_EXCHANGE
void
hikari_workspace_exchange_main_layout_view(struct hikari_workspace *workspace)
{
struct hikari_view *focus_view = workspace->focus_view;
struct hikari_layout *layout = workspace->sheet->layout;
if (focus_view == NULL || layout == NULL ||
!hikari_view_is_tiled(focus_view) || hikari_view_is_dirty(focus_view)) {
return;
}
struct hikari_view *first = hikari_layout_first_view(layout);
if (focus_view == first || hikari_view_is_hidden(first) ||
hikari_view_is_dirty(first)) {
return;
}
hikari_view_exchange(focus_view, first);
hikari_view_center_cursor(first);
}
void
hikari_workspace_only_group(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
struct hikari_group *group = focus_view->group;
struct hikari_view *view = NULL, *view_temp = NULL;
wl_list_for_each_safe (view, view_temp, &workspace->views, workspace_views) {
if (view->group != group) {
hikari_view_hide(view);
}
}
}
void
hikari_workspace_sheet_show_group(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
struct hikari_group *group = focus_view->group;
hikari_view_raise(focus_view);
hikari_workspace_clear(workspace);
hikari_sheet_show_group(workspace->sheet, group);
hikari_server_cursor_focus();
}
void
hikari_workspace_show_group(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
struct hikari_group *group = focus_view->group;
hikari_workspace_clear(workspace);
hikari_group_show(group);
hikari_server_cursor_focus();
}
#define SHOW_VIEWS(cond) \
{ \
struct hikari_view *view, *view_temp, *top = NULL; \
wl_list_for_each_reverse_safe ( \
view, view_temp, &workspace->output->views, output_views) { \
if (cond) { \
if (top == view) { \
break; \
} \
\
if (top == NULL) { \
top = view; \
} \
\
hikari_view_show(view); \
} \
} \
}
void
hikari_workspace_show_all(struct hikari_workspace *workspace)
{
hikari_workspace_clear(workspace);
SHOW_VIEWS(true);
hikari_server_cursor_focus();
}
void
hikari_workspace_show_invisible(struct hikari_workspace *workspace)
{
hikari_workspace_clear(workspace);
SHOW_VIEWS(hikari_view_is_invisible(view));
hikari_server_cursor_focus();
}
#undef SHOW_VIEWS
void
hikari_workspace_hide_group(struct hikari_workspace *workspace)
{
FOCUS_GUARD(workspace, focus_view);
struct hikari_group *group = focus_view->group;
hikari_group_hide(group);
hikari_server_cursor_focus();
}
void
hikari_workspace_show_all_sheet_views(struct hikari_workspace *workspace)
{
struct hikari_sheet *sheet = workspace->sheet;
hikari_workspace_clear(workspace);
hikari_sheet_show_all(sheet);
hikari_server_cursor_focus();
}
void
hikari_workspace_apply_split(
struct hikari_workspace *workspace, struct hikari_split *split)
{
assert(workspace != NULL);
assert(split != NULL);
struct hikari_view *focus_view = workspace->focus_view;
struct hikari_sheet *sheet = workspace->sheet;
if (focus_view != NULL && focus_view->sheet == sheet &&
hikari_view_is_tileable(focus_view)) {
hikari_view_raise(focus_view);
assert(focus_view == hikari_sheet_first_tileable_view(sheet));
}
hikari_workspace_display_sheet_current(workspace);
hikari_sheet_apply_split(sheet, split);
}
void
hikari_workspace_center_cursor(struct hikari_workspace *workspace)
{
struct hikari_output *output = workspace->output;
hikari_cursor_center(&hikari_server.cursor, output, &output->usable_area);
}
struct hikari_view *
hikari_workspace_first_view(struct hikari_workspace *workspace)
{
assert(workspace != NULL);
struct hikari_view *view;
if (workspace->focus_view != NULL) {
view = workspace->focus_view;
} else {
view = hikari_sheet_first_view(workspace->sheet);
}
return view;
}
#undef FOCUS_GUARD