Created
August 8, 2012 11:15
-
-
Save yshui/3294327 to your computer and use it in GitHub Desktop.
render.c cleanup? - Draft
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 f10f9cbd90f323dcc66c130cd1f839de3b75ec67 Mon Sep 17 00:00:00 2001 | |
From: darkraven <[email protected]> | |
Date: Wed, 8 Aug 2012 19:38:12 +0800 | |
Subject: [PATCH] draft | |
--- | |
src/render.c | 339 ++++++++++++++++++++++++++++------------------------------- | |
1 file changed, 161 insertions(+), 178 deletions(-) | |
diff --git a/src/render.c b/src/render.c | |
index bad67f0..50cfd3c 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,66 +53,106 @@ 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; | |
- } | |
+ 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 = 0; | |
- /* 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->deco_rect.x = 0; | |
+ child->deco_rect.y = 0; | |
+ child->deco_rect.width = 0; | |
+ child->deco_rect.height = 0; | |
- child->rect.height = 0; | |
- TAILQ_FOREACH(dockchild, &(child->nodes_head), nodes) | |
- child->rect.height += dockchild->geometry.height; | |
+ TAILQ_FOREACH(dockchild, &(child->nodes_head), nodes) | |
+ child->rect.height += dockchild->geometry.height; | |
- height -= child->rect.height; | |
- } | |
+ height -= child->rect.height; | |
+ y += child->rect.height; | |
- /* Second pass: Set the widths/heights */ | |
- TAILQ_FOREACH(child, &(con->nodes_head), nodes) { | |
- if (child->type == CT_CON) { | |
- child->rect.x = x; | |
- child->rect.y = y; | |
- child->rect.width = con->rect.width; | |
- child->rect.height = 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); | |
} | |
+ } | |
- child->rect.x = x; | |
- child->rect.y = y; | |
- child->rect.width = con->rect.width; | |
+ ws->rect.x = x; | |
+ ws->rect.y = y; | |
+ ws->rect.width = con->rect.width; | |
+ ws->rect.height = height; | |
- child->deco_rect.x = 0; | |
- child->deco_rect.y = 0; | |
- child->deco_rect.width = 0; | |
- child->deco_rect.height = 0; | |
+ render_con(ws, false); | |
+} | |
+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; | |
- y += child->rect.height; | |
+ while (new_height > inset->height) { | |
+ new_height = ((double)con->proportional_height / con->proportional_width) * new_width; | |
- 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); | |
+ 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); | |
+ | |
+ 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", | |
+ 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); | |
+ | |
} | |
+void render_child(Con *con){ | |
+ Con *child; | |
-/* | |
- * "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) { | |
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); | |
+ 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 */ | |
@@ -128,79 +172,6 @@ void render_con(Con *con, bool render_fullscreen) { | |
int i = 0; | |
- 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 */ | |
- 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; | |
- | |
- 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); | |
- | |
- 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", | |
- 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); | |
- } | |
- | |
- /* 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; | |
- } | |
- | |
/* find the height for the decorations */ | |
int deco_height = config.font.height + 4; | |
if (config.font.height & 0x01) | |
@@ -229,65 +200,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) { | |
@@ -394,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