Remove layout.c

When we have type safety we'll need to have functions for
workspace_add_tiling and so on. This means the existing container
functions will be just for containers, so they are being moved to
container.c. At this point layout.c doesn't contain much else, so I've
relocated everything and removed the file.

* container_swap and its static functions have been moved to the swap
command and made static.
* container_recursive_resize has been moved to the resize command and
made static.
* The following have been moved to container.c:
    * container_handle_fullscreen_reparent
    * container_insert_child
    * container_add_sibling
    * container_add_child
    * container_remove_child
    * container_replace_child
    * container_split
* enum movement_direction and sway_dir_to_wlr have been moved to util.c.

Side note: Several commands included layout.h which then included
root.h. With layout.h gone, root.h has to be included by those commands.
This commit is contained in:
Ryan Dwyer 2018-08-26 12:05:16 +10:00
parent 1a30c50ef4
commit 5dbbab7bdc
38 changed files with 449 additions and 479 deletions

View File

@ -175,3 +175,24 @@ failed:
free(current);
return NULL;
}
bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out) {
switch (dir) {
case MOVE_UP:
*out = WLR_DIRECTION_UP;
break;
case MOVE_DOWN:
*out = WLR_DIRECTION_DOWN;
break;
case MOVE_LEFT:
*out = WLR_DIRECTION_LEFT;
break;
case MOVE_RIGHT:
*out = WLR_DIRECTION_RIGHT;
break;
default:
return false;
}
return true;
}

View File

@ -8,8 +8,8 @@
#include <xkbcommon/xkbcommon.h>
#include "list.h"
#include "swaynag.h"
#include "tree/layout.h"
#include "tree/container.h"
#include "sway/tree/root.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"
// TODO: Refactor this shit

View File

@ -53,6 +53,9 @@ struct sway_output;
struct sway_workspace;
struct sway_view;
enum movement_direction;
enum wlr_direction;
struct sway_container_state {
// Container/swayc properties
enum sway_container_layout layout;
@ -341,4 +344,29 @@ void container_add_gaps(struct sway_container *container);
int container_sibling_index(const struct sway_container *child);
void container_handle_fullscreen_reparent(struct sway_container *con,
struct sway_container *old_parent);
void container_add_child(struct sway_container *parent,
struct sway_container *child);
void container_insert_child(struct sway_container *parent,
struct sway_container *child, int i);
struct sway_container *container_add_sibling(struct sway_container *parent,
struct sway_container *child);
struct sway_container *container_remove_child(struct sway_container *child);
struct sway_container *container_replace_child(struct sway_container *child,
struct sway_container *new_child);
bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out);
enum sway_container_layout container_get_default_layout(
struct sway_container *con);
struct sway_container *container_split(struct sway_container *child,
enum sway_container_layout layout);
#endif

View File

@ -1,52 +0,0 @@
#ifndef _SWAY_LAYOUT_H
#define _SWAY_LAYOUT_H
#include <wlr/types/wlr_output_layout.h>
#include <wlr/render/wlr_texture.h>
#include "sway/tree/container.h"
#include "sway/tree/root.h"
#include "config.h"
enum movement_direction {
MOVE_LEFT,
MOVE_RIGHT,
MOVE_UP,
MOVE_DOWN,
MOVE_PARENT,
MOVE_CHILD,
};
enum wlr_edges;
struct sway_container;
void container_handle_fullscreen_reparent(struct sway_container *con,
struct sway_container *old_parent);
void container_add_child(struct sway_container *parent,
struct sway_container *child);
void container_insert_child(struct sway_container *parent,
struct sway_container *child, int i);
struct sway_container *container_add_sibling(struct sway_container *parent,
struct sway_container *child);
struct sway_container *container_remove_child(struct sway_container *child);
struct sway_container *container_replace_child(struct sway_container *child,
struct sway_container *new_child);
bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out);
enum sway_container_layout container_get_default_layout(
struct sway_container *con);
struct sway_container *container_split(struct sway_container *child,
enum sway_container_layout layout);
void container_recursive_resize(struct sway_container *container,
double amount, enum wlr_edges edge);
void container_swap(struct sway_container *con1, struct sway_container *con2);
#endif

View File

