swayc_t *new_floating_view(wlc_handle handle) { const char *title = wlc_view_get_title(handle); swayc_t *view = new_swayc(C_VIEW); sway_log(L_DEBUG, "Adding new view %lu:%x:%s as a floating view", handle, wlc_view_get_type(handle), title); // Setup values view->handle = handle; view->name = title ? strdup(title) : NULL; view->visible = true; // Set the geometry of the floating view const struct wlc_geometry* geometry = wlc_view_get_geometry(handle); // give it requested geometry, but place in center view->x = (active_workspace->width - geometry->size.w) / 2; view->y = (active_workspace->height- geometry->size.h) / 2; view->width = geometry->size.w; view->height = geometry->size.h; view->desired_width = view->width; view->desired_height = view->height; view->is_floating = true; // Case of focused workspace, just create as child of it list_add(active_workspace->floating, view); view->parent = active_workspace; if (active_workspace->focused == NULL) { set_focused_container_for(active_workspace, view); } return view; }
static void handle_view_destroyed(wlc_handle handle) { sway_log(L_DEBUG, "Destroying window %lu", handle); swayc_t *view = get_swayc_for_handle(handle, &root_container); switch (wlc_view_get_type(handle)) { // regular view created regularly case 0: case WLC_BIT_MODAL: if (view) { swayc_t *parent = destroy_view(view); arrange_windows(parent, -1, -1); } break; // takes keyboard focus case WLC_BIT_OVERRIDE_REDIRECT: locked_view_focus = false; break; // Takes container focus case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: locked_container_focus = false; case WLC_BIT_POPUP: break; } set_focused_container(get_focused_view(&root_container)); }
static void handle_view_destroyed(wlc_handle handle) { sway_log(L_DEBUG, "Destroying window %lu", handle); swayc_t *view = get_swayc_for_handle(handle, &root_container); switch (wlc_view_get_type(handle)) { // regular view created regularly case 0: case WLC_BIT_MODAL: case WLC_BIT_POPUP: if (view) { swayc_t *parent = destroy_view(view); arrange_windows(parent, -1, -1); } break; // DMENU has this flag, and takes view_focus, but other things with this // flag dont case WLC_BIT_OVERRIDE_REDIRECT: // locked_view_focus = false; break; case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED: locked_container_focus = false; break; } set_focused_container(get_focused_view(&root_container)); }
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); } } }
static bool should_focus_on_create(struct wlc_view *view) { // Do not allow unmanaged views to steal focus (tooltips, dnds, etc..) // Do not allow parented windows to steal focus, if current window wasn't parent. uint32_t type = wlc_view_get_type(view); struct wlc_view *parent = wlc_view_get_parent(view); return (!(type & WLC_BIT_UNMANAGED) && (!loliwm.active || !parent || parent == loliwm.active)); }
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; } }
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 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 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(); } }
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 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 bool is_modal(struct wlc_view *view) { uint32_t type = wlc_view_get_type(view); return (type & WLC_BIT_MODAL); }
static bool is_managed(struct wlc_view *view) { uint32_t type = wlc_view_get_type(view); return !(type & WLC_BIT_UNMANAGED) && !(type & WLC_BIT_POPUP) && !(type & WLC_BIT_SPLASH); }
static bool is_or(struct wlc_view *view) { return (wlc_view_get_type(view) & WLC_BIT_OVERRIDE_REDIRECT) || (wlc_view_get_state(view) & BIT_BEMENU); }
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; }