diff --git a/openbox/action.c b/openbox/action.c
index ad12c331..b514916f 100644
--- a/openbox/action.c
+++ b/openbox/action.c
@@ -170,6 +170,21 @@ void setup_action_movetoedge_west(Action *a)
a->data.diraction.direction = Direction_West;
}
+void setup_action_top_layer(Action *a)
+{
+ a->data.layer.layer = 1;
+}
+
+void setup_action_normal_layer(Action *a)
+{
+ a->data.layer.layer = 0;
+}
+
+void setup_action_bottom_layer(Action *a)
+{
+ a->data.layer.layer = -1;
+}
+
ActionString actionstrings[] =
{
{
@@ -482,6 +497,31 @@ ActionString actionstrings[] =
action_showmenu,
NULL
},
+ {
+ "sendtotoplayer",
+ action_send_to_layer,
+ setup_action_top_layer
+ },
+ {
+ "togglealwaysontop",
+ action_toggle_layer,
+ setup_action_top_layer
+ },
+ {
+ "sendtonormallayer",
+ action_send_to_layer,
+ setup_action_normal_layer
+ },
+ {
+ "sendtobottomlayer",
+ action_send_to_layer,
+ setup_action_bottom_layer
+ },
+ {
+ "togglealwaysonbottom",
+ action_toggle_layer,
+ setup_action_bottom_layer
+ },
{
"nextwindowlinear",
action_cycle_windows,
@@ -1087,3 +1127,21 @@ void action_movetoedge(union ActionData *data)
x, y, c->area.width, c->area.height, TRUE, TRUE);
}
+
+void action_send_to_layer(union ActionData *data)
+{
+ if (data->layer.c)
+ client_set_layer(data->layer.c, data->layer.layer);
+}
+
+void action_toggle_layer(union ActionData *data)
+{
+ Client *c = data->layer.c;
+
+ if (c) {
+ if (data->layer.layer < 0)
+ client_set_layer(c, c->below ? 0 : -1);
+ else if (data->layer.layer > 0)
+ client_set_layer(c, c->above ? 0 : 1);
+ }
+}
diff --git a/openbox/action.h b/openbox/action.h
index ba5ff223..9066b6ef 100644
--- a/openbox/action.h
+++ b/openbox/action.h
@@ -48,6 +48,11 @@ struct Desktop {
guint desk;
};
+struct Layer {
+ Client *c;
+ int layer; /* < 0 = below, 0 = normal, > 0 = above */
+};
+
struct NextPreviousDesktop {
Client *c;
gboolean wrap;
@@ -89,6 +94,7 @@ union ActionData {
struct MoveResize moveresize;
struct ShowMenu showmenu;
struct CycleWindows cycle;
+ struct Layer layer;
};
typedef struct {
@@ -204,7 +210,12 @@ void action_exit(union ActionData *data);
void action_showmenu(union ActionData *data);
/* CycleWindows */
void action_cycle_windows(union ActionData *data);
-
+/* DirectionalAction */
void action_directional_focus(union ActionData *data);
+/* DirectionalAction */
void action_movetoedge(union ActionData *data);
+/* Layer */
+void action_send_to_layer(union ActionData *data);
+/* Layer */
+void action_toggle_layer(union ActionData *data);
#endif
diff --git a/openbox/client.c b/openbox/client.c
index e1c56042..19a10c21 100644
--- a/openbox/client.c
+++ b/openbox/client.c
@@ -2451,3 +2451,18 @@ Client *client_find_directional(Client *c, Direction dir)
return best_client;
}
+
+void client_set_layer(Client *self, int layer)
+{
+ if (layer < 0) {
+ self->below = TRUE;
+ self->above = FALSE;
+ } else if (layer == 0) {
+ self->below = self->above = FALSE;
+ } else {
+ self->below = FALSE;
+ self->above = TRUE;
+ }
+ client_calc_layer(self);
+ client_change_state(self); /* reflect this in the state hints */
+}
diff --git a/openbox/client.h b/openbox/client.h
index ca410558..5d84df0b 100644
--- a/openbox/client.h
+++ b/openbox/client.h
@@ -497,4 +497,11 @@ Client *client_search_modal_child(Client *self);
/*! Return the "closest" client in the given direction */
Client *client_find_directional(Client *c, Direction dir);
+/*! Set a client window to be above/below other clients.
+ @layer < 0 indicates the client should be placed below other clients.
+ = 0 indicates the client should be placed with other clients.
+ > 0 indicates the client should be placed above other clients.
+*/
+void client_set_layer(Client *self, int layer);
+
#endif