void set_focused_container(swayc_t *c) { if (locked_container_focus || !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; } swayc_t *prev_view = get_focused_view(&root_container); 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); } wlc_view_focus(p->handle); wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); } } }
void set_focused_container_for(swayc_t *a, swayc_t *c) { if (locked_container_focus || !c) { return; } swayc_t *find = c; //Ensure that a is an ancestor of c while (find != a && (find = find->parent)) { if (find == &root_container) { return; } } sway_log(L_DEBUG, "Setting focus for %p:%ld to %p:%ld", a, a->handle, c, c->handle); c->is_focused = true; swayc_t *p = c; while (p != a) { 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_focus(p->handle); wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); } } }
swayc_t *replace_child(swayc_t *child, swayc_t *new_child) { swayc_t *parent = child->parent; if (parent == NULL) { return NULL; } int i = index_child(child); if (child->is_floating) { parent->floating->items[i] = new_child; } else { parent->children->items[i] = new_child; } // Set parent and focus for new_child new_child->parent = child->parent; if (child->parent->focused == child) { child->parent->focused = new_child; } child->parent = NULL; // Set geometry for new child new_child->x = child->x; new_child->y = child->y; new_child->width = child->width; new_child->height = child->height; // reset geometry for child child->width = 0; child->height = 0; // deactivate child if (child->type == C_VIEW) { wlc_view_set_state(child->handle, WLC_BIT_ACTIVATED, false); } return parent; }
static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { swayc_t *c = swayc_by_handle(view); switch (state) { case WLC_BIT_FULLSCREEN: // i3 just lets it become fullscreen wlc_view_set_state(view, state, toggle); if (c) { sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d", view, c->name, toggle); arrange_windows(c->parent, -1, -1); // Set it as focused window for that workspace if its going fullscreen if (toggle) { swayc_t *ws = swayc_parent_by_type(c, C_WORKSPACE); // Set ws focus to c set_focused_container_for(ws, c); } } break; case WLC_BIT_MAXIMIZED: case WLC_BIT_RESIZING: case WLC_BIT_MOVING: break; case WLC_BIT_ACTIVATED: sway_log(L_DEBUG, "View %p requested to be activated", c); break; } return; }
static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { swayc_t *c = NULL; switch(state) { case WLC_BIT_FULLSCREEN: // i3 just lets it become fullscreen wlc_view_set_state(view, state, toggle); c = get_swayc_for_handle(view, &root_container); sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d",view,c->name,toggle); if (c) { arrange_windows(c->parent, -1, -1); // Set it as focused window for that workspace if its going fullscreen if (toggle) { swayc_t *ws = c; while (ws->type != C_WORKSPACE) { ws = ws->parent; } // Set ws focus to c set_focused_container_for(ws, c); } } break; case WLC_BIT_MAXIMIZED: case WLC_BIT_RESIZING: case WLC_BIT_MOVING: case WLC_BIT_ACTIVATED: break; } return; }
bool set_focused_container(swayc_t *c) { if (locked_container_focus || !c) { return false; } swayc_log(L_DEBUG, c, "Setting focus to %p:%ld", c, c->handle); // Get workspace for c, get that workspaces current focused container. swayc_t *workspace = swayc_active_workspace_for(c); swayc_t *focused = get_focused_view(workspace); // if the workspace we are changing focus to has a fullscreen view return if (swayc_is_fullscreen(focused) && focused != c) { return false; } // update container focus from here to root, making necessary changes along // the way swayc_t *p = c; if (p->type != C_OUTPUT && p->type != C_ROOT) { p->is_focused = true; } while (p != &root_container) { update_focus(p); p = p->parent; p->is_focused = false; } // 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_set_state(p->handle, WLC_BIT_ACTIVATED, true); // set focus if view_focus is unlocked if (!locked_view_focus) { wlc_view_focus(p->handle); } } } return true; }
static void view_request_state(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { (void)view; if (state == WLC_BIT_FULLSCREEN && toggle) fullscreen_state_requested = true; wlc_view_set_state(view, state, toggle); if (view_moved_to_output) signal_client(&compositor); }
static bool handle_view_created(wlc_handle handle) { swayc_t *focused = get_focused_container(&root_container); uint32_t type = wlc_view_get_type(handle); // If override_redirect/unmanaged/popup/modal/splach if (type) { sway_log(L_DEBUG,"Unmanaged window of type %x left alone", type); wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); if (type & WLC_BIT_UNMANAGED) { return true; } // For things like Dmenu if (type & WLC_BIT_OVERRIDE_REDIRECT) { override_redirect = true; wlc_view_focus(handle); } // Float popups if (type & WLC_BIT_POPUP) { swayc_t *view = new_floating_view(handle); wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, false); focus_view(view); arrange_windows(active_workspace, -1, -1); } } else { swayc_t *view = new_view(focused, handle); //Set maximize flag for windows. //TODO: floating windows have this unset wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true); unfocus_all(&root_container); focus_view(view); arrange_windows(view->parent, -1, -1); } if (wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { unfocus_all(&root_container); focus_view(focused); arrange_windows(focused, -1, -1); } return true; }
static void relayout(struct wlc_space *space) { if (!space) return; struct wl_list *views; if (!(views = wlc_space_get_userdata(space))) return; uint32_t rwidth, rheight; struct wlc_output *output = wlc_space_get_output(space); wlc_output_get_resolution(output, &rwidth, &rheight); struct wlc_view *v; uint32_t count = 0; wlc_view_for_each_user(v, views) if (is_tiled(v)) ++count; bool toggle = false; uint32_t y = 0, height = rheight / (count > 1 ? count - 1 : 1); uint32_t fheight = (rheight > height * (count - 1) ? height + (rheight - height * (count - 1)) : height); wlc_view_for_each_user(v, views) { if (wlc_view_get_state(v) & WLC_BIT_FULLSCREEN) { wlc_view_resize(v, rwidth, rheight); wlc_view_position(v, 0, 0); } if (wlc_view_get_type(v) & WLC_BIT_SPLASH) wlc_view_position(v, rwidth * 0.5 - wlc_view_get_width(v) * 0.5, rheight * 0.5 - wlc_view_get_height(v) * 0.5); struct wlc_view *parent; if (is_managed(v) && !is_or(v) && (parent = wlc_view_get_parent(v))) layout_parent(v, parent, wlc_view_get_width(v), wlc_view_get_height(v)); if (!is_tiled(v)) continue; uint32_t slave = rwidth * loliwm.cut; wlc_view_set_state(v, WLC_BIT_MAXIMIZED, true); wlc_view_resize(v, (count > 1 ? (toggle ? slave : rwidth - slave) : rwidth), (toggle ? (y == 0 ? fheight : height) : rheight)); wlc_view_position(v, (toggle ? rwidth - slave : 0), y); if (toggle) y += (y == 0 ? fheight : height); toggle = true; } }
static bool handle_view_created(wlc_handle handle) { swayc_t *focused = get_focused_container(&root_container); swayc_t *newview = NULL; switch (wlc_view_get_type(handle)) { // regular view created regularly case 0: newview = new_view(focused, handle); wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true); break; // takes keyboard focus case WLC_BIT_OVERRIDE_REDIRECT: sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT", handle); locked_view_focus = true; wlc_view_focus(handle); wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); wlc_view_bring_to_front(handle); break; // Takes container focus case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT|WLC_BIT_MANAGED", handle); wlc_view_bring_to_front(handle); locked_container_focus = true; break; // set modals as floating containers case WLC_BIT_MODAL: wlc_view_bring_to_front(handle); newview = new_floating_view(handle); case WLC_BIT_POPUP: break; } if (newview) { set_focused_container(newview); arrange_windows(newview->parent, -1, -1); } return true; }
static void set_lock_surface(struct wl_client *client, struct wl_resource *resource, struct wl_resource *_output, struct wl_resource *surface) { swayc_t *output = swayc_by_handle(wlc_handle_from_wl_output_resource(_output)); swayc_t *view = swayc_by_handle(wlc_handle_from_wl_surface_resource(surface)); sway_log(L_DEBUG, "Setting lock surface to %p", view); if (view && output) { swayc_t *workspace = output->focused; if (!swayc_is_child_of(view, workspace)) { move_container_to(view, workspace); } wlc_view_set_state(view->handle, WLC_BIT_FULLSCREEN, true); workspace->fullscreen = view; desktop_shell.is_locked = true; set_focused_container(view); arrange_windows(view, -1, -1); list_add(desktop_shell.lock_surfaces, surface); wl_resource_set_destructor(surface, lock_surface_destructor); } else { sway_log(L_ERROR, "Attempted to set lock surface to non-view"); } }
static void handle_view_destroyed(wlc_handle handle) { sway_log(L_DEBUG, "Destroying window %u", (unsigned int)handle); // Properly handle unmanaged views uint32_t type = wlc_view_get_type(handle); if (type) { wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); sway_log(L_DEBUG,"Unmanaged window of type %x was destroyed", type); if (type & WLC_BIT_UNMANAGED) { // We need to call focus_view() on focus_pointer because unmanaged windows // do not alter the focus structure of the container tree. This makes focus_pointer() // think that it doesn't need to do anything, so we manually focus the result. focus_view(focus_pointer()); return; } if (type & WLC_BIT_OVERRIDE_REDIRECT) { override_redirect = false; focus_view(focus_pointer()); return; } // WLC_BIT_POPUP doesn't need to be dealt with since it's // treated as a floating view. } swayc_t *view = get_swayc_for_handle(handle, &root_container); swayc_t *parent; swayc_t *focused = get_focused_container(&root_container); if (view) { parent = destroy_view(view); arrange_windows(parent, -1, -1); } if (!focused || focused == view) { focus_pointer(); } }
struct cmd_results *cmd_fullscreen(int argc, char **argv) { struct cmd_results *error = NULL; if (config->reading) return cmd_results_new(CMD_FAILURE, "fullscreen", "Can't be used in config file."); if (!config->active) return cmd_results_new(CMD_FAILURE, "fullscreen", "Can only be used when sway is running."); if ((error = checkarg(argc, "fullscreen", EXPECTED_AT_LEAST, 0))) { return error; } swayc_t *container = get_focused_view(&root_container); if(container->type != C_VIEW){ return cmd_results_new(CMD_INVALID, "fullscreen", "Only views can fullscreen"); } swayc_t *workspace = swayc_parent_by_type(container, C_WORKSPACE); bool current = swayc_is_fullscreen(container); wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current); if (container->is_floating) { if (current) { // set dimensions back to what they were before we fullscreened this container->x = container->cached_geometry.origin.x; container->y = container->cached_geometry.origin.y; container->width = container->cached_geometry.size.w; container->height = container->cached_geometry.size.h; } else { // cache dimensions so we can reset them after we "unfullscreen" this struct wlc_geometry geo = { .origin = { .x = container->x, .y = container->y }, .size = { .w = container->width, .h = container->height } }; container->cached_geometry = geo; } }
swayc_t *remove_child(swayc_t *child) { int i; swayc_t *parent = child->parent; if (child->is_floating) { // Special case for floating views for (i = 0; i < parent->floating->length; ++i) { if (parent->floating->items[i] == child) { list_del(parent->floating, i); break; } } i = 0; } else { for (i = 0; i < parent->children->length; ++i) { if (parent->children->items[i] == child) { list_del(parent->children, i); break; } } } // Set focused to new container if (parent->focused == child) { if (parent->children->length > 0) { parent->focused = parent->children->items[i ? i-1:0]; } else if (parent->floating && parent->floating->length) { parent->focused = parent->floating->items[parent->floating->length - 1]; } else { parent->focused = NULL; } } child->parent = NULL; // deactivate view if (child->type == C_VIEW) { wlc_view_set_state(child->handle, WLC_BIT_ACTIVATED, false); } return parent; }
static bool handle_view_created(wlc_handle handle) { // if view is child of another view, the use that as focused container wlc_handle parent = wlc_view_get_parent(handle); swayc_t *focused = NULL; swayc_t *newview = NULL; // Get parent container, to add view in if (parent) { focused = get_swayc_for_handle(parent, &root_container); } if (!focused || focused->type == C_OUTPUT) { focused = get_focused_container(&root_container); } sway_log(L_DEBUG, "handle:%ld type:%x state:%x parent:%ld " "mask:%d (x:%d y:%d w:%d h:%d) title:%s " "class:%s appid:%s", handle, wlc_view_get_type(handle), wlc_view_get_state(handle), parent, wlc_view_get_mask(handle), wlc_view_get_geometry(handle)->origin.x, wlc_view_get_geometry(handle)->origin.y,wlc_view_get_geometry(handle)->size.w, wlc_view_get_geometry(handle)->size.h, wlc_view_get_title(handle), wlc_view_get_class(handle), wlc_view_get_app_id(handle)); // TODO properly figure out how each window should be handled. switch (wlc_view_get_type(handle)) { // regular view created regularly case 0: newview = new_view(focused, handle); wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true); break; // Dmenu keeps viewfocus, but others with this flag dont, for now simulate // dmenu case WLC_BIT_OVERRIDE_REDIRECT: // locked_view_focus = true; wlc_view_focus(handle); wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); wlc_view_bring_to_front(handle); break; // Firefox popups have this flag set. case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: wlc_view_bring_to_front(handle); locked_container_focus = true; break; // Modals, get focus, popups do not case WLC_BIT_MODAL: wlc_view_focus(handle); wlc_view_bring_to_front(handle); newview = new_floating_view(handle); case WLC_BIT_POPUP: wlc_view_bring_to_front(handle); break; } if (newview) { set_focused_container(newview); swayc_t *output = swayc_parent_by_type(newview, C_OUTPUT); arrange_windows(output, -1, -1); } return true; }
static void view_focus(wlc_handle view, bool focus) { printf("focused\n"); wlc_view_set_state(view, WLC_BIT_ACTIVATED, focus); }
static void view_focus(wlc_handle view, bool focus) { wlc_view_set_state(view, WLC_BIT_ACTIVATED, focus); }
bool set_focused_container(swayc_t *c) { if (locked_container_focus || !c || !c->parent) { return false; } swayc_t *active_ws = swayc_active_workspace(); int active_ws_child_count = 0; if (active_ws) { active_ws_child_count = active_ws->children->length + active_ws->floating->length; } swayc_log(L_DEBUG, c, "Setting focus to %p:%" PRIuPTR, c, c->handle); // Get workspace for c, get that workspaces current focused container. swayc_t *workspace = swayc_active_workspace_for(c); swayc_t *focused = get_focused_view(workspace); if (swayc_is_fullscreen(focused) && focused != c) { // if switching to a workspace with a fullscreen view, // focus on the fullscreen view c = focused; } if (c->type == C_VIEW) { // dispatch a window event ipc_event_window(c, "focus"); } // update container focus from here to root, making necessary changes along // the way swayc_t *p = c; if (p->type != C_OUTPUT && p->type != C_ROOT) { p->is_focused = true; } while (p != &root_container) { update_focus(p); p = p->parent; p->is_focused = false; } // 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); update_view_border(focused); } // activate current focus if (p->type == C_VIEW) { wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); // set focus if view_focus is unlocked if (!locked_view_focus) { wlc_view_focus(p->handle); if (p->parent->layout != L_TABBED && p->parent->layout != L_STACKED) { update_view_border(p); } } } // rearrange if parent container is tabbed/stacked swayc_t *parent = swayc_tabbed_stacked_ancestor(p); if (parent != NULL) { arrange_backgrounds(); arrange_windows(parent, -1, -1); } } else if (p->type == C_WORKSPACE) { // remove previous focus if view_focus is unlocked if (!locked_view_focus) { wlc_view_focus(0); } } if (active_ws != workspace) { // active_ws might have been destroyed by now // (focus swap away from empty ws = destroy ws) if (active_ws_child_count == 0) { active_ws = NULL; } ipc_event_workspace(active_ws, workspace, "focus"); } return true; }