allows a window to unmax by resizing.
authorDana Jansens <danakj@orodu.net>
Tue, 18 May 2010 22:47:54 +0000 (18:47 -0400)
committerDana Jansens <danakj@orodu.net>
Thu, 20 May 2010 20:18:03 +0000 (16:18 -0400)
makes "clever" use of the client's pre_max_area values to allow this to happen
without flashing, and preserving them in case the user cancels the resize
after it has become unmaximized.

openbox/client.c
openbox/moveresize.c

index ae97606..e9a2adf 100644 (file)
@@ -1769,9 +1769,10 @@ void client_setup_decor_and_functions(ObClient *self, gboolean reconfig)
     }
 
     if (self->max_horz && self->max_vert) {
-        /* you can't resize fully maximized windows */
-        self->functions &= ~OB_CLIENT_FUNC_RESIZE;
-        /* kill the handle on fully maxed windows */
+        /* once upon a time you couldn't resize maximized windows, that is not
+           the case any more though !
+
+           but do kill the handle on fully maxed windows */
         self->decorations &= ~(OB_FRAME_DECOR_HANDLE | OB_FRAME_DECOR_GRIPS);
     }
 
@@ -2889,11 +2890,11 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
        through this code */
     {
         gint basew, baseh, minw, minh;
-        gint incw, inch;
+        gint incw, inch, maxw, maxh;
         gfloat minratio, maxratio;
 
-        incw = self->fullscreen || self->max_horz ? 1 : self->size_inc.width;
-        inch = self->fullscreen || self->max_vert ? 1 : self->size_inc.height;
+        incw = self->size_inc.width;
+        inch = self->size_inc.height;
         minratio = self->fullscreen || (self->max_horz && self->max_vert) ?
             0 : self->min_ratio;
         maxratio = self->fullscreen || (self->max_horz && self->max_vert) ?
@@ -2929,6 +2930,10 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
         *w -= basew;
         *h -= baseh;
 
+        /* the sizes to used for maximized */
+        maxw = *w;
+        maxh = *h;
+
         /* keep to the increments */
         *w /= incw;
         *h /= inch;
@@ -2944,6 +2949,10 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
         *w *= incw;
         *h *= inch;
 
+        /* if maximized/fs then don't use the size increments */
+        if (self->fullscreen || self->max_horz) *w = maxw;
+        if (self->fullscreen || self->max_vert) *h = maxh;
+
         *w += basew;
         *h += baseh;
 
@@ -3081,7 +3090,7 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h,
        When user = FALSE, then the request is coming from the application
        itself, and we are more strict about when to send a synthetic
        ConfigureNotify.  We strictly follow the rules of the ICCCM sec 4.1.5
-       in this case (if force_reply is true)
+       in this case (or send one if force_reply is true)
 
        When user = TRUE, then the request is coming from "us", like when we
        maximize a window or something.  In this case we are more lenient.  We
index 966ac74..96cd623 100644 (file)
@@ -51,7 +51,11 @@ XSyncAlarm moveresize_alarm = None;
 
 static gboolean moving = FALSE; /* TRUE - moving, FALSE - resizing */
 
+/* starting geometry for the window being moved/resized, so it can be
+   restored */
 static gint start_x, start_y, start_cx, start_cy, start_cw, start_ch;
+static gboolean was_max_horz, was_max_vert;
+static Rect pre_max_area;
 static gint cur_x, cur_y, cur_w, cur_h;
 static guint button;
 static guint32 corner;
@@ -239,6 +243,9 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
     button = b;
     key_resize_edge = -1;
 
+    /* default to not putting max back on cancel */
+    was_max_horz = was_max_vert = FALSE;
+
     /*
       have to change start_cx and start_cy if going to do this..
     if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
@@ -327,6 +334,28 @@ void moveresize_end(gboolean cancel)
                      (cancel ? start_ch : cur_h),
                      TRUE, TRUE, FALSE);
 
+    /* restore the client's maximized state. do this after putting the window
+       back in its original spot to minimize visible flicker */
+    if (cancel && (was_max_horz || was_max_vert)) {
+        const gboolean h = moveresize_client->max_horz;
+        const gboolean v = moveresize_client->max_vert;
+
+        client_maximize(moveresize_client, TRUE,
+                        was_max_horz && was_max_vert ? 0 :
+                        (was_max_horz ? 1 : 2));
+
+        /* replace the premax values with the ones we had saved if
+           the client doesn't have any already set */
+        if (was_max_horz && !h) {
+            moveresize_client->pre_max_area.x = pre_max_area.x;
+            moveresize_client->pre_max_area.width = pre_max_area.width;
+        }
+        if (was_max_vert && !v) {
+            moveresize_client->pre_max_area.y = pre_max_area.y;
+            moveresize_client->pre_max_area.height = pre_max_area.height;
+        }
+    }
+
     /* dont edge warp after its ended */
     cancel_edge_warp();
 
@@ -820,6 +849,33 @@ static void resize_with_keys(KeySym sym, guint state)
         }
     }
 
