summaryrefslogtreecommitdiff
path: root/openbox/actions
diff options
context:
space:
mode:
Diffstat (limited to 'openbox/actions')
-rw-r--r--openbox/actions/desktop.c349
-rw-r--r--openbox/actions/growtoedge.c146
-rw-r--r--openbox/actions/if.c22
-rw-r--r--openbox/actions/resize.c7
-rw-r--r--openbox/actions/showdesktop.c39
-rw-r--r--openbox/actions/showmenu.c84
6 files changed, 328 insertions, 319 deletions
diff --git a/openbox/actions/desktop.c b/openbox/actions/desktop.c
index 8dadf550..c2f73c6b 100644
--- a/openbox/actions/desktop.c
+++ b/openbox/actions/desktop.c
@@ -26,131 +26,62 @@ typedef struct {
} u;
gboolean send;
gboolean follow;
- gboolean interactive;
} Options;
-static gpointer setup_go_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
-static gpointer setup_send_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
+static gpointer setup_func(xmlNodePtr node);
+static gpointer setup_send_func(xmlNodePtr node);
static void free_func(gpointer o);
static gboolean run_func(ObActionsData *data, gpointer options);
-static gboolean i_pre_func(guint state, gpointer options);
-static gboolean i_input_func(guint initial_state,
- XEvent *e,
- ObtIC *ic,
- gpointer options,
- gboolean *used);
-static void i_post_func(gpointer options);
-
/* 3.4-compatibility */
static gpointer setup_go_last_func(xmlNodePtr node);
static gpointer setup_send_last_func(xmlNodePtr node);
static gpointer setup_go_abs_func(xmlNodePtr node);
-static gpointer setup_go_next_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
-static gpointer setup_send_next_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
-static gpointer setup_go_prev_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
-static gpointer setup_send_prev_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
-static gpointer setup_go_left_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
-static gpointer setup_send_left_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
-static gpointer setup_go_right_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
-static gpointer setup_send_right_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
-static gpointer setup_go_up_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
-static gpointer setup_send_up_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
-static gpointer setup_go_down_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
-static gpointer setup_send_down_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post);
+static gpointer setup_go_next_func(xmlNodePtr node);
+static gpointer setup_send_next_func(xmlNodePtr node);
+static gpointer setup_go_prev_func(xmlNodePtr node);
+static gpointer setup_send_prev_func(xmlNodePtr node);
+static gpointer setup_go_left_func(xmlNodePtr node);
+static gpointer setup_send_left_func(xmlNodePtr node);
+static gpointer setup_go_right_func(xmlNodePtr node);
+static gpointer setup_send_right_func(xmlNodePtr node);
+static gpointer setup_go_up_func(xmlNodePtr node);
+static gpointer setup_send_up_func(xmlNodePtr node);
+static gpointer setup_go_down_func(xmlNodePtr node);
+static gpointer setup_send_down_func(xmlNodePtr node);
void action_desktop_startup(void)
{
- actions_register_i("GoToDesktop", setup_go_func, free_func, run_func);
- actions_register_i("SendToDesktop", setup_send_func, free_func, run_func);
+ actions_register("GoToDesktop", setup_func, free_func, run_func);
+ actions_register("SendToDesktop", setup_send_func, free_func, run_func);
/* 3.4-compatibility */
actions_register("DesktopLast", setup_go_last_func, free_func, run_func);
actions_register("SendToDesktopLast", setup_send_last_func,
free_func, run_func);
actions_register("Desktop", setup_go_abs_func, free_func, run_func);
- actions_register_i("DesktopNext", setup_go_next_func, free_func, run_func);
- actions_register_i("SendToDesktopNext", setup_send_next_func,
- free_func, run_func);
- actions_register_i("DesktopPrevious", setup_go_prev_func,
- free_func, run_func);
- actions_register_i("SendToDesktopPrevious", setup_send_prev_func,
- free_func, run_func);
- actions_register_i("DesktopLeft", setup_go_left_func, free_func, run_func);
- actions_register_i("SendToDesktopLeft", setup_send_left_func,
- free_func, run_func);
- actions_register_i("DesktopRight", setup_go_right_func,
- free_func, run_func);
- actions_register_i("SendToDesktopRight", setup_send_right_func,
- free_func, run_func);
- actions_register_i("DesktopUp", setup_go_up_func, free_func, run_func);
- actions_register_i("SendToDesktopUp", setup_send_up_func,
- free_func, run_func);
- actions_register_i("DesktopDown", setup_go_down_func, free_func, run_func);
- actions_register_i("SendToDesktopDown", setup_send_down_func,
- free_func, run_func);
+ actions_register("DesktopNext", setup_go_next_func, free_func, run_func);
+ actions_register("SendToDesktopNext", setup_send_next_func,
+ free_func, run_func);
+ actions_register("DesktopPrevious", setup_go_prev_func,
+ free_func, run_func);
+ actions_register("SendToDesktopPrevious", setup_send_prev_func,
+ free_func, run_func);
+ actions_register("DesktopLeft", setup_go_left_func, free_func, run_func);
+ actions_register("SendToDesktopLeft", setup_send_left_func,
+ free_func, run_func);
+ actions_register("DesktopRight", setup_go_right_func,
+ free_func, run_func);
+ actions_register("SendToDesktopRight", setup_send_right_func,
+ free_func, run_func);
+ actions_register("DesktopUp", setup_go_up_func, free_func, run_func);
+ actions_register("SendToDesktopUp", setup_send_up_func,
+ free_func, run_func);
+ actions_register("DesktopDown", setup_go_down_func, free_func, run_func);
+ actions_register("SendToDesktopDown", setup_send_down_func,
+ free_func, run_func);
}
-static gpointer setup_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_func(xmlNodePtr node)
{
xmlNodePtr n;
Options *o;
@@ -211,36 +142,12 @@ static gpointer setup_func(xmlNodePtr node,
return o;
}
-
-static gpointer setup_go_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
-{
- Options *o;
-
- o = setup_func(node, pre, input, cancel, post);
- if (o->type == RELATIVE) {
- o->interactive = TRUE;
- *pre = i_pre_func;
- *input = i_input_func;
- *post = i_post_func;
- }
-
- return o;
-}
-
-static gpointer setup_send_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_send_func(xmlNodePtr node)
{
xmlNodePtr n;
Options *o;
- o = setup_func(node, pre, input, cancel, post);
+ o = setup_func(node);
if ((n = obt_xml_find_node(node, "desktop"))) {
/* 3.4 compatibility */
o->u.abs.desktop = obt_xml_node_int(n) - 1;
@@ -252,13 +159,6 @@ static gpointer setup_send_func(xmlNodePtr node,
if ((n = obt_xml_find_node(node, "follow")))
o->follow = obt_xml_node_bool(n);
- if (o->type == RELATIVE && o->follow) {
- o->interactive = TRUE;
- *pre = i_pre_func;
- *input = i_input_func;
- *post = i_post_func;
- }
-
return o;
}
@@ -310,62 +210,7 @@ static gboolean run_func(ObActionsData *data, gpointer options)
actions_client_move(data, FALSE);
}
- return o->interactive;
-}
-
-static gboolean i_input_func(guint initial_state,
- XEvent *e,
- ObtIC *ic,
- gpointer options,
- gboolean *used)
-{
- guint mods, initial_mods;
-
- initial_mods = obt_keyboard_only_modmasks(initial_state);
- mods = obt_keyboard_only_modmasks(e->xkey.state);
- if (e->type == KeyRelease) {
- /* remove from the state the mask of the modifier key being
- released, if it is a modifier key being released that is */
- mods &= ~obt_keyboard_keyevent_to_modmask(e);
- }
-
- if (e->type == KeyPress) {
- KeySym sym = obt_keyboard_keypress_to_keysym(e);
-
- /* Escape cancels no matter what */
- if (sym == XK_Escape)
- return FALSE;
-
- /* There were no modifiers and they pressed enter */
- else if ((sym == XK_Return || sym == XK_KP_Enter) && !initial_mods)
- return FALSE;
- }
- /* They released the modifiers */
- else if (e->type == KeyRelease && initial_mods && !(mods & initial_mods))
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean i_pre_func(guint initial_state, gpointer options)
-{
- guint initial_mods = obt_keyboard_only_modmasks(initial_state);
- if (!initial_mods) {
- Options *o = options;
- o->interactive = FALSE;
- return FALSE;
- }
- else {
- screen_show_desktop_popup(screen_desktop, TRUE);
- return TRUE;
- }
-}
-
-static void i_post_func(gpointer options)
-{
- screen_hide_desktop_popup();
+ return FALSE;
}
/* 3.4-compatilibity */
@@ -407,10 +252,7 @@ static gpointer setup_go_abs_func(xmlNodePtr node)
}
static void setup_rel(Options *o, xmlNodePtr node, gboolean lin,
- ObDirection dir,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsIPostFunc *post)
+ ObDirection dir)
{
xmlNodePtr n;
@@ -421,149 +263,88 @@ static void setup_rel(Options *o, xmlNodePtr node, gboolean lin,
if ((n = obt_xml_find_node(node, "wrap")))
o->u.rel.wrap = obt_xml_node_bool(n);
-
- if (input) {
- o->interactive = TRUE;
- *pre = i_pre_func;
- *input = i_input_func;
- *post = i_post_func;
- }
}
-static gpointer setup_go_next_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_go_next_func(xmlNodePtr node)
{
Options *o = g_slice_new0(Options);
- setup_rel(o, node, TRUE, OB_DIRECTION_EAST, pre, input, post);
+ setup_rel(o, node, TRUE, OB_DIRECTION_EAST);
return o;
}
-static gpointer setup_send_next_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_send_next_func(xmlNodePtr node)
{
Options *o = setup_follow(node);
- setup_rel(o, node, TRUE, OB_DIRECTION_EAST,
- pre, (o->follow ? input : NULL), post);
+ setup_rel(o, node, TRUE, OB_DIRECTION_EAST);
return o;
}
-static gpointer setup_go_prev_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_go_prev_func(xmlNodePtr node)
{
Options *o = g_slice_new0(Options);
- setup_rel(o, node, TRUE, OB_DIRECTION_WEST, pre, input, post);
+ setup_rel(o, node, TRUE, OB_DIRECTION_WEST);
return o;
}
-static gpointer setup_send_prev_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_send_prev_func(xmlNodePtr node)
{
Options *o = setup_follow(node);
- setup_rel(o, node, TRUE, OB_DIRECTION_WEST,
- pre, (o->follow ? input : NULL), post);
+ setup_rel(o, node, TRUE, OB_DIRECTION_WEST);
return o;
}
-static gpointer setup_go_left_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_go_left_func(xmlNodePtr node)
{
Options *o = g_slice_new0(Options);
- setup_rel(o, node, FALSE, OB_DIRECTION_WEST, pre, input, post);
+ setup_rel(o, node, FALSE, OB_DIRECTION_WEST);
return o;
}
-static gpointer setup_send_left_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_send_left_func(xmlNodePtr node)
{
Options *o = setup_follow(node);
- setup_rel(o, node, FALSE, OB_DIRECTION_WEST,
- pre, (o->follow ? input : NULL), post);
+ setup_rel(o, node, FALSE, OB_DIRECTION_WEST);
return o;
}
-static gpointer setup_go_right_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_go_right_func(xmlNodePtr node)
{
Options *o = g_slice_new0(Options);
- setup_rel(o, node, FALSE, OB_DIRECTION_EAST, pre, input, post);
+ setup_rel(o, node, FALSE, OB_DIRECTION_EAST);
return o;
}
-static gpointer setup_send_right_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_send_right_func(xmlNodePtr node)
{
Options *o = setup_follow(node);
- setup_rel(o, node, FALSE, OB_DIRECTION_EAST,
- pre, (o->follow ? input : NULL), post);
+ setup_rel(o, node, FALSE, OB_DIRECTION_EAST);
return o;
}
-static gpointer setup_go_up_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_go_up_func(xmlNodePtr node)
{
Options *o = g_slice_new0(Options);
- setup_rel(o, node, FALSE, OB_DIRECTION_NORTH, pre, input, post);
+ setup_rel(o, node, FALSE, OB_DIRECTION_NORTH);
return o;
}
-static gpointer setup_send_up_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_send_up_func(xmlNodePtr node)
{
Options *o = setup_follow(node);
- setup_rel(o, node, FALSE, OB_DIRECTION_NORTH,
- pre, (o->follow ? input : NULL), post);
+ setup_rel(o, node, FALSE, OB_DIRECTION_NORTH);
return o;
}
-static gpointer setup_go_down_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_go_down_func(xmlNodePtr node)
{
Options *o = g_slice_new0(Options);
- setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH, pre, input, post);
+ setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH);
return o;
}
-static gpointer setup_send_down_func(xmlNodePtr node,
- ObActionsIPreFunc *pre,
- ObActionsIInputFunc *input,
- ObActionsICancelFunc *cancel,
- ObActionsIPostFunc *post)
+static gpointer setup_send_down_func(xmlNodePtr node)
{
Options *o = setup_follow(node);
- setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH,
- pre, (o->follow ? input : NULL), post);
+ setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH);
return o;
}
diff --git a/openbox/actions/growtoedge.c b/openbox/actions/growtoedge.c
index d5a7bfdd..acfbcfab 100644
--- a/openbox/actions/growtoedge.c
+++ b/openbox/actions/growtoedge.c
@@ -8,9 +8,11 @@
typedef struct {
ObDirection dir;
gboolean shrink;
+ gboolean fill;
} Options;
-static gpointer setup_func(xmlNodePtr node);
+static gpointer setup_grow_func(xmlNodePtr node);
+static gpointer setup_fill_func(xmlNodePtr node);
static gpointer setup_shrink_func(xmlNodePtr node);
static void free_func(gpointer o);
static gboolean run_func(ObActionsData *data, gpointer options);
@@ -22,7 +24,9 @@ static gpointer setup_west_func(xmlNodePtr node);
void action_growtoedge_startup(void)
{
- actions_register("GrowToEdge", setup_func,
+ actions_register("GrowToEdge", setup_grow_func,
+ free_func, run_func);
+ actions_register("GrowToFill", setup_fill_func,
free_func, run_func);
actions_register("ShrinkToEdge", setup_shrink_func,
free_func, run_func);
@@ -40,7 +44,6 @@ static gpointer setup_func(xmlNodePtr node)
o = g_slice_new0(Options);
o->dir = OB_DIRECTION_NORTH;
- o->shrink = FALSE;
if ((n = obt_xml_find_node(node, "direction"))) {
gchar *s = obt_xml_node_string(n);
@@ -62,12 +65,35 @@ static gpointer setup_func(xmlNodePtr node)
return o;
}
+static gpointer setup_grow_func(xmlNodePtr node)
+{
+ Options *o;
+
+ o = setup_func(node);
+ o->shrink = FALSE;
+ o->fill = FALSE;
+
+ return o;
+}
+
+static gpointer setup_fill_func(xmlNodePtr node)
+{
+ Options *o;
+
+ o = setup_func(node);
+ o->shrink = FALSE;
+ o->fill = TRUE;
+
+ return o;
+}
+
static gpointer setup_shrink_func(xmlNodePtr node)
{
Options *o;
o = setup_func(node);
o->shrink = TRUE;
+ o->fill = FALSE;
return o;
}
@@ -97,6 +123,58 @@ static gboolean do_grow(ObActionsData *data, gint x, gint y, gint w, gint h)
return FALSE;
}
+static gboolean do_grow_all_edges(ObActionsData* data,
+ ObClientDirectionalResizeType resize_type)
+{
+ gint x, y, w, h;
+ gint temp_x, temp_y, temp_w, temp_h;
+
+ client_find_resize_directional(data->client,
+ OB_DIRECTION_NORTH,
+ resize_type,
+ &temp_x, &temp_y, &temp_w, &temp_h);
+ y = temp_y;
+ h = temp_h;
+
+ client_find_resize_directional(data->client,
+ OB_DIRECTION_SOUTH,
+ resize_type,
+ &temp_x, &temp_y, &temp_w, &temp_h);
+ h += temp_h - data->client->area.height;
+
+
+ client_find_resize_directional(data->client,
+ OB_DIRECTION_WEST,
+ resize_type,
+ &temp_x, &temp_y, &temp_w, &temp_h);
+ x = temp_x;
+ w = temp_w;
+
+ client_find_resize_directional(data->client,
+ OB_DIRECTION_EAST,
+ resize_type,
+ &temp_x, &temp_y, &temp_w, &temp_h);
+ w += temp_w - data->client->area.width;
+
+ /* When filling, we allow the window to move to an arbitrary x/y
+ position, since we'll be growing the other edge as well. */
+ int lw, lh;
+ client_try_configure(data->client, &x, &y, &w, &h, &lw, &lh, TRUE);
+
+ if (x == data->client->area.x &&
+ y == data->client->area.y &&
+ w == data->client->area.width &&
+ h == data->client->area.height)
+ {
+ return FALSE;
+ }
+
+ actions_client_move(data, TRUE);
+ client_move_resize(data->client, x, y, w, h);
+ actions_client_move(data, FALSE);
+ return TRUE;
+}
+
static void free_func(gpointer o)
{
g_slice_free(Options, o);
@@ -106,34 +184,62 @@ static void free_func(gpointer o)
static gboolean run_func(ObActionsData *data, gpointer options)
{
Options *o = options;
- gint x, y, w, h;
- ObDirection opp;
- gint half;
- if (!data->client ||
- /* don't allow vertical resize if shaded */
- ((o->dir == OB_DIRECTION_NORTH || o->dir == OB_DIRECTION_SOUTH) &&
- data->client->shaded))
- {
+ if (!data->client)
+ return FALSE;
+
+ gboolean doing_vertical_resize =
+ o->dir == OB_DIRECTION_NORTH ||
+ o->dir == OB_DIRECTION_SOUTH ||
+ o->fill;
+ if (data->client->shaded && doing_vertical_resize)
+ return FALSE;
+
+ if (o->fill) {
+ if (o->shrink) {
+ /* We don't have any implementation of shrinking for the FillToGrow
+ action. */
+ return FALSE;
+ }
+
+ if (do_grow_all_edges(data, CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE))
+ return FALSE;
+
+ /* If all the edges are blocked, then allow them to jump past their
+ current block points. */
+ do_grow_all_edges(data, CLIENT_RESIZE_GROW);
return FALSE;
}
if (!o->shrink) {
- /* try grow */
- client_find_resize_directional(data->client, o->dir, TRUE,
+ gint x, y, w, h;
+
+ /* Try grow. */
+ client_find_resize_directional(data->client,
+ o->dir,
+ CLIENT_RESIZE_GROW,
&x, &y, &w, &h);
+
if (do_grow(data, x, y, w, h))
return FALSE;
}
- /* we couldn't grow, so try shrink! */
- opp = (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
- (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
- (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST :
- OB_DIRECTION_EAST)));
- client_find_resize_directional(data->client, opp, FALSE,
+ /* We couldn't grow, so try shrink! */
+ ObDirection opposite =
+ (o->dir == OB_DIRECTION_NORTH ? OB_DIRECTION_SOUTH :
+ (o->dir == OB_DIRECTION_SOUTH ? OB_DIRECTION_NORTH :
+ (o->dir == OB_DIRECTION_EAST ? OB_DIRECTION_WEST :
+ OB_DIRECTION_EAST)));
+
+ gint x, y, w, h;
+ gint half;
+
+ client_find_resize_directional(data->client,
+ opposite,
+ CLIENT_RESIZE_SHRINK,
&x, &y, &w, &h);
- switch (opp) {
+
+ switch (opposite) {
case OB_DIRECTION_NORTH:
half = data->client->area.y + data->client->area.height / 2;
if (y > half) {
diff --git a/openbox/actions/if.c b/openbox/actions/if.c
index a083d485..a9c4094b 100644
--- a/openbox/actions/if.c
+++ b/openbox/actions/if.c
@@ -79,10 +79,9 @@ typedef struct {
} Query;
typedef struct {
- GArray* queries;
+ GArray *queries;
GSList *thenacts;
GSList *elseacts;
- gboolean stop;
} Options;
static gpointer setup_func(xmlNodePtr node);
@@ -91,6 +90,8 @@ static gboolean run_func_if(ObActionsData *data, gpointer options);
static gboolean run_func_stop(ObActionsData *data, gpointer options);
static gboolean run_func_foreach(ObActionsData *data, gpointer options);
+static gboolean foreach_stop;
+
void action_if_startup(void)
{
actions_register("If", setup_func, free_func, run_func_if);
@@ -313,7 +314,7 @@ static gboolean run_func_if(ObActionsData *data, gpointer options)
gboolean is_true = TRUE;
guint i;
- for (i = 0; i < o->queries->len; ++i) {
+ for (i = 0; is_true && i < o->queries->len; ++i) {
Query *q = g_array_index(o->queries, Query*, i);
ObClient *query_target = NULL;
@@ -327,7 +328,10 @@ static gboolean run_func_if(ObActionsData *data, gpointer options)
}
/* If there's no client to query, then false. */
- is_true &= query_target != NULL;
+ if (!query_target) {
+ is_true = FALSE;
+ break;
+ }
if (q->shaded_on)
is_true &= query_target->shaded;
@@ -427,14 +431,14 @@ static gboolean run_func_if(ObActionsData *data, gpointer options)
static gboolean run_func_foreach(ObActionsData *data, gpointer options)
{
GList *it;
- Options *o = options;
- o->stop = FALSE;
+ foreach_stop = FALSE;
for (it = client_list; it; it = g_list_next(it)) {
data->client = it->data;
run_func_if(data, options);
- if (o->stop) {
+ if (foreach_stop) {
+ foreach_stop = FALSE;
break;
}
}
@@ -444,11 +448,9 @@ static gboolean run_func_foreach(ObActionsData *data, gpointer options)
static gboolean run_func_stop(ObActionsData *data, gpointer options)
{
- Options *o = options;
-
/* This stops the loop above so we don't invoke actions on any more
clients */
- o->stop = TRUE;
+ foreach_stop = TRUE;
/* TRUE causes actions_run_acts to not run further actions on the current
client */
diff --git a/openbox/actions/resize.c b/openbox/actions/resize.c
index f6858d2d..fc85c0b7 100644
--- a/openbox/actions/resize.c
+++ b/openbox/actions/resize.c
@@ -2,6 +2,7 @@
#include "openbox/moveresize.h"
#include "openbox/client.h"
#include "openbox/frame.h"
+#include "openbox/screen.h"
#include "obt/prop.h"
typedef struct {
@@ -95,6 +96,12 @@ static gboolean run_func(ObActionsData *data, gpointer options)
static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
gboolean shaded)
{
+ const Rect *full = screen_physical_area_all_monitors();
+ if (cx < full->x) { cw = cw + cx - full->x; cx = full->x; }
+ if (cy < full->y) { ch = ch + cy - full->y; cy = full->y; }
+ if (cx + cw > full->x + full->width) cw = full->x + full->width - cx;
+ if (cy + ch > full->y + full->height) ch = full->y + full->height - cy;
+
/* let's make x and y client relative instead of screen relative */
x = x - cx;
y = ch - (y - cy); /* y is inverted, 0 is at the bottom of the window */
diff --git a/openbox/actions/showdesktop.c b/openbox/actions/showdesktop.c
index 6dc77d5e..3c3b2d10 100644
--- a/openbox/actions/showdesktop.c
+++ b/openbox/actions/showdesktop.c
@@ -1,17 +1,52 @@
#include "openbox/actions.h"
#include "openbox/screen.h"
+typedef struct {
+ /* If true, windows are unable to be shown while in the showing-desktop
+ state. */
+ gboolean strict;
+} Options;
+
+static gpointer setup_func(xmlNodePtr node);
+static void free_func(gpointer o);
static gboolean run_func(ObActionsData *data, gpointer options);
void action_showdesktop_startup(void)
{
- actions_register("ToggleShowDesktop", NULL, NULL, run_func);
+ actions_register("ToggleShowDesktop", setup_func, free_func, run_func);
+}
+
+static gpointer setup_func(xmlNodePtr node)
+{
+ xmlNodePtr n;
+ Options *o = g_slice_new0(Options);
+ o->strict = FALSE;
+
+ if ((n = obt_xml_find_node(node, "strict")))
+ o->strict = obt_xml_node_bool(n);
+
+ return o;
+}
+
+static void free_func(gpointer o)
+{
+ g_slice_free(Options, o);
}
/* Always return FALSE because its not interactive */
static gboolean run_func(ObActionsData *data, gpointer options)
{
- screen_show_desktop(!screen_showing_desktop, NULL);
+ Options *o = options;
+
+ ObScreenShowDestopMode show_mode;
+ if (screen_showing_desktop())
+ show_mode = SCREEN_SHOW_DESKTOP_NO;
+ else if (!o->strict)
+ show_mode = SCREEN_SHOW_DESKTOP_UNTIL_WINDOW;
+ else
+ show_mode = SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE;
+
+ screen_show_desktop(show_mode, NULL);
return FALSE;
}
diff --git a/openbox/actions/showmenu.c b/openbox/actions/showmenu.c
index 485a31d5..7411e981 100644
--- a/openbox/actions/showmenu.c
+++ b/openbox/actions/showmenu.c
@@ -1,9 +1,17 @@
#include "openbox/actions.h"
#include "openbox/menu.h"
+#include "openbox/place.h"
+#include "openbox/geom.h"
+#include "openbox/screen.h"
+#include "openbox/config.h"
#include <glib.h>
typedef struct {
- gchar *name;
+ gchar *name;
+ GravityPoint position;
+ ObPlaceMonitor monitor_type;
+ gint monitor;
+ gboolean use_position;
} Options;
static gpointer setup_func(xmlNodePtr node);
@@ -17,13 +25,50 @@ void action_showmenu_startup(void)
static gpointer setup_func(xmlNodePtr node)
{
- xmlNodePtr n;
+ xmlNodePtr n, c;
Options *o;
+ gboolean x_pos_given = FALSE;
o = g_slice_new0(Options);
+ o->monitor = -1;
if ((n = obt_xml_find_node(node, "menu")))
o->name = obt_xml_node_string(n);
+
+ if ((n = obt_xml_find_node(node, "position"))) {
+ if ((c = obt_xml_find_node(n->children, "x"))) {
+ if (!obt_xml_node_contains(c, "default")) {
+ config_parse_gravity_coord(c, &o->position.x);
+ x_pos_given = TRUE;
+ }
+ }
+
+ if (x_pos_given && (c = obt_xml_find_node(n->children, "y"))) {
+ if (!obt_xml_node_contains(c, "default")) {
+ config_parse_gravity_coord(c, &o->position.y);
+ o->use_position = TRUE;
+ }
+ }
+
+ /* unlike client placement, x/y is needed to specify a monitor,
+ * either it's under the mouse or it's in an exact actual position */
+ if (o->use_position && (c = obt_xml_find_node(n->children, "monitor"))) {
+ if (!obt_xml_node_contains(c, "default")) {
+ gchar *s = obt_xml_node_string(c);
+ if (!g_ascii_strcasecmp(s, "mouse"))
+ o->monitor_type = OB_PLACE_MONITOR_MOUSE;
+ else if (!g_ascii_strcasecmp(s, "active"))
+ o->monitor_type = OB_PLACE_MONITOR_ACTIVE;
+ else if (!g_ascii_strcasecmp(s, "primary"))
+ o->monitor_type = OB_PLACE_MONITOR_PRIMARY;
+ else if (!g_ascii_strcasecmp(s, "all"))
+ o->monitor_type = OB_PLACE_MONITOR_ALL;
+ else
+ o->monitor = obt_xml_node_int(c) - 1;
+ g_free(s);
+ }
+ }
+ }
return o;
}
@@ -38,10 +83,43 @@ static void free_func(gpointer options)
static gboolean run_func(ObActionsData *data, gpointer options)
{
Options *o = options;
+ GravityPoint position = { { 0, }, };
+ gint monitor = -1;
+
+ if (o->use_position) {
+ if (o->monitor >= 0)
+ monitor = o->monitor;
+ else switch (o->monitor_type) {
+ case OB_PLACE_MONITOR_ANY:
+ case OB_PLACE_MONITOR_PRIMARY:
+ monitor = screen_monitor_primary(FALSE);
+ break;
+ case OB_PLACE_MONITOR_MOUSE:
+ monitor = screen_monitor_pointer();
+ break;
+ case OB_PLACE_MONITOR_ACTIVE:
+ monitor = screen_monitor_active();
+ break;
+ case OB_PLACE_MONITOR_ALL:
+ monitor = screen_num_monitors;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ position = o->position;
+ } else {
+ const Rect *allmon;
+ monitor = screen_num_monitors;
+ allmon = screen_physical_area_monitor(monitor);
+ position.x.pos = data->x - allmon->x;
+ position.y.pos = data->y - allmon->y;
+ }
/* you cannot call ShowMenu from inside a menu */
if (data->uact != OB_USER_ACTION_MENU_SELECTION && o->name)
- menu_show(o->name, data->x, data->y, data->button != 0, data->client);
+ menu_show(o->name, &position, monitor,
+ data->button != 0, o->use_position, data->client);
return FALSE;
}