]> git.sur5r.net Git - i3/i3/commitdiff
Bugfix: Correctly do boundary checking/moving to other workspaces when moving floatin...
authorMichael Stapelberg <michael@stapelberg.de>
Fri, 12 Feb 2010 12:06:59 +0000 (13:06 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Fri, 12 Feb 2010 12:06:59 +0000 (13:06 +0100)
include/data.h
src/floating.c
src/layout.c

index 47343d19b6a736c58ac820b0c2c36d752cff4e89..31cef493d78bed76cf50ff57105867d857293d0e 100644 (file)
@@ -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;
index 1e7a4fac784aed00c0753970f4a3f1e07bf27fa7..ca294cc6db1627a414adfdc5fef571fdd7056f1e 100644 (file)
@@ -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),
index 4b55c0accb1f69ed64a33e5763ad1d74a8e5e9b7..1017c3dd4dbec17a8e78aa8105c61d0170b2ba21 100644 (file)
@@ -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);
 }
 
 /*