+    if (moveresize_client->max_horz &&
+        (key_resize_edge == OB_DIRECTION_WEST ||
+         key_resize_edge == OB_DIRECTION_EAST))
+    {
+        /* unmax horz */
+        was_max_horz = TRUE;
+        pre_max_area.x = moveresize_client->pre_max_area.x;
+        pre_max_area.width = moveresize_client->pre_max_area.width;
+
+        moveresize_client->pre_max_area.x = cur_x;
+        moveresize_client->pre_max_area.width = cur_w;
+        client_maximize(moveresize_client, FALSE, 1);
+    }
+    else if (moveresize_client->max_vert &&
+             (key_resize_edge == OB_DIRECTION_NORTH ||
+              key_resize_edge == OB_DIRECTION_SOUTH))
+    {
+        /* unmax vert */
+        was_max_vert = TRUE;
+        pre_max_area.y = moveresize_client->pre_max_area.y;
+        pre_max_area.height = moveresize_client->pre_max_area.height;
+
+        moveresize_client->pre_max_area.y = cur_y;
+        moveresize_client->pre_max_area.height = cur_h;
+        client_maximize(moveresize_client, FALSE, 2);
+    }
+
     calc_resize(TRUE, resist, &dw, &dh, dir);
     if (key_resize_edge == OB_DIRECTION_WEST)
         cur_x -= dw;
@@ -932,6 +988,46 @@ gboolean moveresize_event(XEvent *e)
             } else
                 g_assert_not_reached();
 
+            /* override the client's max state if desired */
+            if (ABS(dw) >= config_resist_edge) {
+                if (moveresize_client->max_horz) {
+                    /* unmax horz */
+                    was_max_horz = TRUE;
+                    pre_max_area.x = moveresize_client->pre_max_area.x;
+                    pre_max_area.width = moveresize_client->pre_max_area.width;
+
+                    moveresize_client->pre_max_area.x = cur_x;
+                    moveresize_client->pre_max_area.width = cur_w;
+                    client_maximize(moveresize_client, FALSE, 1);
+                }
+            }
+            else if (was_max_horz && !moveresize_client->max_horz) {
+                /* remax horz and put the premax back */
+                client_maximize(moveresize_client, TRUE, 1);
+                moveresize_client->pre_max_area.x = pre_max_area.x;
+                moveresize_client->pre_max_area.width = pre_max_area.width;
+            }
+
+            if (ABS(dh) >= config_resist_edge) {
+                if (moveresize_client->max_vert) {
+                    /* unmax vert */
+                    was_max_vert = TRUE;
+                    pre_max_area.y = moveresize_client->pre_max_area.y;
+                    pre_max_area.height =
+                        moveresize_client->pre_max_area.height;
+
+                    moveresize_client->pre_max_area.y = cur_y;
+                    moveresize_client->pre_max_area.height = cur_h;
+                    client_maximize(moveresize_client, FALSE, 2);
+                }
+            }
+            else if (was_max_vert && !moveresize_client->max_vert) {
+                /* remax vert and put the premax back */
+                client_maximize(moveresize_client, TRUE, 2);
+                moveresize_client->pre_max_area.y = pre_max_area.y;
+                moveresize_client->pre_max_area.height = pre_max_area.height;
+            }
+
             dw -= cur_w - start_cw;
             dh -= cur_h - start_ch;