Created
August 9, 2012 07:02
-
-
Save yshui/3301817 to your computer and use it in GitHub Desktop.
render.c messup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 434b04aff25d7226e71c4d7f2387e7dd30c80b83 Mon Sep 17 00:00:00 2001 | |
From: darkraven <[email protected]> | |
Date: Thu, 9 Aug 2012 15:01:10 +0800 | |
Subject: [PATCH 1/2] logic changes | |
--- | |
src/render.c | 225 ++++++++++++++++++++++++++--------------------------------- | |
1 file changed, 97 insertions(+), 128 deletions(-) | |
diff --git a/src/render.c b/src/render.c | |
index bad67f0..859059e 100644 | |
--- a/src/render.c | |
+++ b/src/render.c | |
@@ -22,6 +22,10 @@ static bool show_debug_borders = false; | |
static void render_l_output(Con *con) { | |
Con *child, *dockchild; | |
+ /* Skip i3-internal outputs */ | |
+ if (con->name[0] == '_' && con->name[1] == '_') | |
+ return; | |
+ | |
int x = con->rect.x; | |
int y = con->rect.y; | |
int height = con->rect.height; | |
@@ -49,53 +53,60 @@ static void render_l_output(Con *con) { | |
* see the dockareas in that case) */ | |
Con *ws = con_get_fullscreen_con(content, CF_OUTPUT); | |
Con *fullscreen = con_get_fullscreen_con(ws, CF_OUTPUT); | |
- if (fullscreen) { | |
- fullscreen->rect = con->rect; | |
- x_raise_con(fullscreen); | |
- render_con(fullscreen, true); | |
- return; | |
- } | |
- | |
- /* First pass: determine the height of all CT_DOCKAREAs (the sum of their | |
- * children) and figure out how many pixels we have left for the rest */ | |
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) { | |
- if (child->type != CT_DOCKAREA) | |
- continue; | |
- | |
- child->rect.height = 0; | |
- TAILQ_FOREACH(dockchild, &(child->nodes_head), nodes) | |
- child->rect.height += dockchild->geometry.height; | |
- | |
- height -= child->rect.height; | |
- } | |
- | |
- /* Second pass: Set the widths/heights */ | |
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) { | |
- if (child->type == CT_CON) { | |
+ if (!fullscreen){ | |
+ /* First pass: determine the height of all CT_DOCKAREAs (the sum of their | |
+ * children) and figure out how many pixels we have left for the rest */ | |
+ TAILQ_FOREACH(child, &(con->nodes_head), nodes) { | |
+ if (child->type != CT_DOCKAREA) | |
+ continue; | |
child->rect.x = x; | |
child->rect.y = y; | |
child->rect.width = con->rect.width; | |
- child->rect.height = height; | |
- } | |
+ child->rect.height = 0; | |
- child->rect.x = x; | |
- child->rect.y = y; | |
- child->rect.width = con->rect.width; | |
+ child->deco_rect.x = 0; | |
+ child->deco_rect.y = 0; | |
+ child->deco_rect.width = 0; | |
+ child->deco_rect.height = 0; | |
- child->deco_rect.x = 0; | |
- child->deco_rect.y = 0; | |
- child->deco_rect.width = 0; | |
- child->deco_rect.height = 0; | |
+ TAILQ_FOREACH(dockchild, &(child->nodes_head), nodes) | |
+ child->rect.height += dockchild->geometry.height; | |
- y += child->rect.height; | |
+ height -= child->rect.height; | |
+ y += child->rect.height; | |
- DLOG("child at (%d, %d) with (%d x %d)\n", | |
- child->rect.x, child->rect.y, child->rect.width, child->rect.height); | |
- x_raise_con(child); | |
- render_con(child, false); | |
+ DLOG("child at (%d, %d) with (%d x %d)\n", | |
+ child->rect.x, child->rect.y, child->rect.width, child->rect.height); | |
+ x_raise_con(child); | |
+ render_con(child, false); | |
+ } | |
} | |
-} | |
+ ws->rect.x = x; | |
+ ws->rect.y = y; | |
+ ws->rect.width = con->rect.width; | |
+ ws->rect.height = height; | |
+ | |
+ render_con(ws, false); | |
+} | |
+bool render_fullscreen(Con *con){ | |
+ /* Check for fullscreen nodes */ | |
+ Con *fullscreen = NULL; | |
+ fullscreen = con_get_fullscreen_con(con, (con->type == CT_ROOT ? CF_GLOBAL : CF_OUTPUT)); | |
+ if (fullscreen) { | |
+ fullscreen->rect = con->rect; | |
+ if (show_debug_borders){ | |
+ fullscreen->rect.x += 2; | |
+ fullscreen->rect.y += 2; | |
+ fullscreen->rect.width -= 2 * 2; | |
+ fullscreen->rect.height -= 2 * 2; | |
+ } | |
+ x_raise_con(fullscreen); | |
+ render_con(fullscreen, true); | |
+ return true; | |
+ } | |
+ return false; | |
+} | |
/* | |
* "Renders" the given container (and its children), meaning that all rects are | |
* updated correctly. Note that this function does not call any xcb_* | |
@@ -105,32 +116,12 @@ static void render_l_output(Con *con) { | |
* | |
*/ | |
void render_con(Con *con, bool render_fullscreen) { | |
- int children = con_num_children(con); | |
DLOG("Rendering %snode %p / %s / layout %d / children %d\n", | |
(render_fullscreen ? "fullscreen " : ""), con, con->name, con->layout, | |
- children); | |
- | |
- /* Copy container rect, subtract container border */ | |
- /* This is the actually usable space inside this container for clients */ | |
- Rect rect = con->rect; | |
- | |
- /* Display a border if this is a leaf node. For container nodes, we don’t | |
- * draw borders (except when in debug mode) */ | |
- if (show_debug_borders) { | |
- rect.x += 2; | |
- rect.y += 2; | |
- rect.width -= 2 * 2; | |
- rect.height -= 2 * 2; | |
- } | |
- | |
- int x = rect.x; | |
- int y = rect.y; | |
- | |
- int i = 0; | |
+ con_num_children(con)); | |
con->mapped = true; | |
- /* if this container contains a window, set the coordinates */ | |
if (con->window) { | |
/* depending on the border style, the rect of the child window | |
* needs to be smaller */ | |
@@ -187,20 +178,56 @@ void render_con(Con *con, bool render_fullscreen) { | |
} | |
DLOG("child will be at %dx%d with size %dx%d\n", inset->x, inset->y, inset->width, inset->height); | |
- } | |
- /* Check for fullscreen nodes */ | |
- Con *fullscreen = NULL; | |
- if (con->type != CT_OUTPUT) { | |
- fullscreen = con_get_fullscreen_con(con, (con->type == CT_ROOT ? CF_GLOBAL : CF_OUTPUT)); | |
- } | |
- if (fullscreen) { | |
- fullscreen->rect = rect; | |
- x_raise_con(fullscreen); | |
- render_con(fullscreen, true); | |
- return; | |
+ } else if (con->type == CT_WORKSPACE) { | |
+ /* Check for fullscreen nodes */ | |
+ if (render_fullscreen(con)) | |
+ return; | |
+ | |
+ render_child(con); | |
+ | |
+ DLOG("Rendering floating windows:\n"); | |
+ Con *child; | |
+ TAILQ_FOREACH(child, &(con->floating_head), floating_windows) { | |
+ DLOG("floating child at (%d,%d) with %d x %d\n", child->rect.x, child->rect.y, child->rect.width, child->rect.height); | |
+ x_raise_con(child); | |
+ render_con(child, false); | |
+ } | |
+ } else if (con->layout == L_OUTPUT) | |
+ render_l_output(con); | |
+ else if (con->type == CT_ROOT) { | |
+ Con *output; | |
+ | |
+ if (render_fullscreen(con)) | |
+ return; | |
+ | |
+ TAILQ_FOREACH(output, &(con->nodes_head), nodes) { | |
+ render_con(output, false); | |
+ } | |
+ } else { | |
+ Con *child; | |
+ | |
+ int children = con_num_children(con); | |
+ assert(TAILQ_FIRST(&con->nodes_head)==0 || children > 0); | |
+ | |
+ /* Copy container rect, subtract container border */ | |
+ /* This is the actually usable space inside this container for clients */ | |
+ Rect rect = con->rect; | |
+ | |
+ /* Display a border if this is a leaf node. For container nodes, we don’t | |
+ * draw borders (except when in debug mode) */ | |
+ if (show_debug_borders) { | |
+ rect.x += 2; | |
+ rect.y += 2; | |
+ rect.width -= 2 * 2; | |
+ rect.height -= 2 * 2; | |
} | |
+ int x = rect.x; | |
+ int y = rect.y; | |
+ | |
+ int i = 0; | |
+ | |
/* find the height for the decorations */ | |
int deco_height = config.font.height + 4; | |
if (config.font.height & 0x01) | |
@@ -229,65 +256,7 @@ void render_con(Con *con, bool render_fullscreen) { | |
} | |
} | |
- if (con->layout == L_OUTPUT) { | |
- /* Skip i3-internal outputs */ | |
- if (con->name[0] == '_' && con->name[1] == '_') | |
- return; | |
- render_l_output(con); | |
- } else if (con->type == CT_ROOT) { | |
- Con *output; | |
- TAILQ_FOREACH(output, &(con->nodes_head), nodes) { | |
- render_con(output, false); | |
- } | |
- | |
- /* We need to render floating windows after rendering all outputs’ | |
- * tiling windows because they need to be on top of *every* output at | |
- * all times. This is important when the user places floating | |
- * windows/containers so that they overlap on another output. */ | |
- DLOG("Rendering floating windows:\n"); | |
- TAILQ_FOREACH(output, &(con->nodes_head), nodes) { | |
- if (output->name[0] == '_' && output->name[1] == '_') | |
- continue; | |
- /* Get the active workspace of that output */ | |
- Con *content = output_get_content(output); | |
- Con *workspace = TAILQ_FIRST(&(content->focus_head)); | |
- | |
- /* Check for (floating!) fullscreen nodes */ | |
- /* XXX: This code duplication is unfortunate. Keep in mind to fix | |
- * this when we clean up the whole render.c */ | |
- Con *fullscreen = NULL; | |
- fullscreen = con_get_fullscreen_con(workspace, CF_OUTPUT); | |
- if (fullscreen) { | |
- /* Either the fullscreen window is inside the floating | |
- * container, then we need to render and raise it now… */ | |
- if (con_inside_floating(fullscreen)) { | |
- fullscreen->rect = output->rect; | |
- x_raise_con(fullscreen); | |
- render_con(fullscreen, true); | |
- continue; | |
- } else { | |
- /* …or it’s a tiling window, in which case the floating | |
- * windows should not overlap it, so we skip rendering this | |
- * output. */ | |
- continue; | |
- } | |
- } | |
- | |
- Con *child; | |
- TAILQ_FOREACH(child, &(workspace->floating_head), floating_windows) { | |
- DLOG("floating child at (%d,%d) with %d x %d\n", child->rect.x, child->rect.y, child->rect.width, child->rect.height); | |
- x_raise_con(child); | |
- render_con(child, false); | |
- } | |
- } | |
- | |
- } else { | |
- | |
- /* FIXME: refactor this into separate functions: */ | |
- Con *child; | |
TAILQ_FOREACH(child, &(con->nodes_head), nodes) { | |
- assert(children > 0); | |
- | |
/* default layout */ | |
if (con->layout == L_SPLITH || con->layout == L_SPLITV) { | |
if (con->layout == L_SPLITH) { | |
-- | |
1.7.11.4 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From f994d24c130635fadef27de7934cd802c1944ee1 Mon Sep 17 00:00:00 2001 | |
From: darkraven <[email protected]> | |
Date: Thu, 9 Aug 2012 15:01:51 +0800 | |
Subject: [PATCH 2/2] moving things around | |
--- | |
src/render.c | 224 +++++++++++++++++++++++++++++++---------------------------- | |
1 file changed, 119 insertions(+), 105 deletions(-) | |
diff --git a/src/render.c b/src/render.c | |
index 859059e..50cfd3c 100644 | |
--- a/src/render.c | |
+++ b/src/render.c | |
@@ -89,122 +89,66 @@ static void render_l_output(Con *con) { | |
render_con(ws, false); | |
} | |
-bool render_fullscreen(Con *con){ | |
- /* Check for fullscreen nodes */ | |
- Con *fullscreen = NULL; | |
- fullscreen = con_get_fullscreen_con(con, (con->type == CT_ROOT ? CF_GLOBAL : CF_OUTPUT)); | |
- if (fullscreen) { | |
- fullscreen->rect = con->rect; | |
- if (show_debug_borders){ | |
- fullscreen->rect.x += 2; | |
- fullscreen->rect.y += 2; | |
- fullscreen->rect.width -= 2 * 2; | |
- fullscreen->rect.height -= 2 * 2; | |
- } | |
- x_raise_con(fullscreen); | |
- render_con(fullscreen, true); | |
- return true; | |
- } | |
- return false; | |
-} | |
-/* | |
- * "Renders" the given container (and its children), meaning that all rects are | |
- * updated correctly. Note that this function does not call any xcb_* | |
- * functions, so the changes are completely done in memory only (and | |
- * side-effect free). As soon as you call x_push_changes(), the changes will be | |
- * updated in X11. | |
- * | |
- */ | |
-void render_con(Con *con, bool render_fullscreen) { | |
- DLOG("Rendering %snode %p / %s / layout %d / children %d\n", | |
- (render_fullscreen ? "fullscreen " : ""), con, con->name, con->layout, | |
- con_num_children(con)); | |
- | |
- con->mapped = true; | |
- | |
- if (con->window) { | |
- /* depending on the border style, the rect of the child window | |
- * needs to be smaller */ | |
- Rect *inset = &(con->window_rect); | |
- *inset = (Rect){0, 0, con->rect.width, con->rect.height}; | |
- if (!render_fullscreen) | |
- *inset = rect_add(*inset, con_border_style_rect(con)); | |
- | |
- /* Obey x11 border */ | |
- inset->width -= (2 * con->border_width); | |
- inset->height -= (2 * con->border_width); | |
- | |
- /* Obey the aspect ratio, if any, unless we are in fullscreen mode. | |
- * | |
- * The spec isn’t explicit on whether the aspect ratio hints should be | |
- * respected during fullscreen mode. Other WMs such as Openbox don’t do | |
- * that, and this post suggests that this is the correct way to do it: | |
- * http://mail.gnome.org/archives/wm-spec-list/2003-May/msg00007.html | |
- * | |
- * Ignoring aspect ratio during fullscreen was necessary to fix MPlayer | |
- * subtitle rendering, see http://bugs.i3wm.org/594 */ | |
- if (!render_fullscreen && | |
+void render_window(Con *con, bool render_fullscreen){ | |
+ assert(con->window); | |
+ /* depending on the border style, the rect of the child window | |
+ * needs to be smaller */ | |
+ Rect *inset = &(con->window_rect); | |
+ *inset = (Rect){0, 0, con->rect.width, con->rect.height}; | |
+ if (!render_fullscreen) | |
+ *inset = rect_add(*inset, con_border_style_rect(con)); | |
+ | |
+ /* Obey x11 border */ | |
+ inset->width -= (2 * con->border_width); | |
+ inset->height -= (2 * con->border_width); | |
+ | |
+ /* Obey the aspect ratio, if any, unless we are in fullscreen mode. | |
+ * | |
+ * The spec isn’t explicit on whether the aspect ratio hints should be | |
+ * respected during fullscreen mode. Other WMs such as Openbox don’t do | |
+ * that, and this post suggests that this is the correct way to do it: | |
+ * http://mail.gnome.org/archives/wm-spec-list/2003-May/msg00007.html | |
+ * | |
+ * Ignoring aspect ratio during fullscreen was necessary to fix MPlayer | |
+ * subtitle rendering, see http://bugs.i3wm.org/594 */ | |
+ if (!render_fullscreen && | |
con->proportional_height != 0 && | |
con->proportional_width != 0) { | |
- double new_height = inset->height + 1; | |
- int new_width = inset->width; | |
- | |
- while (new_height > inset->height) { | |
- new_height = ((double)con->proportional_height / con->proportional_width) * new_width; | |
+ double new_height = inset->height + 1; | |
+ int new_width = inset->width; | |
- if (new_height > inset->height) | |
- new_width--; | |
- } | |
- /* Center the window */ | |
- inset->y += ceil(inset->height / 2) - floor(new_height / 2); | |
- inset->x += ceil(inset->width / 2) - floor(new_width / 2); | |
+ while (new_height > inset->height) { | |
+ new_height = ((double)con->proportional_height / con->proportional_width) * new_width; | |
- inset->height = new_height; | |
- inset->width = new_width; | |
+ if (new_height > inset->height) | |
+ new_width--; | |
} | |
+ /* Center the window */ | |
+ inset->y += ceil(inset->height / 2) - floor(new_height / 2); | |
+ inset->x += ceil(inset->width / 2) - floor(new_width / 2); | |
- if (con->height_increment > 1) { | |
- int old_height = inset->height; | |
- inset->height -= (inset->height - con->base_height) % con->height_increment; | |
- DLOG("Lost %d pixel due to client's height_increment (%d px, base_height = %d)\n", | |
+ inset->height = new_height; | |
+ inset->width = new_width; | |
+ } | |
+ | |
+ if (con->height_increment > 1) { | |
+ int old_height = inset->height; | |
+ inset->height -= (inset->height - con->base_height) % con->height_increment; | |
+ DLOG("Lost %d pixel due to client's height_increment (%d px, base_height = %d)\n", | |
old_height - inset->height, con->height_increment, con->base_height); | |
- } | |
+ } | |
- if (con->width_increment > 1) { | |
- int old_width = inset->width; | |
- inset->width -= (inset->width - con->base_width) % con->width_increment; | |
- DLOG("Lost %d pixel due to client's width_increment (%d px, base_width = %d)\n", | |
+ if (con->width_increment > 1) { | |
+ int old_width = inset->width; | |
+ inset->width -= (inset->width - con->base_width) % con->width_increment; | |
+ DLOG("Lost %d pixel due to client's width_increment (%d px, base_width = %d)\n", | |
old_width - inset->width, con->width_increment, con->base_width); | |
- } | |
- | |
- DLOG("child will be at %dx%d with size %dx%d\n", inset->x, inset->y, inset->width, inset->height); | |
- | |
- } else if (con->type == CT_WORKSPACE) { | |
- /* Check for fullscreen nodes */ | |
- if (render_fullscreen(con)) | |
- return; | |
- | |
- render_child(con); | |
- | |
- DLOG("Rendering floating windows:\n"); | |
- Con *child; | |
- TAILQ_FOREACH(child, &(con->floating_head), floating_windows) { | |
- DLOG("floating child at (%d,%d) with %d x %d\n", child->rect.x, child->rect.y, child->rect.width, child->rect.height); | |
- x_raise_con(child); | |
- render_con(child, false); | |
- } | |
- } else if (con->layout == L_OUTPUT) | |
- render_l_output(con); | |
- else if (con->type == CT_ROOT) { | |
- Con *output; | |
+ } | |
- if (render_fullscreen(con)) | |
- return; | |
+ DLOG("child will be at %dx%d with size %dx%d\n", inset->x, inset->y, inset->width, inset->height); | |
- TAILQ_FOREACH(output, &(con->nodes_head), nodes) { | |
- render_con(output, false); | |
- } | |
- } else { | |
+} | |
+void render_child(Con *con){ | |
Con *child; | |
int children = con_num_children(con); | |
@@ -363,5 +307,75 @@ void render_con(Con *con, bool render_fullscreen) { | |
* (it’s unmapped afterwards). */ | |
x_raise_con(con); | |
} | |
+} | |
+bool render_fullscreen(Con *con){ | |
+ /* Check for fullscreen nodes */ | |
+ Con *fullscreen = NULL; | |
+ fullscreen = con_get_fullscreen_con(con, (con->type == CT_ROOT ? CF_GLOBAL : CF_OUTPUT)); | |
+ if (fullscreen) { | |
+ fullscreen->rect = con->rect; | |
+ if (show_debug_borders){ | |
+ fullscreen->rect.x += 2; | |
+ fullscreen->rect.y += 2; | |
+ fullscreen->rect.width -= 2 * 2; | |
+ fullscreen->rect.height -= 2 * 2; | |
+ } | |
+ x_raise_con(fullscreen); | |
+ render_con(fullscreen, true); | |
+ return true; | |
} | |
+ return false; | |
+} | |
+void render_workspace(Con *con){ | |
+ | |
+ /* Check for fullscreen nodes */ | |
+ if (render_fullscreen(con)) | |
+ return; | |
+ | |
+ render_child(con); | |
+ | |
+ DLOG("Rendering floating windows:\n"); | |
+ Con *child; | |
+ TAILQ_FOREACH(child, &(con->floating_head), floating_windows) { | |
+ DLOG("floating child at (%d,%d) with %d x %d\n", child->rect.x, child->rect.y, child->rect.width, child->rect.height); | |
+ x_raise_con(child); | |
+ render_con(child, false); | |
+ } | |
+} | |
+void render_root(Con *con){ | |
+ Con *output; | |
+ | |
+ if (render_fullscreen(con)) | |
+ return; | |
+ | |
+ TAILQ_FOREACH(output, &(con->nodes_head), nodes) { | |
+ render_con(output, false); | |
+ } | |
+} | |
+ | |
+/* | |
+ * "Renders" the given container (and its children), meaning that all rects are | |
+ * updated correctly. Note that this function does not call any xcb_* | |
+ * functions, so the changes are completely done in memory only (and | |
+ * side-effect free). As soon as you call x_push_changes(), the changes will be | |
+ * updated in X11. | |
+ * | |
+ */ | |
+void render_con(Con *con, bool render_fullscreen) { | |
+ DLOG("Rendering %snode %p / %s / layout %d / children %d\n", | |
+ (render_fullscreen ? "fullscreen " : ""), con, con->name, con->layout, | |
+ con_num_children(con)); | |
+ | |
+ con->mapped = true; | |
+ | |
+ if (con->window) | |
+ render_window(con, render_fullscreen); | |
+ else if (con->type == CT_WORKSPACE) | |
+ render_workspace(con); | |
+ else if (con->layout == L_OUTPUT) | |
+ render_l_output(con); | |
+ else if (con->type == CT_ROOT) { | |
+ render_root(con); | |
+ } else | |
+ render_child(con); | |
} | |
-- | |
1.7.11.4 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment