]> Dogcows Code - chaz/openbox/blobdiff - openbox/actions/moveresizeto.c
Use enum value for monitor in MoveToCenter
[chaz/openbox] / openbox / actions / moveresizeto.c
index ce50e9b902b65f446c9f64dff7725824a549ace9..95de0e98a5ede7bc7209722e6797bb56af72ddc3 100644 (file)
@@ -2,7 +2,7 @@
 #include "openbox/client.h"
 #include "openbox/screen.h"
 #include "openbox/frame.h"
-#include <stdlib.h> /* for atoi */
+#include "openbox/config.h"
 
 enum {
     CURRENT_MONITOR = -1,
@@ -12,15 +12,15 @@ enum {
 };
 
 typedef struct {
-    gboolean xcenter;
-    gboolean ycenter;
-    gboolean xopposite;
-    gboolean yopposite;
-    gint x;
-    gint y;
+    GravityCoord x;
+    GravityCoord y;
     gint w;
+    gint w_denom;
     gint h;
+    gint h_denom;
     gint monitor;
+    gboolean w_sets_client_size;
+    gboolean h_sets_client_size;
 } Options;
 
 static gpointer setup_func(xmlNodePtr node);
@@ -36,54 +36,39 @@ void action_moveresizeto_startup(void)
     actions_register("MoveToCenter", setup_center_func, free_func, run_func);
 }
 
-static void parse_coord(xmlNodePtr n, gint *pos,
-                        gboolean *opposite, gboolean *center)
-{
-    gchar *s = obt_xml_node_string(n);
-    if (g_ascii_strcasecmp(s, "current") != 0) {
-        if (!g_ascii_strcasecmp(s, "center"))
-            *center = TRUE;
-        else {
-            if (s[0] == '-')
-                *opposite = TRUE;
-            if (s[0] == '-' || s[0] == '+')
-                *pos = atoi(s+1);
-            else
-                *pos = atoi(s);
-        }
-    }
-    g_free(s);
-}
-
 static gpointer setup_func(xmlNodePtr node)
 {
     xmlNodePtr n;
     Options *o;
 
     o = g_slice_new0(Options);
-    o->x = G_MININT;
-    o->y = G_MININT;
+    o->x.pos = G_MININT;
+    o->y.pos = G_MININT;
     o->w = G_MININT;
     o->h = G_MININT;
     o->monitor = CURRENT_MONITOR;
 
     if ((n = obt_xml_find_node(node, "x")))
-        parse_coord(n, &o->x, &o->xopposite, &o->xcenter);
+        config_parse_gravity_coord(n, &o->x);
 
     if ((n = obt_xml_find_node(node, "y")))
-        parse_coord(n, &o->y, &o->yopposite, &o->ycenter);
+        config_parse_gravity_coord(n, &o->y);
 
     if ((n = obt_xml_find_node(node, "width"))) {
         gchar *s = obt_xml_node_string(n);
         if (g_ascii_strcasecmp(s, "current") != 0)
-            o->w = obt_xml_node_int(n);
+            config_parse_relative_number(s, &o->w, &o->w_denom);
         g_free(s);
+
+        obt_xml_attr_bool(n, "client", &o->w_sets_client_size);
     }
     if ((n = obt_xml_find_node(node, "height"))) {
         gchar *s = obt_xml_node_string(n);
         if (g_ascii_strcasecmp(s, "current") != 0)
-            o->h = obt_xml_node_int(n);
+            config_parse_relative_number(s, &o->h, &o->h_denom);
         g_free(s);
+
+        obt_xml_attr_bool(n, "client", &o->h_sets_client_size);
     }
 
     if ((n = obt_xml_find_node(node, "monitor"))) {
@@ -139,11 +124,32 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         area = screen_area(c->desktop, mon, NULL);
         carea = screen_area(c->desktop, cmon, NULL);
 
+        /* find a target size for the client/frame. */
         w = o->w;
-        if (w == G_MININT) w = c->area.width;
+        if (w == G_MININT) { /* not given, so no-op with current value */
+            if (o->w_sets_client_size)
+                w = c->area.width;
+            else
+                w = c->frame->area.width;
+        }
+        else if (o->w_denom) /* used for eg. "1/3" or "55%" */
+            w = (w * area->width) / o->w_denom;
 
         h = o->h;
-        if (h == G_MININT) h = c->area.height;
+        if (h == G_MININT) {
+            if (o->h_sets_client_size)
+                h = c->area.height;
+            else
+                h = c->frame->area.height;
+        }
+        else if (o->h_denom)
+            h = (h * area->height) / o->h_denom;
+
+        /* get back to the client's size. */
+        if (!o->w_sets_client_size)
+            w -= c->frame->size.left + c->frame->size.right;
+        if (!o->h_sets_client_size)
+            h -= c->frame->size.top + c->frame->size.bottom;
 
         /* it might not be able to resize how they requested, so find out what
            it will actually be resized to */
@@ -155,16 +161,25 @@ static gboolean run_func(ObActionsData *data, gpointer options)
         w += c->frame->size.left + c->frame->size.right;
         h += c->frame->size.top + c->frame->size.bottom;
 
-        x = o->x;
-        if (o->xcenter) x = (area->width - w) / 2;
-        else if (x == G_MININT) x = c->frame->area.x - carea->x;
-        else if (o->xopposite) x = area->width - w - x;
+        /* get the position */
+        x = o->x.pos;
+        if (o->x.denom) /* relative positions */
+            x = (x * area->width) / o->x.denom;
+        if (o->x.center) x = (area->width - w) / 2;
+        else if (x == G_MININT) /* not specified */
+            x = c->frame->area.x - carea->x;
+        else if (o->x.opposite) /* value relative to right edge instead of left */
+            x = area->width - w - x;
         x += area->x;
 
-        y = o->y;
-        if (o->ycenter) y = (area->height - h) / 2;
-        else if (y == G_MININT) y = c->frame->area.y - carea->y;
-        else if (o->yopposite) y = area->height - h - y;
+        y = o->y.pos;
+        if (o->y.denom)
+            y = (y * area->height) / o->y.denom;
+        if (o->y.center) y = (area->height - h) / 2;
+        else if (y == G_MININT)
+            y = c->frame->area.y - carea->y;
+        else if (o->y.opposite)
+            y = area->height - h - y;
         y += area->y;
 
         /* get the client's size back */
@@ -193,12 +208,12 @@ static gpointer setup_center_func(xmlNodePtr node)
     Options *o;
 
     o = g_slice_new0(Options);
-    o->x = G_MININT;
-    o->y = G_MININT;
+    o->x.pos = G_MININT;
+    o->y.pos = G_MININT;
     o->w = G_MININT;
     o->h = G_MININT;
-    o->monitor = -1;
-    o->xcenter = TRUE;
-    o->ycenter = TRUE;
+    o->monitor = CURRENT_MONITOR;
+    o->x.center = TRUE;
+    o->y.center = TRUE;
     return o;
 }
This page took 0.02007 seconds and 4 git commands to generate.