@ -4,9 +4,19 @@
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/types.h>
#include <wlr/types/wlr_output_layout.h>
#include <xkbcommon/xkbcommon.h>
enum movement_direction {
MOVE_LEFT,
MOVE_RIGHT,
MOVE_UP,
MOVE_DOWN,
MOVE_PARENT,
MOVE_CHILD,
};
/**
* Wrap i into the range [0, max[
*/
@ -71,4 +81,6 @@ char* resolve_path(const char* path);
char *b64_encode(const char* binaryData, size_t len, size_t *flen);
unsigned char *b64_decode(const char *ascii, size_t len, size_t *flen);
bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out);
#endif

View File

@ -8,6 +8,7 @@
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/tree/container.h"
#include "sway/tree/root.h"
#include "sway/tree/workspace.h"
#include "log.h"
#include "stringop.h"

View File

@ -6,7 +6,6 @@
#include "sway/output.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "list.h"

View File

@ -6,9 +6,11 @@
#include "sway/input/seat.h"
#include "sway/output.h"
#include "sway/tree/arrange.h"
#include "sway/tree/root.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "stringop.h"
#include "util.h"
static bool parse_movement_direction(const char *name,
enum movement_direction *out) {

View File

@ -5,7 +5,6 @@
#include "sway/tree/container.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "sway/tree/layout.h"
#include "util.h"
struct cmd_results *cmd_fullscreen(int argc, char **argv) {

View File

@ -1,6 +1,7 @@
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/tree/container.h"
#include "sway/tree/root.h"
#include "sway/tree/view.h"
static void _configure_view(struct sway_container *con, void *data) {

View File

@ -19,6 +19,7 @@
#include "stringop.h"
#include "list.h"
#include "log.h"
#include "util.h"
static const char *expected_syntax =
"Expected 'move <left|right|up|down> <[px] px>' or "

View File

@ -1,7 +1,6 @@
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/output.h"
#include "sway/tree/layout.h"
#include "list.h"
#include "log.h"

View File

@ -159,6 +159,27 @@ static int parallel_size(struct sway_container *c, enum resize_axis a) {
return normalize_axis(a) == RESIZE_AXIS_HORIZONTAL ? c->width : c->height;
}
static void container_recursive_resize(struct sway_container *container,
double amount, enum wlr_edges edge) {
bool layout_match = true;
wlr_log(WLR_DEBUG, "Resizing %p with amount: %f", container, amount);
if (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_RIGHT) {
container->width += amount;
layout_match = container->layout == L_HORIZ;
} else if (edge == WLR_EDGE_TOP || edge == WLR_EDGE_BOTTOM) {
container->height += amount;
layout_match = container->layout == L_VERT;
}
if (container->children) {
for (int i = 0; i < container->children->length; i++) {
struct sway_container *child = container->children->items[i];
double amt = layout_match ?
amount / container->children->length : amount;
container_recursive_resize(child, amt, edge);
}
}
}
static void resize_tiled(struct sway_container *parent, int amount,
enum resize_axis axis) {
struct sway_container *focused = parent;

View File

@ -2,6 +2,7 @@
#include <string.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/tree/root.h"
#include "sway/tree/view.h"
#include "sway/output.h"
#include "list.h"

View File

@ -6,7 +6,6 @@
#include "sway/output.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "list.h"

View File

@ -1,15 +1,141 @@
#define _POSIX_C_SOURCE 200809L
#include <strings.h>
#include <wlr/util/log.h>
#include "config.h"
#include "log.h"
#include "sway/commands.h"
#include "sway/tree/arrange.h"
#include "sway/tree/layout.h"
#include "sway/tree/root.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "stringop.h"
static const char* EXPECTED_SYNTAX =
"Expected 'swap container with id|con_id|mark <arg>'";
static void swap_places(struct sway_container *con1,
struct sway_container *con2) {
struct sway_container *temp = malloc(sizeof(struct sway_container));
temp->x = con1->x;
temp->y = con1->y;
temp->width = con1->width;
temp->height = con1->height;
temp->parent = con1->parent;
con1->x = con2->x;
con1->y = con2->y;
con1->width = con2->width;
con1->height = con2->height;
con2->x = temp->x;
con2->y = temp->y;
con2->width = temp->width;
con2->height = temp->height;
int temp_index = container_sibling_index(con1);
container_insert_child(con2->parent, con1, container_sibling_index(con2));
container_insert_child(temp->parent, con2, temp_index);
free(temp);
}
static void swap_focus(struct sway_container *con1,
struct sway_container *con2, struct sway_seat *seat,
struct sway_container *focus) {
if (focus == con1 || focus == con2) {
struct sway_container *ws1 = container_parent(con1, C_WORKSPACE);
struct sway_container *ws2 = container_parent(con2, C_WORKSPACE);
if (focus == con1 && (con2->parent->layout == L_TABBED
|| con2->parent->layout == L_STACKED)) {
if (workspace_is_visible(ws2)) {
seat_set_focus_warp(seat, con2, false, true);
}
seat_set_focus(seat, ws1 != ws2 ? con2 : con1);
} else if (focus == con2 && (con1->parent->layout == L_TABBED
|| con1->parent->layout == L_STACKED)) {
if (workspace_is_visible(ws1)) {
seat_set_focus_warp(seat, con1, false, true);
}
seat_set_focus(seat, ws1 != ws2 ? con1 : con2);
} else if (ws1 != ws2) {
seat_set_focus(seat, focus == con1 ? con2 : con1);
} else {
seat_set_focus(seat, focus);
}
} else {
seat_set_focus(seat, focus);
}
}
static void container_swap(struct sway_container *con1,
struct sway_container *con2) {
if (!sway_assert(con1 && con2, "Cannot swap with nothing")) {
return;
}
if (!sway_assert(con1->type >= C_CONTAINER && con2->type >= C_CONTAINER,
"Can only swap containers and views")) {
return;
}
if (!sway_assert(!container_has_ancestor(con1, con2)
&& !container_has_ancestor(con2, con1),
"Cannot swap ancestor and descendant")) {
return;
}
if (!sway_assert(!container_is_floating(con1)
&& !container_is_floating(con2),
"Swapping with floating containers is not supported")) {
return;
}
wlr_log(WLR_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id);
int fs1 = con1->is_fullscreen;
int fs2 = con2->is_fullscreen;
if (fs1) {
container_set_fullscreen(con1, false);
}
if (fs2) {
container_set_fullscreen(con2, false);
}
struct sway_seat *seat = input_manager_get_default_seat(input_manager);
struct sway_container *focus = seat_get_focus(seat);
struct sway_container *vis1 = container_parent(
seat_get_focus_inactive(seat, container_parent(con1, C_OUTPUT)),
C_WORKSPACE);
struct sway_container *vis2 = container_parent(
seat_get_focus_inactive(seat, container_parent(con2, C_OUTPUT)),
C_WORKSPACE);
char *stored_prev_name = NULL;
if (prev_workspace_name) {
stored_prev_name = strdup(prev_workspace_name);
}
swap_places(con1, con2);
if (!workspace_is_visible(vis1)) {
seat_set_focus(seat, seat_get_focus_inactive(seat, vis1));
}
if (!workspace_is_visible(vis2)) {
seat_set_focus(seat, seat_get_focus_inactive(seat, vis2));
}
swap_focus(con1, con2, seat, focus);
if (stored_prev_name) {
free(prev_workspace_name);
prev_workspace_name = stored_prev_name;
}
if (fs1) {
container_set_fullscreen(con2, true);
}
if (fs2) {
container_set_fullscreen(con1, true);
}
}
static bool test_con_id(struct sway_container *container, void *con_id) {
return container->id == (size_t)con_id;
}

View File

@ -2,6 +2,7 @@
#include <string.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/tree/root.h"
#include "sway/tree/view.h"
#include "list.h"
#include "log.h"

View File

@ -4,7 +4,6 @@
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/view.h"
#include "sway/tree/layout.h"
#include "util.h"
struct cmd_results *cmd_urgent(int argc, char **argv) {

View File

@ -27,7 +27,7 @@
#include "sway/criteria.h"
#include "sway/swaynag.h"
#include "sway/tree/arrange.h"
#include "sway/tree/layout.h"
#include "sway/tree/root.h"
#include "sway/tree/workspace.h"
#include "cairo.h"
#include "pango.h"

View File

@ -9,6 +9,7 @@
#include <wlr/types/wlr_output_layout.h>
#include "sway/config.h"
#include "sway/output.h"
#include "sway/tree/root.h"
#include "log.h"
int output_name_cmp(const void *item, const void *data) {

View File

@ -6,6 +6,7 @@
#include "sway/criteria.h"
#include "sway/tree/container.h"
#include "sway/config.h"
#include "sway/tree/root.h"
#include "sway/tree/view.h"
#include "stringop.h"
#include "list.h"

View File

@ -9,7 +9,7 @@
#include "sway/output.h"
#include "sway/server.h"
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/tree/root.h"
#include "cairo.h"
#include "config.h"
#include "pango.h"

View File

@ -14,7 +14,6 @@
#include "sway/output.h"
#include "sway/server.h"
#include "sway/tree/arrange.h"
#include "sway/tree/layout.h"
#include "log.h"
static void apply_exclusive(struct wlr_box *usable_area,

View File

@ -23,7 +23,7 @@
#include "sway/server.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/tree/root.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"

View File

@ -24,7 +24,7 @@
#include "sway/server.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/tree/root.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"

View File

@ -13,7 +13,6 @@
#include "sway/server.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/tree/view.h"
static const struct sway_view_child_impl popup_impl;

View File

@ -12,7 +12,6 @@
#include "sway/server.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/tree/view.h"
static const struct sway_view_child_impl popup_impl;

View File

@ -14,7 +14,6 @@
#include "sway/server.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/tree/view.h"
static const char *atom_map[ATOM_LAST] = {

View File

@ -20,6 +20,7 @@
#include "sway/layers.h"
#include "sway/output.h"
#include "sway/tree/arrange.h"
#include "sway/tree/root.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"

View File

@ -25,10 +25,9 @@
#include "sway/output.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/container.h"
#include "sway/tree/root.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "sway/tree/workspace.h"
static void seat_device_destroy(struct sway_seat_device *seat_device) {
if (!seat_device) {

View File

@ -31,6 +31,7 @@
#include "sway/server.h"
#include "sway/input/input-manager.h"
#include "sway/input/seat.h"
#include "sway/tree/root.h"
#include "sway/tree/view.h"
#include "list.h"
#include "log.h"

View File

@ -23,7 +23,7 @@
#include "sway/desktop/transaction.h"
#include "sway/server.h"
#include "sway/swaynag.h"
#include "sway/tree/layout.h"
#include "sway/tree/root.h"
#include "sway/ipc-server.h"
#include "ipc-client.h"
#include "readline.h"

View File

@ -150,7 +150,6 @@ sway_sources = files(
'tree/arrange.c',
'tree/container.c',
'tree/layout.c',
'tree/root.c',
'tree/view.c',
'tree/workspace.c',

View File

@ -24,7 +24,7 @@
#include "sway/desktop/idle_inhibit_v1.h"
#include "sway/input/input-manager.h"
#include "sway/server.h"
#include "sway/tree/layout.h"
#include "sway/tree/root.h"
#include "config.h"
#ifdef HAVE_XWAYLAND
#include "sway/xwayland.h"

View File

@ -7,7 +7,6 @@
#include <wlr/types/wlr_output_layout.h>
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/output.h"
#include "sway/tree/workspace.h"
#include "sway/tree/view.h"

View File

@ -19,7 +19,6 @@
#include "sway/output.h"
#include "sway/server.h"
#include "sway/tree/arrange.h"
#include "sway/tree/layout.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "log.h"
@ -1159,3 +1158,223 @@ void container_add_gaps(struct sway_container *c) {
int container_sibling_index(const struct sway_container *child) {
return list_find(child->parent->children, child);
}
void container_handle_fullscreen_reparent(struct sway_container *con,
struct sway_container *old_parent) {
if (!con->is_fullscreen) {
return;
}
struct sway_container *old_workspace = old_parent;
if (old_workspace && old_workspace->type != C_WORKSPACE) {
old_workspace = container_parent(old_workspace, C_WORKSPACE);
}
struct sway_container *new_workspace = container_parent(con, C_WORKSPACE);
if (old_workspace == new_workspace) {
return;
}
// Unmark the old workspace as fullscreen
if (old_workspace) {
old_workspace->sway_workspace->fullscreen = NULL;
}
// Mark the new workspace as fullscreen
if (new_workspace->sway_workspace->fullscreen) {
container_set_fullscreen(
new_workspace->sway_workspace->fullscreen, false);
}
new_workspace->sway_workspace->fullscreen = con;
// Resize container to new output dimensions
struct sway_container *output = new_workspace->parent;
con->x = output->x;
con->y = output->y;
con->width = output->width;
con->height = output->height;
if (con->type == C_VIEW) {
struct sway_view *view = con->sway_view;
view->x = output->x;
view->y = output->y;
view->width = output->width;
view->height = output->height;
} else {
arrange_windows(new_workspace);
}
}
void container_insert_child(struct sway_container *parent,
struct sway_container *child, int i) {
struct sway_container *old_parent = child->parent;
if (old_parent) {
container_remove_child(child);
}
wlr_log(WLR_DEBUG, "Inserting id:%zd at index %d", child->id, i);
list_insert(parent->children, i, child);
child->parent = parent;
container_handle_fullscreen_reparent(child, old_parent);
}
struct sway_container *container_add_sibling(struct sway_container *fixed,
struct sway_container *active) {
// TODO handle floating
struct sway_container *old_parent = NULL;
if (active->parent) {
old_parent = active->parent;
container_remove_child(active);
}
struct sway_container *parent = fixed->parent;
int i = container_sibling_index(fixed);
list_insert(parent->children, i + 1, active);
active->parent = parent;
container_handle_fullscreen_reparent(active, old_parent);
return active->parent;
}
void container_add_child(struct sway_container *parent,
struct sway_container *child) {
wlr_log(WLR_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)",
child, child->type, child->width, child->height,
parent, parent->type, parent->width, parent->height);
struct sway_container *old_parent = child->parent;
list_add(parent->children, child);
child->parent = parent;
container_handle_fullscreen_reparent(child, old_parent);
if (old_parent) {
container_set_dirty(old_parent);
}
container_set_dirty(child);
}
struct sway_container *container_remove_child(struct sway_container *child) {
if (child->is_fullscreen) {
struct sway_container *workspace = container_parent(child, C_WORKSPACE);
workspace->sway_workspace->fullscreen = NULL;
}
struct sway_container *parent = child->parent;
list_t *list = container_is_floating(child) ?
parent->sway_workspace->floating : parent->children;
int index = list_find(list, child);
if (index != -1) {
list_del(list, index);
}
child->parent = NULL;
container_notify_subtree_changed(parent);
container_set_dirty(parent);
container_set_dirty(child);
return parent;
}
enum sway_container_layout container_get_default_layout(
struct sway_container *con) {
if (con->type != C_OUTPUT) {
con = container_parent(con, C_OUTPUT);
}
if (!sway_assert(con != NULL,
"container_get_default_layout must be called on an attached"
" container below the root container")) {
return 0;
}
if (config->default_layout != L_NONE) {
return config->default_layout;
} else if (config->default_orientation != L_NONE) {
return config->default_orientation;
} else if (con->width >= con->height) {
return L_HORIZ;
} else {
return L_VERT;
}
}
struct sway_container *container_replace_child(struct sway_container *child,
struct sway_container *new_child) {
struct sway_container *parent = child->parent;
if (parent == NULL) {
return NULL;
}
list_t *list = container_is_floating(child) ?
parent->sway_workspace->floating : parent->children;
int i = list_find(list, child);
if (new_child->parent) {
container_remove_child(new_child);
}
list->items[i] = new_child;
new_child->parent = parent;
child->parent = NULL;
// Set geometry for new child
new_child->x = child->x;
new_child->y = child->y;
new_child->width = child->width;
new_child->height = child->height;
// reset geometry for child
child->width = 0;
child->height = 0;
return parent;
}
struct sway_container *container_split(struct sway_container *child,
enum sway_container_layout layout) {
// TODO floating: cannot split a floating container
if (!sway_assert(child, "child cannot be null")) {
return NULL;
}
if (child->type == C_WORKSPACE && child->children->length == 0) {
// Special case: this just behaves like splitt
child->prev_split_layout = child->layout;
child->layout = layout;
return child;
}
struct sway_container *cont = container_create(C_CONTAINER);
wlr_log(WLR_DEBUG, "creating container %p around %p", cont, child);
child->type == C_WORKSPACE ? workspace_remove_gaps(child)
: container_remove_gaps(child);
cont->prev_split_layout = L_NONE;
cont->width = child->width;
cont->height = child->height;
cont->x = child->x;
cont->y = child->y;
struct sway_seat *seat = input_manager_get_default_seat(input_manager);
bool set_focus = (seat_get_focus(seat) == child);
container_add_gaps(cont);
if (child->type == C_WORKSPACE) {
struct sway_container *workspace = child;
while (workspace->children->length) {
struct sway_container *ws_child = workspace->children->items[0];
container_remove_child(ws_child);
container_add_child(cont, ws_child);
}
container_add_child(workspace, cont);
enum sway_container_layout old_layout = workspace->layout;
workspace->layout = layout;
cont->layout = old_layout;
} else {
cont->layout = layout;
container_replace_child(child, cont);
container_add_child(cont, child);
}
if (set_focus) {
seat_set_focus(seat, cont);
seat_set_focus(seat, child);
}
container_notify_subtree_changed(cont);
return cont;
}

View File

@ -1,403 +0,0 @@
#define _POSIX_C_SOURCE 200809L
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_layout.h>
#include "config.h"
#include "sway/debug.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/output.h"
#include "sway/tree/workspace.h"
#include "sway/tree/view.h"
#include "sway/input/seat.h"
#include "sway/ipc-server.h"
#include "list.h"
#include "log.h"
void container_handle_fullscreen_reparent(struct sway_container *con,
struct sway_container *old_parent) {
if (!con->is_fullscreen) {
return;
}
struct sway_container *old_workspace = old_parent;
if (old_workspace && old_workspace->type != C_WORKSPACE) {
old_workspace = container_parent(old_workspace, C_WORKSPACE);
}
struct sway_container *new_workspace = container_parent(con, C_WORKSPACE);
if (old_workspace == new_workspace) {
return;
}
// Unmark the old workspace as fullscreen
if (old_workspace) {
old_workspace->sway_workspace->fullscreen = NULL;
}
// Mark the new workspace as fullscreen
if (new_workspace->sway_workspace->fullscreen) {
container_set_fullscreen(
new_workspace->sway_workspace->fullscreen, false);
}
new_workspace->sway_workspace->fullscreen = con;
// Resize container to new output dimensions
struct sway_container *output = new_workspace->parent;
con->x = output->x;
con->y = output->y;
con->width = output->width;
con->height = output->height;
if (con->type == C_VIEW) {
struct sway_view *view = con->sway_view;
view->x = output->x;
view->y = output->y;
view->width = output->width;
view->height = output->height;
} else {
arrange_windows(new_workspace);
}
}
void container_insert_child(struct sway_container *parent,
struct sway_container *child, int i) {
struct sway_container *old_parent = child->parent;
if (old_parent) {
container_remove_child(child);
}
wlr_log(WLR_DEBUG, "Inserting id:%zd at index %d", child->id, i);
list_insert(parent->children, i, child);
child->parent = parent;
container_handle_fullscreen_reparent(child, old_parent);
}
struct sway_container *container_add_sibling(struct sway_container *fixed,
struct sway_container *active) {
// TODO handle floating
struct sway_container *old_parent = NULL;
if (active->parent) {
old_parent = active->parent;
container_remove_child(active);
}
struct sway_container *parent = fixed->parent;
int i = container_sibling_index(fixed);
list_insert(parent->children, i + 1, active);
active->parent = parent;
container_handle_fullscreen_reparent(active, old_parent);
return active->parent;
}
void container_add_child(struct sway_container *parent,
struct sway_container *child) {
wlr_log(WLR_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)",
child, child->type, child->width, child->height,
parent, parent->type, parent->width, parent->height);
struct sway_container *old_parent = child->parent;
list_add(parent->children, child);
child->parent = parent;
container_handle_fullscreen_reparent(child, old_parent);
if (old_parent) {
container_set_dirty(old_parent);
}
container_set_dirty(child);
}
struct sway_container *container_remove_child(struct sway_container *child) {
if (child->is_fullscreen) {
struct sway_container *workspace = container_parent(child, C_WORKSPACE);
workspace->sway_workspace->fullscreen = NULL;
}
struct sway_container *parent = child->parent;
list_t *list = container_is_floating(child) ?
parent->sway_workspace->floating : parent->children;
int index = list_find(list, child);
if (index != -1) {
list_del(list, index);
}
child->parent = NULL;
container_notify_subtree_changed(parent);
container_set_dirty(parent);
container_set_dirty(child);
return parent;
}
bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out) {
switch (dir) {
case MOVE_UP:
*out = WLR_DIRECTION_UP;
break;
case MOVE_DOWN:
*out = WLR_DIRECTION_DOWN;
break;
case MOVE_LEFT:
*out = WLR_DIRECTION_LEFT;
break;
case MOVE_RIGHT:
*out = WLR_DIRECTION_RIGHT;
break;
default:
return false;
}
return true;
}
enum sway_container_layout container_get_default_layout(
struct sway_container *con) {
if (con->type != C_OUTPUT) {
con = container_parent(con, C_OUTPUT);
}
if (!sway_assert(con != NULL,
"container_get_default_layout must be called on an attached"
" container below the root container")) {
return 0;
}
if (config->default_layout != L_NONE) {
return config->default_layout;
} else if (config->default_orientation != L_NONE) {
return config->default_orientation;
} else if (con->width >= con->height) {
return L_HORIZ;
} else {
return L_VERT;
}
}
struct sway_container *container_replace_child(struct sway_container *child,
struct sway_container *new_child) {
struct sway_container *parent = child->parent;
if (parent == NULL) {
return NULL;
}
list_t *list = container_is_floating(child) ?
parent->sway_workspace->floating : parent->children;
int i = list_find(list, child);
if (new_child->parent) {
container_remove_child(new_child);
}
list->items[i] = new_child;
new_child->parent = parent;
child->parent = NULL;
// Set geometry for new child
new_child->x = child->x;
new_child->y = child->y;
new_child->width = child->width;
new_child->height = child->height;
// reset geometry for child
child->width = 0;
child->height = 0;
return parent;
}
struct sway_container *container_split(struct sway_container *child,
enum sway_container_layout layout) {
// TODO floating: cannot split a floating container
if (!sway_assert(child, "child cannot be null")) {
return NULL;
}
if (child->type == C_WORKSPACE && child->children->length == 0) {
// Special case: this just behaves like splitt
child->prev_split_layout = child->layout;
child->layout = layout;
return child;
}
struct sway_container *cont = container_create(C_CONTAINER);
wlr_log(WLR_DEBUG, "creating container %p around %p", cont, child);
child->type == C_WORKSPACE ? workspace_remove_gaps(child)
: container_remove_gaps(child);
cont->prev_split_layout = L_NONE;
cont->width = child->width;
cont->height = child->height;
cont->x = child->x;
cont->y = child->y;
struct sway_seat *seat = input_manager_get_default_seat(input_manager);
bool set_focus = (seat_get_focus(seat) == child);
container_add_gaps(cont);
if (child->type == C_WORKSPACE) {
struct sway_container *workspace = child;
while (workspace->children->length) {
struct sway_container *ws_child = workspace->children->items[0];
container_remove_child(ws_child);
container_add_child(cont, ws_child);
}
container_add_child(workspace, cont);
enum sway_container_layout old_layout = workspace->layout;
workspace->layout = layout;
cont->layout = old_layout;
} else {
cont->layout = layout;
container_replace_child(child, cont);
container_add_child(cont, child);
}
if (set_focus) {
seat_set_focus(seat, cont);
seat_set_focus(seat, child);
}
container_notify_subtree_changed(cont);
return cont;
}
void container_recursive_resize(struct sway_container *container,
double amount, enum wlr_edges edge) {
bool layout_match = true;
wlr_log(WLR_DEBUG, "Resizing %p with amount: %f", container, amount);
if (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_RIGHT) {
container->width += amount;
layout_match = container->layout == L_HORIZ;
} else if (edge == WLR_EDGE_TOP || edge == WLR_EDGE_BOTTOM) {
container->height += amount;
layout_match = container->layout == L_VERT;
}
if (container->children) {
for (int i = 0; i < container->children->length; i++) {
struct sway_container *child = container->children->items[i];
double amt = layout_match ?
amount / container->children->length : amount;
container_recursive_resize(child, amt, edge);
}
}
}
static void swap_places(struct sway_container *con1,
struct sway_container *con2) {
struct sway_container *temp = malloc(sizeof(struct sway_container));
temp->x = con1->x;
temp->y = con1->y;
temp->width = con1->width;
temp->height = con1->height;
temp->parent = con1->parent;
con1->x = con2->x;
con1->y = con2->y;
con1->width = con2->width;
con1->height = con2->height;
con2->x = temp->x;
con2->y = temp->y;
con2->width = temp->width;
con2->height = temp->height;
int temp_index = container_sibling_index(con1);
container_insert_child(con2->parent, con1, container_sibling_index(con2));
container_insert_child(temp->parent, con2, temp_index);
free(temp);
}
static void swap_focus(struct sway_container *con1,
struct sway_container *con2, struct sway_seat *seat,
struct sway_container *focus) {
if (focus == con1 || focus == con2) {
struct sway_container *ws1 = container_parent(con1, C_WORKSPACE);
struct sway_container *ws2 = container_parent(con2, C_WORKSPACE);
if (focus == con1 && (con2->parent->layout == L_TABBED
|| con2->parent->layout == L_STACKED)) {
if (workspace_is_visible(ws2)) {
seat_set_focus_warp(seat, con2, false, true);
}
seat_set_focus(seat, ws1 != ws2 ? con2 : con1);
} else if (focus == con2 && (con1->parent->layout == L_TABBED
|| con1->parent->layout == L_STACKED)) {
if (workspace_is_visible(ws1)) {
seat_set_focus_warp(seat, con1, false, true);
}
seat_set_focus(seat, ws1 != ws2 ? con1 : con2);
} else if (ws1 != ws2) {
seat_set_focus(seat, focus == con1 ? con2 : con1);
} else {
seat_set_focus(seat, focus);
}
} else {
seat_set_focus(seat, focus);
}
}
void container_swap(struct sway_container *con1, struct sway_container *con2) {
if (!sway_assert(con1 && con2, "Cannot swap with nothing")) {
return;
}
if (!sway_assert(con1->type >= C_CONTAINER && con2->type >= C_CONTAINER,
"Can only swap containers and views")) {
return;
}
if (!sway_assert(!container_has_ancestor(con1, con2)
&& !container_has_ancestor(con2, con1),
"Cannot swap ancestor and descendant")) {
return;
}
if (!sway_assert(!container_is_floating(con1)
&& !container_is_floating(con2),
"Swapping with floating containers is not supported")) {
return;
}
wlr_log(WLR_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id);
int fs1 = con1->is_fullscreen;
int fs2 = con2->is_fullscreen;
if (fs1) {
container_set_fullscreen(con1, false);
}
if (fs2) {
container_set_fullscreen(con2, false);
}
struct sway_seat *seat = input_manager_get_default_seat(input_manager);
struct sway_container *focus = seat_get_focus(seat);
struct sway_container *vis1 = container_parent(
seat_get_focus_inactive(seat, container_parent(con1, C_OUTPUT)),
C_WORKSPACE);
struct sway_container *vis2 = container_parent(
seat_get_focus_inactive(seat, container_parent(con2, C_OUTPUT)),
C_WORKSPACE);
char *stored_prev_name = NULL;
if (prev_workspace_name) {
stored_prev_name = strdup(prev_workspace_name);
}
swap_places(con1, con2);
if (!workspace_is_visible(vis1)) {
seat_set_focus(seat, seat_get_focus_inactive(seat, vis1));
}
if (!workspace_is_visible(vis2)) {
seat_set_focus(seat, seat_get_focus_inactive(seat, vis2));
}
swap_focus(con1, con2, seat, focus);
if (stored_prev_name) {
free(prev_workspace_name);
prev_workspace_name = stored_prev_name;
}
if (fs1) {
container_set_fullscreen(con2, true);
}
if (fs2) {
container_set_fullscreen(con1, true);
}
}

View File

@ -18,7 +18,6 @@
#include "sway/input/seat.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "sway/config.h"