fixed plenty of bugs and crashes, and restored fullscreen/floating behavior. also fixed mode_toggle

This commit is contained in:
taiyu 2015-08-20 17:34:08 -07:00
parent b93f068611
commit e2046e6aba
7 changed files with 135 additions and 114 deletions

View file

@ -2,8 +2,8 @@
#define _SWAY_CONTAINER_H #define _SWAY_CONTAINER_H
#include <wlc/wlc.h> #include <wlc/wlc.h>
typedef struct sway_container swayc_t; typedef struct sway_container swayc_t;
#include "layout.h" #include "layout.h"
#include "focus.h"
enum swayc_types{ enum swayc_types{
C_ROOT, C_ROOT,
@ -78,11 +78,15 @@ swayc_t *destroy_container(swayc_t *container);
// parent // parent
swayc_t *destroy_view(swayc_t *view); swayc_t *destroy_view(swayc_t *view);
// Container info
bool swayc_is_fullscreen(swayc_t *view);
// Container Lookup // Container Lookup
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 *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); 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 *);

View file

@ -25,7 +25,4 @@ void unfocus_all(swayc_t *container);
void focus_view(swayc_t *view); 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_swayc_in_direction(swayc_t *container, enum movement_direction dir);
#endif #endif

View file

@ -294,6 +294,8 @@ static bool cmd_focus(struct sway_config *config, int argc, char **argv) {
} else if (strcasecmp(argv[0], "mode_toggle") == 0) { } else if (strcasecmp(argv[0], "mode_toggle") == 0) {
int i; int i;
swayc_t *focused = get_focused_view(active_workspace); swayc_t *focused = get_focused_view(active_workspace);
// Dont change focus if fullscreen
if (!swayc_is_fullscreen(focused)) {
if (focused->is_floating) { if (focused->is_floating) {
if (active_workspace->children->length > 0) { if (active_workspace->children->length > 0) {
for (i = 0;i < active_workspace->floating->length; i++) { for (i = 0;i < active_workspace->floating->length; i++) {
@ -328,6 +330,7 @@ static bool cmd_focus(struct sway_config *config, int argc, char **argv) {
} }
} }
} }
}
return true; return true;
} }
@ -506,16 +509,13 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) {
} }
swayc_t *container = get_focused_view(&root_container); 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); wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current);
// Resize workspace if going from fullscreen -> notfullscreen // Resize workspace
// otherwise just resize container
if (current) {
container = swayc_parent_by_type(container, C_WORKSPACE); container = swayc_parent_by_type(container, C_WORKSPACE);
} if (container) {
// Only resize container when going into fullscreen
arrange_windows(container, -1, -1); arrange_windows(container, -1, -1);
}
return true; return true;
} }

View file

