]> Dogcows Code - chaz/openbox/blobdiff - plugins/resistance.c
use the frame's position in the maximize function since they're converted to the...
[chaz/openbox] / plugins / resistance.c
index d9c9517dac1bf42234b095496efdc8b68eb0c85c..56ad9d9125229debb365d78a85c1afb5b1cdeca8 100644 (file)
@@ -26,7 +26,7 @@ void plugin_setup_config()
     config_set("resistance.windows", Config_Bool, val);
 }
 
-static void resist(Client *c, int *x, int *y)
+static void resist_move(Client *c, int *x, int *y)
 {
     GList *it;
     Rect *area;
@@ -34,7 +34,7 @@ static void resist(Client *c, int *x, int *y)
     int al, at, ar, ab; /* screen area edges */
     int cl, ct, cr, cb; /* current edges */
     int w, h; /* current size */
-    gboolean snapx = FALSE, snapy = FALSE;
+    Client *snapx = NULL, *snapy = NULL;
     ConfigValue resist, window_resist;
 
     if (!config_get("resistance", Config_Integer, &resist) ||
@@ -77,14 +77,32 @@ static void resist(Client *c, int *x, int *y)
                window edge available, without going all the way from
                bottom-to-top in the stacking list
             */
-            if (!snapx && cl >= tr && l < tr && l >= tr - resist.integer)
-                *x = tr, snapx = TRUE;
-            else if (!snapx && cr <= tl && r > tl && r <= tl + resist.integer)
-                *x = tl - w + 1, snapx = TRUE;
-            else if (!snapy && ct >= tb && t < tb && t >= tb - resist.integer)
-                *y = tb, snapy = TRUE;
-            else if (!snapy && cb <= tt && b > tt && b <= tt + resist.integer)
-                *y = tt - h + 1, snapy = TRUE;
+            if (snapx == NULL) {
+                if (cl >= tr && l < tr && l >= tr - resist.integer)
+                    *x = tr, snapx = target;
+                else if (cr <= tl && r > tl && r <= tl + resist.integer)
+                    *x = tl - w + 1, snapx = target;
+                if (snapx != NULL) {
+                    /* try to corner snap to the window */
+                    if (ct > tt && t <= tt && t > tt - resist.integer)
+                        *y = tt + 1, snapy = target;
+                    else if (cb < tb && b >= tb && b < tb + resist.integer)
+                        *y = tb - h, snapy = target;
+                }
+            }
+            if (snapy == NULL) {
+                if (ct >= tb && t < tb && t >= tb - resist.integer)
+                    *y = tb, snapy = target;
+                else if (cb <= tt && b > tt && b <= tt + resist.integer)
+                    *y = tt - h + 1, snapy = target;
+                if (snapy != NULL) {
+                    /* try to corner snap to the window */
+                    if (cl > tl && l <= tl && l > tl - resist.integer)
+                        *x = tl + 1, snapx = target;
+                    else if (cr < tr && r >= tr && r < tr + resist.integer)
+                        *x = tr - w, snapx = target;
+                }
+            }
 
             if (snapx && snapy) break;
         }
@@ -107,16 +125,160 @@ static void resist(Client *c, int *x, int *y)
         *y = ab - h + 1;
 }
 
