From 03e83c7ef94e90a78390209af8d9c2a0c0adb237 Mon Sep 17 00:00:00 2001 From: taiyu Date: Tue, 18 Aug 2015 11:22:52 -0700 Subject: [PATCH] restored fullscreen/focus behavior --- sway/commands.c | 2 +- sway/container.c | 31 ++++++++++++++++--- sway/focus.c | 77 +++++++++++++++++++++++++++++++++++------------- sway/handlers.c | 19 +++++++++++- sway/layout.c | 62 ++++++++++++++++++++++++-------------- sway/workspace.c | 58 +++++++++++++++--------------------- 6 files changed, 166 insertions(+), 83 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index ae0bdbe4a..6c3efb3b1 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -408,7 +408,7 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) { return false; } - swayc_t *container = get_focused_container(&root_container); + swayc_t *container = get_focused_view(&root_container); bool current = (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) > 0; wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current); //Resize workspace if going from fullscreen -> notfullscreen diff --git a/sway/container.c b/sway/container.c index c83cd7201..62c5bda08 100644 --- a/sway/container.c +++ b/sway/container.c @@ -4,6 +4,7 @@ #include "config.h" #include "container.h" #include "workspace.h" +#include "focus.h" #include "layout.h" #include "log.h" @@ -21,11 +22,26 @@ static swayc_t *new_swayc(enum swayc_types type) { } static void free_swayc(swayc_t *c) { - //TODO does not properly handle containers with children, - //TODO but functions that call this usually check for that + // TODO does not properly handle containers with children, + // TODO but functions that call this usually check for that if (c->children) { + if (c->children->length) { + int i; + for (i = 0; i < c->children->length; ++i) { + free_swayc(c->children->items[i]); + } + } list_free(c->children); } + if (c->floating) { + if (c->floating->length) { + int i; + for (i = 0; i < c->floating->length; ++i) { + free_swayc(c->floating->items[i]); + } + } + list_free(c->floating); + } if (c->parent) { remove_child(c); } @@ -194,7 +210,7 @@ swayc_t *new_floating_view(wlc_handle handle) { list_add(active_workspace->floating, view); view->parent = active_workspace; if (active_workspace->focused == NULL) { - active_workspace->focused = view; + set_focused_container_for(active_workspace, view); } return view; } @@ -291,7 +307,7 @@ swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *da } void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { - if (!container->children || !container->children->length) { + if (!container || !container->children || !container->children->length) { return; } int i; @@ -300,6 +316,13 @@ void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), voi f(child, data); container_map(child, f, data); } + if (container->type == C_WORKSPACE) { + for (i = 0; i < container->floating->length; ++i) { + swayc_t *child = container->floating->items[i]; + f(child, data); + container_map(child, f, data); + } + } } void set_view_visibility(swayc_t *view, void *data) { diff --git a/sway/focus.c b/sway/focus.c index 7e3af56cd..628316dd6 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -14,11 +14,15 @@ static void update_focus(swayc_t *c) { swayc_t *parent = c->parent; if (parent->focused != c) { switch (c->type) { + // Shouldnt happen case C_ROOT: return; + + // Case where output changes case C_OUTPUT: wlc_output_focus(c->handle); break; - // switching workspaces + + // Case where workspace changes case C_WORKSPACE: if (parent->focused) { swayc_t *ws = parent->focused; @@ -29,10 +33,12 @@ static void update_focus(swayc_t *c) { mask = 2; container_map(c, set_view_visibility, &mask); wlc_output_set_mask(parent->handle, 2); + c->parent->focused = c; destroy_workspace(ws); } active_workspace = c; break; + default: case C_VIEW: case C_CONTAINER: @@ -49,6 +55,10 @@ bool move_focus(enum movement_direction direction) { return false; } swayc_t *current = get_focused_container(&root_container); + if (current->type == C_VIEW + && wlc_view_get_state(current->handle) & WLC_BIT_FULLSCREEN) { + return false; + } swayc_t *parent = current->parent; if (direction == MOVE_PARENT) { @@ -128,23 +138,39 @@ void set_focused_container(swayc_t *c) { return; } sway_log(L_DEBUG, "Setting focus to %p:%ld", c, c->handle); - if (c->type != C_ROOT && c->type != C_OUTPUT) { - c->is_focused = true; + + // Find previous focused view, and the new focused view, if they are the same return + swayc_t *focused = get_focused_view(&root_container); + swayc_t *workspace = active_workspace; + if (focused == get_focused_view(c)) { + return; } - swayc_t *prev_view = get_focused_view(&root_container); + + // update container focus from here to root, making necessary changes along + // the way swayc_t *p = c; while (p != &root_container) { update_focus(p); p = p->parent; p->is_focused = false; } - if (!locked_view_focus) { - p = get_focused_view(c); - // Set focus to p - if (p && !(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { - if (prev_view) { - wlc_view_set_state(prev_view->handle, WLC_BIT_ACTIVATED, false); - } + + // 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) { + return; + } + + // get new focused view and set focus to it. + p = get_focused_view(c); + if (p->type == C_VIEW && !(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { + // unactivate previous focus + if (focused->type == C_VIEW) { + wlc_view_set_state(focused->handle, WLC_BIT_ACTIVATED, false); + } + // activate current focus + if (p->type == C_VIEW) { wlc_view_focus(p->handle); wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); } @@ -156,12 +182,25 @@ void set_focused_container_for(swayc_t *a, swayc_t *c) { return; } swayc_t *find = c; - //Ensure that a is an ancestor of c + // Ensure that a is an ancestor of c while (find != a && (find = find->parent)) { if (find == &root_container) { return; } } + // Check if we changing a parent container that will see chnage + bool effective = true; + while (find != &root_container) { + if (find->parent->focused != find) { + effective = false; + } + find = find->parent; + } + if (effective) { + // Go to set_focused_container + set_focused_container(c); + return; + } sway_log(L_DEBUG, "Setting focus for %p:%ld to %p:%ld", a, a->handle, c, c->handle); @@ -173,19 +212,17 @@ void set_focused_container_for(swayc_t *a, swayc_t *c) { p = p->parent; p->is_focused = false; } - if (!locked_view_focus) { - p = get_focused_view(c); - // Set focus to p - if (p) { - wlc_view_focus(p->handle); - wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); - } - } } swayc_t *get_focused_view(swayc_t *parent) { while (parent && parent->type != C_VIEW) { + if (parent->type == C_WORKSPACE && parent->focused == NULL) { + return parent; + } parent = parent->focused; } + if (parent == NULL) { + return active_workspace; + } return parent; } diff --git a/sway/handlers.c b/sway/handlers.c index 4980f65cd..ec2b123ea 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -106,6 +106,12 @@ static void handle_output_destroyed(wlc_handle output) { if (i < list->length) { destroy_output(list->items[i]); } + if (list->length == 0) { + active_workspace = NULL; + } else { + //switch to other outputs active workspace + workspace_switch(((swayc_t *)root_container.children->items[0])->focused); + } } static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { @@ -320,6 +326,9 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct mouse_origin = *origin; bool changed_floating = false; int i = 0; + if (!active_workspace) { + return false; + } // Do checks to determine if proper keys are being held swayc_t *view = active_workspace->focused; if (m1_held && view) { @@ -400,7 +409,11 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct } } if (config->focus_follows_mouse && prev_handle != handle) { - set_focused_container(container_under_pointer()); + //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)) { + set_focused_container(container_under_pointer()); + } } prev_handle = handle; prev_pos = mouse_origin; @@ -414,6 +427,10 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, uint32_t button, enum wlc_button_state state) { 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) { + return false; + } if (state == WLC_BUTTON_STATE_PRESSED) { sway_log(L_DEBUG, "Mouse button %u pressed", button); if (button == 272) { diff --git a/sway/layout.c b/sway/layout.c index e2ea46a70..105359d26 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -1,11 +1,12 @@ #include #include #include -#include "list.h" -#include "log.h" #include "layout.h" +#include "log.h" +#include "list.h" #include "container.h" #include "workspace.h" +#include "focus.h" swayc_t root_container; @@ -79,9 +80,10 @@ swayc_t *remove_child(swayc_t *child) { } } } + //Set focused to new container if (parent->focused == child) { if (parent->children->length > 0) { - parent->focused = parent->children->items[i?i-1:0]; + set_focused_container_for(parent, parent->children->items[i?i-1:0]); } else { parent->focused = NULL; } @@ -209,26 +211,42 @@ void arrange_windows(swayc_t *container, int width, int height) { if (container->type == C_WORKSPACE) { for (i = 0; i < container->floating->length; ++i) { swayc_t *view = container->floating->items[i]; - // Set the geometry - struct wlc_geometry geometry = { - .origin = { - .x = view->x, - .y = view->y - }, - .size = { - .w = view->width, - .h = view->height + if (view->type == C_VIEW) { + // Set the geometry + struct wlc_geometry geometry = { + .origin = { + .x = view->x, + .y = view->y + }, + .size = { + .w = view->width, + .h = view->height + } + }; + if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) { + swayc_t *parent = view; + while (parent->type != C_OUTPUT) { + parent = parent->parent; + } + geometry.origin.x = 0; + geometry.origin.y = 0; + geometry.size.w = parent->width; + geometry.size.h = parent->height; + wlc_view_set_geometry(view->handle, &geometry); + wlc_view_bring_to_front(view->handle); + } else { + wlc_view_set_geometry(view->handle, &geometry); + view->width = width; + view->height = height; + // Bring the views to the front in order of the list, the list + // will be kept up to date so that more recently focused views + // have higher indexes + // This is conditional on there not being a fullscreen view in the workspace + if (!container->focused + || !(wlc_view_get_state(container->focused->handle) & WLC_BIT_FULLSCREEN)) { + wlc_view_bring_to_front(view->handle); + } } - }; - wlc_view_set_geometry(view->handle, &geometry); - - // Bring the views to the front in order of the list, the list - // will be kept up to date so that more recently focused views - // have higher indexes - // This is conditional on there not being a fullscreen view in the workspace - if (!container->focused - || !(wlc_view_get_state(container->focused->handle) & WLC_BIT_FULLSCREEN)) { - wlc_view_bring_to_front(view->handle); } } } diff --git a/sway/workspace.c b/sway/workspace.c index ed5458042..05a669fee 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -178,43 +178,37 @@ void workspace_switch(swayc_t *workspace) { return; } sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); - - // Remove focus from current view - swayc_t *current = get_focused_view(&root_container); - if (current && current->type == C_VIEW) { - wlc_view_set_state(current->handle, WLC_BIT_ACTIVATED, false); - } - - set_focused_container(workspace); + set_focused_container(get_focused_view(workspace)); + arrange_windows(workspace, -1, -1); active_workspace = workspace; } /* XXX:DEBUG:XXX */ static void container_log(const swayc_t *c) { fprintf(stderr, "focus:%c|", - c->is_focused ? 'F' : //Focused - c == active_workspace ? 'W' : //active workspace - c == &root_container ? 'R' : //root - 'X');//not any others + c->is_focused ? 'F' : //Focused + c == active_workspace ? 'W' : //active workspace + c == &root_container ? 'R' : //root + 'X');//not any others fprintf(stderr,"(%p)",c); fprintf(stderr,"(p:%p)",c->parent); fprintf(stderr,"(f:%p)",c->focused); fprintf(stderr,"(h:%ld)",c->handle); fprintf(stderr,"Type:"); fprintf(stderr, - c->type == C_ROOT ? "Root|" : - c->type == C_OUTPUT ? "Output|" : - c->type == C_WORKSPACE ? "Workspace|" : - c->type == C_CONTAINER ? "Container|" : - c->type == C_VIEW ? "View|" : "Unknown|"); + c->type == C_ROOT ? "Root|" : + c->type == C_OUTPUT ? "Output|" : + c->type == C_WORKSPACE ? "Workspace|" : + c->type == C_CONTAINER ? "Container|" : + c->type == C_VIEW ? "View|" : "Unknown|"); fprintf(stderr,"layout:"); fprintf(stderr, - c->layout == L_NONE ? "NONE|" : - c->layout == L_HORIZ ? "Horiz|": - c->layout == L_VERT ? "Vert|": - c->layout == L_STACKED ? "Stacked|": - c->layout == L_FLOATING ? "Floating|": - "Unknown|"); + c->layout == L_NONE ? "NONE|" : + c->layout == L_HORIZ ? "Horiz|": + c->layout == L_VERT ? "Vert|": + c->layout == L_STACKED ? "Stacked|": + c->layout == L_FLOATING ? "Floating|": + "Unknown|"); fprintf(stderr, "w:%d|h:%d|", c->width, c->height); fprintf(stderr, "x:%d|y:%d|", c->x, c->y); fprintf(stderr, "vis:%c|", c->visible?'t':'f'); @@ -223,30 +217,24 @@ static void container_log(const swayc_t *c) { fprintf(stderr, "children:%d\n",c->children?c->children->length:0); } void layout_log(const swayc_t *c, int depth) { - int i; - int e = c->children?c->children->length:0; - for (i = 0; i < depth; ++i) fputc(' ', stderr); + int i, d; + int e = c->children ? c->children->length : 0; container_log(c); if (e) { - for (i = 0; i < depth; ++i) fputc(' ', stderr); - fprintf(stderr,"(\n"); for (i = 0; i < e; ++i) { + fputc('|',stderr); + for (d = 0; d < depth; ++d) fputc('-', stderr); layout_log(c->children->items[i], depth + 1); } - for (i = 0; i < depth; ++i) fputc(' ', stderr); - fprintf(stderr,")\n"); } if (c->type == C_WORKSPACE) { e = c->floating?c->floating->length:0; - for (i = 0; i < depth; ++i) fputc(' ', stderr); if (e) { - for (i = 0; i < depth; ++i) fputc(' ', stderr); - fprintf(stderr,"(\n"); for (i = 0; i < e; ++i) { + fputc('|',stderr); + for (d = 0; d < depth; ++d) fputc('-', stderr); layout_log(c->floating->items[i], depth + 1); } - for (i = 0; i < depth; ++i) fputc(' ', stderr); - fprintf(stderr,")\n"); } } }