diff --git a/data/rc.xsd b/data/rc.xsd
index 75dd660e8..c15043ca2 100644
--- a/data/rc.xsd
+++ b/data/rc.xsd
@@ -176,6 +176,8 @@
+
+
diff --git a/openbox/actions/growtoedge.c b/openbox/actions/growtoedge.c
index fa1b2c7ed..b4a2b927b 100644
--- a/openbox/actions/growtoedge.c
+++ b/openbox/actions/growtoedge.c
@@ -9,6 +9,8 @@ typedef struct {
ObDirection dir;
gboolean shrink;
gboolean fill;
+ gboolean once;
+ gboolean strict;
} Options;
static gpointer setup_grow_func(xmlNodePtr node);
@@ -62,6 +64,12 @@ static gpointer setup_func(xmlNodePtr node)
g_free(s);
}
+ if ((n = obt_xml_find_node(node, "once")))
+ o->once = obt_xml_node_bool(n);
+
+ if ((n = obt_xml_find_node(node, "strict")))
+ o->strict = obt_xml_node_bool(n);
+
return o;
}
@@ -207,7 +215,9 @@ static gboolean run_func(ObActionsData *data, gpointer options)
/* If all the edges are blocked, then allow them to jump past their
current block points. */
- do_grow_all_edges(data, CLIENT_RESIZE_GROW);
+ if (!o->once)
+ do_grow_all_edges(data, CLIENT_RESIZE_GROW);
+
return FALSE;
}
@@ -215,7 +225,13 @@ static gboolean run_func(ObActionsData *data, gpointer options)
gint x, y, w, h;
/* Try grow. */
- client_find_resize_directional(data->client,
+ if (o->once)
+ client_find_resize_directional(data->client,
+ o->dir,
+ CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE,
+ &x, &y, &w, &h);
+ else
+ client_find_resize_directional(data->client,
o->dir,
CLIENT_RESIZE_GROW,
&x, &y, &w, &h);
@@ -224,7 +240,11 @@ static gboolean run_func(ObActionsData *data, gpointer options)
return FALSE;
}
- /* We couldn't grow, so try shrink! */
+ /* We couldn't grow, so try shrink!
+ Except when on strict mode. */
+ if (o->strict)
+ return FALSE;
+
ObDirection opposite =
(o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
(o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
@@ -278,6 +298,8 @@ static gpointer setup_north_func(xmlNodePtr node)
Options *o = g_slice_new0(Options);
o->shrink = FALSE;
o->dir = OB_DIRECTION_NORTH;
+ o->once = FALSE;
+ o->strict = FALSE;
return o;
}
@@ -286,6 +308,8 @@ static gpointer setup_south_func(xmlNodePtr node)
Options *o = g_slice_new0(Options);
o->shrink = FALSE;
o->dir = OB_DIRECTION_SOUTH;
+ o->once = FALSE;
+ o->strict = FALSE;
return o;
}
@@ -294,6 +318,8 @@ static gpointer setup_east_func(xmlNodePtr node)
Options *o = g_slice_new0(Options);
o->shrink = FALSE;
o->dir = OB_DIRECTION_EAST;
+ o->once = FALSE;
+ o->strict = FALSE;
return o;
}
@@ -302,5 +328,7 @@ static gpointer setup_west_func(xmlNodePtr node)
Options *o = g_slice_new0(Options);
o->shrink = FALSE;
o->dir = OB_DIRECTION_WEST;
+ o->once = FALSE;
+ o->strict = FALSE;
return o;
}
diff --git a/openbox/actions/movetoedge.c b/openbox/actions/movetoedge.c
index ef5b69201..e3d668597 100644
--- a/openbox/actions/movetoedge.c
+++ b/openbox/actions/movetoedge.c
@@ -7,6 +7,7 @@
typedef struct {
ObDirection dir;
+ gboolean once;
} Options;
static gpointer setup_func(xmlNodePtr node);
@@ -53,6 +54,9 @@ static gpointer setup_func(xmlNodePtr node)
g_free(s);
}
+ if ((n = obt_xml_find_node(node, "once")))
+ o->once = obt_xml_node_bool(n);
+
return o;
}
@@ -69,7 +73,11 @@ static gboolean run_func(ObActionsData *data, gpointer options)
if (data->client) {
gint x, y;
- client_find_move_directional(data->client, o->dir, &x, &y);
+ if (o->once)
+ client_find_move_directional(data->client, o->dir, CLIENT_MOVE_MOVE_IF_NOT_ON_EDGE, &x, &y);
+ else
+ client_find_move_directional(data->client, o->dir, CLIENT_MOVE_MOVE, &x, &y);
+
if (x != data->client->area.x || y != data->client->area.y) {
actions_client_move(data, TRUE);
client_move(data->client, x, y);
@@ -85,6 +93,7 @@ static gpointer setup_north_func(xmlNodePtr node)
{
Options *o = g_slice_new0(Options);
o->dir = OB_DIRECTION_NORTH;
+ o->once = FALSE;
return o;
}
@@ -92,6 +101,7 @@ static gpointer setup_south_func(xmlNodePtr node)
{
Options *o = g_slice_new0(Options);
o->dir = OB_DIRECTION_SOUTH;
+ o->once = FALSE;
return o;
}
@@ -99,6 +109,7 @@ static gpointer setup_east_func(xmlNodePtr node)
{
Options *o = g_slice_new0(Options);
o->dir = OB_DIRECTION_EAST;
+ o->once = FALSE;
return o;
}
@@ -106,6 +117,7 @@ static gpointer setup_west_func(xmlNodePtr node)
{
Options *o = g_slice_new0(Options);
o->dir = OB_DIRECTION_WEST;
+ o->once = FALSE;
return o;
}
diff --git a/openbox/client.c b/openbox/client.c
index 5e6569e0e..ddc5afbc7 100644
--- a/openbox/client.c
+++ b/openbox/client.c
@@ -4468,7 +4468,7 @@ void client_find_edge_directional(ObClient *self, ObDirection dir,
g_slice_free(Rect, a);
}
-void client_find_move_directional(ObClient *self, ObDirection dir,
+void client_find_move_directional(ObClient *self, ObDirection dir, ObClientDirectionalMoveType move_type,
gint *x, gint *y)
{
gint head, size;
@@ -4478,24 +4478,52 @@ void client_find_move_directional(ObClient *self, ObDirection dir,
switch (dir) {
case OB_DIRECTION_EAST:
head = RECT_RIGHT(self->frame->area);
+ switch (move_type) {
+ case CLIENT_MOVE_MOVE_IF_NOT_ON_EDGE:
+ head -= 1;
+ break;
+ case CLIENT_MOVE_MOVE:
+ break;
+ }
size = self->frame->area.width;
e_start = RECT_TOP(self->frame->area);
e_size = self->frame->area.height;
break;
case OB_DIRECTION_WEST:
head = RECT_LEFT(self->frame->area);
+ switch (move_type) {
+ case CLIENT_MOVE_MOVE_IF_NOT_ON_EDGE:
+ head += 1;
+ break;
+ case CLIENT_MOVE_MOVE:
+ break;
+ }
size = self->frame->area.width;
e_start = RECT_TOP(self->frame->area);
e_size = self->frame->area.height;
break;
case OB_DIRECTION_NORTH:
head = RECT_TOP(self->frame->area);
+ switch (move_type) {
+ case CLIENT_MOVE_MOVE_IF_NOT_ON_EDGE:
+ head += 1;
+ break;
+ case CLIENT_MOVE_MOVE:
+ break;
+ }
size = self->frame->area.height;
e_start = RECT_LEFT(self->frame->area);
e_size = self->frame->area.width;
break;
case OB_DIRECTION_SOUTH:
head = RECT_BOTTOM(self->frame->area);
+ switch (move_type) {
+ case CLIENT_MOVE_MOVE_IF_NOT_ON_EDGE:
+ head -= 1;
+ break;
+ case CLIENT_MOVE_MOVE:
+ break;
+ }
size = self->frame->area.height;
e_start = RECT_LEFT(self->frame->area);
e_size = self->frame->area.width;
@@ -4506,6 +4534,7 @@ void client_find_move_directional(ObClient *self, ObDirection dir,
client_find_edge_directional(self, dir, head, size,
e_start, e_size, &e, &near);
+
*x = self->frame->area.x;
*y = self->frame->area.y;
switch (dir) {
diff --git a/openbox/client.h b/openbox/client.h
index 11a014000..1568aa0a1 100644
--- a/openbox/client.h
+++ b/openbox/client.h
@@ -487,7 +487,13 @@ void client_find_edge_directional(ObClient *self, ObDirection dir,
gint my_head, gint my_tail,
gint my_edge_start, gint my_edge_size,
gint *dest, gboolean *near_edge);
-void client_find_move_directional(ObClient *self, ObDirection dir,
+
+typedef enum {
+ CLIENT_MOVE_MOVE,
+ CLIENT_MOVE_MOVE_IF_NOT_ON_EDGE,
+} ObClientDirectionalMoveType;
+
+void client_find_move_directional(ObClient *self, ObDirection dir, ObClientDirectionalMoveType move_type,
gint *x, gint *y);
typedef enum {
diff --git a/openbox/moveresize.c b/openbox/moveresize.c
index d12a64de5..3f20c5d68 100644
--- a/openbox/moveresize.c
+++ b/openbox/moveresize.c
@@ -694,7 +694,7 @@ static void move_with_keys(KeySym sym, guint state)
else /* sym == XK_Up */
dir = OB_DIRECTION_NORTH;
- client_find_move_directional(moveresize_client, dir, &x, &y);
+ client_find_move_directional(moveresize_client, dir, CLIENT_MOVE_MOVE, &x, &y);
dx = x - moveresize_client->area.x;
dy = y - moveresize_client->area.y;
} else {