Output of awesome --version:
awesome v4.3-318-g6101ef51 (Too long)
• Compiled against Lua 5.3.4 (running with Lua 5.3)
• D-Bus support: ✔
• xcb-errors support: ✘
• execinfo support: ✔
• xcb-randr version: 1.6
• LGI version: 0.9.2
How to reproduce the issue:
Run awesome with the following changes to the default config:
diff --git a/awesomerc.lua b/awesomerc.lua
index 5d2bd2c1..bbfa6639 100644
--- a/awesomerc.lua
+++ b/awesomerc.lua
@@ -468,6 +468,7 @@ awful.rules.rules = {
border_color = beautiful.border_normal,
focus = awful.client.focus.filter,
raise = true,
+ size_hints_honor = false,
keys = clientkeys,
buttons = clientbuttons,
screen = awful.screen.preferred,
@@ -551,7 +552,7 @@ client.connect_signal("request::titlebars", function(c)
end)
)
- awful.titlebar(c) : setup {
+ awful.titlebar(c, { position = "bottom" }) : setup {
{ -- Left
awful.titlebar.widget.iconwidget(c),
buttons = buttons,
Then open a client window and slowly resize it either from the bottom or from the top side, so that the height will change in 1px increments.
Actual result:
The bottom titlebar content seems to stick to the top edge of the window (it does not move when the bottom edge is dragged, and moves when the top edge is dragged), and disappears beyond the titlebar area boundary; eventualy the whole titlebar becomes filled with the background color. The whole titlebar gets redrawn properly when either the mouse is hovered over the place where titlebar buttons should appear, or the window width is changed.
Moving the window with a corrupted titlebar beyond the screen edge and back does not fix the corruption.
The same problem happens with the right titlebar (but it needs a bigger custom config to reproduce; I used bgimage to draw my titlebar without any widgets); in this case the titlebar content seems to stick to the left edge of the window. Top and left titlebars do not seem to have this problem.
Expected result:
The titlebar should not be corrupted when the window is resized.
Looks like nothing forces a full redraw of titlebars when the client is resized, and the only thing which happens is an Expose event on the frame window. However, that event specifies only a very small rectangle that needs redrawing; e.g., for the bottom titlebar:
Therefore client_refresh_titlebar_partial() redraws only those parts of the titlebar, and the rest is left as is (and because of the north-west bit gravity the frame window content moves together with the top left corner of the frame window, therefore in case of resizing from the top edge the content of the bottom titlebar seems to shift).
Also it seems that moving the window beyond the screen edge and back does not generate any Expose events (looks like the X server enables backing store even if it was not requested).
Thanks for figuring this out already. Today is a good day, because all bug reports come pre-debugged. :-)
(looks like the X server enables backing store even if it was not requested).
That is most likely a side-effect of AwesomeWM using depth=32 windows. I think these are handled in the server by redirecting.
Since Lua has to (and does) redraw titlebars when their size changes and since the frame window is created with a BitGravity of NorthWest, do you agree that the following patch should be the right fix?
Actually... Lua could already be done redrawing the titlebar, so it might not be the best idea to rely on that. Instead, client_refresh_titlebar_partial will check drawable->refreshed and do nothing if a repaint is still pending.
diff --git a/objects/client.c b/objects/client.c
index e7b4c751d..f13f74791 100644
--- a/objects/client.c
+++ b/objects/client.c
@@ -957,6 +957,8 @@ static drawable_t *titlebar_get_drawable(lua_State *L, client_t *c, int cl_idx,
static void client_resize_do(client_t *c, area_t geometry);
static void client_set_maximized_common(lua_State *L, int cidx, bool s, const char* type, const int val);
static bool client_unban_internal(client_t *c);
+static void client_refresh_titlebar_right(client_t *c);
+static void client_refresh_titlebar_bottom(client_t *c);
/** Collect a client.
* \param L The Lua VM state.
@@ -1433,6 +1435,17 @@ client_geometry_refresh(void)
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
(uint32_t[]) { real_geometry.x, real_geometry.y, real_geometry.width, real_geometry.height });
+ /* The frame window contains the titlebars. It has a BitGravity of
+ * NorthWest. Resizing a window does not generate expose events for
+ * areas that are already visible before. Thus, the right and bottom
+ * titlebars can be corrupted by redraws and need to be updated.
+ * (top/left do not move!)
+ */
+ if (geometry.width != c->x11_frame_geometry.width)
+ client_refresh_titlebar_right(c);
+ if (geometry.height != c->x11_frame_geometry.height)
+ client_refresh_titlebar_bottom(c);
+
c->x11_frame_geometry = geometry;
c->x11_client_geometry = real_geometry;
Your patch fixes titlebar redraw problems which appear when the client window is resized. However, there is another corner case — the size of some titlebars may change too, and changing the size of the top titlebar also changes the position of all other titlebars relative to the frame window, which causes the same “missing redraw” problem for the left and right titlebars. In addition, it is possible to change the size of both the top and the bottom titlebars so that the frame window height remains the same, and in this case the height change check in client_geometry_refresh() does not notice the change (it would not do anything anyway, because the bottom titlebar would be redrawn due to its size change, but the left and right titlebars are not redrawn properly).
Test case (mod+Shift+arrows — increase size of one titlebar, mod+Shift+Ctrl+arrows — decrease size of one titlebar, mod+Ctrl+arrows — move client window inside the frame by decreasing the size of one titlebar and increasing the size of the opposite one):
diff --git a/awesomerc.lua b/awesomerc.lua
index 5d2bd2c1..abb726f1 100644
--- a/awesomerc.lua
+++ b/awesomerc.lua
@@ -344,6 +344,89 @@ globalkeys = gears.table.join(
-- @DOC_CLIENT_KEYBINDINGS@
clientkeys = gears.table.join(
+ awful.key({ modkey, "Shift" }, "Up",
+ function (c)
+ local d, size = c:titlebar_top()
+ c:titlebar_top(size + 1)
+ end,
+ {description = "increase top titlebar size", group = "client"}),
+ awful.key({ modkey, "Shift" }, "Right",
+ function (c)
+ local d, size = c:titlebar_right()
+ c:titlebar_right(size + 1)
+ end,
+ {description = "increase right titlebar size", group = "client"}),
+ awful.key({ modkey, "Shift" }, "Down",
+ function (c)
+ local d, size = c:titlebar_bottom()
+ c:titlebar_bottom(size + 1)
+ end,
+ {description = "increase bottom titlebar size", group = "client"}),
+ awful.key({ modkey, "Shift" }, "Left",
+ function (c)
+ local d, size = c:titlebar_left()
+ c:titlebar_left(size + 1)
+ end,
+ {description = "increase left titlebar size", group = "client"}),
+
+ awful.key({ modkey, "Control", "Shift" }, "Up",
+ function (c)
+ local d, size = c:titlebar_top()
+ c:titlebar_top(size - 1)
+ end,
+ {description = "decrease top titlebar size", group = "client"}),
+ awful.key({ modkey, "Control", "Shift" }, "Right",
+ function (c)
+ local d, size = c:titlebar_right()
+ c:titlebar_right(size - 1)
+ end,
+ {description = "decrease right titlebar size", group = "client"}),
+ awful.key({ modkey, "Control", "Shift" }, "Down",
+ function (c)
+ local d, size = c:titlebar_bottom()
+ c:titlebar_bottom(size - 1)
+ end,
+ {description = "decrease bottom titlebar size", group = "client"}),
+ awful.key({ modkey, "Control", "Shift" }, "Left",
+ function (c)
+ local d, size = c:titlebar_left()
+ c:titlebar_left(size - 1)
+ end,
+ {description = "decrease left titlebar size", group = "client"}),
+
+ awful.key({ modkey, "Control", }, "Up",
+ function (c)
+ local _, size_1 = c:titlebar_top()
+ local _, size_2 = c:titlebar_bottom()
+ c:titlebar_top(size_1 - 1)
+ c:titlebar_bottom(size_2 + 1)
+ end,
+ {description = "move client up inside the frame", group = "client"}),
+ awful.key({ modkey, "Control", }, "Right",
+ function (c)
+ local _, size_1 = c:titlebar_right()
+ local _, size_2 = c:titlebar_left()
+ c:titlebar_right(size_1 - 1)
+ c:titlebar_left(size_2 + 1)
+ end,
+ {description = "move client right inside the frame", group = "client"}),
+ awful.key({ modkey, "Control", }, "Down",
+ function (c)
+ local _, size_1 = c:titlebar_bottom()
+ local _, size_2 = c:titlebar_top()
+ c:titlebar_bottom(size_1 - 1)
+ c:titlebar_top(size_2 + 1)
+ end,
+ {description = "move client down inside the frame", group = "client"}),
+ awful.key({ modkey, "Control", }, "Left",
+ function (c)
+ local _, size_1 = c:titlebar_left()
+ local _, size_2 = c:titlebar_right()
+ c:titlebar_left(size_1 - 1)
+ c:titlebar_right(size_2 + 1)
+ end,
+ {description = "move client left inside the frame", group = "client"}),
+
awful.key({ modkey, }, "f",
function (c)
c.fullscreen = not c.fullscreen
@@ -468,6 +551,7 @@ awful.rules.rules = {
border_color = beautiful.border_normal,
focus = awful.client.focus.filter,
raise = true,
+ size_hints_honor = false,
keys = clientkeys,
buttons = clientbuttons,
screen = awful.screen.preferred,
@@ -539,6 +623,28 @@ end)
-- @DOC_TITLEBARS@
-- Add a titlebar if titlebars_enabled is set to true in the rules.
client.connect_signal("request::titlebars", function(c)
+ if true then
+ local tb_options = {
+ { "top", "#444444", "#cccccc", },
+ { "right", "#884444", "#ff0000", },
+ { "bottom", "#448844", "#00ff00", },
+ { "left", "#888844", "#ffff00", },
+ }
+ for _, opt in ipairs(tb_options) do
+ awful.titlebar(c, {
+ size = 20,
+ position = opt[1],
+ bg = opt[2],
+ bgimage = function(_, cr, width, height)
+ cr:set_source(gears.color(opt[3]))
+ cr:set_line_width(1)
+ cr:rectangle(0.5, 0.5, width - 1, height - 1)
+ cr:stroke()
+ end,
+ })
+ end
+ return
+ end
-- buttons for the titlebar
local buttons = gears.table.join(
awful.button({ }, 1, function()
I came up with this patch, which seems to handle my test cases correctly, but probably needs some more polishing:
diff --git a/objects/client.c b/objects/client.c
index 38a45cd6..a11c0a05 100644
--- a/objects/client.c
+++ b/objects/client.c
@@ -956,6 +956,7 @@ static area_t titlebar_get_area(client_t *c, client_titlebar_t bar);
static drawable_t *titlebar_get_drawable(lua_State *L, client_t *c, int cl_idx, client_titlebar_t bar);
static void client_resize_do(client_t *c, area_t geometry);
static void client_set_maximized_common(lua_State *L, int cidx, bool s, const char* type, const int val);
+static void client_refresh_titlebar(client_t *c, client_titlebar_t bar);
/** Collect a client.
* \param L The Lua VM state.
@@ -1419,6 +1420,21 @@ client_geometry_refresh(void)
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
(uint32_t[]) { real_geometry.x, real_geometry.y, real_geometry.width, real_geometry.height });
+ /* The frame window contains the titlebars. It has a BitGravity of
+ * NorthWest. Resizing a window does not generate expose events for
+ * areas that are already visible before. Thus, the right and bottom
+ * titlebars can be corrupted by redraws and need to be updated.
+ * (top/left do not move!)
+ */
+ if (geometry.width != c->x11_frame_geometry.width)
+ c->titlebar[CLIENT_TITLEBAR_RIGHT].need_refresh = true;
+ if (geometry.height != c->x11_frame_geometry.height)
+ c->titlebar[CLIENT_TITLEBAR_BOTTOM].need_refresh = true;
+ for (client_titlebar_t bar = CLIENT_TITLEBAR_TOP; bar < CLIENT_TITLEBAR_COUNT; bar++) {
+ if (c->titlebar[bar].need_refresh)
+ client_refresh_titlebar(c, bar);
+ }
+
c->x11_frame_geometry = geometry;
c->x11_client_geometry = real_geometry;
@@ -2853,12 +2869,19 @@ client_refresh_titlebar_partial(client_t *c, client_titlebar_t bar, int16_t x, i
globalconf.gc, x - area.x, y - area.y, x, y, width, height);
}
-#define HANDLE_TITLEBAR_REFRESH(name, index) \
-static void \
-client_refresh_titlebar_ ## name(client_t *c) \
-{ \
- area_t area = titlebar_get_area(c, index); \
- client_refresh_titlebar_partial(c, index, area.x, area.y, area.width, area.height); \
+static void
+client_refresh_titlebar(client_t *c, client_titlebar_t bar)
+{
+ area_t area = titlebar_get_area(c, bar);
+ client_refresh_titlebar_partial(c, bar, area.x, area.y, area.width, area.height);
+ c->titlebar[bar].need_refresh = false;
+}
+
+#define HANDLE_TITLEBAR_REFRESH(name, index) \
+static void \
+client_refresh_titlebar_ ## name(client_t *c) \
+{ \
+ client_refresh_titlebar(c, index); \
}
HANDLE_TITLEBAR_REFRESH(top, CLIENT_TITLEBAR_TOP)
HANDLE_TITLEBAR_REFRESH(right, CLIENT_TITLEBAR_RIGHT)
@@ -2925,6 +2948,9 @@ titlebar_resize(lua_State *L, int cidx, client_t *c, client_titlebar_t bar, int
geometry.height += change;
diff_top = change;
property_name = "property::titlebar_top";
+ c->titlebar[CLIENT_TITLEBAR_RIGHT].need_refresh = true;
+ c->titlebar[CLIENT_TITLEBAR_BOTTOM].need_refresh = true;
+ c->titlebar[CLIENT_TITLEBAR_LEFT].need_refresh = true;
break;
case CLIENT_TITLEBAR_BOTTOM:
geometry.height += change;
@@ -2940,6 +2966,7 @@ titlebar_resize(lua_State *L, int cidx, client_t *c, client_titlebar_t bar, int
geometry.width += change;
diff_left = change;
property_name = "property::titlebar_left";
+ c->titlebar[CLIENT_TITLEBAR_RIGHT].need_refresh = true;
break;
default:
fatal("Unknown titlebar kind %d\n", (int) bar);
diff --git a/objects/client.h b/objects/client.h
index 45bc9338..5705d113 100644
--- a/objects/client.h
+++ b/objects/client.h
@@ -182,6 +182,8 @@ struct client_t
struct {
/** The size of this bar. */
uint16_t size;
+ /** The bar needs a full refresh if this is true. */
+ bool need_refresh;
/** The drawable for this bar. */
drawable_t *drawable;
} titlebar[CLIENT_TITLEBAR_COUNT];
Wow. Thanks a lot for catching that!
New attempt that tries to get away without any new variables. We can compare the old and new titlebar positions to decide if we need to repaint. This time I didn't do any testing at all for this patch.
diff --git a/objects/client.c b/objects/client.c
index e7b4c751d..4932eda3d 100644
--- a/objects/client.c
+++ b/objects/client.c
@@ -957,6 +957,8 @@ static drawable_t *titlebar_get_drawable(lua_State *L, client_t *c, int cl_idx,
static void client_resize_do(client_t *c, area_t geometry);
static void client_set_maximized_common(lua_State *L, int cidx, bool s, const char* type, const int val);
static bool client_unban_internal(client_t *c);
+static void client_refresh_titlebar_right(client_t *c);
+static void client_refresh_titlebar_bottom(client_t *c);
/** Collect a client.
* \param L The Lua VM state.
@@ -1433,6 +1435,22 @@ client_geometry_refresh(void)
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
(uint32_t[]) { real_geometry.x, real_geometry.y, real_geometry.width, real_geometry.height });
+ /* The frame window contains the titlebars. It has a BitGravity of
+ * NorthWest. Thus, when the size of the frame window or the titlebar
+ * changes, the top and left titlebar still contain the correct content,
+ * but the right and bottom titlebar could move and need to be
+ * repainted, even though we do not get an Expose event. Detect this and
+ * redraw affected titlebars if they moved.
+ */
+ double titlebar_bottom_old_y_position = c->x11_frame_geometry.height - c->titlebar[CLIENT_TITLEBAR_BOTTOM].size;
+ double titlebar_right_old_x_position = c->x11_frame_geometry.width - c->titlebar[CLIENT_TITLEBAR_RIGHT].size;
+ double titlebar_bottom_new_y_position = titlebar_get_area(c, CLIENT_TITLEBAR_BOTTOM).y;
+ double titlebar_right_new_x_position = titlebar_get_area(c, CLIENT_TITLEBAR_RIGHT).x;
+ if (titlebar_bottom_old_y_position != titlebar_bottom_new_y_position)
+ client_refresh_titlebar_bottom(c);
+ if (titlebar_right_old_x_position != titlebar_right_new_x_position)
+ client_refresh_titlebar_right(c);
+
c->x11_frame_geometry = geometry;
c->x11_client_geometry = real_geometry;
To detect the Y movement of the bottom titlebar and the X movement of the right titlebar, just detecting changes in the height or width of x11_frame_geometry should be enough. What is missing in your code is detection of the Y movement of the left and right titlebars, which could happen when the height of the top titlebar is changed. This can be detected by checking for changes in x11_client_geometry.y — if it is changed, at least the left and right titlebars must be refreshed (the bottom titlebar should be refreshed too, but using the x11_frame_geometry.height check for it should be enough).
Or we may try this logic, calculating the coordinates of the top left corner of various titlebars directly:
x11_client_geometry.y changed ⇒ refresh left and rightx11_client_geometry.x + x11_client_geometry.width changed ⇒ refresh rightx11_client_geometry.y + x11_client_geometry.height changed ⇒ refresh bottomTo detect the Y movement of the bottom titlebar and the X movement of the right titlebar, just detecting changes in the height or width of x11_frame_geometry should be enough.
After some thinking about it: Right. Although perhaps checking if their position changed is more intuitive for the reader. I'm not sure.
What is missing in your code is detection of the Y movement of the left and right titlebars
Oh, one more special case which I overlooked...
I'm not totally happy with your patch, because if I resize the top titlebar to another size and then back, no redraw is actually needed. For that reason I think that my approach is better.
Anyway, since you seem to always find problems in my patches and do the hard work of figuring out what to do, I propose the following:
need_refresh variables)static void client_refresh_moved_titlebars(client_t *c, area_t whatever_areas_are_needed(might_be_none_since_client_t_contains_everything)). This is becoming complicated enough that I think that this is a good idea for keeping the other function short and not too complicated.Would this be okay with you?
I'll leave it to you if you want to do the magic of "if this changed, then this changed" or if you want to do "compute old and new titlebar positions and check which titlebars moved". I prefer the later, you seem to prefer the former.
Actually I did not really like those variables too, and now I see that client_geometry_refresh() has access to all data that is needed to detect movement of all titlebars, therefore I will try to redo the patch as you suggested.
Actually... isn't comparing real_geometry with c->x11_client_geometry enough? Turn both of these from (x,y,width,height) into (x,y,x+width,y+height) [i.e. top left corner and bottom right corner of the client window inside of its frame window].
Since real_geometry is computed based on the titlebar sizes, this is not really surprising. Also, now that I have written this, I guess this is equivalent to what you had in mind.
[I think you know this already, but I want to write this down explicitly: c->x11_[frame|client]_geometry is the current geometry of the frame and client window and geometry and real_geometry are the new values. Based on the old values, one could re-compute the old titlebar sizes and positions and check if it ends up being the same as the new positions (which titlebar_get_area) computes.]
An easy solution which causes some unneeded refreshes:
static void
client_refresh_moved_titlebars(client_t *c, area_t real_geometry)
{
if (real_geometry.y != c->x11_client_geometry.y) {
client_refresh_titlebar_left(c);
client_refresh_titlebar_right(c);
} else if (real_geometry.x + real_geometry.width !=
c->x11_client_geometry.x + c->x11_client_geometry.width) {
client_refresh_titlebar_right(c);
}
if (real_geometry.y + real_geometry.height !=
c->x11_client_geometry.y + c->x11_client_geometry.height) {
client_refresh_titlebar_bottom(c);
}
}
Because awesome_refresh() calls luaA_emit_refresh() before client_refresh(), the delayed redraw of resized titlebars happens before client_refresh_moved_titlebars(), and this simple code refreshes those titlebars again. BTW, this ordering also means that the titlebar refresh happens before the frame and client windows are reconfigured with their new geometry (but the destination coordinates are already updated for the new geometry), therefore some parts of titlebars are clipped (the clipped areas are refreshed when the subsequent Expose event arrives).
A version which seems to work correctly in my testing, but tries to avoid unneeded refreshes:
/** Refresh all titlebars that have been moved but not resized.
*
* After the client and/or titlebar geometry is changed, some titlebars may be
* moved to a different position relative to the frame window, and need to be
* redrawn in the new position. If the titlebar area size changes during this
* movement, client_resize_do() will trigger a full refresh of such titlebars
* through drawable_set_geometry(). However, if both height and width of some
* titlebar areas remains unchanged, client_resize_do() will not refresh those
* titlebars; perform a refresh of such titlebars here.
*/
static void
client_refresh_moved_titlebars(client_t *c, area_t frame_geometry, area_t client_geometry)
{
bool left_and_right_titlebars_moved_vertically =
AREA_TOP(client_geometry) != AREA_TOP(c->x11_client_geometry);
if (left_and_right_titlebars_moved_vertically) {
if ((client_geometry.height == c->x11_client_geometry.height)
&& (client_geometry.x == c->x11_client_geometry.x))
client_refresh_titlebar_left(c);
}
if (left_and_right_titlebars_moved_vertically
|| AREA_RIGHT(client_geometry) != AREA_RIGHT(c->x11_client_geometry)) {
if (client_geometry.height == c->x11_client_geometry.height) {
int new_right_titlebar_width =
frame_geometry.width - AREA_RIGHT(client_geometry);
int old_right_titlebar_width =
c->x11_frame_geometry.width - AREA_RIGHT(c->x11_client_geometry);
if (new_right_titlebar_width == old_right_titlebar_width)
client_refresh_titlebar_right(c);
}
}
if (AREA_BOTTOM(client_geometry) != AREA_BOTTOM(c->x11_client_geometry)) {
if (frame_geometry.width == c->x11_frame_geometry.width) {
int new_bottom_titlebar_height =
frame_geometry.height - AREA_BOTTOM(client_geometry);
int old_bottom_titlebar_height =
c->x11_frame_geometry.height - AREA_BOTTOM(c->x11_client_geometry);
if (new_bottom_titlebar_height == old_bottom_titlebar_height)
client_refresh_titlebar_bottom(c);
}
}
}
The Expose events for parts of refreshed titlebars still arrive later and cause some unneeded redrawing, but detecting this is probably too much work for too little gain.
Thinking about this problem makes my head spin.
I prefer the first code snippet. It makes my head spin slightly less. So... the goal for the second, more complicated version is to detect cases where the size of the titlebar also changed, so Lua had to do a full redraw anyway. Thus, in this case the redraw already happened through :refresh() (plus Expose events later), so we do not have to redraw anything here.
I'm not completely sure I worry about this extra redraw all that much, but this causing-head-spinning code worries me a bit. How about adding a flag to client_t::titlebar for each titlebar. Something like bool was_size_increased. This flag is set when this specific titlebar is resized to a larger size. When it is set, client_refresh_titlebar_partial() does not do anything. Also, when it is set, your new client_refresh_moved_titlebars() unsets it and calls client_refresh_titlebar_NAME(c).
Does this idea seem like it would simplify the code?
static void
client_refresh_moved_titlebars(client_t *c, area_t real_geometry)
{
bool need_refresh[CLIENT_TITLEBAR_COUNT];
for (client_titlebar_t bar = CLIENT_TITLEBAR_TOP; bar < CLIENT_TITLEBAR_COUNT; bar++) {
need_refresh[bar] = c->titlebar[bar].was_size_increased;
c->titlebar[bar].was_size_increased = false;
}
if (real_geometry.y != c->x11_client_geometry.y) {
/* The top titlebar got larger, so these titlebars moved down. */
need_refresh[CLIENT_TITLEBAR_LEFT] = true;
need_refresh[CLIENT_TITLEBAR_RIGHT] = true;
} else if (real_geometry.x + real_geometry.width !=
c->x11_client_geometry.x + c->x11_client_geometry.width) {
/* The right titlebar changed its x-position */
need_refresh[CLIENT_TITLEBAR_RIGHT] = true;
}
if (real_geometry.y + real_geometry.height !=
c->x11_client_geometry.y + c->x11_client_geometry.height) {
/* The bottom titlebar changed its y-position */
need_refresh[CLIENT_TITLEBAR_BOTTOM] = true;
}
for (client_titlebar_t bar = CLIENT_TITLEBAR_TOP; bar < CLIENT_TITLEBAR_COUNT; bar++) {
if (need_refresh[bar]) {
Sigh. No good function to call here. I think we need a client_refresh_titlebar(c, bar) here that is basically the same as the current client_refresh_titlebar_NAME(). The latter function could then just call this new client_refresh_titlebar(c, bar);
}
}
}
(If wanted, we could also do wrap the xcb_configure_window calls that actually resize windows with xcb_grab_server() unselect expose events on the frame window and select expose events on the frame window again xcb_ungrab_server(). That would get rid of the extra Expose events.)
(Also: kudos for finding the AREA_TOP macros and friends)
bool was_size_increased
Perhaps was_resized is a better idea. It is conceptually simpler and I fail to see any downsides (only "titlebar redraws are slightly delayed", but that "slightly" is most likely unmeasurable).
Most helpful comment
Actually I did not really like those variables too, and now I see that
client_geometry_refresh()has access to all data that is needed to detect movement of all titlebars, therefore I will try to redo the patch as you suggested.