mirror of
https://github.com/swaywm/sway.git
synced 2026-04-28 06:46:26 -04:00
fixed plenty of bugs and crashes, and restored fullscreen/floating behavior. also fixed mode_toggle
This commit is contained in:
parent
b93f068611
commit
e2046e6aba
7 changed files with 135 additions and 114 deletions
|
|
@ -2,8 +2,8 @@
|
|||
#define _SWAY_CONTAINER_H
|
||||
#include <wlc/wlc.h>
|
||||
typedef struct sway_container swayc_t;
|
||||
|
||||
#include "layout.h"
|
||||
#include "focus.h"
|
||||
|
||||
enum swayc_types{
|
||||
C_ROOT,
|
||||
|
|
@ -78,11 +78,15 @@ swayc_t *destroy_container(swayc_t *container);
|
|||
// parent
|
||||
swayc_t *destroy_view(swayc_t *view);
|
||||
|
||||
// Container info
|
||||
bool swayc_is_fullscreen(swayc_t *view);
|
||||
|
||||
// Container Lookup
|
||||
|
||||
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_by_handle(wlc_handle handle);
|
||||
swayc_t *swayc_by_direction(swayc_t *container, enum movement_direction dir);
|
||||
|
||||
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 *);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,4 @@ void unfocus_all(swayc_t *container);
|
|||
void focus_view(swayc_t *view);
|
||||
void focus_view_for(swayc_t *ancestor, swayc_t *container);
|
||||
|
||||
swayc_t *get_focused_container(swayc_t *parent);
|
||||
swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -294,36 +294,39 @@ static bool cmd_focus(struct sway_config *config, int argc, char **argv) {
|
|||
} else if (strcasecmp(argv[0], "mode_toggle") == 0) {
|
||||
int i;
|
||||
swayc_t *focused = get_focused_view(active_workspace);
|
||||
if (focused->is_floating) {
|
||||
if (active_workspace->children->length > 0) {
|
||||
for (i = 0;i < active_workspace->floating->length; i++) {
|
||||
if (active_workspace->floating->items[i] == focused) {
|
||||
floating_toggled_index = i;
|
||||
break;
|
||||
// Dont change focus if fullscreen
|
||||
if (!swayc_is_fullscreen(focused)) {
|
||||
if (focused->is_floating) {
|
||||
if (active_workspace->children->length > 0) {
|
||||
for (i = 0;i < active_workspace->floating->length; i++) {
|
||||
if (active_workspace->floating->items[i] == focused) {
|
||||
floating_toggled_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (active_workspace->children->length > tiled_toggled_index) {
|
||||
set_focused_container(get_focused_view(active_workspace->children->items[tiled_toggled_index]));
|
||||
} else {
|
||||
set_focused_container(get_focused_view(active_workspace->children->items[0]));
|
||||
tiled_toggled_index = 0;
|
||||
}
|
||||
}
|
||||
if (active_workspace->children->length > tiled_toggled_index) {
|
||||
set_focused_container(get_focused_view(active_workspace->children->items[tiled_toggled_index]));
|
||||
} else {
|
||||
set_focused_container(get_focused_view(active_workspace->children->items[0]));
|
||||
tiled_toggled_index = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (active_workspace->floating->length > 0) {
|
||||
for (i = 0;i < active_workspace->children->length; i++) {
|
||||
if (active_workspace->children->items[i] == focused) {
|
||||
tiled_toggled_index = i;
|
||||
break;
|
||||
} else {
|
||||
if (active_workspace->floating->length > 0) {
|
||||
for (i = 0;i < active_workspace->children->length; i++) {
|
||||
if (active_workspace->children->items[i] == focused) {
|
||||
tiled_toggled_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (active_workspace->floating->length > floating_toggled_index) {
|
||||
swayc_t *floating = active_workspace->floating->items[floating_toggled_index];
|
||||
set_focused_container(get_focused_view(floating));
|
||||
} else {
|
||||
swayc_t *floating = active_workspace->floating->items[active_workspace->floating->length - 1];
|
||||
set_focused_container(get_focused_view(floating));
|
||||
tiled_toggled_index = active_workspace->floating->length - 1;
|
||||
}
|
||||
}
|
||||
if (active_workspace->floating->length > floating_toggled_index) {
|
||||
swayc_t *floating = active_workspace->floating->items[floating_toggled_index];
|
||||
set_focused_container(get_focused_view(floating));
|
||||
} else {
|
||||
swayc_t *floating = active_workspace->floating->items[active_workspace->floating->length - 1];
|
||||
set_focused_container(get_focused_view(floating));
|
||||
tiled_toggled_index = active_workspace->floating->length - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -506,16 +509,13 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) {
|
|||
}
|
||||
|
||||
swayc_t *container = get_focused_view(&root_container);
|
||||
bool current = (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) > 0;
|
||||
bool current = swayc_is_fullscreen(container);
|
||||
wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current);
|
||||
// Resize workspace if going from fullscreen -> notfullscreen
|
||||
// otherwise just resize container
|
||||
if (current) {
|
||||
container = swayc_parent_by_type(container, C_WORKSPACE);
|
||||
// Resize workspace
|
||||
container = swayc_parent_by_type(container, C_WORKSPACE);
|
||||
if (container) {
|
||||
arrange_windows(container, -1, -1);
|
||||
}
|
||||
// Only resize container when going into fullscreen
|
||||
arrange_windows(container, -1, -1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,17 +32,16 @@ static void free_swayc(swayc_t *cont) {
|
|||
if (!ASSERT_NONNULL(cont)) {
|
||||
return;
|
||||
}
|
||||
if (cont->handle > 0) {
|
||||
sway_log(L_DEBUG, "destroying container %p, handle:%ld",cont, cont->handle);
|
||||
if (cont->handle) {
|
||||
wlc_handle_set_user_data(cont->handle, 0);
|
||||
}
|
||||
// TODO does not properly handle containers with children,
|
||||
// TODO but functions that call this usually check for that
|
||||
// Destroy all children
|
||||
if (cont->children) {
|
||||
if (cont->children->length) {
|
||||
int i;
|
||||
for (i = 0; i < cont->children->length; ++i) {
|
||||
free_swayc(cont->children->items[i]);
|
||||
}
|
||||
// children remove themselves from parent, so continue until theres no
|
||||
// more children
|
||||
while (cont->children->length) {
|
||||
free_swayc(cont->children->items[0]);
|
||||
}
|
||||
list_free(cont->children);
|
||||
}
|
||||
|
|
@ -255,7 +254,7 @@ DESTROY_FUNC destroy_output(swayc_t *output) {
|
|||
if (output->children->length == 0) {
|
||||
// TODO move workspaces to other outputs
|
||||
}
|
||||
sway_log(L_DEBUG, "OUTPUT: Destroying output '%lu'", output->handle);
|
||||
sway_log(L_DEBUG, "%s:'%lu'", __func__, output->handle);
|
||||
free_swayc(output);
|
||||
return &root_container;
|
||||
}
|
||||
|
|
@ -288,7 +287,7 @@ DESTROY_FUNC destroy_container(swayc_t *container) {
|
|||
return NULL;
|
||||
}
|
||||
while (container->children->length == 0 && container->type == C_CONTAINER) {
|
||||
sway_log(L_DEBUG, "Container: Destroying container '%p'", container);
|
||||
sway_log(L_DEBUG, "%s: '%p'", __func__, container);
|
||||
swayc_t *parent = container->parent;
|
||||
free_swayc(container);
|
||||
container = parent;
|
||||
|
|
@ -300,7 +299,7 @@ DESTROY_FUNC destroy_view(swayc_t *view) {
|
|||
if (!ASSERT_NONNULL(view)) {
|
||||
return NULL;
|
||||
}
|
||||
sway_log(L_DEBUG, "Destroying view '%p'", view);
|
||||
sway_log(L_DEBUG, "%s: '%p'", __func__, view);
|
||||
swayc_t *parent = view->parent;
|
||||
free_swayc(view);
|
||||
|
||||
|
|
@ -312,6 +311,14 @@ DESTROY_FUNC destroy_view(swayc_t *view) {
|
|||
}
|
||||
#undef DESTROY_FUNC
|
||||
|
||||
// Container info function
|
||||
|
||||
bool swayc_is_fullscreen(swayc_t *view) {
|
||||
return view
|
||||
&& view->type == C_VIEW
|
||||
&& (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN);
|
||||
}
|
||||
|
||||
// Container lookup
|
||||
|
||||
swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) {
|
||||
|
|
@ -344,6 +351,56 @@ swayc_t *swayc_by_handle(wlc_handle handle) {
|
|||
return wlc_handle_get_user_data(handle);
|
||||
}
|
||||
|
||||
swayc_t *swayc_by_direction(swayc_t *container, enum movement_direction dir) {
|
||||
swayc_t *parent = container->parent;
|
||||
|
||||
if (dir == MOVE_PARENT) {
|
||||
if (parent->type == C_OUTPUT) {
|
||||
return NULL;
|
||||
} else {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
// Test if we can even make a difference here
|
||||
bool can_move = false;
|
||||
int diff = 0;
|
||||
if (dir == MOVE_LEFT || dir == MOVE_RIGHT) {
|
||||
if (parent->layout == L_HORIZ || parent->type == C_ROOT) {
|
||||
can_move = true;
|
||||
diff = dir == MOVE_LEFT ? -1 : 1;
|
||||
}
|
||||
} else {
|
||||
if (parent->layout == L_VERT) {
|
||||
can_move = true;
|
||||
diff = dir == MOVE_UP ? -1 : 1;
|
||||
}
|
||||
}
|
||||
if (can_move) {
|
||||
int i;
|
||||
for (i = 0; i < parent->children->length; ++i) {
|
||||
swayc_t *child = parent->children->items[i];
|
||||
if (child == container) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int desired = i + diff;
|
||||
if (desired < 0 || desired >= parent->children->length) {
|
||||
can_move = false;
|
||||
} else {
|
||||
return parent->children->items[desired];
|
||||
}
|
||||
}
|
||||
if (!can_move) {
|
||||
container = parent;
|
||||
parent = parent->parent;
|
||||
if (!parent) {
|
||||
// Nothing we can do
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) {
|
||||
if (!container->children) {
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ static void update_focus(swayc_t *c) {
|
|||
}
|
||||
|
||||
bool move_focus(enum movement_direction direction) {
|
||||
swayc_t *view = get_swayc_in_direction(
|
||||
get_focused_container(&root_container), direction);
|
||||
swayc_t *view = get_focused_container(&root_container);
|
||||
view = swayc_by_direction(view, direction);
|
||||
if (view) {
|
||||
if (direction == MOVE_PARENT) {
|
||||
set_focused_container(view);
|
||||
|
|
@ -103,8 +103,8 @@ void set_focused_container(swayc_t *c) {
|
|||
|
||||
// if the workspace is the same, and previous focus is fullscreen, dont
|
||||
// change focus
|
||||
if (workspace == active_workspace
|
||||
&& wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) {
|
||||
sway_log(L_DEBUG,"%p==%p, f:%d", workspace, active_workspace, swayc_is_fullscreen(focused));
|
||||
if (workspace == active_workspace && swayc_is_fullscreen(focused)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -422,8 +422,7 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct
|
|||
if (config->focus_follows_mouse && prev_handle != handle) {
|
||||
// Dont change focus if fullscreen
|
||||
swayc_t *focused = get_focused_view(view);
|
||||
if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)
|
||||
&& !(pointer_state.l_held || pointer_state.r_held)) {
|
||||
if (!swayc_is_fullscreen(focused) && !(pointer_state.l_held || pointer_state.r_held)) {
|
||||
set_focused_container(container_under_pointer());
|
||||
}
|
||||
}
|
||||
|
|
@ -451,7 +450,7 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w
|
|||
uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) {
|
||||
swayc_t *focused = get_focused_container(&root_container);
|
||||
// dont change focus if fullscreen
|
||||
if (focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) {
|
||||
if (swayc_is_fullscreen(focused)) {
|
||||
return false;
|
||||
}
|
||||
if (state == WLC_BUTTON_STATE_PRESSED) {
|
||||
|
|
|
|||
|
|
@ -107,12 +107,12 @@ swayc_t *remove_child(swayc_t *child) {
|
|||
parent->focused = NULL;
|
||||
}
|
||||
}
|
||||
child->parent = NULL;
|
||||
return parent;
|
||||
}
|
||||
|
||||
// Fitting functions
|
||||
#define FIT_FUNC __attribute__((nonnull)) static void
|
||||
|
||||
FIT_FUNC _fit_view(swayc_t *view) {
|
||||
sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, view,
|
||||
view->width, view->height, view->x, view->y);
|
||||
|
|
@ -174,7 +174,6 @@ FIT_FUNC _fit_container(swayc_t *container) {
|
|||
}
|
||||
s += *prev_w;
|
||||
}
|
||||
sway_log(L_DEBUG,"s:%f",s);
|
||||
if (s < 0.001) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -307,6 +306,7 @@ __attribute__((nonnull)) static wlc_handle order_children(swayc_t *swayc, wlc_ha
|
|||
// Put handle below current top, or if there is no top, set it as bottom
|
||||
if (top) {
|
||||
wlc_view_send_below(bottom, top);
|
||||
sway_log(L_DEBUG,"putting %ld below %ld", bottom, top);
|
||||
} else {
|
||||
top = bottom;
|
||||
}
|
||||
|
|
@ -322,6 +322,7 @@ __attribute__((nonnull)) static wlc_handle order_children(swayc_t *swayc, wlc_ha
|
|||
// Update current top, send it below previous bottom, and set new bottom
|
||||
top = order_children(*child, bottom);
|
||||
wlc_view_send_below(top, bottom);
|
||||
sway_log(L_DEBUG,"putting %ld below %ld", bottom, top);
|
||||
bottom = top;
|
||||
}
|
||||
|
||||
|
|
@ -330,18 +331,32 @@ __attribute__((nonnull)) static wlc_handle order_children(swayc_t *swayc, wlc_ha
|
|||
if (swayc->type == C_WORKSPACE) {
|
||||
// TODO using the same hacky implementation as before.
|
||||
// send floating windows to front
|
||||
len = swayc->children->length;
|
||||
len = swayc->floating->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) {
|
||||
|
||||
bool tofront = swayc->parent->focused == swayc;
|
||||
// Send focused view to front or back if fullscreen depending on tofront
|
||||
if (!focused->is_floating && swayc_is_fullscreen(focused)) {
|
||||
if (tofront) {
|
||||
wlc_view_bring_to_front(focused->handle);
|
||||
sway_log(L_DEBUG,"bring %ld to front (fullscreen)", focused->handle);
|
||||
// we dont want to bring floating windows above fullscreen
|
||||
// window
|
||||
tofront = false;
|
||||
} else {
|
||||
wlc_view_send_to_back(focused->handle);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < len; ++i, ++child) {
|
||||
if (tofront) {
|
||||
wlc_view_bring_to_front((*child)->handle);
|
||||
sway_log(L_DEBUG,"bring %ld to front (floating)", focused->handle);
|
||||
} else {
|
||||
wlc_view_send_to_back((*child)->handle);
|
||||
sway_log(L_DEBUG,"sending %ld to back (floating)", focused->handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -358,54 +373,3 @@ void arrange_windows(swayc_t *container, int width, int height) {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir) {
|
||||
swayc_t *parent = container->parent;
|
||||
|
||||
if (dir == MOVE_PARENT) {
|
||||
if (parent->type == C_OUTPUT) {
|
||||
return NULL;
|
||||
} else {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
// Test if we can even make a difference here
|
||||
bool can_move = false;
|
||||
int diff = 0;
|
||||
if (dir == MOVE_LEFT || dir == MOVE_RIGHT) {
|
||||
if (parent->layout == L_HORIZ || parent->type == C_ROOT) {
|
||||
can_move = true;
|
||||
diff = dir == MOVE_LEFT ? -1 : 1;
|
||||
}
|
||||
} else {
|
||||
if (parent->layout == L_VERT) {
|
||||
can_move = true;
|
||||
diff = dir == MOVE_UP ? -1 : 1;
|
||||
}
|
||||
}
|
||||
if (can_move) {
|
||||
int i;
|
||||
for (i = 0; i < parent->children->length; ++i) {
|
||||
swayc_t *child = parent->children->items[i];
|
||||
if (child == container) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int desired = i + diff;
|
||||
if (desired < 0 || desired >= parent->children->length) {
|
||||
can_move = false;
|
||||
} else {
|
||||
return parent->children->items[desired];
|
||||
}
|
||||
}
|
||||
if (!can_move) {
|
||||
container = parent;
|
||||
parent = parent->parent;
|
||||
if (!parent) {
|
||||
// Nothing we can do
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue