/* * @brief range a column of window on the given geometry. */ static void relayout_onecol(const wlc_handle *views, const size_t nviews, const struct wlc_geometry *geo) { if (nviews == 0) return; size_t y = geo->origin.y; //if nviews == 0, crashes size_t srow = (size_t) (geo->size.h / nviews); for (size_t i = 0; i < nviews; i++) { struct wlc_geometry g = { {geo->origin.x, y},//point {geo->size.w, srow}//size }; //fprintf(debug_file, "the geometry for %d view is: x %d, y %d, w %d, h %d\n", // i, // g.origin.x, // g.origin.y, // g.size.w, // g.size.h); //fflush(debug_file); y += srow; wlc_view_set_geometry(views[i], 0, &g); } }
/** * * @brief the simple floating windows relayout strategy, which is actually * doing nothing. * * Tested */ static void relayout_float(const tw_handle *views, const size_t nviews, const wlc_geometry *geo) { //this method has to be called in safe env. if(!views || !geo) return; const wlc_size *r = &geo->size; //this method is not safe, how do you ensure you will not access //unallocated memory? c++ vector? for (size_t i = 0; i < nviews; i++) { debug_log("relayout_float\n"); //the only thing we are doing here is ensure the the window //does not go out or border, but is may not be good, since //windows can have border struct wlc_geometry g = *wlc_view_get_geometry(views[i]); g.size.h = (g.size.h > 0) ? g.size.h : 100;//give a initial height if not avaliable g.size.w = (g.size.w > 0) ? g.size.w : 100;//give a initial wpidth if not avaliable int32_t view_botton = g.origin.y+g.size.h; int32_t view_right = g.origin.x+g.size.w; g.size.h = MIN(view_botton, r->h) - g.origin.y; g.size.w = MIN(view_right, r->w) - g.origin.x; wlc_view_set_geometry(views[i], 0, &g); wlc_view_bring_to_front(views[i]); } }
static void relayout_onerow(const wlc_handle *views, const size_t nviews, const struct wlc_geometry *geo) { if (nviews == 0) return; size_t x = geo->origin.x; //if nviews == 0, crashes size_t scol = (size_t) (geo->size.w / nviews); for (size_t i = 0; i < nviews; i++) { struct wlc_geometry g = { {x, geo->origin.y},//point {scol, geo->size.h}//size }; x += scol; wlc_view_set_geometry(views[i], 0, &g); } }
static void relayout(wlc_handle output) { const struct wlc_size *r; if (!(r = wlc_output_get_resolution(output))) return; size_t memb; const wlc_handle *views = wlc_output_get_views(output, &memb); bool toggle = false; uint32_t y = 0; uint32_t w = r->w / 2, h = r->h / chck_maxu32((1 + memb) / 2, 1); for (size_t i = 0; i < memb; ++i) { struct wlc_geometry g = { { (toggle ? w : 0), y }, { (!toggle && i == memb - 1 ? r->w : w), h } }; wlc_view_set_geometry(views[i], &g); y = y + (!(toggle = !toggle) ? h : 0); } }
static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) { static struct wlc_origin prev_pos; static wlc_handle prev_handle = 0; mouse_origin = *origin; bool changed_floating = false; bool changed_tiling = false; int min_sane_w = 100; int min_sane_h = 60; if (!active_workspace) { return false; } // Do checks to determine if proper keys are being held swayc_t *view = container_under_pointer(); uint32_t edge = 0; if (pointer_state.floating.drag && view) { if (view->is_floating) { int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; view->x += dx; view->y += dy; changed_floating = true; } } else if (pointer_state.floating.resize && view) { if (view->is_floating) { int dx = mouse_origin.x - prev_pos.x; int dy = mouse_origin.y - prev_pos.y; // Move and resize the view based on the dx/dy and mouse position int midway_x = view->x + view->width/2; int midway_y = view->y + view->height/2; if (dx < 0) { if (!pointer_state.lock.right) { if (view->width > min_sane_w) { changed_floating = true; view->width += dx; edge += WLC_RESIZE_EDGE_RIGHT; } } else if (mouse_origin.x < midway_x && !pointer_state.lock.left) { changed_floating = true; view->x += dx; view->width -= dx; edge += WLC_RESIZE_EDGE_LEFT; } } else if (dx > 0) { if (mouse_origin.x > midway_x && !pointer_state.lock.right) { changed_floating = true; view->width += dx; edge += WLC_RESIZE_EDGE_RIGHT; } else if (!pointer_state.lock.left) { if (view->width > min_sane_w) { changed_floating = true; view->x += dx; view->width -= dx; edge += WLC_RESIZE_EDGE_LEFT; } } } if (dy < 0) { if (!pointer_state.lock.bottom) { if (view->height > min_sane_h) { changed_floating = true; view->height += dy; edge += WLC_RESIZE_EDGE_BOTTOM; } } else if (mouse_origin.y < midway_y && !pointer_state.lock.top) { changed_floating = true; view->y += dy; view->height -= dy; edge += WLC_RESIZE_EDGE_TOP; } } else if (dy > 0) { if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) { changed_floating = true; view->height += dy; edge += WLC_RESIZE_EDGE_BOTTOM; } else if (!pointer_state.lock.top) { if (view->height > min_sane_h) { changed_floating = true; view->y += dy; view->height -= dy; edge += WLC_RESIZE_EDGE_TOP; } } } } } else if (pointer_state.tiling.resize && view) { bool valid = true; double dx = mouse_origin.x - prev_pos.x; double dy = mouse_origin.y - prev_pos.y; if ((dx < 0 || mouse_origin.x < pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_left) { changed_tiling = true; valid = false; } else if (dx > 0 && pointer_state.lock.temp_left) { pointer_state.lock.temp_left = false; } if ((dx > 0 || mouse_origin.x > pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_right) { changed_tiling = true; valid = false; } else if (dx < 0 && pointer_state.lock.temp_right) { pointer_state.lock.temp_right = false; } if ((dy < 0 || mouse_origin.y < pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_up) { changed_tiling = true; valid = false; } else if (dy > 0 && pointer_state.lock.temp_up) { pointer_state.lock.temp_up = false; } if ((dy > 0 || mouse_origin.y > pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_down) { changed_tiling = true; valid = false; } else if (dy < 0 && pointer_state.lock.temp_down) { pointer_state.lock.temp_down = false; } if (!view->is_floating && valid) { // Handle layout resizes -- Find the biggest parent container then apply resizes to that // and its bordering siblings swayc_t *parent = view; if (!pointer_state.lock.bottom) { while (parent->type != C_WORKSPACE) { // TODO: Absolute value is a bad hack here to compensate for rounding. Find a better // way of doing this. if (fabs(parent->parent->y + parent->parent->height - (view->y + view->height)) <= 1) { parent = parent->parent; } else { break; } } if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) { swayc_t *sibling = get_swayc_in_direction(parent, MOVE_DOWN); if (sibling) { if ((parent->height > min_sane_h || dy > 0) && (sibling->height > min_sane_h || dy < 0)) { recursive_resize(parent, dy, WLC_RESIZE_EDGE_BOTTOM); recursive_resize(sibling, -1 * dy, WLC_RESIZE_EDGE_TOP); changed_tiling = true; } else { pointer_state.tiling.lock_pos.y = mouse_origin.y; if (parent->height < min_sane_h) { pointer_state.lock.temp_up = true; } else if (sibling->height < min_sane_h) { pointer_state.lock.temp_down = true; } } } } } else if (!pointer_state.lock.top) { while (parent->type != C_WORKSPACE) { if (fabs(parent->parent->y - view->y) <= 1) { parent = parent->parent; } else { break; } } if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) { swayc_t *sibling = get_swayc_in_direction(parent, MOVE_UP); if (sibling) { if ((parent->height > min_sane_h || dy < 0) && (sibling->height > min_sane_h || dy > 0)) { recursive_resize(parent, -1 * dy, WLC_RESIZE_EDGE_TOP); recursive_resize(sibling, dy, WLC_RESIZE_EDGE_BOTTOM); changed_tiling = true; } else { pointer_state.tiling.lock_pos.y = mouse_origin.y; if (parent->height < min_sane_h) { pointer_state.lock.temp_down = true; } else if (sibling->height < min_sane_h) { pointer_state.lock.temp_up = true; } } } } } parent = view; if (!pointer_state.lock.right) { while (parent->type != C_WORKSPACE) { if (fabs(parent->parent->x + parent->parent->width - (view->x + view->width)) <= 1) { parent = parent->parent; } else { sway_log(L_DEBUG, "view: %f vs parent: %f", view->x + view->width, parent->parent->x + parent->parent->width); break; } } if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) { swayc_t *sibling = get_swayc_in_direction(parent, MOVE_RIGHT); if (sibling) { if ((parent->width > min_sane_w || dx > 0) && (sibling->width > min_sane_w || dx < 0)) { recursive_resize(parent, dx, WLC_RESIZE_EDGE_RIGHT); recursive_resize(sibling, -1 * dx, WLC_RESIZE_EDGE_LEFT); changed_tiling = true; } else { pointer_state.tiling.lock_pos.x = mouse_origin.x; if (parent->width < min_sane_w) { pointer_state.lock.temp_left = true; } else if (sibling->width < min_sane_w) { pointer_state.lock.temp_right = true; } } } } } else if (!pointer_state.lock.left) { while (parent->type != C_WORKSPACE) { if (fabs(parent->parent->x - view->x) <= 1 && parent->parent) { parent = parent->parent; } else { break; } } if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) { swayc_t *sibling = get_swayc_in_direction(parent, MOVE_LEFT); if (sibling) { if ((parent->width > min_sane_w || dx < 0) && (sibling->width > min_sane_w || dx > 0)) { recursive_resize(parent, -1 * dx, WLC_RESIZE_EDGE_LEFT); recursive_resize(sibling, dx, WLC_RESIZE_EDGE_RIGHT); changed_tiling = true; } else { pointer_state.tiling.lock_pos.x = mouse_origin.x; if (parent->width < min_sane_w) { pointer_state.lock.temp_right = true; } else if (sibling->width < min_sane_w) { pointer_state.lock.temp_left = true; } } } } } arrange_windows(active_workspace, -1, -1); } } if (config->focus_follows_mouse && prev_handle != handle) { // 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) && !(pointer_state.l_held || pointer_state.r_held)) { set_focused_container(container_under_pointer()); } } prev_handle = handle; prev_pos = mouse_origin; if (changed_floating) { struct wlc_geometry geometry = { .origin = { .x = view->x, .y = view->y }, .size = { .w = view->width, .h = view->height } }; wlc_view_set_geometry(view->handle, edge, &geometry); return true; }
void arrange_windows(swayc_t *container, int width, int height) { int i; if (width == -1 || height == -1) { sway_log(L_DEBUG, "Arranging layout for %p", container); width = container->width; height = container->height; } int x = 0, y = 0; switch (container->type) { case C_ROOT: for (i = 0; i < container->children->length; ++i) { swayc_t *child = container->children->items[i]; sway_log(L_DEBUG, "Arranging output at %d", x); child->x = x; child->y = y; arrange_windows(child, -1, -1); // Removed for now because wlc works with relative positions // Addition can be reconsidered once wlc positions are changed // x += child->width; } return; case C_OUTPUT: container->width = width; container->height = height; // These lines make x/y negative and result in stuff glitching out // Their addition can be reconsidered once wlc positions are changed // x -= container->x; // y -= container->y; for (i = 0; i < container->children->length; ++i) { swayc_t *child = container->children->items[i]; child->x = x + container->gaps; child->y = y + container->gaps; child->width = width - container->gaps * 2; child->height = height - container->gaps * 2; sway_log(L_DEBUG, "Arranging workspace #%d at %d, %d", i, child->x, child->y); arrange_windows(child, -1, -1); } return; case C_VIEW: { struct wlc_geometry geometry = { .origin = { .x = container->x + container->gaps, .y = container->y + container->gaps }, .size = { .w = width - container->gaps * 2, .h = height - container->gaps * 2 } }; if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) { swayc_t *parent = container; 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(container->handle, 0, &geometry); wlc_view_bring_to_front(container->handle); } else { wlc_view_set_geometry(container->handle, 0, &geometry); container->width = width; container->height = height; } sway_log(L_DEBUG, "Set view to %d x %d @ %d, %d", geometry.size.w, geometry.size.h, geometry.origin.x, geometry.origin.y); } return; default: container->width = width; container->height = height; break; }