diff --git a/include/xcb.h b/include/xcb.h index 4d7eafa0..185163b4 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -108,7 +108,7 @@ void xcb_draw_rect(xcb_connection_t *conn, xcb_drawable_t drawable, * The truth is, however, that we will manage them. * */ -void fake_configure_notify(xcb_connection_t *conn, Rect r, xcb_window_t window); +void fake_configure_notify(xcb_connection_t *conn, Rect r, xcb_window_t window, int border_width); /** * Generates a configure_notify_event with absolute coordinates (relative to diff --git a/src/floating.c b/src/floating.c index 0266dfa2..8d3ce4e2 100644 --- a/src/floating.c +++ b/src/floating.c @@ -103,6 +103,7 @@ void floating_enable(Con *con, bool automatic) { int deco_height = config.font.height + 5; DLOG("Original rect: (%d, %d) with %d x %d\n", con->rect.x, con->rect.y, con->rect.width, con->rect.height); + DLOG("Geometry = (%d, %d) with %d x %d\n", con->geometry.x, con->geometry.y, con->geometry.width, con->geometry.height); Rect zero = { 0, 0, 0, 0 }; nc->rect = con->geometry; /* If the geometry was not set (split containers), we need to determine a @@ -122,9 +123,13 @@ void floating_enable(Con *con, bool automatic) { /* add pixels for the decoration */ /* TODO: don’t add them when the user automatically puts new windows into * 1pixel/borderless mode */ - nc->rect.height += deco_height + 4; + nc->rect.height += deco_height + 2; nc->rect.width += 4; + /* Honor the X11 border */ + nc->rect.height += con->border_width * 2; + nc->rect.width += con->border_width * 2; + /* Some clients (like GIMP’s color picker window) get mapped * to (0, 0), so we push them to a reasonable position * (centered over their leader) */ diff --git a/src/handlers.c b/src/handlers.c index 72e135db..b3467990 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -353,25 +353,27 @@ static int handle_configure_request(xcb_configure_request_event_t *event) { bsr.y += deco_height; bsr.height -= deco_height; } - con = con->parent; + Con *floatingcon = con->parent; DLOG("Container is a floating leaf node, will do that.\n"); if (event->value_mask & XCB_CONFIG_WINDOW_X) { - con->rect.x = event->x + (-1) * bsr.x; - DLOG("proposed x = %d, new x is %d\n", event->x, con->rect.x); + floatingcon->rect.x = event->x + (-1) * bsr.x; + DLOG("proposed x = %d, new x is %d\n", event->x, floatingcon->rect.x); } if (event->value_mask & XCB_CONFIG_WINDOW_Y) { - con->rect.y = event->y + (-1) * bsr.y; - DLOG("proposed y = %d, new y is %d\n", event->y, con->rect.y); + floatingcon->rect.y = event->y + (-1) * bsr.y; + DLOG("proposed y = %d, new y is %d\n", event->y, floatingcon->rect.y); } if (event->value_mask & XCB_CONFIG_WINDOW_WIDTH) { - con->rect.width = event->width + (-1) * bsr.width; - DLOG("proposed width = %d, new width is %d\n", event->width, con->rect.width); + floatingcon->rect.width = event->width + (-1) * bsr.width; + floatingcon->rect.width += con->border_width * 2; + DLOG("proposed width = %d, new width is %d (x11 border %d)\n", event->width, floatingcon->rect.width, con->border_width); } if (event->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { - con->rect.height = event->height + (-1) * bsr.height; - DLOG("proposed height = %d, new height is %d\n", event->height, con->rect.height); + floatingcon->rect.height = event->height + (-1) * bsr.height; + floatingcon->rect.height += con->border_width * 2; + DLOG("proposed height = %d, new height is %d (x11 border %d)\n", event->height, floatingcon->rect.height, con->border_width); } - floating_maybe_reassign_ws(con); + floating_maybe_reassign_ws(floatingcon); tree_render(); } diff --git a/src/xcb.c b/src/xcb.c index b11b0ca6..09f0fb25 100644 --- a/src/xcb.c +++ b/src/xcb.c @@ -168,7 +168,7 @@ void xcb_draw_rect(xcb_connection_t *conn, xcb_drawable_t drawable, xcb_gcontext * The truth is, however, that we will manage them. * */ -void fake_configure_notify(xcb_connection_t *conn, Rect r, xcb_window_t window) { +void fake_configure_notify(xcb_connection_t *conn, Rect r, xcb_window_t window, int border_width) { /* Every X11 event is 32 bytes long. Therefore, XCB will copy 32 bytes. * In order to properly initialize these bytes, we allocate 32 bytes even * though we only need less for an xcb_configure_notify_event_t */ @@ -184,7 +184,7 @@ void fake_configure_notify(xcb_connection_t *conn, Rect r, xcb_window_t window) generated_event->width = r.width; generated_event->height = r.height; - generated_event->border_width = 0; + generated_event->border_width = border_width; generated_event->above_sibling = XCB_NONE; generated_event->override_redirect = false; @@ -211,7 +211,7 @@ void fake_absolute_configure_notify(Con *con) { DLOG("fake rect = (%d, %d, %d, %d)\n", absolute.x, absolute.y, absolute.width, absolute.height); - fake_configure_notify(conn, absolute, con->window->id); + fake_configure_notify(conn, absolute, con->window->id, con->border_width); } /* diff --git a/testcases/t/04-floating.t b/testcases/t/04-floating.t index d4aea828..fcf73f08 100644 --- a/testcases/t/04-floating.t +++ b/testcases/t/04-floating.t @@ -51,7 +51,7 @@ sleep 0.25; ($absolute, $top) = $window->rect; cmp_ok($absolute->{width}, '==', 80, "i3 let the width at 80"); -cmp_ok($absolute->{height}, '==', 92, "i3 let the height at 90"); +cmp_ok($absolute->{height}, '==', 90, "i3 let the height at 90"); # We need to compare the position with decorations due to the way # we do decoration rendering (on the parent frame) in the tree branch @@ -60,4 +60,31 @@ cmp_ok($top->{y}, '==', 19, 'i3 mapped it to y=18'); $window->unmap; +##################################################################### +# check that a tiling window which is then made floating still has +# at least the size of its initial geometry +##################################################################### + +$window = $x->root->create_child( + class => WINDOW_CLASS_INPUT_OUTPUT, + rect => [ 1, 1, 80, 90], + background_color => '#C0C0C0', + #window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'), +); + +isa_ok($window, 'X11::XCB::Window'); + +$window->map; + +sleep 0.25; + +cmd 'floating enable'; + +($absolute, $top) = $window->rect; + +cmp_ok($absolute->{width}, '==', 80, "i3 let the width at 80"); +cmp_ok($absolute->{height}, '==', 90, "i3 let the height at 90"); + +$window->unmap; + done_testing;