-static void event(ObEvent *e, void *foo)
+static void resist_size(Client *c, int *w, int *h, Corner corn)
 {
-    g_assert(e->type == Event_Client_Moving);
+    GList *it;
+    Client *t; /* target */
+    int lt, rb; /* my left/top and right/bottom sides */
+    int dlt, drb; /* my destination left/top and right/bottom sides */
+    int tlt, trb; /* target's left/top and right/bottom sides */
+    Rect *area;
+    int al, at, ar, ab; /* screen boundaries */
+    Client *snapx = NULL, *snapy = NULL;
+    ConfigValue resist, window_resist;
+
+    if (!config_get("resistance", Config_Integer, &resist) ||
+        resist.integer < 0) {
+        resist.integer = DEFAULT_RESISTANCE;
+        config_set("resistance", Config_Integer, resist);
+    }
+    if (!config_get("resistance.windows", Config_Bool, &window_resist))
+        g_assert_not_reached();
+
+    /* get the screen boundaries */
+    area = screen_area(c->desktop);
+    al = area->x;
+    at = area->y;
+    ar = al + area->width - 1;
+    ab = at + area->height - 1;
+
+    /* horizontal snapping */
+
+    lt = c->frame->area.x;
+    rb = lt + c->frame->area.width - 1;
+
+    /* snap to other windows */
+    if (window_resist.bool) {
+        for (it = stacking_list; !snapx && it != NULL; it = it->next) {
+            t = it->data;
 
-    resist(e->data.c.client, &e->data.c.num[0], &e->data.c.num[1]);
+            /* don't snap to invisibles or ourself */
+            if (!t->frame->visible || t == c) continue;
+
+            switch (corn) {
+            case Corner_TopLeft:
+            case Corner_BottomLeft:
+                dlt = lt;
+                drb = rb + *w - c->frame->area.width;
+                tlt = t->frame->area.x;
+                if (rb < tlt && drb >= tlt && drb < tlt + resist.integer)
+                    *w = tlt - lt, snapx = t;
+                break;
+            case Corner_TopRight:
+            case Corner_BottomRight:
+                dlt = lt - *w + c->frame->area.width;
+                drb = rb;
+                trb = t->frame->area.x + t->frame->area.width - 1;
+                if (lt > trb && dlt <= trb && dlt > trb - resist.integer)
+                    *w = rb - trb, snapx = t;
+                break;
+            }
+        }
+    }
+
+    /* snap to screen edges */
+    switch (corn) {
+    case Corner_TopLeft:
+    case Corner_BottomLeft:
+        dlt = lt;
+        drb = rb + *w - c->frame->area.width;
+        if (rb <= ar && drb > ar && drb <= ar + resist.integer)
+            *w = ar - lt + 1;
+        break;
+    case Corner_TopRight:
+    case Corner_BottomRight:
+        dlt = lt - *w + c->frame->area.width;
+        drb = rb;
+        if (lt >= al && dlt < al && dlt >= al - resist.integer)
+            *w = rb - al + 1;
+        break;
+    }
+
+    /* vertical snapping */
+
+    lt = c->frame->area.y;
+    rb = lt + c->frame->area.height - 1;
+
+    /* snap to other windows */
+    if (window_resist.bool) {
+        for (it = stacking_list; !snapy && it != NULL; it = it->next) {
+            t = it->data;
+
+            /* don't snap to invisibles or ourself */
+            if (!t->frame->visible || t == c) continue;
+
+            switch (corn) {
+            case Corner_TopLeft:
+            case Corner_TopRight:
+                dlt = lt;
+                drb = rb + *h - c->frame->area.height;
+                tlt = t->frame->area.y;
+                if (rb < tlt && drb >= tlt && drb < tlt + resist.integer)
+                    *h = tlt - lt, snapy = t;
+                break;
+            case Corner_BottomLeft:
+            case Corner_BottomRight:
+                dlt = lt - *h + c->frame->area.height;
+                drb = rb;
+                trb = t->frame->area.y + t->frame->area.height - 1;
+                if (lt > trb && dlt <= trb && dlt > trb - resist.integer)
+                    *h = rb - trb, snapy = t;
+                break;
+            }
+        }
+    }
+
+    /* snap to screen edges */
+    switch (corn) {
+    case Corner_TopLeft:
+    case Corner_TopRight:
+        dlt = lt;
+        drb = rb + *h - c->frame->area.height;
+        if (rb <= ab && drb > ab && drb <= ab + resist.integer)
+            *h = ab - lt + 1;
+        break;
+    case Corner_BottomLeft:
+    case Corner_BottomRight:
+        dlt = lt - *h + c->frame->area.height;
+        drb = rb;
+        if (lt >= at && dlt < at && dlt >= at - resist.integer)
+            *h = rb - at + 1;
+        break;
+    }
+
+    /* round down for size increments */
+    *w -= c->frame->area.width + c->frame->size.left + c->frame->size.right;
+    *w = *w / c->size_inc.width * c->size_inc.width;
+    *w += c->frame->area.width + c->frame->size.left + c->frame->size.right;
+
+    *h -= c->frame->area.height + c->frame->size.top + c->frame->size.bottom;
+    *h = *h / c->size_inc.height * c->size_inc.height;
+    *h += c->frame->area.height + c->frame->size.top + c->frame->size.bottom;
+}
+
+static void event(ObEvent *e, void *foo)
+{
+    if (e->type == Event_Client_Moving)
+        resist_move(e->data.c.client, &e->data.c.num[0], &e->data.c.num[1]);
+    else if (e->type == Event_Client_Resizing)
+        resist_size(e->data.c.client, &e->data.c.num[0], &e->data.c.num[1],
+                    e->data.c.num[2]);
 }
 
 void plugin_startup()
 {
-    dispatch_register(Event_Client_Moving, (EventHandler)event, NULL);
+    dispatch_register(Event_Client_Moving | Event_Client_Resizing,
+                      (EventHandler)event, NULL);
 }
 
 void plugin_shutdown()
This page took 0.024769 seconds and 4 git commands to generate.