From e893902585aa813746eb939649d8d28cf89abbf4 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sun, 6 Sep 2009 16:50:45 +0200 Subject: [PATCH] Implement horizontal resize --- include/layout.h | 3 ++ src/layout.c | 41 ++++++++++++++++++++------ src/resize.c | 75 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 94 insertions(+), 25 deletions(-) diff --git a/include/layout.h b/include/layout.h index bd5bbcc3..a96aabc3 100644 --- a/include/layout.h +++ b/include/layout.h @@ -22,6 +22,9 @@ */ int get_unoccupied_x(Workspace *workspace); +/** See get_unoccupied_x */ +int get_unoccupied_y(Workspace *workspace); + /** * (Re-)draws window decorations for a given Client onto the given * drawable/graphic context. When in stacking mode, the window decorations diff --git a/src/layout.c b/src/layout.c index 7d5ec868..f861171a 100644 --- a/src/layout.c +++ b/src/layout.c @@ -63,16 +63,27 @@ int get_unoccupied_x(Workspace *workspace) { } /* See get_unoccupied_x() */ -int get_unoccupied_y(Workspace *workspace, int col) { - int unoccupied = workspace->rect.height; - float default_factor = ((float)workspace->rect.height / workspace->rows) / workspace->rect.height; +int get_unoccupied_y(Workspace *workspace) { + int height = workspace->rect.height; + i3Font *font = load_font(global_conn, config.font); + + /* Reserve space for dock clients */ + Client *client; + SLIST_FOREACH(client, &(workspace->screen->dock_clients), dock_clients) + height -= client->desired_height; + + /* Space for the internal bar */ + height -= (font->height + 6); + + int unoccupied = height; + float default_factor = ((float)height / workspace->rows) / height; LOG("get_unoccupied_y(), starting with %d, default_factor = %f\n", unoccupied, default_factor); for (int rows = 0; rows < workspace->rows; rows++) { LOG("height_factor[%d] = %f\n", rows, workspace->height_factor[rows]); if (workspace->height_factor[rows] == 0) - unoccupied -= workspace->rect.height * default_factor; + unoccupied -= height * default_factor; } LOG("unoccupied space: %d\n", unoccupied); @@ -587,7 +598,7 @@ void render_workspace(xcb_connection_t *conn, i3Screen *screen, Workspace *r_ws) /* Go through the whole table and render what’s necessary */ FOR_TABLE(r_ws) { Container *container = r_ws->table[cols][rows]; - int single_width = -1, single_height; + int single_width = -1, single_height = -1; /* Update position of the container */ container->row = rows; container->col = cols; @@ -604,11 +615,25 @@ void render_workspace(xcb_connection_t *conn, i3Screen *screen, Workspace *r_ws) single_width = container->width; } + LOG("height is %d\n", height); + + container->height = 0; + + for (int c = 0; c < container->rowspan; c++) { + if (r_ws->height_factor[rows+c] == 0) + container->height += (height / r_ws->rows); + else container->height += get_unoccupied_y(r_ws) * r_ws->height_factor[rows+c]; + + if (single_height == -1) + single_height = container->height; + } + + //if (container->height_factor == 0) - container->height = (height / r_ws->rows); + //container->height = (height / r_ws->rows); //else container->height = get_unoccupied_y(r_ws, cols) * container->height_factor; - single_height = container->height; - container->height *= container->rowspan; + //single_height = container->height; + //container->height *= container->rowspan; /* Render the container if it is not empty */ render_container(conn, container); diff --git a/src/resize.c b/src/resize.c index 09a8d083..ded8da82 100644 --- a/src/resize.c +++ b/src/resize.c @@ -47,13 +47,6 @@ int resize_graphical_handler(xcb_connection_t *conn, Workspace *ws, int first, i LOG("Screen dimensions: (%d, %d) %d x %d\n", screen->rect.x, screen->rect.y, screen->rect.width, screen->rect.height); - /* FIXME: horizontal resizing causes empty spaces to exist */ - if (orientation == O_HORIZONTAL) { - LOG("Sorry, horizontal resizing is not yet activated due to creating layout bugs." - "If you are brave, enable the code for yourself and try fixing it.\n"); - return 1; - } - uint32_t mask = 0; uint32_t values[2]; @@ -123,6 +116,7 @@ int resize_graphical_handler(xcb_connection_t *conn, Workspace *ws, int first, i xcb_destroy_window(conn, grabwin); xcb_flush(conn); + /* TODO: refactor this, both blocks are very identical */ if (orientation == O_VERTICAL) { LOG("Resize was from X = %d to X = %d\n", event->root_x, new_position); if (event->root_x == new_position) { @@ -188,22 +182,69 @@ int resize_graphical_handler(xcb_connection_t *conn, Workspace *ws, int first, i LOG("\n\n\n"); } else { -#if 0 - LOG("Resize was from Y = %d to Y = %d\n", event->root_y, new_position); + LOG("Resize was from X = %d to X = %d\n", event->root_y, new_position); if (event->root_y == new_position) { LOG("Nothing changed, not updating anything\n"); return 1; } - /* Convert 0 (for default height_factor) to actual numbers */ - if (first->height_factor == 0) - first->height_factor = ((float)ws->rect.height / ws->rows) / ws->rect.height; - if (second->height_factor == 0) - second->height_factor = ((float)ws->rect.height / ws->rows) / ws->rect.height; + int default_height = ws->rect.height / ws->rows; + int old_unoccupied_y = get_unoccupied_y(ws); + + /* We pre-calculate the unoccupied space to see if we need to adapt sizes before + * doing the resize */ + int new_unoccupied_y = old_unoccupied_y; + + if (old_unoccupied_y == 0) + old_unoccupied_y = ws->rect.height; - first->height_factor *= (float)(first->height + (new_position - event->root_y)) / first->height; - second->height_factor *= (float)(second->height - (new_position - event->root_y)) / second->height; -#endif + if (ws->height_factor[first] == 0) + new_unoccupied_y += default_height; + + if (ws->height_factor[second] == 0) + new_unoccupied_y += default_height; + + LOG("\n\n\n"); + LOG("old = %d, new = %d\n", old_unoccupied_y, new_unoccupied_y); + + /* If the space used for customly resized columns has changed we need to adapt the + * other customly resized columns, if any */ + if (new_unoccupied_y != old_unoccupied_y) + for (int row = 0; row < ws->rows; row++) { + if (ws->height_factor[row] == 0) + continue; + + LOG("Updating other column (%d) (current width_factor = %f)\n", row, ws->height_factor[row]); + ws->height_factor[row] = (ws->height_factor[row] * old_unoccupied_y) / new_unoccupied_y; + LOG("to %f\n", ws->height_factor[row]); + } + + LOG("old_unoccupied_y = %d\n", old_unoccupied_y); + + LOG("Updating first (before = %f)\n", ws->height_factor[first]); + /* Convert 0 (for default width_factor) to actual numbers */ + if (ws->height_factor[first] == 0) + ws->height_factor[first] = ((float)ws->rect.height / ws->rows) / new_unoccupied_y; + + LOG("middle = %f\n", ws->height_factor[first]); + int old_height = ws->height_factor[first] * old_unoccupied_y; + LOG("first->width = %d, new_position = %d, event->root_x = %d\n", old_height, new_position, event->root_y); + ws->height_factor[first] *= (float)(old_height + (new_position - event->root_y)) / old_height; + LOG("-> %f\n", ws->height_factor[first]); + + + LOG("Updating second (before = %f)\n", ws->height_factor[second]); + if (ws->height_factor[second] == 0) + ws->height_factor[second] = ((float)ws->rect.height / ws->rows) / new_unoccupied_y; + LOG("middle = %f\n", ws->height_factor[second]); + old_height = ws->height_factor[second] * old_unoccupied_y; + LOG("second->width = %d, new_position = %d, event->root_x = %d\n", old_height, new_position, event->root_y); + ws->height_factor[second] *= (float)(old_height - (new_position - event->root_y)) / old_height; + LOG("-> %f\n", ws->height_factor[second]); + + LOG("new unoccupied_y = %d\n", get_unoccupied_y(ws)); + + LOG("\n\n\n"); } render_layout(conn); -- 2.39.5