mirror of
https://github.com/swaywm/sway.git
synced 2026-04-27 06:46:25 -04:00
proper view ordering
This commit is contained in:
parent
cc5713aee6
commit
b93f068611
6 changed files with 269 additions and 209 deletions
|
|
@ -82,6 +82,7 @@ swayc_t *destroy_view(swayc_t *view);
|
||||||
|
|
||||||
swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types);
|
swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types);
|
||||||
swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts);
|
swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts);
|
||||||
|
swayc_t *swayc_by_handle(wlc_handle handle);
|
||||||
|
|
||||||
swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data);
|
swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data);
|
||||||
void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *);
|
void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ void focus_view(swayc_t *view);
|
||||||
void focus_view_for(swayc_t *ancestor, swayc_t *container);
|
void focus_view_for(swayc_t *ancestor, swayc_t *container);
|
||||||
|
|
||||||
swayc_t *get_focused_container(swayc_t *parent);
|
swayc_t *get_focused_container(swayc_t *parent);
|
||||||
swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent);
|
|
||||||
swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir);
|
swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,17 @@
|
||||||
#define ASSERT_NONNULL(PTR) \
|
#define ASSERT_NONNULL(PTR) \
|
||||||
sway_assert (PTR, "%s: " #PTR "must be non-null", __func__)
|
sway_assert (PTR, "%s: " #PTR "must be non-null", __func__)
|
||||||
|
|
||||||
static swayc_t *new_swayc(enum swayc_types type) {
|
static swayc_t *new_swayc(enum swayc_types type, wlc_handle handle) {
|
||||||
swayc_t *c = calloc(1, sizeof(swayc_t));
|
swayc_t *c = calloc(1, sizeof(swayc_t));
|
||||||
c->handle = -1;
|
if (handle > 0) {
|
||||||
|
c->handle = handle;
|
||||||
|
wlc_handle_set_user_data(handle, c);
|
||||||
|
} else {
|
||||||
|
c->handle = 0;
|
||||||
|
}
|
||||||
c->layout = L_NONE;
|
c->layout = L_NONE;
|
||||||
c->type = type;
|
c->type = type;
|
||||||
|
c->gaps = 0;
|
||||||
if (type != C_VIEW) {
|
if (type != C_VIEW) {
|
||||||
c->children = create_list();
|
c->children = create_list();
|
||||||
}
|
}
|
||||||
|
|
@ -26,6 +32,9 @@ static void free_swayc(swayc_t *cont) {
|
||||||
if (!ASSERT_NONNULL(cont)) {
|
if (!ASSERT_NONNULL(cont)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (cont->handle > 0) {
|
||||||
|
wlc_handle_set_user_data(cont->handle, 0);
|
||||||
|
}
|
||||||
// TODO does not properly handle containers with children,
|
// TODO does not properly handle containers with children,
|
||||||
// TODO but functions that call this usually check for that
|
// TODO but functions that call this usually check for that
|
||||||
if (cont->children) {
|
if (cont->children) {
|
||||||
|
|
@ -58,7 +67,7 @@ static void free_swayc(swayc_t *cont) {
|
||||||
// New containers
|
// New containers
|
||||||
|
|
||||||
static bool workspace_test(swayc_t *view, void *name) {
|
static bool workspace_test(swayc_t *view, void *name) {
|
||||||
return strcasecmp(view->name, (char *)name) == 0;
|
return strcasecmp(view->name, name) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
swayc_t *new_output(wlc_handle handle) {
|
swayc_t *new_output(wlc_handle handle) {
|
||||||
|
|
@ -66,12 +75,10 @@ swayc_t *new_output(wlc_handle handle) {
|
||||||
const char *name = wlc_output_get_name(handle);
|
const char *name = wlc_output_get_name(handle);
|
||||||
sway_log(L_DEBUG, "Added output %lu:%s", handle, name);
|
sway_log(L_DEBUG, "Added output %lu:%s", handle, name);
|
||||||
|
|
||||||
swayc_t *output = new_swayc(C_OUTPUT);
|
swayc_t *output = new_swayc(C_OUTPUT, handle);
|
||||||
output->width = size->w;
|
output->width = size->w;
|
||||||
output->height = size->h;
|
output->height = size->h;
|
||||||
output->handle = handle;
|
|
||||||
output->name = name ? strdup(name) : NULL;
|
output->name = name ? strdup(name) : NULL;
|
||||||
output->gaps = config->gaps_outer + config->gaps_inner / 2;
|
|
||||||
|
|
||||||
add_child(&root_container, output);
|
add_child(&root_container, output);
|
||||||
|
|
||||||
|
|
@ -112,13 +119,14 @@ swayc_t *new_workspace(swayc_t *output, const char *name) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle);
|
sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle);
|
||||||
swayc_t *workspace = new_swayc(C_WORKSPACE);
|
swayc_t *workspace = new_swayc(C_WORKSPACE, 0);
|
||||||
|
|
||||||
workspace->layout = L_HORIZ; // TODO: default layout
|
workspace->layout = L_HORIZ; // TODO: default layout
|
||||||
workspace->x = output->x;
|
workspace->x = output->x;
|
||||||
workspace->y = output->y;
|
workspace->y = output->y;
|
||||||
workspace->width = output->width;
|
workspace->width = output->width;
|
||||||
workspace->height = output->height;
|
workspace->height = output->height;
|
||||||
|
workspace->gaps = config->gaps_outer;
|
||||||
workspace->name = strdup(name);
|
workspace->name = strdup(name);
|
||||||
workspace->visible = true;
|
workspace->visible = true;
|
||||||
workspace->floating = create_list();
|
workspace->floating = create_list();
|
||||||
|
|
@ -131,7 +139,7 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) {
|
||||||
if (!ASSERT_NONNULL(child)) {
|
if (!ASSERT_NONNULL(child)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
swayc_t *cont = new_swayc(C_CONTAINER);
|
swayc_t *cont = new_swayc(C_CONTAINER, 0);
|
||||||
|
|
||||||
sway_log(L_DEBUG, "creating container %p around %p", cont, child);
|
sway_log(L_DEBUG, "creating container %p around %p", cont, child);
|
||||||
|
|
||||||
|
|
@ -177,11 +185,10 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
const char *title = wlc_view_get_title(handle);
|
const char *title = wlc_view_get_title(handle);
|
||||||
swayc_t *view = new_swayc(C_VIEW);
|
swayc_t *view = new_swayc(C_VIEW, handle);
|
||||||
sway_log(L_DEBUG, "Adding new view %lu:%s to container %p %d",
|
sway_log(L_DEBUG, "Adding new view %lu:%s to container %p %d",
|
||||||
handle, title, sibling, sibling ? sibling->type : 0);
|
handle, title, sibling, sibling ? sibling->type : 0);
|
||||||
// Setup values
|
// Setup values
|
||||||
view->handle = handle;
|
|
||||||
view->name = title ? strdup(title) : NULL;
|
view->name = title ? strdup(title) : NULL;
|
||||||
view->visible = true;
|
view->visible = true;
|
||||||
view->is_focused = true;
|
view->is_focused = true;
|
||||||
|
|
@ -208,11 +215,10 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) {
|
||||||
|
|
||||||
swayc_t *new_floating_view(wlc_handle handle) {
|
swayc_t *new_floating_view(wlc_handle handle) {
|
||||||
const char *title = wlc_view_get_title(handle);
|
const char *title = wlc_view_get_title(handle);
|
||||||
swayc_t *view = new_swayc(C_VIEW);
|
swayc_t *view = new_swayc(C_VIEW, handle);
|
||||||
sway_log(L_DEBUG, "Adding new view %lu:%x:%s as a floating view",
|
sway_log(L_DEBUG, "Adding new view %lu:%x:%s as a floating view",
|
||||||
handle, wlc_view_get_type(handle), title);
|
handle, wlc_view_get_type(handle), title);
|
||||||
// Setup values
|
// Setup values
|
||||||
view->handle = handle;
|
|
||||||
view->name = title ? strdup(title) : NULL;
|
view->name = title ? strdup(title) : NULL;
|
||||||
view->visible = true;
|
view->visible = true;
|
||||||
|
|
||||||
|
|
@ -241,7 +247,8 @@ swayc_t *new_floating_view(wlc_handle handle) {
|
||||||
|
|
||||||
// Destroy container
|
// Destroy container
|
||||||
|
|
||||||
swayc_t *destroy_output(swayc_t *output) {
|
#define DESTROY_FUNC __attribute__((nonnull)) swayc_t *
|
||||||
|
DESTROY_FUNC destroy_output(swayc_t *output) {
|
||||||
if (!ASSERT_NONNULL(output)) {
|
if (!ASSERT_NONNULL(output)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +260,7 @@ swayc_t *destroy_output(swayc_t *output) {
|
||||||
return &root_container;
|
return &root_container;
|
||||||
}
|
}
|
||||||
|
|
||||||
swayc_t *destroy_workspace(swayc_t *workspace) {
|
DESTROY_FUNC destroy_workspace(swayc_t *workspace) {
|
||||||
if (!ASSERT_NONNULL(workspace)) {
|
if (!ASSERT_NONNULL(workspace)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -276,7 +283,7 @@ swayc_t *destroy_workspace(swayc_t *workspace) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
swayc_t *destroy_container(swayc_t *container) {
|
DESTROY_FUNC destroy_container(swayc_t *container) {
|
||||||
if (!ASSERT_NONNULL(container)) {
|
if (!ASSERT_NONNULL(container)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -289,7 +296,7 @@ swayc_t *destroy_container(swayc_t *container) {
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
swayc_t *destroy_view(swayc_t *view) {
|
DESTROY_FUNC destroy_view(swayc_t *view) {
|
||||||
if (!ASSERT_NONNULL(view)) {
|
if (!ASSERT_NONNULL(view)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -303,6 +310,7 @@ swayc_t *destroy_view(swayc_t *view) {
|
||||||
}
|
}
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
#undef DESTROY_FUNC
|
||||||
|
|
||||||
// Container lookup
|
// Container lookup
|
||||||
|
|
||||||
|
|
@ -332,6 +340,11 @@ swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts layout) {
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
swayc_t *swayc_by_handle(wlc_handle handle) {
|
||||||
|
return wlc_handle_get_user_data(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) {
|
swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) {
|
||||||
if (!container->children) {
|
if (!container->children) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -398,10 +411,11 @@ void reset_gaps(swayc_t *view, void *data) {
|
||||||
if (!ASSERT_NONNULL(view)) {
|
if (!ASSERT_NONNULL(view)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (view->type == C_OUTPUT) {
|
if (view->type == C_WORKSPACE) {
|
||||||
view->gaps = config->gaps_outer;
|
view->gaps = config->gaps_outer;
|
||||||
}
|
}
|
||||||
if (view->type == C_VIEW) {
|
if (view->type == C_VIEW) {
|
||||||
view->gaps = config->gaps_inner;
|
view->gaps = config->gaps_inner;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ static void handle_output_destroyed(wlc_handle output) {
|
||||||
|
|
||||||
static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) {
|
static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) {
|
||||||
sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h);
|
sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h);
|
||||||
swayc_t *c = get_swayc_for_handle(output, &root_container);
|
swayc_t *c = swayc_by_handle(output);
|
||||||
if (!c) return;
|
if (!c) return;
|
||||||
c->width = to->w;
|
c->width = to->w;
|
||||||
c->height = to->h;
|
c->height = to->h;
|
||||||
|
|
@ -121,7 +121,7 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_output_focused(wlc_handle output, bool focus) {
|
static void handle_output_focused(wlc_handle output, bool focus) {
|
||||||
swayc_t *c = get_swayc_for_handle(output, &root_container);
|
swayc_t *c = swayc_by_handle(output);
|
||||||
// if for some reason this output doesnt exist, create it.
|
// if for some reason this output doesnt exist, create it.
|
||||||
if (!c) {
|
if (!c) {
|
||||||
handle_output_created(output);
|
handle_output_created(output);
|
||||||
|
|
@ -139,7 +139,7 @@ static bool handle_view_created(wlc_handle handle) {
|
||||||
|
|
||||||
// Get parent container, to add view in
|
// Get parent container, to add view in
|
||||||
if (parent) {
|
if (parent) {
|
||||||
focused = get_swayc_for_handle(parent, &root_container);
|
focused = swayc_by_handle(parent);
|
||||||
}
|
}
|
||||||
if (!focused || focused->type == C_OUTPUT) {
|
if (!focused || focused->type == C_OUTPUT) {
|
||||||
focused = get_focused_container(&root_container);
|
focused = get_focused_container(&root_container);
|
||||||
|
|
@ -196,7 +196,7 @@ static bool handle_view_created(wlc_handle handle) {
|
||||||
|
|
||||||
static void handle_view_destroyed(wlc_handle handle) {
|
static void handle_view_destroyed(wlc_handle handle) {
|
||||||
sway_log(L_DEBUG, "Destroying window %lu", handle);
|
sway_log(L_DEBUG, "Destroying window %lu", handle);
|
||||||
swayc_t *view = get_swayc_for_handle(handle, &root_container);
|
swayc_t *view = swayc_by_handle(handle);
|
||||||
|
|
||||||
switch (wlc_view_get_type(handle)) {
|
switch (wlc_view_get_type(handle)) {
|
||||||
// regular view created regularly
|
// regular view created regularly
|
||||||
|
|
@ -230,7 +230,7 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo
|
||||||
// If the view is floating, then apply the geometry.
|
// If the view is floating, then apply the geometry.
|
||||||
// Otherwise save the desired width/height for the view.
|
// Otherwise save the desired width/height for the view.
|
||||||
// This will not do anything for the time being as WLC improperly sends geometry requests
|
// This will not do anything for the time being as WLC improperly sends geometry requests
|
||||||
swayc_t *view = get_swayc_for_handle(handle, &root_container);
|
swayc_t *view = swayc_by_handle(handle);
|
||||||
if (view) {
|
if (view) {
|
||||||
view->desired_width = geometry->size.w;
|
view->desired_width = geometry->size.w;
|
||||||
view->desired_height = geometry->size.h;
|
view->desired_height = geometry->size.h;
|
||||||
|
|
@ -246,7 +246,7 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) {
|
static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) {
|
||||||
swayc_t *c = get_swayc_for_handle(view, &root_container);
|
swayc_t *c = swayc_by_handle(view);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case WLC_BIT_FULLSCREEN:
|
case WLC_BIT_FULLSCREEN:
|
||||||
// i3 just lets it become fullscreen
|
// i3 just lets it become fullscreen
|
||||||
|
|
|
||||||
421
sway/layout.c
421
sway/layout.c
|
|
@ -18,6 +18,8 @@ void init_layout(void) {
|
||||||
root_container.handle = -1;
|
root_container.handle = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Children of container functions
|
||||||
|
|
||||||
static int index_child(swayc_t *parent, swayc_t *child) {
|
static int index_child(swayc_t *parent, swayc_t *child) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < parent->children->length; ++i) {
|
for (i = 0; i < parent->children->length; ++i) {
|
||||||
|
|
@ -108,211 +110,254 @@ swayc_t *remove_child(swayc_t *child) {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fitting functions
|
||||||
|
#define FIT_FUNC __attribute__((nonnull)) static void
|
||||||
|
|
||||||
void arrange_windows(swayc_t *container, int width, int height) {
|
FIT_FUNC _fit_view(swayc_t *view) {
|
||||||
int i;
|
sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, view,
|
||||||
if (width == -1 || height == -1) {
|
view->width, view->height, view->x, view->y);
|
||||||
sway_log(L_DEBUG, "Arranging layout for %p", container);
|
struct wlc_geometry geo;
|
||||||
width = container->width;
|
if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) {
|
||||||
height = container->height;
|
swayc_t *op = swayc_parent_by_type(view, C_OUTPUT);
|
||||||
}
|
geo = (struct wlc_geometry){
|
||||||
|
.origin = { .x = 0, .y = 0 },
|
||||||
int x = 0, y = 0;
|
.size = { .w = op->width, .h = op->height }
|
||||||
switch (container->type) {
|
|
||||||
case C_ROOT:
|
|
||||||
for (i = 0; i < container->children->length; ++i) {
|
|
||||||
swayc_t *child = container->children->items[i];
|
|
||||||
sway_log(L_DEBUG, "Arranging output at %d", x);
|
|
||||||
child->x = x;
|
|
||||||
child->y = y;
|
|
||||||
arrange_windows(child, -1, -1);
|
|
||||||
// Removed for now because wlc works with relative positions
|
|
||||||
// Addition can be reconsidered once wlc positions are changed
|
|
||||||
// x += child->width;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case C_OUTPUT:
|
|
||||||
container->width = width;
|
|
||||||
container->height = height;
|
|
||||||
// These lines make x/y negative and result in stuff glitching out
|
|
||||||
// Their addition can be reconsidered once wlc positions are changed
|
|
||||||
// x -= container->x;
|
|
||||||
// y -= container->y;
|
|
||||||
for (i = 0; i < container->children->length; ++i) {
|
|
||||||
swayc_t *child = container->children->items[i];
|
|
||||||
child->x = x + container->gaps;
|
|
||||||
child->y = y + container->gaps;
|
|
||||||
child->width = width - container->gaps * 2;
|
|
||||||
child->height = height - container->gaps * 2;
|
|
||||||
sway_log(L_DEBUG, "Arranging workspace #%d at %d, %d", i, child->x, child->y);
|
|
||||||
arrange_windows(child, -1, -1);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case C_VIEW:
|
|
||||||
{
|
|
||||||
struct wlc_geometry geometry = {
|
|
||||||
.origin = {
|
|
||||||
.x = container->x + container->gaps / 2,
|
|
||||||
.y = container->y + container->gaps / 2
|
|
||||||
},
|
|
||||||
.size = {
|
|
||||||
.w = width - container->gaps,
|
|
||||||
.h = height - container->gaps
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) {
|
|
||||||
swayc_t *parent = swayc_parent_by_type(container, C_OUTPUT);
|
|
||||||
geometry.origin.x = 0;
|
|
||||||
geometry.origin.y = 0;
|
|
||||||
geometry.size.w = parent->width;
|
|
||||||
geometry.size.h = parent->height;
|
|
||||||
wlc_view_set_geometry(container->handle, 0, &geometry);
|
|
||||||
wlc_view_bring_to_front(container->handle);
|
|
||||||
} else {
|
} else {
|
||||||
wlc_view_set_geometry(container->handle, 0, &geometry);
|
if (view->is_floating) {
|
||||||
container->width = width;
|
geo = (struct wlc_geometry){
|
||||||
container->height = height;
|
|
||||||
}
|
|
||||||
sway_log(L_DEBUG, "Set view to %d x %d @ %d, %d", geometry.size.w, geometry.size.h,
|
|
||||||
geometry.origin.x, geometry.origin.y);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
container->width = width;
|
|
||||||
container->height = height;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
x = y = 0;
|
|
||||||
double scale = 0;
|
|
||||||
switch (container->layout) {
|
|
||||||
case L_HORIZ:
|
|
||||||
default:
|
|
||||||
// Calculate total width
|
|
||||||
for (i = 0; i < container->children->length; ++i) {
|
|
||||||
int *old_width = &((swayc_t *)container->children->items[i])->width;
|
|
||||||
if (*old_width <= 0) {
|
|
||||||
if (container->children->length > 1) {
|
|
||||||
*old_width = width / (container->children->length - 1);
|
|
||||||
} else {
|
|
||||||
*old_width = width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scale += *old_width;
|
|
||||||
}
|
|
||||||
// Resize windows
|
|
||||||
if (scale > 0.1) {
|
|
||||||
scale = width / scale;
|
|
||||||
sway_log(L_DEBUG, "Arranging %p horizontally", container);
|
|
||||||
for (i = 0; i < container->children->length; ++i) {
|
|
||||||
swayc_t *child = container->children->items[i];
|
|
||||||
sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %d by %f)", child, child->type, width, scale);
|
|
||||||
child->x = x + container->x;
|
|
||||||
child->y = y + container->y;
|
|
||||||
arrange_windows(child, child->width * scale, height);
|
|
||||||
x += child->width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case L_VERT:
|
|
||||||
// Calculate total height
|
|
||||||
for (i = 0; i < container->children->length; ++i) {
|
|
||||||
int *old_height = &((swayc_t *)container->children->items[i])->height;
|
|
||||||
if (*old_height <= 0) {
|
|
||||||
if (container->children->length > 1) {
|
|
||||||
*old_height = height / (container->children->length - 1);
|
|
||||||
} else {
|
|
||||||
*old_height = height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scale += *old_height;
|
|
||||||
}
|
|
||||||
// Resize
|
|
||||||
if (scale > 0.1) {
|
|
||||||
scale = height / scale;
|
|
||||||
sway_log(L_DEBUG, "Arranging %p vertically", container);
|
|
||||||
for (i = 0; i < container->children->length; ++i) {
|
|
||||||
swayc_t *child = container->children->items[i];
|
|
||||||
sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %d by %f)", child, child->type, height, scale);
|
|
||||||
child->x = x + container->x;
|
|
||||||
child->y = y + container->y;
|
|
||||||
arrange_windows(child, width, child->height * scale);
|
|
||||||
y += child->height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Arrage floating layouts for workspaces last
|
|
||||||
if (container->type == C_WORKSPACE) {
|
|
||||||
for (i = 0; i < container->floating->length; ++i) {
|
|
||||||
swayc_t *view = container->floating->items[i];
|
|
||||||
if (view->type == C_VIEW) {
|
|
||||||
// Set the geometry
|
|
||||||
struct wlc_geometry geometry = {
|
|
||||||
.origin = {
|
.origin = {
|
||||||
.x = view->x,
|
.x = view->x,
|
||||||
.y = view->y
|
.y = view->y,
|
||||||
},
|
},
|
||||||
.size = {
|
.size = {
|
||||||
.w = view->width,
|
.w = view->width,
|
||||||
.h = view->height
|
.h = view->height,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) {
|
|
||||||
swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT);
|
|
||||||
geometry.origin.x = 0;
|
|
||||||
geometry.origin.y = 0;
|
|
||||||
geometry.size.w = parent->width;
|
|
||||||
geometry.size.h = parent->height;
|
|
||||||
wlc_view_set_geometry(view->handle, 0, &geometry);
|
|
||||||
wlc_view_bring_to_front(view->handle);
|
|
||||||
} else {
|
} else {
|
||||||
wlc_view_set_geometry(view->handle, 0, &geometry);
|
geo = (struct wlc_geometry){
|
||||||
// Bring the views to the front in order of the list, the list
|
.origin = {
|
||||||
// will be kept up to date so that more recently focused views
|
.x = view->x + view->gaps / 2,
|
||||||
// have higher indexes
|
.y = view->y + view->gaps / 2,
|
||||||
// This is conditional on there not being a fullscreen view in the workspace
|
},
|
||||||
if (!container->focused
|
.size = {
|
||||||
|| !(wlc_view_get_state(container->focused->handle) & WLC_BIT_FULLSCREEN)) {
|
.w = view->width - view->gaps,
|
||||||
wlc_view_bring_to_front(view->handle);
|
.h = view->height - view->gaps
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wlc_view_set_geometry(view->handle, 0, &geo);
|
||||||
|
}
|
||||||
|
|
||||||
|
FIT_FUNC _fit_container(swayc_t *container) {
|
||||||
|
sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, container,
|
||||||
|
container->width, container->height, container->x, container->y);
|
||||||
|
swayc_t **child = (swayc_t **)container->children->items;
|
||||||
|
int i, len = container->children->length;
|
||||||
|
// geometry
|
||||||
|
int x = container->x;
|
||||||
|
int y = container->y;
|
||||||
|
int w = container->width;
|
||||||
|
int h = container->height;
|
||||||
|
// scaling
|
||||||
|
double s = 0;
|
||||||
|
switch (container->layout) {
|
||||||
|
default:
|
||||||
|
case L_HORIZ:
|
||||||
|
// Find scaling amount required to fit children in parent
|
||||||
|
for (i = 0; i < len; ++i, ++child) {
|
||||||
|
int *prev_w = &(*child)->width;
|
||||||
|
if (*prev_w <= 0) {
|
||||||
|
*prev_w = w / (len > 1 ? len - 1 : 1);
|
||||||
|
}
|
||||||
|
s += *prev_w;
|
||||||
|
}
|
||||||
|
sway_log(L_DEBUG,"s:%f",s);
|
||||||
|
if (s < 0.001) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s = w / s;
|
||||||
|
child = (swayc_t **)container->children->items;
|
||||||
|
for (i = 0; i < len; ++i, ++child) {
|
||||||
|
// Set geometry
|
||||||
|
(*child)->x = x;
|
||||||
|
(*child)->y = y;
|
||||||
|
// Scale width to fit in container
|
||||||
|
(*child)->width *= s;
|
||||||
|
(*child)->height = h;
|
||||||
|
// Increment x offset
|
||||||
|
x += (*child)->width;
|
||||||
|
// Recursibly resize children, depending on its type
|
||||||
|
((*child)->type == C_VIEW ? _fit_view : _fit_container)(*child);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
case L_VERT:
|
||||||
|
// Find scaling amount required to fit children in parent
|
||||||
|
for (i = 0; i < len; ++i, ++child) {
|
||||||
|
int *prev_h = &(*child)->height;
|
||||||
|
if (*prev_h <= 0) {
|
||||||
|
*prev_h = h / (len > 1 ? len - 1 : 1);
|
||||||
|
}
|
||||||
|
s += *prev_h;
|
||||||
|
}
|
||||||
|
if (s < 0.001) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s = h / s;
|
||||||
|
child = (swayc_t **)container->children->items;
|
||||||
|
for (i = 0; i < len; ++i, ++child) {
|
||||||
|
// Set geometry
|
||||||
|
(*child)->x = x;
|
||||||
|
(*child)->y = y;
|
||||||
|
// Scale height to fit in container
|
||||||
|
(*child)->height *= s;
|
||||||
|
(*child)->width = w;
|
||||||
|
// Increment y offset
|
||||||
|
y += (*child)->height;
|
||||||
|
// Recursibly resize children, depending on its type
|
||||||
|
((*child)->type == C_VIEW ? _fit_view : _fit_container)(*child);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FIT_FUNC _fit_workspace(swayc_t *workspace) {
|
||||||
|
workspace->x += workspace->gaps;
|
||||||
|
workspace->y += workspace->gaps;
|
||||||
|
workspace->width -= workspace->gaps * 2;
|
||||||
|
workspace->height -= workspace->gaps * 2;
|
||||||
|
sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, workspace,
|
||||||
|
workspace->width, workspace->height, workspace->x,workspace->y);
|
||||||
|
// workspace is treated same as container for tiling
|
||||||
|
_fit_container(workspace);
|
||||||
|
// Handle floating containers
|
||||||
|
swayc_t **child = (swayc_t **)workspace->floating->items;
|
||||||
|
int i, len = workspace->floating->length;
|
||||||
|
for (i = 0; i < len; ++i, ++child) {
|
||||||
|
// Fit floating depending on view
|
||||||
|
((*child)->type == C_VIEW ? _fit_view : _fit_container)(*child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FIT_FUNC _fit_output(swayc_t *output) {
|
||||||
|
sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, output, output->width,
|
||||||
|
output->height, output->x,output->y);
|
||||||
|
swayc_t **child = (swayc_t **)output->children->items;
|
||||||
|
int i, len = output->children->length;
|
||||||
|
int x = output->x;
|
||||||
|
int y = output->y;
|
||||||
|
int w = output->width;
|
||||||
|
int h = output->height;
|
||||||
|
for (i = 0; i < len; ++i, ++child) {
|
||||||
|
// Set geometry with gaps
|
||||||
|
(*child)->x = x;
|
||||||
|
(*child)->y = y;
|
||||||
|
(*child)->width = w;
|
||||||
|
(*child)->height = h;
|
||||||
|
// recursivly fit children
|
||||||
|
_fit_workspace(*child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FIT_FUNC _fit_root(swayc_t *root) {
|
||||||
|
sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, root, root->width,
|
||||||
|
root->height, root->x,root->y);
|
||||||
|
swayc_t **child = (swayc_t **)root->children->items;
|
||||||
|
int i, len = root->children->length;
|
||||||
|
for (i = 0; i < len; ++i, ++child) {
|
||||||
|
(*child)->x = 0;
|
||||||
|
(*child)->y = 0;
|
||||||
|
_fit_output(*child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FIT_FUNC fit_children_in(swayc_t *swayc) {
|
||||||
|
switch (swayc->type) {
|
||||||
|
case C_ROOT: _fit_root(swayc); return;
|
||||||
|
case C_WORKSPACE: swayc = swayc->parent;
|
||||||
|
case C_OUTPUT: _fit_output(swayc); return;
|
||||||
|
case C_VIEW: swayc = swayc->parent;
|
||||||
|
case C_CONTAINER: _fit_container(swayc); return;
|
||||||
|
default: sway_assert(false, "%s: invalid type", __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef FIT_FUNC
|
||||||
|
|
||||||
|
__attribute__((nonnull)) static wlc_handle order_children(swayc_t *swayc, wlc_handle top) {
|
||||||
|
// return handle
|
||||||
|
if (swayc->type == C_VIEW) {
|
||||||
|
return swayc->handle;
|
||||||
|
}
|
||||||
|
// return if no focus
|
||||||
|
if (swayc->focused == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO fix floating implementation.
|
||||||
|
// Recurse and get handle of focused container
|
||||||
|
wlc_handle bottom = order_children(swayc->focused, top);
|
||||||
|
|
||||||
|
// TODO Used properly in workspace case
|
||||||
|
wlc_handle topmost = bottom;
|
||||||
|
(void) topmost;
|
||||||
|
|
||||||
|
// Put handle below current top, or if there is no top, set it as bottom
|
||||||
|
if (top) {
|
||||||
|
wlc_view_send_below(bottom, top);
|
||||||
|
} else {
|
||||||
|
top = bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recurse for all children with the current bottom handle as their top.
|
||||||
|
int i, len = swayc->children->length;
|
||||||
|
swayc_t **child = (swayc_t **)swayc->children->items;
|
||||||
|
for (i = 0; i < len; ++i, ++child) {
|
||||||
|
// Skip over the focused child
|
||||||
|
if (*child == swayc->focused) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Update current top, send it below previous bottom, and set new bottom
|
||||||
|
top = order_children(*child, bottom);
|
||||||
|
wlc_view_send_below(top, bottom);
|
||||||
|
bottom = top;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO fix floating implementation.
|
||||||
|
// If we are at a workspace, put floating containers above topmost
|
||||||
|
if (swayc->type == C_WORKSPACE) {
|
||||||
|
// TODO using the same hacky implementation as before.
|
||||||
|
// send floating windows to front
|
||||||
|
len = swayc->children->length;
|
||||||
|
child = (swayc_t **)swayc->floating->items;
|
||||||
|
|
||||||
|
// chekc whether to send floating windows to the back or front
|
||||||
|
swayc_t *focused = get_focused_view(swayc);
|
||||||
|
bool tofront = swayc->parent->focused == swayc || (focused->type == C_VIEW
|
||||||
|
&& (wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN));
|
||||||
|
for (i = 0; i < len; ++i) {
|
||||||
|
if (tofront) {
|
||||||
|
wlc_view_bring_to_front((*child)->handle);
|
||||||
|
} else {
|
||||||
|
wlc_view_send_to_back((*child)->handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Return the bottom of this, which shall be the top of others,
|
||||||
|
return bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arrange layout
|
||||||
|
|
||||||
|
void arrange_windows(swayc_t *container, int width, int height) {
|
||||||
|
fit_children_in(container);
|
||||||
|
order_children(container, 0);
|
||||||
layout_log(&root_container, 0);
|
layout_log(&root_container, 0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) {
|
|
||||||
if (parent->children == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search for floating workspaces
|
|
||||||
int i;
|
|
||||||
if (parent->type == C_WORKSPACE) {
|
|
||||||
for (i = 0; i < parent->floating->length; ++i) {
|
|
||||||
swayc_t *child = parent->floating->items[i];
|
|
||||||
if (child->handle == handle) {
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < parent->children->length; ++i) {
|
|
||||||
swayc_t *child = parent->children->items[i];
|
|
||||||
if (child->handle == handle) {
|
|
||||||
return child;
|
|
||||||
} else {
|
|
||||||
swayc_t *res;
|
|
||||||
if ((res = get_swayc_for_handle(handle, child))) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir) {
|
swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir) {
|
||||||
swayc_t *parent = container->parent;
|
swayc_t *parent = container->parent;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ static const char *verbosity_colors[] = {
|
||||||
"", // L_SILENT
|
"", // L_SILENT
|
||||||
"\x1B[1;31m", // L_ERROR
|
"\x1B[1;31m", // L_ERROR
|
||||||
"\x1B[1;34m", // L_INFO
|
"\x1B[1;34m", // L_INFO
|
||||||
"\x1B[1;30m", // L_DEBUG
|
"\x1B[1;32m", // L_DEBUG
|
||||||
};
|
};
|
||||||
|
|
||||||
void init_log(int verbosity) {
|
void init_log(int verbosity) {
|
||||||
|
|
@ -151,6 +151,7 @@ static void container_log(const swayc_t *c) {
|
||||||
void layout_log(const swayc_t *c, int depth) {
|
void layout_log(const swayc_t *c, int depth) {
|
||||||
int i, d;
|
int i, d;
|
||||||
int e = c->children ? c->children->length : 0;
|
int e = c->children ? c->children->length : 0;
|
||||||
|
if (L_DEBUG > v) return;
|
||||||
container_log(c);
|
container_log(c);
|
||||||
if (e) {
|
if (e) {
|
||||||
for (i = 0; i < e; ++i) {
|
for (i = 0; i < e; ++i) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue