From: Michael Stapelberg Date: Tue, 3 Mar 2009 00:14:11 +0000 (+0100) Subject: Bugfix: Override client’s moves/resizes in configure_notify_event X-Git-Tag: 3.a~124 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=dd325879d1a1cf2346d846596ddfdf7ac4f1bef5;p=i3%2Fi3 Bugfix: Override client’s moves/resizes in configure_notify_event --- diff --git a/include/data.h b/include/data.h index cba4440b..3c308c6b 100644 --- a/include/data.h +++ b/include/data.h @@ -192,8 +192,10 @@ struct Client { /* Backpointer. A client is inside a container */ Container *container; - /* x, y, width, height */ + /* x, y, width, height of the frame */ Rect rect; + /* x, y, width, height of the child (relative to its frame) */ + Rect child_rect; /* Height which was determined by reading the _NET_WM_STRUT_PARTIAL top/bottom of the screen reservation */ diff --git a/src/handlers.c b/src/handlers.c index 9abea181..ebedbccf 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -324,6 +324,30 @@ int handle_map_notify_event(void *prophs, xcb_connection_t *conn, xcb_map_notify int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_notify_event_t *event) { printf("handle_configure_event\n"); ignore_notify_event = event->sequence; + printf("event->x = %d, ->y = %d, ->width = %d, ->height = %d\n", event->x, event->y, event->width, event->height); + Client *client = table_get(byChild, event->window); + if (client == NULL) { + printf("client not managed, ignoring\n"); + return 1; + } + + if (client->container->workspace->fullscreen_client == client) { + printf("client in fullscreen, not touching\n"); + return 1; + } + + /* Let’s see if the application has changed size/position on its own *sigh*… */ + if ((event->x != client->child_rect.x) || + (event->y != client->child_rect.y) || + (event->width != client->child_rect.width) || + (event->height != client->child_rect.height)) { + /* Who is your window manager? Who’s that, huh? I AM YOUR WINDOW MANAGER! */ + printf("Application wanted to resize itself. Fixed that.\n"); + client->force_reconfigure = true; + render_container(conn, client->container); + xcb_flush(conn); + } + return 1; } diff --git a/src/layout.c b/src/layout.c index a47fef11..50195524 100644 --- a/src/layout.c +++ b/src/layout.c @@ -164,32 +164,52 @@ static void resize_client(xcb_connection_t *connection, Client *client) { XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; - Rect rect; + Rect *rect = &(client->child_rect); switch (client->container->mode) { case MODE_STACK: - rect.x = 2; - rect.y = 0; - rect.width = client->rect.width - (2 + 2); - rect.height = client->rect.height - 2; + rect->x = 2; + rect->y = 0; + rect->width = client->rect.width - (2 + 2); + rect->height = client->rect.height - 2; break; default: if (client->titlebar_position == TITLEBAR_OFF) { - rect.x = 0; - rect.y = 0; - rect.width = client->rect.width; - rect.height = client->rect.height; + rect->x = 0; + rect->y = 0; + rect->width = client->rect.width; + rect->height = client->rect.height; } else { - rect.x = 2; - rect.y = font->height + 2 + 2; - rect.width = client->rect.width - (2 + 2); - rect.height = client->rect.height - ((font->height + 2 + 2) + 2); + rect->x = 2; + rect->y = font->height + 2 + 2; + rect->width = client->rect.width - (2 + 2); + rect->height = client->rect.height - ((font->height + 2 + 2) + 2); } break; } - printf("child will be at %dx%d with size %dx%d\n", rect.x, rect.y, rect.width, rect.height); + printf("child will be at %dx%d with size %dx%d\n", rect->x, rect->y, rect->width, rect->height); - xcb_configure_window(connection, client->child, mask, &(rect.x)); + xcb_configure_window(connection, client->child, mask, &(rect->x)); + + /* After configuring a child window we need to fake a configure_notify_event according + to ICCCM 4.2.3. This seems rather broken, especially since X sends exactly the same + configure_notify_event automatically according to xtrace. Anyone knows details? */ + xcb_configure_notify_event_t event; + + event.event = client->child; + event.window = client->child; + event.response_type = XCB_CONFIGURE_NOTIFY; + + event.x = rect->x; + event.y = rect->y; + event.width = rect->width; + event.height = rect->height; + + event.border_width = 0; + event.above_sibling = XCB_NONE; + event.override_redirect = false; + + xcb_send_event(connection, false, client->child, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char*)&event); } /* @@ -221,15 +241,10 @@ void render_container(xcb_connection_t *connection, Container *container) { /* TODO: vertical default layout */ if (client->force_reconfigure | HAS_CHANGED(client->rect.width, container->width) | - HAS_CHANGED(client->rect.height, container->height / num_clients)) { + HAS_CHANGED(client->rect.height, container->height / num_clients)) resize_client(connection, client); - } else printf("no reconfigure necessary\n"); - printf("after client->rect.width = %d, client->rect.height = %d\n", client->rect.width, - client->rect.height); - - if (client->force_reconfigure) - client->force_reconfigure = false; + client->force_reconfigure = false; current_client++; }