From 4c78ed7d178fcfde014cb78d3b9d205b7bf5c2f6 Mon Sep 17 00:00:00 2001 From: taiyu Date: Tue, 25 Aug 2015 09:49:38 -0700 Subject: [PATCH] order layouts, view_visibility, some renames --- include/container.h | 12 ++++-- include/layout.h | 2 +- sway/commands.c | 4 +- sway/config.c | 2 +- sway/container.c | 102 +++++++++++++++++++++++++++++++++----------- sway/focus.c | 27 ++++++------ sway/handlers.c | 6 ++- sway/ipc.c | 4 +- sway/layout.c | 90 +++++++++++++++++++++++++++++++------- 9 files changed, 185 insertions(+), 64 deletions(-) diff --git a/include/container.h b/include/container.h index aadba5de..38a935bb 100644 --- a/include/container.h +++ b/include/container.h @@ -99,11 +99,15 @@ swayc_t *swayc_active_workspace_for(swayc_t *view); bool swayc_is_fullscreen(swayc_t *view); // Mapping functions - -void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *); +void swayc_map(swayc_t *, void f(swayc_t *)); +void swayc_map_r(swayc_t *, void f(swayc_t *, void *), void *); // Mappings -void set_view_visibility(swayc_t *view, void *data); -void reset_gaps(swayc_t *view, void *data); +void swayc_show(swayc_t *view); +void swayc_hide(swayc_t *view); +// Sets visibility depending on parent +void swayc_inherit_visibility(swayc_t *view); + +void reset_gaps(swayc_t *view); #endif diff --git a/include/layout.h b/include/layout.h index 11bf1a28..2d32190b 100644 --- a/include/layout.h +++ b/include/layout.h @@ -26,8 +26,8 @@ void move_container(swayc_t* container,swayc_t* root,enum movement_direction dir // Layout void update_geometry(swayc_t *view); void arrange_windows(swayc_t *container, double width, double height); +void order_windows(swayc_t *container); -swayc_t *get_focused_container(swayc_t *parent); swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir); swayc_t *get_swayc_in_direction_under(swayc_t *container, enum movement_direction dir, swayc_t *limit); diff --git a/sway/commands.c b/sway/commands.c index 21ff5c7f..bdf80235 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -176,7 +176,7 @@ static bool cmd_exec(struct sway_config *config, int argc, char **argv) { return cmd_exec_always(config, argc, argv); } -static void kill_views(swayc_t *container, void *data) { +static void kill_views(swayc_t *container) { if (container->type == C_VIEW) { wlc_view_close(container->handle); } @@ -187,7 +187,7 @@ static bool cmd_exit(struct sway_config *config, int argc, char **argv) { return false; } // Close all views - container_map(&root_container, kill_views, NULL); + swayc_map(&root_container, kill_views); sway_terminate(); return true; } diff --git a/sway/config.c b/sway/config.c index 53fc860a..86b44031 100644 --- a/sway/config.c +++ b/sway/config.c @@ -237,7 +237,7 @@ _continue: if (is_active) { temp_config->reloading = false; - container_map(&root_container, reset_gaps, NULL); + swayc_map(&root_container, reset_gaps); arrange_windows(&root_container, -1, -1); } config = temp_config; diff --git a/sway/container.c b/sway/container.c index d23cef8f..fa57a64e 100644 --- a/sway/container.c +++ b/sway/container.c @@ -16,6 +16,7 @@ static swayc_t *new_swayc(enum swayc_types type) { c->handle = -1; c->layout = L_NONE; c->type = type; + c->visible = true; if (type != C_VIEW) { c->children = create_list(); } @@ -477,7 +478,7 @@ swayc_t *swayc_active_workspace_for(swayc_t *cont) { /* Fallthrough */ case C_OUTPUT: - cont = cont->focused; + cont = cont ? cont->focused : NULL; /* Fallthrough */ case C_WORKSPACE: @@ -496,43 +497,96 @@ bool swayc_is_fullscreen(swayc_t *view) { // Mapping -void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { - if (container) { - int i; - if (container->children) { - for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - f(child, data); - container_map(child, f, data); +void swayc_map(swayc_t *c, void f(swayc_t *)) { + if (c) { + int i, len; + swayc_t **child; + if (c->children) { + child = (swayc_t **)c->children->items; + len = c->children->length; + for (i = 0; i < len; ++i, ++child) { + f(*child); + swayc_map(*child,f); } } - if (container->floating) { - for (i = 0; i < container->floating->length; ++i) { - swayc_t *child = container->floating->items[i]; - f(child, data); - container_map(child, f, data); + if (c->floating) { + child = (swayc_t **)c->floating->items; + len = c->floating->length; + for (i = 0; i < len; ++i, ++child) { + f(*child); + swayc_map(*child,f); } } } } -void set_view_visibility(swayc_t *view, void *data) { +void swayc_map_r(swayc_t *c, void f(swayc_t *, void *), void *data) { + if (c) { + int i, len; + swayc_t **child; + if (c->children) { + child = (swayc_t **)c->children->items; + len = c->children->length; + for (i = 0; i < len; ++i, ++child) { + f(*child, data); + swayc_map_r(*child, f, data); + } + } + if (c->floating) { + child = (swayc_t **)c->floating->items; + len = c->floating->length; + for (i = 0; i < len; ++i, ++child) { + f(*child, data); + swayc_map_r(*child, f, data); + } + } + } +} + +// Set bitmask to 1 +void swayc_show(swayc_t *view) { if (!ASSERT_NONNULL(view)) { return; } - uint32_t *p = data; if (view->type == C_VIEW) { - wlc_view_set_mask(view->handle, *p); - if (*p == 2) { - wlc_view_bring_to_front(view->handle); - } else { - wlc_view_send_to_back(view->handle); - } + wlc_view_set_mask(view->handle, 1); } - view->visible = (*p == 2); + view->visible = true; } -void reset_gaps(swayc_t *view, void *data) { +// Set bitmask to 0 +void swayc_hide(swayc_t *view) { + if (!ASSERT_NONNULL(view)) { + return; + } + if (view->type == C_VIEW) { + wlc_view_set_mask(view->handle, 0); + } + view->visible = false; +} + +void swayc_inherit_visibility(swayc_t *view) { + if (!view || view->type == C_ROOT || view->type == C_OUTPUT) { + return; + } + swayc_t *parent = view->parent; + // inherit parent if invisible + if ((view->visible = parent->visible)) { + // Hide or show depending on parent layout + if (parent->layout == L_STACKED || parent->layout == L_TABBED) { + view->visible = parent->focused == view; + } else { + view->visible = true; + } + } + if (view->visible) { + swayc_show(view); + } else { + swayc_hide(view); + } +} + +void reset_gaps(swayc_t *view) { if (!ASSERT_NONNULL(view)) { return; } diff --git a/sway/focus.c b/sway/focus.c index e369de30..5d7e437e 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -28,14 +28,13 @@ static void update_focus(swayc_t *c) { if (parent->focused) { swayc_t *ws = parent->focused; // hide visibility of old workspace - uint32_t mask = 1; - container_map(ws, set_view_visibility, &mask); - // set visibility of new workspace - mask = 2; - container_map(c, set_view_visibility, &mask); - wlc_output_set_mask(parent->handle, 2); + swayc_hide(ws); + swayc_map(ws, swayc_inherit_visibility); destroy_workspace(ws); } + // set visibility of new workspace + swayc_show(c); + swayc_map(c, swayc_inherit_visibility); break; default: @@ -165,14 +164,16 @@ void set_focused_container_for(swayc_t *a, swayc_t *c) { } swayc_t *get_focused_view(swayc_t *parent) { - while (parent && parent->type != C_VIEW) { - if (parent->type == C_WORKSPACE && parent->focused == NULL) { - return parent; + swayc_t *c = parent; + while (c && c->type != C_VIEW) { + if (c->type == C_WORKSPACE && c->focused == NULL) { + return c; } - parent = parent->focused; + c = c->focused; } - if (parent == NULL) { - return swayc_active_workspace_for(parent); + if (c == NULL) { + c = swayc_active_workspace_for(parent); } - return parent; + return c; } + diff --git a/sway/handlers.c b/sway/handlers.c index 3a4e31ae..8aa0a42c 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -207,6 +207,7 @@ static bool handle_view_created(wlc_handle handle) { static void handle_view_destroyed(wlc_handle handle) { sway_log(L_DEBUG, "Destroying window %lu", handle); swayc_t *view = swayc_by_handle(handle); + swayc_t *focus = get_focused_view(&root_container); switch (wlc_view_get_type(handle)) { // regular view created regularly @@ -227,7 +228,10 @@ static void handle_view_destroyed(wlc_handle handle) { locked_container_focus = false; break; } - set_focused_container(get_focused_view(&root_container)); + // get and set new focus + if (focus && view == focus) { + set_focused_container(get_focused_view(&root_container)); + } } static void handle_view_focus(wlc_handle view, bool focus) { diff --git a/sway/ipc.c b/sway/ipc.c index 0b36d758..af44c5aa 100644 --- a/sway/ipc.c +++ b/sway/ipc.c @@ -209,7 +209,7 @@ void ipc_client_handle_command(struct ipc_client *client) { case IPC_GET_WORKSPACES: { list_t *workspaces = create_list(); - container_map(&root_container, ipc_get_workspaces_callback, workspaces); + swayc_map_r(&root_container, ipc_get_workspaces_callback, workspaces); char *json = json_list(workspaces); free_flat_list(workspaces); ipc_send_reply(client, json, strlen(json)); @@ -219,7 +219,7 @@ void ipc_client_handle_command(struct ipc_client *client) { case IPC_GET_OUTPUTS: { list_t *outputs = create_list(); - container_map(&root_container, ipc_get_outputs_callback, outputs); + swayc_map_r(&root_container, ipc_get_outputs_callback, outputs); char *json = json_list(outputs); free_flat_list(outputs); ipc_send_reply(client, json, strlen(json)); diff --git a/sway/layout.c b/sway/layout.c index a37e137c..10d92e10 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -203,6 +203,68 @@ void move_container(swayc_t *container,swayc_t* root,enum movement_direction dir } +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; + } + + // Recurse and get handle of focused container + wlc_handle bottom = _order_children(swayc->focused, top); + + // 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; + } + + // If we are at a workspace, put floating containers above topmost + if (swayc->type == C_WORKSPACE) { + // 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; +} + +void order_windows(swayc_t *swayc) { + _order_children(swayc, 0); +} + + void update_geometry(swayc_t *container) { if (container->type != C_VIEW) { return; @@ -228,7 +290,7 @@ void update_geometry(swayc_t *container) { return; } -void arrange_windows(swayc_t *container, double width, double height) { +static void _arrange_windows(swayc_t *container, double width, double height) { int i; if (width == -1 || height == -1) { sway_log(L_DEBUG, "Arranging layout for %p", container); @@ -242,7 +304,7 @@ void arrange_windows(swayc_t *container, double width, double height) { for (i = 0; i < container->children->length; ++i) { swayc_t *child = container->children->items[i]; sway_log(L_DEBUG, "Arranging output at %d", x); - arrange_windows(child, -1, -1); + _arrange_windows(child, -1, -1); x += child->width; } return; @@ -257,7 +319,7 @@ void arrange_windows(swayc_t *container, double width, double height) { child->width = width - container->gaps * 2; child->height = height - container->gaps * 2; sway_log(L_DEBUG, "Arranging workspace #%d at %f, %f", i, child->x, child->y); - arrange_windows(child, -1, -1); + _arrange_windows(child, -1, -1); } return; case C_VIEW: @@ -301,7 +363,7 @@ void arrange_windows(swayc_t *container, double width, double height) { sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); child->x = x + container->x; child->y = y + container->y; - arrange_windows(child, child->width * scale, height); + _arrange_windows(child, child->width * scale, height); x += child->width; } } @@ -328,7 +390,7 @@ void arrange_windows(swayc_t *container, double width, double height) { sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); child->x = x + container->x; child->y = y + container->y; - arrange_windows(child, width, child->height * scale); + _arrange_windows(child, width, child->height * scale); y += child->height; } } @@ -350,6 +412,12 @@ void arrange_windows(swayc_t *container, double width, double height) { } } } +} + +void arrange_windows(swayc_t *container, double width, double height) { + _arrange_windows(container, width, height); + order_windows(container); + swayc_map(container, swayc_inherit_visibility); layout_log(&root_container, 0); } @@ -476,17 +544,7 @@ void recursive_resize(swayc_t *container, double amount, enum wlc_resize_edge ed layout_match = container->layout == L_VERT; } if (container->type == C_VIEW) { - struct wlc_geometry geometry = { - .origin = { - .x = container->x + container->gaps / 2, - .y = container->y + container->gaps / 2 - }, - .size = { - .w = container->width - container->gaps, - .h = container->height - container->gaps - } - }; - wlc_view_set_geometry(container->handle, edge, &geometry); + update_geometry(container); return; } if (layout_match) {