From b10f0bbc67720ab71badec1dbbe17da329f3e34a Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Sat, 16 Mar 2019 23:57:47 +0000 Subject: [PATCH] win: always refresh window size in map_win Instead queue up configure notification while the window is unmapped, just update the window geometry when the window is mapped. Simplify the logic a little bit. Signed-off-by: Yuxuan Shui --- src/compton.c | 12 +++++------- src/win.c | 41 ++++++++++++++++++++++++----------------- src/win.h | 3 --- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/compton.c b/src/compton.c index 02afb6c..23e58c1 100644 --- a/src/compton.c +++ b/src/compton.c @@ -825,17 +825,13 @@ void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) { if (w->state == WSTATE_UNMAPPED || w->state == WSTATE_UNMAPPING || w->state == WSTATE_DESTROYING) { - /* save the configure event for when the window maps */ - w->need_configure = true; - w->queue_configure = *ce; + // Only restack the window to make sure we can handle future restack + // notification correctly restack_win(ps, w, ce->above_sibling); } else { - if (!w->need_configure) { - restack_win(ps, w, ce->above_sibling); - } + restack_win(ps, w, ce->above_sibling); bool factor_change = false; - w->need_configure = false; win_extents(w, &damage); // If window geometry change, free old extents @@ -848,6 +844,8 @@ void configure_win(session_t *ps, xcb_configure_notify_event_t *ce) { if (w->g.width != ce->width || w->g.height != ce->height || w->g.border_width != ce->border_width) { + log_trace("Window size changed, %dx%d -> %dx%d", w->g.width, + w->g.height, ce->width, ce->height); w->g.width = ce->width; w->g.height = ce->height; w->g.border_width = ce->border_width; diff --git a/src/win.c b/src/win.c index 5dbdeee..01335b0 100644 --- a/src/win.c +++ b/src/win.c @@ -876,8 +876,6 @@ void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) { .state = WSTATE_UNMAPPED, // updated by window state changes .in_openclose = true, // set to false after first map is done, // true here because window is just created - .need_configure = false, // set to true when window is configured - // while unmapped. .queue_configure = {}, // same as above .reg_ignore_valid = false, // set to true when damaged .flags = 0, // updated by property/attributes/etc change @@ -955,18 +953,15 @@ void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) { log_debug("Adding window %#010x, prev %#010x", id, prev); xcb_get_window_attributes_cookie_t acookie = xcb_get_window_attributes(ps->c, id); - xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(ps->c, id); xcb_get_window_attributes_reply_t *a = xcb_get_window_attributes_reply(ps->c, acookie, NULL); - xcb_get_geometry_reply_t *g = xcb_get_geometry_reply(ps->c, gcookie, NULL); - if (!a || !g || a->map_state == XCB_MAP_STATE_UNVIEWABLE) { + if (!a || a->map_state == XCB_MAP_STATE_UNVIEWABLE) { // Failed to get window attributes or geometry probably means // the window is gone already. Unviewable means the window is // already reparented elsewhere. // BTW, we don't care about Input Only windows, except for stacking // proposes, so we need to keep track of them still. free(a); - free(g); return; } @@ -979,10 +974,8 @@ void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) { *new = win_def; new->id = id; new->a = *a; - new->g = *g; pixman_region32_init(&new->bounding_shape); - free(g); free(a); // Create Damage for window (if not Input Only) @@ -1000,8 +993,6 @@ void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) { new->pictfmt = x_get_pictform_for_visual(ps->c, new->a.visual); } - win_on_win_size_change(ps, new); - // Find window insertion point win **p = NULL; if (prev) { @@ -1645,6 +1636,29 @@ void map_win(session_t *ps, win *w) { return; } + // We stopped processing window size change when we were unmapped, refresh the + // size of the window + xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(ps->c, w->id); + xcb_get_geometry_reply_t *g = xcb_get_geometry_reply(ps->c, gcookie, NULL); + + if (!g) { + log_error("Failed to get the geometry of window %#010x", w->id); + return; + } + + w->g = *g; + free(g); + + win_on_win_size_change(ps, w); + log_trace("Window size: %dx%d", w->g.width, w->g.height); + + // Rant: window size could change after we queried its geometry here and before + // we get its pixmap. Later, when we get back to the event processing loop, we + // will get the notification about size change from Xserver and try to refresh the + // pixmap, while the pixmap is actually already up-to-date (i.e. the notification + // is stale). There is basically no real way to prevent this, aside from grabbing + // the server. + // XXX ??? assert(!win_is_focused_real(ps, w)); @@ -1712,13 +1726,6 @@ void map_win(session_t *ps, win *w) { w->ever_damaged = false; - /* if any configure events happened while - the window was unmapped, then configure - the window to its correct place */ - if (w->need_configure) { - configure_win(ps, &w->queue_configure); - } - // We stopped listening on ShapeNotify events // when the window is unmapped (XXX we shouldn't), // so the shape of the window might have changed, diff --git a/src/win.h b/src/win.h index 4cba9eb..39f9e17 100644 --- a/src/win.h +++ b/src/win.h @@ -165,9 +165,6 @@ struct win { region_t bounding_shape; /// Window flags. Definitions above. int_fast16_t flags; - /// Whether there's a pending ConfigureNotify happening - /// when the window is unmapped. - bool need_configure; /// Queued ConfigureNotify when the window is unmapped. xcb_configure_notify_event_t queue_configure; /// The region of screen that will be obscured when windows above is painted,