summaryrefslogtreecommitdiff
path: root/openbox
diff options
context:
space:
mode:
Diffstat (limited to 'openbox')
-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
-rw-r--r--openbox/client.c80
-rw-r--r--openbox/client.h13
-rw-r--r--openbox/client_menu.c12
-rw-r--r--openbox/config.c81
-rw-r--r--openbox/config.h2
-rw-r--r--openbox/dock.c16
-rw-r--r--openbox/event.c48
-rw-r--r--openbox/frame.c19
-rw-r--r--openbox/frame.h2
-rw-r--r--openbox/framerender.c76
-rw-r--r--openbox/keyboard.c2
-rw-r--r--openbox/menu.c14
-rw-r--r--openbox/menu.h4
-rw-r--r--openbox/menuframe.c56
-rw-r--r--openbox/menuframe.h5
-rw-r--r--openbox/mouse.c2
-rw-r--r--openbox/moveresize.c9
-rw-r--r--openbox/openbox.c8
-rw-r--r--openbox/place.c89
-rw-r--r--openbox/place.h3
-rw-r--r--openbox/place_overlap.c46
-rw-r--r--openbox/screen.c98
-rw-r--r--openbox/screen.h19
-rw-r--r--openbox/stacking.c64
-rw-r--r--openbox/stacking.h4
31 files changed, 846 insertions, 573 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;
}
diff --git a/openbox/client.c b/openbox/client.c
index c97abd5a..3ff278ae 100644
--- a/openbox/client.c
+++ b/openbox/client.c
@@ -2734,7 +2734,7 @@ gboolean client_should_show(ObClient *self)
{
if (self->iconic)
return FALSE;
- if (client_normal(self) && screen_showing_desktop)
+ if (client_normal(self) && screen_showing_desktop())
return FALSE;
if (self->desktop == screen_desktop || self->desktop == DESKTOP_ALL)
return TRUE;
@@ -4080,7 +4080,7 @@ gboolean client_focus(ObClient *self)
static void client_present(ObClient *self, gboolean here, gboolean raise,
gboolean unshade)
{
- if (client_normal(self) && screen_showing_desktop)
+ if (client_normal(self) && screen_showing_desktop())
screen_show_desktop(FALSE, self);
if (self->iconic)
client_iconify(self, FALSE, here, FALSE);
@@ -4535,8 +4535,9 @@ void client_find_move_directional(ObClient *self, ObDirection dir,
frame_frame_gravity(self->frame, x, y);
}
-void client_find_resize_directional(ObClient *self, ObDirection side,
- gboolean grow,
+void client_find_resize_directional(ObClient *self,
+ ObDirection side,
+ ObClientDirectionalResizeType resize_type,
gint *x, gint *y, gint *w, gint *h)
{
gint head;
@@ -4544,31 +4545,84 @@ void client_find_resize_directional(ObClient *self, ObDirection side,
gboolean near;
ObDirection dir;
+ gboolean grow;
+ switch (resize_type) {
+ case CLIENT_RESIZE_GROW:
+ grow = TRUE;
+ break;
+ case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+ grow = TRUE;
+ break;
+ case CLIENT_RESIZE_SHRINK:
+ grow = FALSE;
+ break;
+ }
+
switch (side) {
case OB_DIRECTION_EAST:
- head = RECT_RIGHT(self->frame->area) +
- (self->size_inc.width - 1) * (grow ? 1 : 0);
+ head = RECT_RIGHT(self->frame->area);
+ switch (resize_type) {
+ case CLIENT_RESIZE_GROW:
+ head += self->size_inc.width - 1;
+ break;
+ case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+ head -= 1;
+ break;
+ case CLIENT_RESIZE_SHRINK:
+ break;
+ }
+
e_start = RECT_TOP(self->frame->area);
e_size = self->frame->area.height;
dir = grow ? OB_DIRECTION_EAST : OB_DIRECTION_WEST;
break;
case OB_DIRECTION_WEST:
- head = RECT_LEFT(self->frame->area) -
- (self->size_inc.width - 1) * (grow ? 1 : 0);
+ head = RECT_LEFT(self->frame->area);
+ switch (resize_type) {
+ case CLIENT_RESIZE_GROW:
+ head -= self->size_inc.width - 1;
+ break;
+ case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+ head += 1;
+ break;
+ case CLIENT_RESIZE_SHRINK:
+ break;
+ }
+
e_start = RECT_TOP(self->frame->area);
e_size = self->frame->area.height;
dir = grow ? OB_DIRECTION_WEST : OB_DIRECTION_EAST;
break;
case OB_DIRECTION_NORTH:
- head = RECT_TOP(self->frame->area) -
- (self->size_inc.height - 1) * (grow ? 1 : 0);
+ head = RECT_TOP(self->frame->area);
+ switch (resize_type) {
+ case CLIENT_RESIZE_GROW:
+ head -= self->size_inc.height - 1;
+ break;
+ case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+ head += 1;
+ break;
+ case CLIENT_RESIZE_SHRINK:
+ break;
+ }
+
e_start = RECT_LEFT(self->frame->area);
e_size = self->frame->area.width;
dir = grow ? OB_DIRECTION_NORTH : OB_DIRECTION_SOUTH;
break;
case OB_DIRECTION_SOUTH:
- head = RECT_BOTTOM(self->frame->area) +
- (self->size_inc.height - 1) * (grow ? 1 : 0);
+ head = RECT_BOTTOM(self->frame->area);
+ switch (resize_type) {
+ case CLIENT_RESIZE_GROW:
+ head += self->size_inc.height - 1;
+ break;
+ case CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE:
+ head -= 1;
+ break;
+ case CLIENT_RESIZE_SHRINK:
+ break;
+ }
+
e_start = RECT_LEFT(self->frame->area);
e_size = self->frame->area.width;
dir = grow ? OB_DIRECTION_SOUTH : OB_DIRECTION_NORTH;
@@ -4607,7 +4661,7 @@ void client_find_resize_directional(ObClient *self, ObDirection side,
if (grow == near) --e;
delta = e - RECT_BOTTOM(self->frame->area);
*h += delta;
- break;
+ break;
default:
g_assert_not_reached();
}
diff --git a/openbox/client.h b/openbox/client.h
index 5ae2d3d2..11a01400 100644
--- a/openbox/client.h
+++ b/openbox/client.h
@@ -489,8 +489,17 @@ void client_find_edge_directional(ObClient *self, ObDirection dir,
gint *dest, gboolean *near_edge);
void client_find_move_directional(ObClient *self, ObDirection dir,
gint *x, gint *y);
-void client_find_resize_directional(ObClient *self, ObDirection side,
- gboolean grow,
+
+typedef enum {
+ CLIENT_RESIZE_GROW,
+ CLIENT_RESIZE_GROW_IF_NOT_ON_EDGE,
+ CLIENT_RESIZE_SHRINK,
+} ObClientDirectionalResizeType;
+
+/*! Moves the client area passed in to grow/shrink the given edge. */
+void client_find_resize_directional(ObClient *self,
+ ObDirection side,
+ ObClientDirectionalResizeType resize_type,
gint *x, gint *y, gint *w, gint *h);
/*! Fullscreen's or unfullscreen's the client window
diff --git a/openbox/client_menu.c b/openbox/client_menu.c
index c6cdd635..4a3b286f 100644
--- a/openbox/client_menu.c
+++ b/openbox/client_menu.c
@@ -276,7 +276,7 @@ static gboolean send_to_menu_update(ObMenuFrame *frame, gpointer data)
if ((desk == DESKTOP_ALL && c->desktop != DESKTOP_ALL) ||
(c->desktop == DESKTOP_ALL && desk == screen_desktop))
{
- e->data.normal.mask = ob_rr_theme->btn_desk->mask;
+ e->data.normal.mask = ob_rr_theme->btn_desk->unpressed_mask;
set_icon_color(e);
} else
e->data.normal.mask = NULL;
@@ -392,7 +392,7 @@ void client_menu_startup(void)
menu_add_submenu(menu, CLIENT_LAYER, LAYER_MENU_NAME);
e = menu_add_normal(menu, CLIENT_RESTORE, _("R_estore"), NULL, TRUE);
- e->data.normal.mask = ob_rr_theme->btn_max->toggled_mask;
+ e->data.normal.mask = ob_rr_theme->btn_max->unpressed_toggled_mask;
set_icon_color(e);
menu_add_normal(menu, CLIENT_MOVE, _("_Move"), NULL, TRUE);
@@ -400,15 +400,15 @@ void client_menu_startup(void)
menu_add_normal(menu, CLIENT_RESIZE, _("Resi_ze"), NULL, TRUE);
e = menu_add_normal(menu, CLIENT_ICONIFY, _("Ico_nify"), NULL, TRUE);
- e->data.normal.mask = ob_rr_theme->btn_iconify->mask;
+ e->data.normal.mask = ob_rr_theme->btn_iconify->unpressed_mask;
set_icon_color(e);
e = menu_add_normal(menu, CLIENT_MAXIMIZE, _("Ma_ximize"), NULL, TRUE);
- e->data.normal.mask = ob_rr_theme->btn_max->mask;
+ e->data.normal.mask = ob_rr_theme->btn_max->unpressed_mask;
set_icon_color(e);
e = menu_add_normal(menu, CLIENT_SHADE, _("_Roll up/down"), NULL, TRUE);
- e->data.normal.mask = ob_rr_theme->btn_shade->mask;
+ e->data.normal.mask = ob_rr_theme->btn_shade->unpressed_mask;
set_icon_color(e);
menu_add_normal(menu, CLIENT_DECORATE, _("Un/_Decorate"), NULL, TRUE);
@@ -416,6 +416,6 @@ void client_menu_startup(void)
menu_add_separator(menu, -1, NULL);
e = menu_add_normal(menu, CLIENT_CLOSE, _("_Close"), NULL, TRUE);
- e->data.normal.mask = ob_rr_theme->btn_close->mask;
+ e->data.normal.mask = ob_rr_theme->btn_close->unpressed_mask;
set_icon_color(e);
}
diff --git a/openbox/config.c b/openbox/config.c
index 76f48569..dad5d1bf 100644
--- a/openbox/config.c
+++ b/openbox/config.c
@@ -83,8 +83,9 @@ guint config_dock_show_delay;
guint config_dock_app_move_button;
guint config_dock_app_move_modifiers;
-guint config_keyboard_reset_keycode;
-guint config_keyboard_reset_state;
+guint config_keyboard_reset_keycode;
+guint config_keyboard_reset_state;
+gboolean config_keyboard_rebind_on_mapping_notify;
gint config_mouse_threshold;
gint config_mouse_dclicktime;
@@ -503,6 +504,9 @@ static void parse_keyboard(xmlNodePtr node, gpointer d)
parse_key(n, NULL);
n = obt_xml_find_node(n->next, "keybind");
}
+
+ if ((n = obt_xml_find_node(node->children, "rebindOnMappingNotify")))
+ config_keyboard_rebind_on_mapping_notify = obt_xml_node_bool(n);
}
/*
@@ -540,13 +544,15 @@ static void parse_mouse(xmlNodePtr node, gpointer d)
if ((n = obt_xml_find_node(node, "screenEdgeWarpMouse")))
config_mouse_screenedgewarp = obt_xml_node_bool(n);
- n = obt_xml_find_node(node, "context");
- while (n) {
+ for (n = obt_xml_find_node(node, "context");
+ n;
+ n = obt_xml_find_node(n->next, "context"))
+ {
gchar *modcxstr;
ObFrameContext cx;
if (!obt_xml_attr_string(n, "name", &cxstr))
- goto next_n;
+ continue;
modcxstr = g_strdup(cxstr); /* make a copy to mutilate */
while (frame_next_context_from_string(modcxstr, &cx)) {
@@ -561,10 +567,15 @@ static void parse_mouse(xmlNodePtr node, gpointer d)
continue;
}
- nbut = obt_xml_find_node(n->children, "mousebind");
- while (nbut) {
+ for (nbut = obt_xml_find_node(n->children, "mousebind");
+ nbut;
+ nbut = obt_xml_find_node(nbut->next, "mousebind"))
+ {
+
+ gchar **button, **buttons;
+
if (!obt_xml_attr_string(nbut, "button", &buttonstr))
- goto next_nbut;
+ continue;
if (obt_xml_attr_contains(nbut, "action", "press"))
mact = OB_MOUSE_ACTION_PRESS;
else if (obt_xml_attr_contains(nbut, "action", "release"))
@@ -576,25 +587,31 @@ static void parse_mouse(xmlNodePtr node, gpointer d)
else if (obt_xml_attr_contains(nbut, "action", "drag"))
mact = OB_MOUSE_ACTION_MOTION;
else
- goto next_nbut;
+ continue;
- nact = obt_xml_find_node(nbut->children, "action");
- while (nact) {
+ buttons = g_strsplit(buttonstr, " ", 0);
+ for (nact = obt_xml_find_node(nbut->children, "action");
+ nact;
+ nact = obt_xml_find_node(nact->next, "action"))
+ {
ObActionsAct *action;
- if ((action = actions_parse(nact)))
- mouse_bind(buttonstr, cx, mact, action);
- nact = obt_xml_find_node(nact->next, "action");
+ /* actions_parse() creates one ref to the action, but we need
+ * exactly one ref per binding we use it for. */
+ if ((action = actions_parse(nact))) {
+ for (button = buttons; *button; ++button) {
+ actions_act_ref(action);
+ mouse_bind(*button, cx, mact, action);
+ }
+ actions_act_unref(action);
+ }
}
- g_free(buttonstr);
- next_nbut:
- nbut = obt_xml_find_node(nbut->next, "mousebind");
+ g_strfreev(buttons);
+ g_free(buttonstr);
}
}
g_free(modcxstr);
g_free(cxstr);
- next_n:
- n = obt_xml_find_node(n->next, "context");
}
}
@@ -703,8 +720,10 @@ static void parse_theme(xmlNodePtr node, gpointer d)
config_theme_window_list_icon_size = 96;
}
- n = obt_xml_find_node(node, "font");
- while (n) {
+ for (n = obt_xml_find_node(node, "font");
+ n;
+ n = obt_xml_find_node(n->next, "font"))
+ {
xmlNodePtr fnode;
RrFont **font;
gchar *name = g_strdup(RrDefaultFontFamily);
@@ -727,7 +746,7 @@ static void parse_theme(xmlNodePtr node, gpointer d)
else if (obt_xml_attr_contains(n, "place","InactiveOnScreenDisplay"))
font = &config_font_inactiveosd;
else
- goto next_font;
+ continue;
if ((fnode = obt_xml_find_node(n->children, "name"))) {
g_free(name);
@@ -754,8 +773,6 @@ static void parse_theme(xmlNodePtr node, gpointer d)
*font = RrFontOpen(ob_rr_inst, name, size, weight, slant);
g_free(name);
- next_font:
- n = obt_xml_find_node(n->next, "font");
}
}
@@ -784,12 +801,13 @@ static void parse_desktops(xmlNodePtr node, gpointer d)
g_slist_free(config_desktops_names);
config_desktops_names = NULL;
- nname = obt_xml_find_node(n->children, "name");
- while (nname) {
+ for (nname = obt_xml_find_node(n->children, "name");
+ nname;
+ nname = obt_xml_find_node(nname->next, "name"))
+ {
config_desktops_names =
g_slist_append(config_desktops_names,
obt_xml_node_string(nname));
- nname = obt_xml_find_node(nname->next, "name");
}
}
if ((n = obt_xml_find_node(node, "popupTime")))
@@ -905,7 +923,7 @@ static void parse_dock(xmlNodePtr node, gpointer d)
config_dock_show_delay = obt_xml_node_int(n);
if ((n = obt_xml_find_node(node, "moveButton"))) {
gchar *str = obt_xml_node_string(n);
- guint b, s;
+ guint b = 0, s = 0;
if (translate_button(str, &s, &b)) {
config_dock_app_move_button = b;
config_dock_app_move_modifiers = s;
@@ -939,12 +957,14 @@ static void parse_menu(xmlNodePtr node, gpointer d)
#endif
}
- while ((node = obt_xml_find_node(node, "file"))) {
+ for (node = obt_xml_find_node(node, "file");
+ node;
+ node = obt_xml_find_node(node->next, "file"))
+ {
gchar *c = obt_xml_node_string(node);
config_menu_files = g_slist_append(config_menu_files,
obt_paths_expand_tilde(c));
g_free(c);
- node = node->next;
}
}
@@ -1120,6 +1140,7 @@ void config_startup(ObtXmlInst *i)
translate_key("C-g", &config_keyboard_reset_state,
&config_keyboard_reset_keycode);
+ config_keyboard_rebind_on_mapping_notify = TRUE;
bind_default_keyboard();
diff --git a/openbox/config.h b/openbox/config.h
index fc1d217e..96a66cf1 100644
--- a/openbox/config.h
+++ b/openbox/config.h
@@ -179,6 +179,8 @@ extern guint config_desktop_popup_time;
extern guint config_keyboard_reset_keycode;
/*! The modifiers of the key combo which resets the keybaord chains */
extern guint config_keyboard_reset_state;
+/*! Reload the keyboard bindings when the mapping changes */
+extern gboolean config_keyboard_rebind_on_mapping_notify;
/*! Number of pixels a drag must go before being considered a drag */
extern gint config_mouse_threshold;
diff --git a/openbox/dock.c b/openbox/dock.c
index f18683d6..ea9b7f49 100644
--- a/openbox/dock.c
+++ b/openbox/dock.c
@@ -632,8 +632,6 @@ static gboolean hide_timeout(gpointer data)
dock->hidden = TRUE;
dock_configure();
- hide_timeout_id = 0;
-
return FALSE; /* don't repeat */
}
@@ -643,30 +641,32 @@ static gboolean show_timeout(gpointer data)
dock->hidden = FALSE;
dock_configure();
- show_timeout_id = 0;
-
return FALSE; /* don't repeat */
}
+static void destroy_timeout(gpointer data)
+{
+ gint *id = data;
+ *id = 0;
+}
+
void dock_hide(gboolean hide)
{
if (!hide) {
if (dock->hidden && config_dock_hide) {
show_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
config_dock_show_delay,
- show_timeout, NULL, NULL);
+ show_timeout, &show_timeout_id, destroy_timeout);
} else if (!dock->hidden && config_dock_hide && hide_timeout_id) {
if (hide_timeout_id) g_source_remove(hide_timeout_id);
- hide_timeout_id = 0;
}
} else {
if (!dock->hidden && config_dock_hide) {
hide_timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
config_dock_hide_delay,
- hide_timeout, NULL, NULL);
+ hide_timeout, &hide_timeout_id, destroy_timeout);
} else if (dock->hidden && config_dock_hide && show_timeout_id) {
if (show_timeout_id) g_source_remove(show_timeout_id);
- show_timeout_id = 0;
}
}
}
diff --git a/openbox/event.c b/openbox/event.c
index 1b3a0e46..5774f67d 100644
--- a/openbox/event.c
+++ b/openbox/event.c
@@ -206,6 +206,7 @@ static Window event_get_window(XEvent *e)
switch (((XkbAnyEvent*)e)->xkb_type) {
case XkbBellNotify:
window = ((XkbBellNotifyEvent*)e)->window;
+ break;
default:
window = None;
}
@@ -636,11 +637,13 @@ static void event_process(const XEvent *ec, gpointer data)
else if (e->type == MappingNotify) {
/* keyboard layout changes for modifier mapping changes. reload the
modifier map, and rebind all the key bindings as appropriate */
- ob_debug("Keyboard map changed. Reloading keyboard bindings.");
- ob_set_state(OB_STATE_RECONFIGURING);
- obt_keyboard_reload();
- keyboard_rebind();
- ob_set_state(OB_STATE_RUNNING);
+ if (config_keyboard_rebind_on_mapping_notify) {
+ ob_debug("Keyboard map changed. Reloading keyboard bindings.");
+ ob_set_state(OB_STATE_RECONFIGURING);
+ obt_keyboard_reload();
+ keyboard_rebind();
+ ob_set_state(OB_STATE_RUNNING);
+ }
}
else if (e->type == ClientMessage) {
/* This is for _NET_WM_REQUEST_FRAME_EXTENTS messages. They come for
@@ -772,7 +775,12 @@ static void event_handle_root(XEvent *e)
if (d > 0 && d <= 1000)
screen_set_num_desktops(d);
} else if (msgtype == OBT_PROP_ATOM(NET_SHOWING_DESKTOP)) {
- screen_show_desktop(e->xclient.data.l[0] != 0, NULL);
+ ObScreenShowDestopMode show_mode;
+ if (e->xclient.data.l[0] != 0)
+ show_mode = SCREEN_SHOW_DESKTOP_UNTIL_WINDOW;
+ else
+ show_mode = SCREEN_SHOW_DESKTOP_NO;
+ screen_show_desktop(show_mode, NULL);
} else if (msgtype == OBT_PROP_ATOM(OB_CONTROL)) {
ob_debug("OB_CONTROL: %d", e->xclient.data.l[0]);
if (e->xclient.data.l[0] == 1)
@@ -1190,7 +1198,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
}
if (e->xconfigurerequest.value_mask & CWStackMode) {
- ObClient *sibling = NULL;
+ ObWindow *sibling = NULL;
gulong ignore_start;
gboolean ok = TRUE;
@@ -1201,7 +1209,11 @@ static void event_handle_client(ObClient *client, XEvent *e)
if (win && WINDOW_IS_CLIENT(win) &&
WINDOW_AS_CLIENT(win) != client)
{
- sibling = WINDOW_AS_CLIENT(win);
+ sibling = win;
+ }
+ else if (win && WINDOW_IS_DOCK(win))
+ {
+ sibling = win;
}
else
/* an invalid sibling was specified so don't restack at
@@ -1552,13 +1564,17 @@ static void event_handle_client(ObClient *client, XEvent *e)
"invalid source indication %ld",
client->title, e->xclient.data.l[0]);
} else {
- ObClient *sibling = NULL;
+ ObWindow *sibling = NULL;
if (e->xclient.data.l[1]) {
ObWindow *win = window_find(e->xclient.data.l[1]);
if (WINDOW_IS_CLIENT(win) &&
WINDOW_AS_CLIENT(win) != client)
{
- sibling = WINDOW_AS_CLIENT(win);
+ sibling = win;
+ }
+ if (WINDOW_IS_DOCK(win))
+ {
+ sibling = win;
}
if (sibling == NULL)
ob_debug_type(OB_DEBUG_APP_BUGS,
@@ -1820,8 +1836,14 @@ static gboolean event_handle_menu_input(XEvent *ev)
if ((e = menu_entry_frame_under(ev->xbutton.x_root,
ev->xbutton.y_root)))
{
- if (ev->type == ButtonPress && e->frame->child)
- menu_frame_select(e->frame->child, NULL, TRUE);
+ if (ev->type == ButtonPress) {
+ /* We know this is a new press, so we don't have to
+ * block release events anymore */
+ menu_hide_delay_reset();
+
+ if (e->frame->child)
+ menu_frame_select(e->frame->child, NULL, TRUE);
+ }
menu_frame_select(e->frame, e, TRUE);
if (ev->type == ButtonRelease)
menu_entry_frame_execute(e, ev->xbutton.state);
@@ -2106,6 +2128,7 @@ static gboolean focus_delay_func(gpointer data)
if (client_focus(d->client) && config_focus_raise)
stacking_raise(CLIENT_AS_WINDOW(d->client));
event_curtime = old;
+
return FALSE; /* no repeat */
}
@@ -2118,6 +2141,7 @@ static gboolean unfocus_delay_func(gpointer data)
event_curserial = d->serial;
focus_nothing();
event_curtime = old;
+
return FALSE; /* no repeat */
}
diff --git a/openbox/frame.c b/openbox/frame.c
index 3dbcf126..89669726 100644
--- a/openbox/frame.c
+++ b/openbox/frame.c
@@ -1664,8 +1664,7 @@ static void flash_done(gpointer data)
{
ObFrame *self = data;
- if (self->focused != self->flash_on)
- frame_adjust_focus(self, self->focused);
+ self->flash_timer = 0;
}
static gboolean flash_timeout(gpointer data)
@@ -1679,8 +1678,12 @@ static gboolean flash_timeout(gpointer data)
now.tv_usec >= self->flash_end.tv_usec))
self->flashing = FALSE;
- if (!self->flashing)
+ if (!self->flashing) {
+ if (self->focused != self->flash_on)
+ frame_adjust_focus(self, self->focused);
+
return FALSE; /* we are done */
+ }
self->flash_on = !self->flash_on;
if (!self->focused) {
@@ -1787,14 +1790,12 @@ static gboolean frame_animate_iconify(gpointer p)
XMoveResizeWindow(obt_display, self->window, x, y, w, h);
XFlush(obt_display);
- if (time == 0)
- frame_end_iconify_animation(self);
-
return time > 0; /* repeat until we're out of time */
}
-void frame_end_iconify_animation(ObFrame *self)
+void frame_end_iconify_animation(gpointer data)
{
+ ObFrame *self = data;
/* see if there is an animation going */
if (self->iconify_animation_going == 0) return;
@@ -1811,6 +1812,7 @@ void frame_end_iconify_animation(ObFrame *self)
/* we're not animating any more ! */
self->iconify_animation_going = 0;
+ self->iconify_animation_timer = 0;
XMoveResizeWindow(obt_display, self->window,
self->area.x, self->area.y,
@@ -1861,7 +1863,8 @@ void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying)
self->iconify_animation_timer =
g_timeout_add_full(G_PRIORITY_DEFAULT,
FRAME_ANIMATE_ICONIFY_STEP_TIME,
- frame_animate_iconify, self, NULL);
+ frame_animate_iconify, self,
+ frame_end_iconify_animation);
/* do the first step */
diff --git a/openbox/frame.h b/openbox/frame.h
index 915c08db..ae29c3b1 100644
--- a/openbox/frame.h
+++ b/openbox/frame.h
@@ -265,7 +265,7 @@ void frame_flash_stop(ObFrame *self);
will be called when the animation finishes. But if another animation is
started in the meantime, the callback will never get called. */
void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying);
-void frame_end_iconify_animation(ObFrame *self);
+void frame_end_iconify_animation(gpointer data);
#define frame_iconify_animating(f) (f->iconify_animation_going != 0)
diff --git a/openbox/framerender.c b/openbox/framerender.c
index 041e6d17..094d5962 100644
--- a/openbox/framerender.c
+++ b/openbox/framerender.c
@@ -131,115 +131,115 @@ void framerender_frame(ObFrame *self)
t = ob_rr_theme->a_focused_title;
l = ob_rr_theme->a_focused_label;
m = (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) ?
- ob_rr_theme->btn_max->a_disabled_focused :
+ ob_rr_theme->btn_max->a_focused_disabled :
(self->client->max_vert || self->client->max_horz ?
(self->max_press ?
- ob_rr_theme->btn_max->a_toggled_focused_pressed :
+ ob_rr_theme->btn_max->a_focused_pressed_toggled :
(self->max_hover ?
- ob_rr_theme->btn_max->a_toggled_hover_focused :
- ob_rr_theme->btn_max->a_toggled_focused_unpressed)) :
+ ob_rr_theme->btn_max->a_focused_hover_toggled :
+ ob_rr_theme->btn_max->a_focused_unpressed_toggled)) :
(self->max_press ?
ob_rr_theme->btn_max->a_focused_pressed :
(self->max_hover ?
- ob_rr_theme->btn_max->a_hover_focused :
+ ob_rr_theme->btn_max->a_focused_hover :
ob_rr_theme->btn_max->a_focused_unpressed))));
n = ob_rr_theme->a_icon;
i = (!(self->decorations & OB_FRAME_DECOR_ICONIFY) ?
- ob_rr_theme->btn_iconify->a_disabled_focused :
+ ob_rr_theme->btn_iconify->a_focused_disabled :
(self->iconify_press ?
ob_rr_theme->btn_iconify->a_focused_pressed :
(self->iconify_hover ?
- ob_rr_theme->btn_iconify->a_hover_focused :
+ ob_rr_theme->btn_iconify->a_focused_hover :
ob_rr_theme->btn_iconify->a_focused_unpressed)));
d = (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) ?
- ob_rr_theme->btn_desk->a_disabled_focused :
+ ob_rr_theme->btn_desk->a_focused_disabled :
(self->client->desktop == DESKTOP_ALL ?
(self->desk_press ?
- ob_rr_theme->btn_desk->a_toggled_focused_pressed :
+ ob_rr_theme->btn_desk->a_focused_pressed_toggled :
(self->desk_hover ?
- ob_rr_theme->btn_desk->a_toggled_hover_focused :
- ob_rr_theme->btn_desk->a_toggled_focused_unpressed)) :
+ ob_rr_theme->btn_desk->a_focused_hover_toggled :
+ ob_rr_theme->btn_desk->a_focused_unpressed_toggled)) :
(self->desk_press ?
ob_rr_theme->btn_desk->a_focused_pressed :
(self->desk_hover ?
- ob_rr_theme->btn_desk->a_hover_focused :
+ ob_rr_theme->btn_desk->a_focused_hover :
ob_rr_theme->btn_desk->a_focused_unpressed))));
s = (!(self->decorations & OB_FRAME_DECOR_SHADE) ?
- ob_rr_theme->btn_shade->a_disabled_focused :
+ ob_rr_theme->btn_shade->a_focused_disabled :
(self->client->shaded ?
(self->shade_press ?
- ob_rr_theme->btn_shade->a_toggled_focused_pressed :
+ ob_rr_theme->btn_shade->a_focused_pressed_toggled :
(self->shade_hover ?
- ob_rr_theme->btn_shade->a_toggled_hover_focused :
- ob_rr_theme->btn_shade->a_toggled_focused_unpressed)) :
+ ob_rr_theme->btn_shade->a_focused_hover_toggled :
+ ob_rr_theme->btn_shade->a_focused_unpressed_toggled)) :
(self->shade_press ?
ob_rr_theme->btn_shade->a_focused_pressed :
(self->shade_hover ?
- ob_rr_theme->btn_shade->a_hover_focused :
+ ob_rr_theme->btn_shade->a_focused_hover :
ob_rr_theme->btn_shade->a_focused_unpressed))));
c = (!(self->decorations & OB_FRAME_DECOR_CLOSE) ?
- ob_rr_theme->btn_close->a_disabled_focused :
+ ob_rr_theme->btn_close->a_focused_disabled :
(self->close_press ?
ob_rr_theme->btn_close->a_focused_pressed :
(self->close_hover ?
- ob_rr_theme->btn_close->a_hover_focused :
+ ob_rr_theme->btn_close->a_focused_hover :
ob_rr_theme->btn_close->a_focused_unpressed)));
} else {
t = ob_rr_theme->a_unfocused_title;
l = ob_rr_theme->a_unfocused_label;
m = (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) ?
- ob_rr_theme->btn_max->a_disabled_unfocused :
+ ob_rr_theme->btn_max->a_unfocused_disabled :
(self->client->max_vert || self->client->max_horz ?
(self->max_press ?
- ob_rr_theme->btn_max->a_toggled_unfocused_pressed :
+ ob_rr_theme->btn_max->a_unfocused_pressed_toggled :
(self->max_hover ?
- ob_rr_theme->btn_max->a_toggled_hover_unfocused :
- ob_rr_theme->btn_max->a_toggled_unfocused_unpressed)) :
+ ob_rr_theme->btn_max->a_unfocused_hover_toggled :
+ ob_rr_theme->btn_max->a_unfocused_unpressed_toggled)) :
(self->max_press ?
ob_rr_theme->btn_max->a_unfocused_pressed :
(self->max_hover ?
- ob_rr_theme->btn_max->a_hover_unfocused :
+ ob_rr_theme->btn_max->a_unfocused_hover :
ob_rr_theme->btn_max->a_unfocused_unpressed))));
n = ob_rr_theme->a_icon;
i = (!(self->decorations & OB_FRAME_DECOR_ICONIFY) ?
- ob_rr_theme->btn_iconify->a_disabled_unfocused :
+ ob_rr_theme->btn_iconify->a_unfocused_disabled :
(self->iconify_press ?
ob_rr_theme->btn_iconify->a_unfocused_pressed :
(self->iconify_hover ?
- ob_rr_theme->btn_iconify->a_hover_unfocused :
+ ob_rr_theme->btn_iconify->a_unfocused_hover :
ob_rr_theme->btn_iconify->a_unfocused_unpressed)));
d = (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) ?
- ob_rr_theme->btn_desk->a_disabled_unfocused :
+ ob_rr_theme->btn_desk->a_unfocused_disabled :
(self->client->desktop == DESKTOP_ALL ?
(self->desk_press ?
- ob_rr_theme->btn_desk->a_toggled_unfocused_pressed :
+ ob_rr_theme->btn_desk->a_unfocused_pressed_toggled :
(self->desk_hover ?
- ob_rr_theme->btn_desk->a_toggled_hover_unfocused :
- ob_rr_theme->btn_desk->a_toggled_unfocused_unpressed)) :
+ ob_rr_theme->btn_desk->a_unfocused_hover_toggled :
+ ob_rr_theme->btn_desk->a_unfocused_unpressed_toggled)) :
(self->desk_press ?
ob_rr_theme->btn_desk->a_unfocused_pressed :
(self->desk_hover ?
- ob_rr_theme->btn_desk->a_hover_unfocused :
+ ob_rr_theme->btn_desk->a_unfocused_hover :
ob_rr_theme->btn_desk->a_unfocused_unpressed))));
s = (!(self->decorations & OB_FRAME_DECOR_SHADE) ?
- ob_rr_theme->btn_shade->a_disabled_unfocused :
+ ob_rr_theme->btn_shade->a_unfocused_disabled :
(self->client->shaded ?
(self->shade_press ?
- ob_rr_theme->btn_shade->a_toggled_unfocused_pressed :
+ ob_rr_theme->btn_shade->a_unfocused_pressed_toggled :
(self->shade_hover ?
- ob_rr_theme->btn_shade->a_toggled_hover_unfocused :
- ob_rr_theme->btn_shade->a_toggled_unfocused_unpressed)) :
+ ob_rr_theme->btn_shade->a_unfocused_hover_toggled :
+ ob_rr_theme->btn_shade->a_unfocused_unpressed_toggled)) :
(self->shade_press ?
ob_rr_theme->btn_shade->a_unfocused_pressed :
(self->shade_hover ?
- ob_rr_theme->btn_shade->a_hover_unfocused :
+ ob_rr_theme->btn_shade->a_unfocused_hover :
ob_rr_theme->btn_shade->a_unfocused_unpressed))));
c = (!(self->decorations & OB_FRAME_DECOR_CLOSE) ?
- ob_rr_theme->btn_close->a_disabled_unfocused :
+ ob_rr_theme->btn_close->a_unfocused_disabled :
(self->close_press ?
ob_rr_theme->btn_close->a_unfocused_pressed :
(self->close_hover ?
- ob_rr_theme->btn_close->a_hover_unfocused :
+ ob_rr_theme->btn_close->a_unfocused_hover :
ob_rr_theme->btn_close->a_unfocused_unpressed)));
}
clear = ob_rr_theme->a_clear;
diff --git a/openbox/keyboard.c b/openbox/keyboard.c
index 8f4424ea..29abca82 100644
--- a/openbox/keyboard.c
+++ b/openbox/keyboard.c
@@ -270,8 +270,8 @@ gboolean keyboard_event(ObClient *client, const XEvent *e)
e->xkey.state, e->xkey.x_root, e->xkey.y_root,
0, OB_FRAME_CONTEXT_NONE, client);
}
- break;
used = TRUE;
+ break;
}
p = p->next_sibling;
}
diff --git a/openbox/menu.c b/openbox/menu.c
index 7c49cedb..8804e128 100644
--- a/openbox/menu.c
+++ b/openbox/menu.c
@@ -277,7 +277,7 @@ static gunichar parse_shortcut(const gchar *label, gboolean allow_shortcut,
return shortcut;
}
-static void parse_menu_item(xmlNodePtr node, gpointer data)
+static void parse_menu_item(xmlNodePtr node, gpointer data)
{
ObMenuParseState *state = data;
gchar *label;
@@ -454,10 +454,12 @@ static gboolean menu_hide_delay_func(gpointer data)
{
menu_can_hide = TRUE;
menu_timeout_id = 0;
+
return FALSE; /* no repeat */
}
-void menu_show(gchar *name, gint x, gint y, gboolean mouse, ObClient *client)
+void menu_show(gchar *name, const GravityPoint *pos, gint monitor,
+ gboolean mouse, gboolean user_positioned, ObClient *client)
{
ObMenu *self;
ObMenuFrame *frame;
@@ -479,7 +481,7 @@ void menu_show(gchar *name, gint x, gint y, gboolean mouse, ObClient *client)
menu_clear_pipe_caches();
frame = menu_frame_new(self, 0, client);
- if (!menu_frame_show_topmenu(frame, x, y, mouse))
+ if (!menu_frame_show_topmenu(frame, pos, monitor, mouse, user_positioned))
menu_frame_free(frame);
else {
if (!mouse) {
@@ -517,6 +519,12 @@ gboolean menu_hide_delay_reached(void)
return menu_can_hide;
}
+void menu_hide_delay_reset(void)
+{
+ if (menu_timeout_id) g_source_remove(menu_timeout_id);
+ menu_hide_delay_func(NULL);
+}
+
static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type, gint id)
{
ObMenuEntry *self;
diff --git a/openbox/menu.h b/openbox/menu.h
index 7d719729..8c2ecd77 100644
--- a/openbox/menu.h
+++ b/openbox/menu.h
@@ -181,9 +181,11 @@ void menu_clear_pipe_caches(void);
void menu_show_all_shortcuts(ObMenu *self, gboolean show);
-void menu_show(gchar *name, gint x, gint y, gboolean mouse,
+void menu_show(gchar *name, const GravityPoint *pos, gint monitor,
+ gboolean mouse, gboolean user_positioned,
struct _ObClient *client);
gboolean menu_hide_delay_reached(void);
+void menu_hide_delay_reset(void);
/*! The show function is called right after a menu is shown */
void menu_set_show_func(ObMenu *menu, ObMenuShowFunc func);
diff --git a/openbox/menuframe.c b/openbox/menuframe.c
index 3252bb3c..c37fdcc5 100644
--- a/openbox/menuframe.c
+++ b/openbox/menuframe.c
@@ -203,8 +203,6 @@ static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry,
static void menu_entry_frame_free(ObMenuEntryFrame *self)
{
if (self) {
- menu_entry_unref(self->entry);
-
window_remove(self->window);
XDestroyWindow(obt_display, self->text);
@@ -221,6 +219,7 @@ static void menu_entry_frame_free(ObMenuEntryFrame *self)
g_hash_table_remove(menu_frame_map, &self->bullet);
}
+ menu_entry_unref(self->entry);
g_slice_free(ObMenuEntryFrame, self);
}
}
@@ -232,10 +231,18 @@ void menu_frame_move(ObMenuFrame *self, gint x, gint y)
XMoveWindow(obt_display, self->window, self->area.x, self->area.y);
}
-static void menu_frame_place_topmenu(ObMenuFrame *self, gint *x, gint *y)
+static void menu_frame_place_topmenu(ObMenuFrame *self, const GravityPoint *pos,
+ gint *x, gint *y, gint monitor,
+ gboolean user_positioned)
{
gint dx, dy;
+ screen_apply_gravity_point(x, y, self->area.width, self->area.height,
+ pos, screen_physical_area_monitor(monitor));
+
+ if (user_positioned)
+ return;
+
if (config_menu_middle) {
gint myx;
@@ -989,20 +996,26 @@ static gboolean menu_frame_show(ObMenuFrame *self)
return TRUE;
}
-gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
- gboolean mouse)
+gboolean menu_frame_show_topmenu(ObMenuFrame *self, const GravityPoint *pos,
+ gint monitor, gboolean mouse,
+ gboolean user_positioned)
{
gint px, py;
+ gint x, y;
if (menu_frame_is_visible(self))
return TRUE;
if (!menu_frame_show(self))
return FALSE;
- if (self->menu->place_func)
+ if (self->menu->place_func) {
+ x = pos->x.pos;
+ y = pos->y.pos;
self->menu->place_func(self, &x, &y, mouse, self->menu->data);
- else
- menu_frame_place_topmenu(self, &x, &y);
+ } else {
+ menu_frame_place_topmenu(self, pos, &x, &y, monitor,
+ user_positioned);
+ }
menu_frame_move(self, x, y);
@@ -1023,7 +1036,6 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
static void remove_submenu_hide_timeout(ObMenuFrame *child)
{
if (submenu_hide_timer) g_source_remove(submenu_hide_timer);
- submenu_hide_timer = 0;
}
gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
@@ -1121,11 +1133,9 @@ void menu_frame_hide_all(void)
{
GList *it;
- if (config_submenu_show_delay) {
+ if (config_submenu_show_delay && submenu_show_timer)
/* remove any submenu open requests */
- if (submenu_show_timer) g_source_remove(submenu_show_timer);
- submenu_show_timer = 0;
- }
+ g_source_remove(submenu_show_timer);
if ((it = g_list_last(menu_frame_visible)))
menu_frame_hide(it->data);
}
@@ -1175,6 +1185,11 @@ static gboolean submenu_show_timeout(gpointer data)
return FALSE;
}
+static void submenu_show_dest(gpointer data)
+{
+ submenu_show_timer = 0;
+}
+
static gboolean submenu_hide_timeout(gpointer data)
{
g_assert(menu_frame_visible);
@@ -1182,6 +1197,11 @@ static gboolean submenu_hide_timeout(gpointer data)
return FALSE;
}
+static void submenu_hide_dest(gpointer data)
+{
+ submenu_hide_timer = 0;
+}
+
void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
gboolean immediate)
{
@@ -1203,11 +1223,9 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
if (!entry && oldchild_entry)
entry = oldchild_entry;
- if (config_submenu_show_delay) {
+ if (config_submenu_show_delay && submenu_show_timer)
/* remove any submenu open requests */
- if (submenu_show_timer) g_source_remove(submenu_show_timer);
- submenu_show_timer = 0;
- }
+ g_source_remove(submenu_show_timer);
self->selected = entry;
@@ -1231,7 +1249,7 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
submenu_hide_timer =
g_timeout_add_full(G_PRIORITY_DEFAULT,
config_submenu_hide_delay,
- submenu_hide_timeout, oldchild, NULL);
+ submenu_hide_timeout, oldchild, submenu_hide_dest);
}
}
}
@@ -1251,7 +1269,7 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
g_timeout_add_full(G_PRIORITY_DEFAULT,
config_submenu_show_delay,
submenu_show_timeout,
- self->selected, NULL);
+ self->selected, submenu_show_dest);
}
}
/* hide the grandchildren of this menu. and move the cursor to
diff --git a/openbox/menuframe.h b/openbox/menuframe.h
index 2d7a2ae0..7b295b6f 100644
--- a/openbox/menuframe.h
+++ b/openbox/menuframe.h
@@ -120,8 +120,9 @@ void menu_frame_move(ObMenuFrame *self, gint x, gint y);
void menu_frame_move_on_screen(ObMenuFrame *self, gint x, gint y,
gint *dx, gint *dy);
-gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
- gboolean mouse);
+gboolean menu_frame_show_topmenu(ObMenuFrame *self, const GravityPoint *pos,
+ gint monitor, gboolean mouse,
+ gboolean user_positioned);
gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
ObMenuEntryFrame *parent_entry);
diff --git a/openbox/mouse.c b/openbox/mouse.c
index 2f0c8f59..4da22f3c 100644
--- a/openbox/mouse.c
+++ b/openbox/mouse.c
@@ -372,7 +372,7 @@ gboolean mouse_event(ObClient *client, XEvent *e)
gboolean mouse_bind(const gchar *buttonstr, ObFrameContext context,
ObMouseAction mact, ObActionsAct *action)
{
- guint state, button;
+ guint state = 0, button = 0;
ObMouseBinding *b;
GSList *it;
diff --git a/openbox/moveresize.c b/openbox/moveresize.c
index 333a1bea..d12a64de 100644
--- a/openbox/moveresize.c
+++ b/openbox/moveresize.c
@@ -795,8 +795,13 @@ static void resize_with_keys(KeySym sym, guint state)
else /* if (sym == XK_Up)) */
dir = OB_DIRECTION_NORTH;
- client_find_resize_directional(moveresize_client, key_resize_edge,
- key_resize_edge == dir,
+ ObClientDirectionalResizeType resize_type =
+ key_resize_edge == dir ? CLIENT_RESIZE_GROW
+ : CLIENT_RESIZE_SHRINK;
+
+ client_find_resize_directional(moveresize_client,
+ key_resize_edge,
+ resize_type,
&x, &y, &w, &h);
dw = w - moveresize_client->area.width;
dh = h - moveresize_client->area.height;
diff --git a/openbox/openbox.c b/openbox/openbox.c
index cba04995..1671a0d3 100644
--- a/openbox/openbox.c
+++ b/openbox/openbox.c
@@ -329,11 +329,11 @@ gint main(gint argc, gchar **argv)
menu_startup(reconfigure);
prompt_startup(reconfigure);
- /* do this after everything is started so no events will get
- missed */
- xqueue_listen();
-
if (!reconfigure) {
+ /* do this after everything is started so no events will get
+ missed */
+ xqueue_listen();
+
guint32 xid;
ObWindow *w;
diff --git a/openbox/place.c b/openbox/place.c
index 7d5c8694..de2c7dc9 100644
--- a/openbox/place.c
+++ b/openbox/place.c
@@ -257,13 +257,13 @@ static Rect* choose_monitor(ObClient *c, gboolean client_to_be_foregrounded,
static gboolean place_under_mouse(ObClient *client, gint *x, gint *y,
Size frame_size)
{
- if (config_place_policy != OB_PLACE_POLICY_MOUSE)
- return FALSE;
-
gint l, r, t, b;
gint px, py;
Rect *area;
+ if (config_place_policy != OB_PLACE_POLICY_MOUSE)
+ return FALSE;
+
ob_debug("placing under mouse");
if (!screen_pointer_pos(&px, &py))
@@ -295,25 +295,8 @@ static gboolean place_per_app_setting_position(ObClient *client, Rect *screen,
ob_debug("placing by per-app settings");
- if (settings->position.x.center)
- *x = screen->x + screen->width / 2 - client->area.width / 2;
- else if (settings->position.x.opposite)
- *x = screen->x + screen->width - frame_size.width -
- settings->position.x.pos;
- else
- *x = screen->x + settings->position.x.pos;
- if (settings->position.x.denom)
- *x = (*x * screen->width) / settings->position.x.denom;
-
- if (settings->position.y.center)
- *y = screen->y + screen->height / 2 - client->area.height / 2;
- else if (settings->position.y.opposite)
- *y = screen->y + screen->height - frame_size.height -
- settings->position.y.pos;
- else
- *y = screen->y + settings->position.y.pos;
- if (settings->position.y.denom)
- *y = (*y * screen->height) / settings->position.y.denom;
+ screen_apply_gravity_point(x, y, frame_size.width, frame_size.height,
+ &settings->position, screen);
return TRUE;
}
@@ -377,11 +360,11 @@ static gboolean place_transient_splash(ObClient *client, Rect *area,
b = MAX(b, RECT_BOTTOM(m->frame->area));
}
}
- if (!first) {
- *x = ((r + 1 - l) - frame_size.width) / 2 + l;
- *y = ((b + 1 - t) - frame_size.height) / 2 + t;
- return TRUE;
- }
+ }
+ if (!first) {
+ *x = ((r + 1 - l) - frame_size.width) / 2 + l;
+ *y = ((b + 1 - t) - frame_size.height) / 2 + t;
+ return TRUE;
}
}
@@ -406,8 +389,19 @@ static gboolean place_least_overlap(ObClient *c, Rect *head, int *x, int *y,
GSList* potential_overlap_clients = NULL;
gint n_client_rects = config_dock_hide ? 0 : 1;
- /* if we're "showing desktop", ignore all existing windows */
- if (!screen_showing_desktop) {
+ /* If we're "showing desktop", and going to allow this window to
+ be shown now, then ignore all existing windows */
+ gboolean ignore_windows = FALSE;
+ switch (screen_show_desktop_mode) {
+ case SCREEN_SHOW_DESKTOP_NO:
+ case SCREEN_SHOW_DESKTOP_UNTIL_WINDOW:
+ break;
+ case SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE:
+ ignore_windows = TRUE;
+ break;
+ }
+
+ if (!ignore_windows) {
GList* it;
for (it = client_list; it != NULL; it = g_list_next(it)) {
ObClient* maybe_client = (ObClient*)it->data;
@@ -432,24 +426,27 @@ static gboolean place_least_overlap(ObClient *c, Rect *head, int *x, int *y,
n_client_rects += 1;
}
}
- Rect client_rects[n_client_rects];
-
- GSList* it;
- guint i = 0;
- if (!config_dock_hide)
- dock_get_area(&client_rects[i++]);
- for (it = potential_overlap_clients; it != NULL; it = g_slist_next(it)) {
- ObClient* potential_overlap_client = (ObClient*)it->data;
- client_rects[i] = potential_overlap_client->frame->area;
- i += 1;
- }
- g_slist_free(potential_overlap_clients);
- Point result;
- place_overlap_find_least_placement(client_rects, n_client_rects, head,
- &frame_size, &result);
- *x = result.x;
- *y = result.y;
+ if (n_client_rects) {
+ Rect client_rects[n_client_rects];
+ GSList* it;
+ Point result;
+ guint i = 0;
+
+ if (!config_dock_hide)
+ dock_get_area(&client_rects[i++]);
+ for (it = potential_overlap_clients; it != NULL; it = g_slist_next(it)) {
+ ObClient* potential_overlap_client = (ObClient*)it->data;
+ client_rects[i] = potential_overlap_client->frame->area;
+ i += 1;
+ }
+ g_slist_free(potential_overlap_clients);
+
+ place_overlap_find_least_placement(client_rects, n_client_rects, head,
+ &frame_size, &result);
+ *x = result.x;
+ *y = result.y;
+ }
return TRUE;
}
diff --git a/openbox/place.h b/openbox/place.h
index 3bc679e0..792fc387 100644
--- a/openbox/place.h
+++ b/openbox/place.h
@@ -38,7 +38,8 @@ typedef enum
OB_PLACE_MONITOR_ANY,
OB_PLACE_MONITOR_ACTIVE,
OB_PLACE_MONITOR_MOUSE,
- OB_PLACE_MONITOR_PRIMARY
+ OB_PLACE_MONITOR_PRIMARY,
+ OB_PLACE_MONITOR_ALL
} ObPlaceMonitor;
/*! Return TRUE if openbox chose the position for the window, and FALSE if
diff --git a/openbox/place_overlap.c b/openbox/place_overlap.c
index ac7255bf..ed7ff6c0 100644
--- a/openbox/place_overlap.c
+++ b/openbox/place_overlap.c
@@ -19,7 +19,9 @@
#include "config.h"
#include "geom.h"
#include "place_overlap.h"
+#include "obt/bsearch.h"
+#include <glib.h>
#include <stdlib.h>
static void make_grid(const Rect* client_rects,
@@ -170,29 +172,23 @@ static int total_overlap(const Rect* client_rects,
return overlap;
}
-/* Unfortunately, the libc bsearch() function cannot be used to find the
- position of a value that is not in the array, and glib doesn't
- provide a binary search function at all. So, tricky as it is, if we
- want to avoid linear scan of the edge array, we have to roll our
- own. */
-static int grid_position(int value,
- const int* edges,
- int max_edges)
+static int find_first_grid_position_greater_or_equal(int search_value,
+ const int* edges,
+ int max_edges)
{
- int low = 0;
- int high = max_edges - 1;
- int mid = low + (high - low) / 2;
- while (low != mid) {
- if (value < edges[mid])
- high = mid;
- else if (value > edges[mid])
- low = mid;
- else /* value == edges[mid] */
- return mid;
- mid = low + (high - low) / 2;
- }
- /* we get here when low == mid. can have low == high or low == high - 1 */
- return (value <= edges[low] ? low : high);
+ g_assert(max_edges >= 2);
+ g_assert(search_value >= edges[0]);
+ g_assert(search_value <= edges[max_edges - 1]);
+
+ BSEARCH_SETUP();
+ BSEARCH(int, edges, 0, max_edges, search_value);
+
+ if (BSEARCH_FOUND())
+ return BSEARCH_AT();
+
+ g_assert(BSEARCH_FOUND_NEAREST_SMALLER());
+ /* Get the nearest larger instead. */
+ return BSEARCH_AT() + 1;
}
static void expand_width(Rect* r, int by)
@@ -263,9 +259,11 @@ static void center_in_field(Point* top_left,
{
/* Find minimal rectangle. */
int orig_right_edge_index =
- grid_position(top_left->x + req_size->width, x_edges, max_edges);
+ find_first_grid_position_greater_or_equal(
+ top_left->x + req_size->width, x_edges, max_edges);
int orig_bottom_edge_index =
- grid_position(top_left->y + req_size->height, y_edges, max_edges);
+ find_first_grid_position_greater_or_equal(
+ top_left->y + req_size->height, y_edges, max_edges);
ExpandInfo i = {
.top_left = top_left,
.orig_width = x_edges[orig_right_edge_index] - top_left->x,
diff --git a/openbox/screen.c b/openbox/screen.c
index 9295194e..e758ada1 100644
--- a/openbox/screen.c
+++ b/openbox/screen.c
@@ -57,15 +57,15 @@ static gboolean replace_wm(void);
static void screen_tell_ksplash(void);
static void screen_fallback_focus(void);
-guint screen_num_desktops;
-guint screen_num_monitors;
-guint screen_desktop;
-guint screen_last_desktop;
-gboolean screen_showing_desktop;
-ObDesktopLayout screen_desktop_layout;
-gchar **screen_desktop_names;
-Window screen_support_win;
-Time screen_desktop_user_time = CurrentTime;
+guint screen_num_desktops;
+guint screen_num_monitors;
+guint screen_desktop;
+guint screen_last_desktop;
+ObScreenShowDestopMode screen_show_desktop_mode;
+ObDesktopLayout screen_desktop_layout;
+gchar **screen_desktop_names;
+Window screen_support_win;
+Time screen_desktop_user_time = CurrentTime;
static Size screen_physical_size;
static guint screen_old_desktop;
@@ -445,9 +445,9 @@ void screen_startup(gboolean reconfig)
screen_last_desktop = screen_desktop;
/* don't start in showing-desktop mode */
- screen_showing_desktop = FALSE;
+ screen_show_desktop_mode = SCREEN_SHOW_DESKTOP_NO;
OBT_PROP_SET32(obt_root(ob_screen),
- NET_SHOWING_DESKTOP, CARDINAL, screen_showing_desktop);
+ NET_SHOWING_DESKTOP, CARDINAL, screen_showing_desktop());
if (session_desktop_layout_present &&
screen_validate_layout(&session_desktop_layout))
@@ -1218,15 +1218,33 @@ void screen_update_desktop_names(void)
screen_num_desktops);
}
-void screen_show_desktop(gboolean show, ObClient *show_only)
+void screen_show_desktop(ObScreenShowDestopMode show_mode, ObClient *show_only)
{
GList *it;
- if (show == screen_showing_desktop) return; /* no change */
+ ObScreenShowDestopMode before_mode = screen_show_desktop_mode;
- screen_showing_desktop = show;
+ gboolean showing_before = screen_showing_desktop();
+ screen_show_desktop_mode = show_mode;
+ gboolean showing_after = screen_showing_desktop();
- if (show) {
+ if (showing_before == showing_after) {
+ /* No change. */
+ screen_show_desktop_mode = before_mode;
+ return;
+ }
+
+ if (screen_show_desktop_mode == SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE &&
+ show_only != NULL)
+ {
+ /* If we're showing the desktop until the show-mode is toggled, we
+ don't allow breaking out of showing-desktop mode unless we're
+ showing all the windows again. */
+ screen_show_desktop_mode = before_mode;
+ return;
+ }
+
+ if (showing_after) {
/* hide windows bottom to top */
for (it = g_list_last(stacking_list); it; it = g_list_previous(it)) {
if (WINDOW_IS_CLIENT(it->data)) {
@@ -1250,7 +1268,7 @@ void screen_show_desktop(gboolean show, ObClient *show_only)
}
}
- if (show) {
+ if (showing_after) {
/* focus the desktop */
for (it = focus_order; it; it = g_list_next(it)) {
ObClient *c = it->data;
@@ -1275,8 +1293,23 @@ void screen_show_desktop(gboolean show, ObClient *show_only)
}
}
- show = !!show; /* make it boolean */
- OBT_PROP_SET32(obt_root(ob_screen), NET_SHOWING_DESKTOP, CARDINAL, show);
+ OBT_PROP_SET32(obt_root(ob_screen),
+ NET_SHOWING_DESKTOP,
+ CARDINAL,
+ !!showing_after);
+}
+
+gboolean screen_showing_desktop()
+{
+ switch (screen_show_desktop_mode) {
+ case SCREEN_SHOW_DESKTOP_NO:
+ return FALSE;
+ case SCREEN_SHOW_DESKTOP_UNTIL_WINDOW:
+ case SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE:
+ return TRUE;
+ }
+ g_assert_not_reached();
+ return FALSE;
}
void screen_install_colormap(ObClient *client, gboolean install)
@@ -1648,7 +1681,7 @@ guint screen_find_monitor(const Rect *search)
{
guint i;
guint mostpx_index = screen_num_monitors;
- guint mostpx = 0;
+ glong mostpx = 0;
guint closest_distance_index = screen_num_monitors;
guint closest_distance = G_MAXUINT;
GSList *counted = NULL;
@@ -1895,3 +1928,30 @@ gboolean screen_compare_desktops(guint a, guint b)
b = screen_desktop;
return a == b;
}
+
+void screen_apply_gravity_point(gint *x, gint *y, gint width, gint height,
+ const GravityPoint *position, const Rect *area)
+{
+ if (position->x.center)
+ *x = area->width / 2 - width / 2;
+ else {
+ *x = position->x.pos;
+ if (position->x.denom)
+ *x = (*x * area->width) / position->x.denom;
+ if (position->x.opposite)
+ *x = area->width - width - *x;
+ }
+
+ if (position->y.center)
+ *y = area->height / 2 - height / 2;
+ else {
+ *y = position->y.pos;
+ if (position->y.denom)
+ *y = (*y * area->height) / position->y.denom;
+ if (position->y.opposite)
+ *y = area->height - height - *y;
+ }
+
+ *x += area->x;
+ *y += area->y;
+}
diff --git a/openbox/screen.h b/openbox/screen.h
index a6a3995b..6c26ce89 100644
--- a/openbox/screen.h
+++ b/openbox/screen.h
@@ -26,6 +26,12 @@ struct _ObClient;
#define DESKTOP_ALL (0xffffffff)
+typedef enum {
+ SCREEN_SHOW_DESKTOP_NO,
+ SCREEN_SHOW_DESKTOP_UNTIL_WINDOW,
+ SCREEN_SHOW_DESKTOP_UNTIL_TOGGLE
+} ObScreenShowDestopMode;
+
/*! The number of available desktops */
extern guint screen_num_desktops;
/*! The number of virtual "xinerama" screens/heads */
@@ -35,7 +41,7 @@ extern guint screen_desktop;
/*! The desktop which was last visible */
extern guint screen_last_desktop;
/*! Are we in showing-desktop mode? */
-extern gboolean screen_showing_desktop;
+extern ObScreenShowDestopMode screen_show_desktop_mode;
/*! The support window also used for focus and stacking */
extern Window screen_support_win;
/*! The last time at which the user changed desktops */
@@ -90,7 +96,11 @@ void screen_hide_desktop_popup(void);
show is FALSE (restoring from show-desktop mode), and the rest are
iconified.
*/
-void screen_show_desktop(gboolean show, struct _ObClient *show_only);
+void screen_show_desktop(ObScreenShowDestopMode show_mode,
+ struct _ObClient *show_only);
+
+/*! Returns true if showing desktop mode is enabled. */
+gboolean screen_showing_desktop();
/*! Updates the desktop layout from the root property if available */
void screen_update_layout(void);
@@ -172,4 +182,9 @@ guint screen_monitor_pointer(void);
*/
gboolean screen_compare_desktops(guint a, guint b);
+/*! Resolve a gravity point into absolute coordinates.
+ * width and height are the size of the object being placed, used for
+ * aligning to right/bottom edges of the area. */
+void screen_apply_gravity_point(gint *x, gint *y, gint width, gint height,
+ const GravityPoint *position, const Rect *area);
#endif
diff --git a/openbox/stacking.c b/openbox/stacking.c
index 58551b5d..0ef900aa 100644
--- a/openbox/stacking.c
+++ b/openbox/stacking.c
@@ -26,6 +26,8 @@
#include "window.h"
#include "event.h"
#include "debug.h"
+#include "dock.h"
+#include "config.h"
#include "obt/prop.h"
GList *stacking_list = NULL;
@@ -567,14 +569,18 @@ void stacking_add_nonintrusive(ObWindow *win)
/*! Returns TRUE if client is occluded by the sibling. If sibling is NULL it
tries against all other clients.
*/
-static gboolean stacking_occluded(ObClient *client, ObClient *sibling)
+static gboolean stacking_occluded(ObClient *client, ObWindow *sibling_win)
{
GList *it;
gboolean occluded = FALSE;
+ ObClient *sibling = NULL;
+
+ if (sibling_win && WINDOW_IS_CLIENT(sibling_win))
+ sibling = WINDOW_AS_CLIENT(sibling_win);
/* no need for any looping in this case */
if (sibling && client->layer != sibling->layer)
- return occluded;
+ return FALSE;
for (it = g_list_previous(g_list_find(stacking_list, client)); it;
it = g_list_previous(it))
@@ -601,6 +607,21 @@ static gboolean stacking_occluded(ObClient *client, ObClient *sibling)
break; /* we past its layer */
}
}
+ } else if (WINDOW_IS_DOCK(it->data)) {
+ ObDock *dock = it->data;
+ if (RECT_INTERSECTS_RECT(dock->area, client->frame->area))
+ {
+ if (sibling_win != NULL) {
+ if (DOCK_AS_WINDOW(dock) == sibling_win) {
+ occluded = TRUE;
+ break;
+ }
+ }
+ else if (config_dock_layer == client->layer) {
+ occluded = TRUE;
+ break;
+ }
+ }
}
return occluded;
}
@@ -608,14 +629,18 @@ static gboolean stacking_occluded(ObClient *client, ObClient *sibling)
/*! Returns TRUE if client occludes the sibling. If sibling is NULL it tries
against all other clients.
*/
-static gboolean stacking_occludes(ObClient *client, ObClient *sibling)
+static gboolean stacking_occludes(ObClient *client, ObWindow *sibling_win)
{
GList *it;
gboolean occludes = FALSE;
+ ObClient *sibling = NULL;
+
+ if (sibling_win && WINDOW_IS_CLIENT(sibling_win))
+ sibling = WINDOW_AS_CLIENT(sibling_win);
/* no need for any looping in this case */
if (sibling && client->layer != sibling->layer)
- return occludes;
+ return FALSE;
for (it = g_list_next(g_list_find(stacking_list, client));
it; it = g_list_next(it))
@@ -643,14 +668,35 @@ static gboolean stacking_occludes(ObClient *client, ObClient *sibling)
}
}
}
+ else if (WINDOW_IS_DOCK(it->data)) {
+ ObDock *dock = it->data;
+ if (RECT_INTERSECTS_RECT(dock->area, client->frame->area))
+ {
+ if (sibling_win != NULL) {
+ if (DOCK_AS_WINDOW(dock) == sibling_win) {
+ occludes = TRUE;
+ break;
+ }
+ }
+ else if (config_dock_layer == client->layer) {
+ occludes = TRUE;
+ break;
+ }
+ }
+ }
return occludes;
}
-gboolean stacking_restack_request(ObClient *client, ObClient *sibling,
+gboolean stacking_restack_request(ObClient *client, ObWindow *sibling_win,
gint detail)
{
gboolean ret = FALSE;
+ ObClient *sibling = NULL;
+
+ if (sibling_win && WINDOW_IS_CLIENT(sibling_win))
+ sibling = WINDOW_AS_CLIENT(sibling_win);
+
if (sibling && ((client->desktop != sibling->desktop &&
client->desktop != DESKTOP_ALL &&
sibling->desktop != DESKTOP_ALL) ||
@@ -674,7 +720,7 @@ gboolean stacking_restack_request(ObClient *client, ObClient *sibling,
client->title, sibling ? sibling->title : "(all)");
/* if this client occludes sibling (or anything if NULL), then
lower it to the bottom */
- if (stacking_occludes(client, sibling)) {
+ if (stacking_occludes(client, sibling_win)) {
stacking_lower(CLIENT_AS_WINDOW(client));
ret = TRUE;
}
@@ -688,7 +734,7 @@ gboolean stacking_restack_request(ObClient *client, ObClient *sibling,
case TopIf:
ob_debug("Restack request TopIf for client %s sibling %s",
client->title, sibling ? sibling->title : "(all)");
- if (stacking_occluded(client, sibling)) {
+ if (stacking_occluded(client, sibling_win)) {
stacking_raise(CLIENT_AS_WINDOW(client));
ret = TRUE;
}
@@ -696,11 +742,11 @@ gboolean stacking_restack_request(ObClient *client, ObClient *sibling,
case Opposite:
ob_debug("Restack request Opposite for client %s sibling %s",
client->title, sibling ? sibling->title : "(all)");
- if (stacking_occluded(client, sibling)) {
+ if (stacking_occluded(client, sibling_win)) {
stacking_raise(CLIENT_AS_WINDOW(client));
ret = TRUE;
}
- else if (stacking_occludes(client, sibling)) {
+ else if (stacking_occludes(client, sibling_win)) {
stacking_lower(CLIENT_AS_WINDOW(client));
ret = TRUE;
}
diff --git a/openbox/stacking.h b/openbox/stacking.h
index c14aa2ed..ebfa1755 100644
--- a/openbox/stacking.h
+++ b/openbox/stacking.h
@@ -71,7 +71,7 @@ void stacking_below(struct _ObWindow *window, struct _ObWindow *below);
/*! Restack a window based upon a sibling (or all windows) in various ways.
@param client The client to be restacked
- @param sibling Another client to compare to, or NULL to compare to all
+ @param sibling A window to compare to, or NULL to compare to all
windows
@param detail One of Above, Below, TopIf, BottomIf, Opposite
@return TRUE if the client was restacked
@@ -79,7 +79,7 @@ void stacking_below(struct _ObWindow *window, struct _ObWindow *below);
how each detail works with and without a sibling.
*/
gboolean stacking_restack_request(struct _ObClient *client,
- struct _ObClient *sibling,
+ struct _ObWindow *sibling_win,
gint detail);
#endif