From 8f7bd538d89d2a366a9224632ab522afeeaa8f64 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 12 Nov 2010 21:41:10 +0100 Subject: [PATCH] implement configure requests, adapt testcase testcase does not pass 100% due to clients not being reparented correctly yet. --- include/con.h | 8 ++ include/handlers.h | 3 +- include/util.h | 1 + src/con.c | 17 ++++ src/handlers.c | 150 ++++++++++++------------------- src/main.c | 3 + src/render.c | 8 +- src/util.c | 7 ++ testcases/Makefile | 2 +- testcases/t/04-floating.t | 13 +-- testcases/t/12-floating-resize.t | 11 +-- 11 files changed, 108 insertions(+), 115 deletions(-) diff --git a/include/con.h b/include/con.h index fb862150..c4c4a270 100644 --- a/include/con.h +++ b/include/con.h @@ -129,4 +129,12 @@ int con_orientation(Con *con); */ Con *con_next_focused(Con *con); +/* + * Returns a "relative" Rect which contains the amount of pixels that need to + * be added to the original Rect to get the final position (obviously the + * amount of pixels for normal, 1pixel and borderless are different). + * + */ +Rect con_border_style_rect(Con *con); + #endif diff --git a/include/handlers.h b/include/handlers.h index b4a9486a..185320de 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -79,6 +79,7 @@ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_n */ int handle_screen_change(void *prophs, xcb_connection_t *conn, xcb_generic_event_t *e); +#endif /** * Configure requests are received when the application wants to resize @@ -90,7 +91,7 @@ int handle_screen_change(void *prophs, xcb_connection_t *conn, */ int handle_configure_request(void *prophs, xcb_connection_t *conn, xcb_configure_request_event_t *event); -#endif + /** * Our window decorations were unmapped. That means, the window will be killed * now, so we better clean up before. diff --git a/include/util.h b/include/util.h index cca6985d..8a399d45 100644 --- a/include/util.h +++ b/include/util.h @@ -37,6 +37,7 @@ while (0) int min(int a, int b); int max(int a, int b); bool rect_contains(Rect rect, uint32_t x, uint32_t y); +Rect rect_add(Rect a, Rect b); /** * Updates *destination with new_value and returns true if it was changed or false diff --git a/src/con.c b/src/con.c index 4b0b2307..02d46db5 100644 --- a/src/con.c +++ b/src/con.c @@ -430,3 +430,20 @@ Con *con_next_focused(Con *con) { return next; } + +/* + * Returns a "relative" Rect which contains the amount of pixels that need to + * be added to the original Rect to get the final position (obviously the + * amount of pixels for normal, 1pixel and borderless are different). + * + */ +Rect con_border_style_rect(Con *con) { + if (con->border_style == BS_NORMAL) + return (Rect){2, 0, -(2 * 2), -2}; + + if (con->border_style == BS_1PIXEL) + return (Rect){1, 1, -2, -2}; + + if (con->border_style == BS_NONE) + return (Rect){0, 0, 0, 0}; +} diff --git a/src/handlers.c b/src/handlers.c index 0e497b04..a339abdf 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -274,7 +274,7 @@ int handle_map_request(void *prophs, xcb_connection_t *conn, xcb_map_request_eve x_push_changes(croot); return 1; } -#if 0 + /* * Configure requests are received when the application wants to resize windows on their own. * @@ -282,108 +282,70 @@ int handle_map_request(void *prophs, xcb_connection_t *conn, xcb_map_request_eve * */ int handle_configure_request(void *prophs, xcb_connection_t *conn, xcb_configure_request_event_t *event) { - DLOG("window 0x%08x wants to be at %dx%d with %dx%d\n", - event->window, event->x, event->y, event->width, event->height); + Con *con; - Client *client = table_get(&by_child, event->window); - if (client == NULL) { - uint32_t mask = 0; - uint32_t values[7]; - int c = 0; -#define COPY_MASK_MEMBER(mask_member, event_member) do { \ - if (event->value_mask & mask_member) { \ - mask |= mask_member; \ - values[c++] = event->event_member; \ - } \ -} while (0) + DLOG("window 0x%08x wants to be at %dx%d with %dx%d\n", + event->window, event->x, event->y, event->width, event->height); - COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_X, x); - COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_Y, y); - COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_WIDTH, width); - COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_HEIGHT, height); - COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_BORDER_WIDTH, border_width); - COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_SIBLING, sibling); - COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_STACK_MODE, stack_mode); + /* For unmanaged windows, we just execute the configure request. As soon as + * it gets mapped, we will take over anyways. */ + if ((con = con_by_window_id(event->window)) == NULL) { + DLOG("Configure request for unmanaged window, can do that.\n"); - xcb_configure_window(conn, event->window, mask, values); - xcb_flush(conn); + uint32_t mask = 0; + uint32_t values[7]; + int c = 0; +#define COPY_MASK_MEMBER(mask_member, event_member) do { \ + if (event->value_mask & mask_member) { \ + mask |= mask_member; \ + values[c++] = event->event_member; \ + } \ +} while (0) - return 1; - } + COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_X, x); + COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_Y, y); + COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_WIDTH, width); + COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_HEIGHT, height); + COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_BORDER_WIDTH, border_width); + COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_SIBLING, sibling); + COPY_MASK_MEMBER(XCB_CONFIG_WINDOW_STACK_MODE, stack_mode); - if (client->fullscreen) { - DLOG("Client is in fullscreen mode\n"); + xcb_configure_window(conn, event->window, mask, values); + xcb_flush(conn); - Rect child_rect = client->workspace->rect; - child_rect.x = child_rect.y = 0; - fake_configure_notify(conn, child_rect, client->child); + return 1; + } - return 1; + DLOG("Configure request!\n"); + if (con_is_floating(con) && con_is_leaf(con)) { + /* we actually need to apply the size/position changes to the *parent* + * container */ + Rect bsr = con_border_style_rect(con); + if (con->border_style == BS_NORMAL) + bsr.height -= 17; + con = 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); } - - /* Floating clients can be reconfigured */ - if (client_is_floating(client)) { - i3Font *font = load_font(conn, config.font); - int mode = (client->container != NULL ? client->container->mode : MODE_DEFAULT); - /* TODO: refactor this code. we need a function to translate - * coordinates of child_rect/rect. */ - - if (event->value_mask & XCB_CONFIG_WINDOW_X) { - if (mode == MODE_STACK || mode == MODE_TABBED) { - client->rect.x = event->x - 2; - } else { - if (client->titlebar_position == TITLEBAR_OFF && client->borderless) - client->rect.x = event->x; - else if (client->titlebar_position == TITLEBAR_OFF && !client->borderless) - client->rect.x = event->x - 1; - else client->rect.x = event->x - 2; - } - } - if (event->value_mask & XCB_CONFIG_WINDOW_Y) { - if (mode == MODE_STACK || mode == MODE_TABBED) { - client->rect.y = event->y - 2; - } else { - if (client->titlebar_position == TITLEBAR_OFF && client->borderless) - client->rect.y = event->y; - else if (client->titlebar_position == TITLEBAR_OFF && !client->borderless) - client->rect.y = event->y - 1; - else client->rect.y = event->y - font->height - 2 - 2; - } - } - if (event->value_mask & XCB_CONFIG_WINDOW_WIDTH) { - if (mode == MODE_STACK || mode == MODE_TABBED) { - client->rect.width = event->width + 2 + 2; - } else { - if (client->titlebar_position == TITLEBAR_OFF && client->borderless) - client->rect.width = event->width; - else if (client->titlebar_position == TITLEBAR_OFF && !client->borderless) - client->rect.width = event->width + (1 + 1); - else client->rect.width = event->width + (2 + 2); - } - } - if (event->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { - if (mode == MODE_STACK || mode == MODE_TABBED) { - client->rect.height = event->height + 2; - } else { - if (client->titlebar_position == TITLEBAR_OFF && client->borderless) - client->rect.height = event->height; - else if (client->titlebar_position == TITLEBAR_OFF && !client->borderless) - client->rect.height = event->height + (1 + 1); - else client->rect.height = event->height + (font->height + 2 + 2) + 2; - } - } - - DLOG("Accepted new position/size for floating client: (%d, %d) size %d x %d\n", - client->rect.x, client->rect.y, client->rect.width, client->rect.height); - - /* Push the new position/size to X11 */ - reposition_client(conn, client); - resize_client(conn, client); - xcb_flush(conn); - - return 1; + 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); + } + 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); + } + 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); } + tree_render(); + } + return 1; +#if 0 /* Dock clients can be reconfigured in their height */ if (client->dock) { DLOG("Reconfiguring height of this dock client\n"); @@ -413,7 +375,9 @@ int handle_configure_request(void *prophs, xcb_connection_t *conn, xcb_configure fake_absolute_configure_notify(conn, client); return 1; +#endif } +#if 0 /* * Configuration notifies are only handled because we need to set up ignore for diff --git a/src/main.c b/src/main.c index a0eb9192..417c2b27 100644 --- a/src/main.c +++ b/src/main.c @@ -218,6 +218,9 @@ int main(int argc, char *argv[]) { for us is _NET_WM_STATE, we honour _NET_WM_STATE_FULLSCREEN */ xcb_event_set_client_message_handler(&evenths, handle_client_message, NULL); + /* Configure request = window tried to change size on its own */ + xcb_event_set_configure_request_handler(&evenths, handle_configure_request, NULL); + /* Setup NetWM atoms */ #define GET_ATOM(name) \ do { \ diff --git a/src/render.c b/src/render.c index 469ceaa8..523b9188 100644 --- a/src/render.c +++ b/src/render.c @@ -51,12 +51,8 @@ void render_con(Con *con) { /* depending on the border style, the rect of the child window * needs to be smaller */ Rect *inset = &(con->window_rect); - - if (con->border_style == BS_NORMAL) - *inset = (Rect){2, 0, con->rect.width - (2 * 2), con->rect.height - 2}; - else if (con->border_style == BS_1PIXEL) - *inset = (Rect){1, 1, con->rect.width - 2, con->rect.height - 1}; - else *inset = (Rect){0, 0, con->rect.width, con->rect.height}; + *inset = (Rect){0, 0, con->rect.width, con->rect.height}; + *inset = rect_add(*inset, con_border_style_rect(con)); /* Obey the aspect ratio, if any */ if (con->proportional_height != 0 && diff --git a/src/util.c b/src/util.c index c8f4ee38..fc3ada5f 100644 --- a/src/util.c +++ b/src/util.c @@ -38,6 +38,13 @@ bool rect_contains(Rect rect, uint32_t x, uint32_t y) { y <= (rect.y + rect.height)); } +Rect rect_add(Rect a, Rect b) { + return (Rect){a.x + b.x, + a.y + b.y, + a.width + b.width, + a.height + b.height}; +} + /* * Updates *destination with new_value and returns true if it was changed or false * if it was the same diff --git a/testcases/Makefile b/testcases/Makefile index 06a7cfa1..6d7898b8 100644 --- a/testcases/Makefile +++ b/testcases/Makefile @@ -1,5 +1,5 @@ test: - PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(1)" -It/lib t/34*.t + PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(1)" -It/lib t/12*.t all: test diff --git a/testcases/t/04-floating.t b/testcases/t/04-floating.t index 9607b2e2..d16fa8b7 100644 --- a/testcases/t/04-floating.t +++ b/testcases/t/04-floating.t @@ -1,7 +1,7 @@ #!perl # vim:ts=4:sw=4:expandtab -use i3test tests => 10; +use i3test tests => 11; use X11::XCB qw(:all); use Time::HiRes qw(sleep); @@ -29,8 +29,8 @@ sleep(0.25); my ($absolute, $top) = $window->rect; ok($window->mapped, 'Window is mapped'); -ok($absolute->{width} >= 75, 'i3 raised the width to 75'); -ok($absolute->{height} >= 50, 'i3 raised the height to 50'); +cmp_ok($absolute->{width}, '>=', 75, 'i3 raised the width to 75'); +cmp_ok($absolute->{height}, '>=', 50, 'i3 raised the height to 50'); ok($absolute->{x} != 0 && $absolute->{y} != 0, 'i3 did not map it to (0x0)'); @@ -51,10 +51,11 @@ sleep(0.25); ($absolute, $top) = $window->rect; -ok($absolute->{width} == 80, "i3 let the width at 80"); -ok($absolute->{height} == 90, "i3 let the height at 90"); +cmp_ok($absolute->{width}, '==', 80, "i3 let the width at 80"); +cmp_ok($absolute->{height}, '==', 90, "i3 let the height at 90"); -ok($top->{x} == 1 && $top->{y} == 1, "i3 mapped it to (1,1)"); +cmp_ok($top->{x}, '==', 1, 'i3 mapped it to x=1'); +cmp_ok($top->{y}, '==', 1, 'i3 mapped it to y=1'); $window->unmap; diff --git a/testcases/t/12-floating-resize.t b/testcases/t/12-floating-resize.t index a5fb3c57..42ca43c0 100644 --- a/testcases/t/12-floating-resize.t +++ b/testcases/t/12-floating-resize.t @@ -12,9 +12,6 @@ BEGIN { use_ok('X11::XCB::Connection') or BAIL_OUT('Cannot load X11::XCB::Connection'); } -SKIP: { - skip "border styles not yet implemented", 14; - my $x = X11::XCB::Connection->new; my $i3 = i3("/tmp/nestedcons"); @@ -31,7 +28,7 @@ my $window = $x->root->create_child( rect => [ 0, 0, 30, 30], background_color => '#C0C0C0', # replace the type with 'utility' as soon as the coercion works again in X11::XCB - type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'), + window_type => $x->atom(name => '_NET_WM_WINDOW_TYPE_UTILITY'), ); isa_ok($window, 'X11::XCB::Window'); @@ -70,13 +67,11 @@ sub test_resize { test_resize; # Test borderless -$i3->command('bb')->recv; +$i3->command('border none')->recv; test_resize; # Test with 1-px-border -$i3->command('bp')->recv; +$i3->command('border 1pixel')->recv; test_resize; - -} -- 2.39.5