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 <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2019-03-16 23:57:47 +00:00
parent 8dc250a415
commit b10f0bbc67
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
3 changed files with 29 additions and 27 deletions

View File

@ -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 || if (w->state == WSTATE_UNMAPPED || w->state == WSTATE_UNMAPPING ||
w->state == WSTATE_DESTROYING) { w->state == WSTATE_DESTROYING) {
/* save the configure event for when the window maps */ // Only restack the window to make sure we can handle future restack
w->need_configure = true; // notification correctly
w->queue_configure = *ce;
restack_win(ps, w, ce->above_sibling); restack_win(ps, w, ce->above_sibling);
} else { } else {
if (!w->need_configure) {
restack_win(ps, w, ce->above_sibling); restack_win(ps, w, ce->above_sibling);
}
bool factor_change = false; bool factor_change = false;
w->need_configure = false;
win_extents(w, &damage); win_extents(w, &damage);
// If window geometry change, free old extents // 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 || if (w->g.width != ce->width || w->g.height != ce->height ||
w->g.border_width != ce->border_width) { 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.width = ce->width;
w->g.height = ce->height; w->g.height = ce->height;
w->g.border_width = ce->border_width; w->g.border_width = ce->border_width;

View File

@ -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 .state = WSTATE_UNMAPPED, // updated by window state changes
.in_openclose = true, // set to false after first map is done, .in_openclose = true, // set to false after first map is done,
// true here because window is just created // true here because window is just created
.need_configure = false, // set to true when window is configured
// while unmapped.
.queue_configure = {}, // same as above .queue_configure = {}, // same as above
.reg_ignore_valid = false, // set to true when damaged .reg_ignore_valid = false, // set to true when damaged
.flags = 0, // updated by property/attributes/etc change .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); 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_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_t *a =
xcb_get_window_attributes_reply(ps->c, acookie, NULL); 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 || a->map_state == XCB_MAP_STATE_UNVIEWABLE) {
if (!a || !g || a->map_state == XCB_MAP_STATE_UNVIEWABLE) {
// Failed to get window attributes or geometry probably means // Failed to get window attributes or geometry probably means
// the window is gone already. Unviewable means the window is // the window is gone already. Unviewable means the window is
// already reparented elsewhere. // already reparented elsewhere.
// BTW, we don't care about Input Only windows, except for stacking // BTW, we don't care about Input Only windows, except for stacking
// proposes, so we need to keep track of them still. // proposes, so we need to keep track of them still.
free(a); free(a);
free(g);
return; return;
} }
@ -979,10 +974,8 @@ void add_win(session_t *ps, xcb_window_t id, xcb_window_t prev) {
*new = win_def; *new = win_def;
new->id = id; new->id = id;
new->a = *a; new->a = *a;
new->g = *g;
pixman_region32_init(&new->bounding_shape); pixman_region32_init(&new->bounding_shape);
free(g);
free(a); free(a);
// Create Damage for window (if not Input Only) // 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); new->pictfmt = x_get_pictform_for_visual(ps->c, new->a.visual);
} }
win_on_win_size_change(ps, new);
// Find window insertion point // Find window insertion point
win **p = NULL; win **p = NULL;
if (prev) { if (prev) {
@ -1645,6 +1636,29 @@ void map_win(session_t *ps, win *w) {
return; 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 ??? // XXX ???
assert(!win_is_focused_real(ps, w)); assert(!win_is_focused_real(ps, w));
@ -1712,13 +1726,6 @@ void map_win(session_t *ps, win *w) {
w->ever_damaged = false; 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 // We stopped listening on ShapeNotify events
// when the window is unmapped (XXX we shouldn't), // when the window is unmapped (XXX we shouldn't),
// so the shape of the window might have changed, // so the shape of the window might have changed,

View File

@ -165,9 +165,6 @@ struct win {
region_t bounding_shape; region_t bounding_shape;
/// Window flags. Definitions above. /// Window flags. Definitions above.
int_fast16_t flags; int_fast16_t flags;
/// Whether there's a pending <code>ConfigureNotify</code> happening
/// when the window is unmapped.
bool need_configure;
/// Queued <code>ConfigureNotify</code> when the window is unmapped. /// Queued <code>ConfigureNotify</code> when the window is unmapped.
xcb_configure_notify_event_t queue_configure; xcb_configure_notify_event_t queue_configure;
/// The region of screen that will be obscured when windows above is painted, /// The region of screen that will be obscured when windows above is painted,