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) { set_focused_container_for(parent, parent->children->items[i?i-1:0]); } else { parent->focused = NULL; } } return parent; }
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; }
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_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; }
void add_floating(swayc_t *ws, swayc_t *child) { sway_log(L_DEBUG, "Adding %p (%d, %dx%d) to %p (%d, %dx%d)", child, child->type, child->width, child->height, ws, ws->type, ws->width, ws->height); list_add(ws->floating, child); child->parent = ws; child->is_floating = true; if (!ws->focused) { set_focused_container_for(ws, child); } }
void add_child(swayc_t *parent, swayc_t *child) { sway_log(L_DEBUG, "Adding %p (%d, %dx%d) to %p (%d, %dx%d)", child, child->type, child->width, child->height, parent, parent->type, parent->width, parent->height); list_add(parent->children, child); child->parent = parent; // set focus for this container if (parent->children->length == 1) { set_focused_container_for(parent, child); } }
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(parent, child); parent->children->items[i] = new_child; new_child->parent = child->parent; if (child->parent->focused == child) { set_focused_container_for(child->parent, new_child); } child->parent = NULL; return parent; }
swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { if (!ASSERT_NONNULL(child)) { return NULL; } swayc_t *cont = new_swayc(C_CONTAINER); sway_log(L_DEBUG, "creating container %p around %p", cont, child); cont->layout = layout; cont->width = child->width; cont->height = child->height; cont->x = child->x; cont->y = child->y; cont->visible = child->visible; /* Container inherits all of workspaces children, layout and whatnot */ if (child->type == C_WORKSPACE) { swayc_t *workspace = child; // reorder focus cont->focused = workspace->focused; workspace->focused = cont; // set all children focu to container int i; for (i = 0; i < workspace->children->length; ++i) { ((swayc_t *)workspace->children->items[i])->parent = cont; } // Swap children list_t *tmp_list = workspace->children; workspace->children = cont->children; cont->children = tmp_list; // add container to workspace chidren add_child(workspace, cont); // give them proper layouts cont->layout = workspace->layout; workspace->layout = layout; set_focused_container_for(workspace, get_focused_view(workspace)); } else { // Or is built around container swayc_t *parent = replace_child(child, cont); if (parent) { add_child(cont, child); } } return cont; }
void move_container(swayc_t *container, enum movement_direction dir) { enum swayc_layouts layout; if (container->is_floating || (container->type != C_VIEW && container->type != C_CONTAINER)) { return; } if (dir == MOVE_UP || dir == MOVE_DOWN) { layout = L_VERT; } else if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { layout = L_HORIZ; } else { return; } swayc_t *parent = container->parent; swayc_t *child = container; bool ascended = false; while (true) { sway_log(L_DEBUG, "container:%p, parent:%p, child %p,", container,parent,child); if (parent->layout == layout || (parent->layout == L_TABBED && layout == L_HORIZ) || (parent->layout == L_STACKED && layout == L_VERT)) { int diff; // If it has ascended (parent has moved up), no container is removed // so insert it at index, or index+1. // if it has not, the moved container is removed, so it needs to be // inserted at index-1, or index+1 if (ascended) { diff = dir == MOVE_LEFT || dir == MOVE_UP ? 0 : 1; } else { diff = dir == MOVE_LEFT || dir == MOVE_UP ? -1 : 1; } int desired = index_child(child) + diff; // when it has ascended, legal insertion position is 0:len // when it has not, legal insertion position is 0:len-1 if (desired >= 0 && desired - ascended < parent->children->length) { if (!ascended) { child = parent->children->items[desired]; // Move container into sibling container if (child->type == C_CONTAINER) { parent = child; // Insert it in first/last if matching layout, otherwise // inesrt it next to focused container if (parent->layout == layout || (parent->layout == L_TABBED && layout == L_HORIZ) || (parent->layout == L_STACKED && layout == L_VERT)) { desired = (diff < 0) * parent->children->length; } else { desired = index_child(child->focused); } //reset geometry container->width = container->height = 0; } } swayc_t *old_parent = remove_child(container); insert_child(parent, container, desired); destroy_container(old_parent); sway_log(L_DEBUG,"Moving to %p %d",parent, desired); break; } } // Change parent layout if we need to if (parent->children->length == 1 && parent->layout != layout) { parent->layout = layout; continue; } if (parent->type == C_WORKSPACE) { // We simply cannot move any further. if (parent->layout == layout) { break; } // Create container around workspace to insert child into parent = new_container(parent, layout); } ascended = true; child = parent; parent = child->parent; } arrange_windows(parent->parent, -1, -1); set_focused_container_for(parent->parent, container); }