From: Michael Stapelberg Date: Fri, 12 Feb 2010 12:06:59 +0000 (+0100) Subject: Bugfix: Correctly do boundary checking/moving to other workspaces when moving floatin... X-Git-Tag: 3.e~6^2~150 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=87f8c501da5c32648b2ff48b6201a03d667d17a1;p=i3%2Fi3 Bugfix: Correctly do boundary checking/moving to other workspaces when moving floating clients via keyboard (Thanks sasha) --- diff --git a/include/data.h b/include/data.h index 47343d19..31cef493 100644 --- a/include/data.h +++ b/include/data.h @@ -78,6 +78,12 @@ enum { * It needs to be packed so that the compiler will not add any padding bytes. * (it is used in src/ewmh.c for example) * + * Note that x and y can contain signed values in some cases (for example when + * used for the coordinates of a window, which can be set outside of the + * visible area, but not when specifying the position of a workspace for the + * _NET_WM_WORKAREA hint). Not declaring x/y as int32_t saves us a lot of + * typecasts. + * */ struct Rect { uint32_t x; diff --git a/src/floating.c b/src/floating.c index 1e7a4fac..ca294cc6 100644 --- a/src/floating.c +++ b/src/floating.c @@ -411,28 +411,37 @@ void floating_focus_direction(xcb_connection_t *conn, Client *currently_focused, void floating_move(xcb_connection_t *conn, Client *currently_focused, direction_t direction) { DLOG("floating move\n"); + Rect destination = currently_focused->rect; + Rect *screen = &(currently_focused->workspace->screen->rect); + switch (direction) { case D_LEFT: - if (currently_focused->rect.x < 10) - return; - currently_focused->rect.x -= 10; + destination.x -= 10; break; case D_RIGHT: - currently_focused->rect.x += 10; + destination.x += 10; break; case D_UP: - if (currently_focused->rect.y < 10) - return; - currently_focused->rect.y -= 10; + destination.y -= 10; break; case D_DOWN: - currently_focused->rect.y += 10; + destination.y += 10; break; /* to make static analyzers happy */ default: break; } + /* Prevent windows from vanishing completely */ + if ((int32_t)(destination.x + destination.width - 5) <= (int32_t)screen->x || + (int32_t)(destination.x + 5) >= (int32_t)(screen->x + screen->width) || + (int32_t)(destination.y + destination.height - 5) <= (int32_t)screen->y || + (int32_t)(destination.y + 5) >= (int32_t)(screen->y + screen->height)) { + DLOG("boundary check failed, not moving\n"); + return; + } + + currently_focused->rect = destination; reposition_client(conn, currently_focused); /* Because reposition_client does not send a faked configure event (only resize does), diff --git a/src/layout.c b/src/layout.c index 4b55c0ac..1017c3dd 100644 --- a/src/layout.c +++ b/src/layout.c @@ -228,7 +228,9 @@ void reposition_client(xcb_connection_t *conn, Client *client) { return; /* If the client is floating, we need to check if we moved it to a different workspace */ - if (client->workspace->screen == (screen = get_screen_containing(client->rect.x, client->rect.y))) + screen = get_screen_containing(client->rect.x + (client->rect.width / 2), + client->rect.y + (client->rect.height / 2)); + if (client->workspace->screen == screen) return; if (screen == NULL) { @@ -239,6 +241,8 @@ void reposition_client(xcb_connection_t *conn, Client *client) { DLOG("Client is on workspace %p with screen %p\n", client->workspace, client->workspace->screen); DLOG("but screen at %d, %d is %p\n", client->rect.x, client->rect.y, screen); floating_assign_to_workspace(client, screen->current_workspace); + + set_focus(conn, client, true); } /*