@ -32,17 +32,16 @@ static void free_swayc(swayc_t *cont) {
if (!ASSERT_NONNULL(cont)) { if (!ASSERT_NONNULL(cont)) {
return; 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); wlc_handle_set_user_data(cont->handle, 0);
} }
// TODO does not properly handle containers with children, // Destroy all children
// TODO but functions that call this usually check for that
if (cont->children) { if (cont->children) {
if (cont->children->length) { // children remove themselves from parent, so continue until theres no
int i; // more children
for (i = 0; i < cont->children->length; ++i) { while (cont->children->length) {
free_swayc(cont->children->items[i]); free_swayc(cont->children->items[0]);
}
} }
list_free(cont->children); list_free(cont->children);
} }
@ -255,7 +254,7 @@ DESTROY_FUNC destroy_output(swayc_t *output) {
if (output->children->length == 0) { if (output->children->length == 0) {
// TODO move workspaces to other outputs // 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); free_swayc(output);
return &root_container; return &root_container;
} }
@ -288,7 +287,7 @@ DESTROY_FUNC destroy_container(swayc_t *container) {
return NULL; return NULL;
} }
while (container->children->length == 0 && container->type == C_CONTAINER) { 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; swayc_t *parent = container->parent;
free_swayc(container); free_swayc(container);
container = parent; container = parent;
@ -300,7 +299,7 @@ DESTROY_FUNC destroy_view(swayc_t *view) {
if (!ASSERT_NONNULL(view)) { if (!ASSERT_NONNULL(view)) {
return NULL; return NULL;
} }
sway_log(L_DEBUG, "Destroying view '%p'", view); sway_log(L_DEBUG, "%s: '%p'", __func__, view);
swayc_t *parent = view->parent; swayc_t *parent = view->parent;
free_swayc(view); free_swayc(view);
@ -312,6 +311,14 @@ DESTROY_FUNC destroy_view(swayc_t *view) {
} }
#undef DESTROY_FUNC #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 // Container lookup
swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { 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); 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) { swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) {
if (!container->children) { if (!container->children) {

View file

@ -54,8 +54,8 @@ static void update_focus(swayc_t *c) {
} }
bool move_focus(enum movement_direction direction) { bool move_focus(enum movement_direction direction) {
swayc_t *view = get_swayc_in_direction( swayc_t *view = get_focused_container(&root_container);
get_focused_container(&root_container), direction); view = swayc_by_direction(view, direction);
if (view) { if (view) {
if (direction == MOVE_PARENT) { if (direction == MOVE_PARENT) {
set_focused_container(view); 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 // if the workspace is the same, and previous focus is fullscreen, dont
// change focus // change focus
if (workspace == active_workspace sway_log(L_DEBUG,"%p==%p, f:%d", workspace, active_workspace, swayc_is_fullscreen(focused));
&& wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { if (workspace == active_workspace && swayc_is_fullscreen(focused)) {
return; return;
} }

View file

@ -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) { if (config->focus_follows_mouse && prev_handle != handle) {
// Dont change focus if fullscreen // Dont change focus if fullscreen
swayc_t *focused = get_focused_view(view); swayc_t *focused = get_focused_view(view);
if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) if (!swayc_is_fullscreen(focused) && !(pointer_state.l_held || pointer_state.r_held)) {
&& !(pointer_state.l_held || pointer_state.r_held)) {
set_focused_container(container_under_pointer()); 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) { uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) {
swayc_t *focused = get_focused_container(&root_container); swayc_t *focused = get_focused_container(&root_container);
// dont change focus if fullscreen // 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; return false;
} }
if (state == WLC_BUTTON_STATE_PRESSED) { if (state == WLC_BUTTON_STATE_PRESSED) {

View file

@ -107,12 +107,12 @@ swayc_t *remove_child(swayc_t *child) {
parent->focused = NULL; parent->focused = NULL;
} }
} }
child->parent = NULL;
return parent; return parent;
} }
// Fitting functions // Fitting functions
#define FIT_FUNC __attribute__((nonnull)) static void #define FIT_FUNC __attribute__((nonnull)) static void
FIT_FUNC _fit_view(swayc_t *view) { FIT_FUNC _fit_view(swayc_t *view) {
sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, view, sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, view,
view->width, view->height, view->x, view->y); view->width, view->height, view->x, view->y);
@ -174,7 +174,6 @@ FIT_FUNC _fit_container(swayc_t *container) {
} }
s += *prev_w; s += *prev_w;
} }
sway_log(L_DEBUG,"s:%f",s);
if (s < 0.001) { if (s < 0.001) {
return; 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 // Put handle below current top, or if there is no top, set it as bottom
if (top) { if (top) {
wlc_view_send_below(bottom, top); wlc_view_send_below(bottom, top);
sway_log(L_DEBUG,"putting %ld below %ld", bottom, top);
} else { } else {
top = bottom; 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 // Update current top, send it below previous bottom, and set new bottom
top = order_children(*child, bottom); top = order_children(*child, bottom);
wlc_view_send_below(top, bottom); wlc_view_send_below(top, bottom);
sway_log(L_DEBUG,"putting %ld below %ld", bottom, top);
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) { if (swayc->type == C_WORKSPACE) {
// TODO using the same hacky implementation as before. // TODO using the same hacky implementation as before.
// send floating windows to front // send floating windows to front
len = swayc->children->length; len = swayc->floating->length;
child = (swayc_t **)swayc->floating->items; child = (swayc_t **)swayc->floating->items;
// chekc whether to send floating windows to the back or front // chekc whether to send floating windows to the back or front
swayc_t *focused = get_focused_view(swayc); 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)); bool tofront = swayc->parent->focused == swayc;
for (i = 0; i < len; ++i) { // 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) { if (tofront) {
wlc_view_bring_to_front((*child)->handle); wlc_view_bring_to_front((*child)->handle);
sway_log(L_DEBUG,"bring %ld to front (floating)", focused->handle);
} else { } else {
wlc_view_send_to_back((*child)->handle); 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; 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;
}
}
}
}