Clients Menus and Slits are all 'ObWindow's now. Stacking is done with ObWindows. Slits add themselves to the stacking order, as do clients of course. Added some macros for adding/removing to the stacking order.
@@ -26,13 +26,13 @@ openbox3_SOURCES=parse.tab.c parse.lex.c action.c client.c config.c \
extensions.c focus.c frame.c grab.c menu.c menu_render.c \ openbox.c framerender.c parse.c plugin.c prop.c screen.c \ stacking.c dispatch.c event.c group.c timer.c xerror.c \ - moveresize.c startup.c popup.c slit.c + moveresize.c startup.c popup.c slit.c window.c noinst_HEADERS=action.h client.h config.h dispatch.h event.h extensions.h \ focus.h frame.h framerender.h geom.h gettext.h grab.h group.h \ menu.h openbox.h parse.h parse.tab.h plugin.h prop.h screen.h \ stacking.h timer.h xerror.h moveresize.h startup.h popup.h \ - slit.h + slit.h window.h # kill the implicit .c.y rule %.c: %.y
@@ -222,14 +222,14 @@ void action_focusraise(union ActionData *data)
{ if (data->client.c) { client_focus(data->client.c); - stacking_raise(data->client.c); + stacking_raise(CLIENT_AS_WINDOW(data->client.c)); } } void action_raise(union ActionData *data) { if (data->client.c) - stacking_raise(data->client.c); + stacking_raise(CLIENT_AS_WINDOW(data->client.c)); } void action_unshaderaise(union ActionData *data)@@ -238,7 +238,7 @@ if (data->client.c) {
if (data->client.c->shaded) client_shade(data->client.c, FALSE); else - stacking_raise(data->client.c); + stacking_raise(CLIENT_AS_WINDOW(data->client.c)); } }@@ -246,7 +246,7 @@ void action_shadelower(union ActionData *data)
{ if (data->client.c) { if (data->client.c->shaded) - stacking_lower(data->client.c); + stacking_lower(CLIENT_AS_WINDOW(data->client.c)); else client_shade(data->client.c, TRUE); }@@ -255,7 +255,7 @@
void action_lower(union ActionData *data) { if (data->client.c) - stacking_lower(data->client.c); + stacking_lower(CLIENT_AS_WINDOW(data->client.c)); } void action_close(union ActionData *data)
@@ -158,7 +158,7 @@ Client *c;
w = startup_stack_order[i-1]; c = g_hash_table_lookup(client_map, &w); - if (c) stacking_lower(c); + if (c) stacking_lower(CLIENT_AS_WINDOW(c)); } g_free(startup_stack_order); startup_stack_order = NULL;@@ -222,6 +222,7 @@
/* create the Client struct, and populate it from the hints on the window */ self = g_new(Client, 1); + self->obwin.type = Window_Client; self->window = window; client_get_all(self);@@ -242,14 +243,14 @@
grab_server(FALSE); client_list = g_list_append(client_list, self); - stacking_list = g_list_append(stacking_list, self); + stacking_add(self); g_assert(!g_hash_table_lookup(client_map, &self->window)); g_hash_table_insert(client_map, &self->window, self); /* update the focus lists */ focus_order_add_new(self); - stacking_raise(self); + stacking_raise(CLIENT_AS_WINDOW(self)); screen_update_struts();@@ -336,7 +337,7 @@
frame_hide(self->frame); client_list = g_list_remove(client_list, self); - stacking_list = g_list_remove(stacking_list, self); + stacking_remove(self); g_hash_table_remove(client_map, &self->window); /* update the focus lists */@@ -1455,8 +1456,7 @@ static StackLayer calc_layer(Client *self)
{ StackLayer l; - if (self->iconic) l = Layer_Icon; - else if (self->fullscreen) l = Layer_Fullscreen; + if (self->fullscreen) l = Layer_Fullscreen; else if (self->type == Type_Desktop) l = Layer_Desktop; else if (self->type == Type_Dock) { if (!self->below) l = Layer_Top;@@ -1484,7 +1484,7 @@ calc_recursive(it->data, orig, l, raised ? raised : l != old);
if (!raised && l != old) if (orig->frame) /* only restack if the original window is managed */ - stacking_raise(self); + stacking_raise(CLIENT_AS_WINDOW(self)); } void client_calc_layer(Client *self)@@ -2028,7 +2028,7 @@ if (!donthide)
client_showhide(self); /* raise if it was not already on the desktop */ if (old != DESKTOP_ALL) - stacking_raise(self); + stacking_raise(CLIENT_AS_WINDOW(self)); screen_update_struts(); /* add to the new desktop(s) */@@ -2310,7 +2310,7 @@ return;
if (self->shaded) client_shade(self, FALSE); client_focus(self); - stacking_raise(self); + stacking_raise(CLIENT_AS_WINDOW(self)); } gboolean client_focused(Client *self)
@@ -110,6 +110,8 @@ } Decoration;
typedef struct Client { + ObWindow obwin; + Window window; /*! The window's decorations. NULL while the window is being managed! */
@@ -13,6 +13,8 @@ /*! Focus the last focused window as a fallback when switching desktops */
extern gboolean config_focus_last_on_desktop; /*! Show a popup dialog while cycling focus */ extern gboolean config_focus_popup; +/*! The number of slits to create */ +extern int config_slit_number; /* The name of the theme */ char *config_theme;
@@ -916,6 +916,8 @@
static void event_handle_slit(Slit *s, XEvent *e) { switch (e->type) { + case ButtonPress: + stacking_raise(SLIT_AS_WINDOW(s)); case EnterNotify: slit_hide(s, FALSE); break;
@@ -40,8 +40,7 @@ focus_backup = XCreateWindow(ob_display, ob_root,
-100, -100, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect, &attrib); - XMapWindow(ob_display, focus_backup); - stacking_raise_internal(focus_backup); + XMapRaised(ob_display, focus_backup); /* start with nothing focused */ focus_set_client(NULL);
@@ -186,7 +186,6 @@ if (!theme) return 1;
menu_startup(); frame_startup(); - stacking_startup(); moveresize_startup(); focus_startup(); screen_startup();@@ -215,7 +214,6 @@ group_shutdown();
screen_shutdown(); focus_shutdown(); moveresize_shutdown(); - stacking_shutdown(); frame_shutdown(); menu_shutdown(); grab_shutdown();
@@ -1,38 +1,13 @@
#include "slit.h" #include "screen.h" #include "grab.h" -#include "timer.h" #include "openbox.h" #include "render/theme.h" -#include "render/render.h" #define SLIT_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \ EnterWindowMask | LeaveWindowMask) #define SLITAPP_EVENT_MASK (StructureNotifyMask) -struct Slit { - Window frame; - - /* user-requested position stuff */ - SlitPosition pos; - int gravity; - int user_x, user_y; - - /* actual position (when not auto-hidden) */ - int x, y; - int w, h; - - gboolean horz; - gboolean hide; - gboolean hidden; - - Appearance *a_frame; - - Timer *hide_timer; - - GList *slit_apps; -}; - GHashTable *slit_map = NULL; GHashTable *slit_app_map = NULL;@@ -53,12 +28,14 @@ slit_app_map = g_hash_table_new(g_int_hash, g_int_equal);
nslits = 1; slit = g_new0(struct Slit, nslits); + slit->obwin.type = Window_Slit; for (i = 0; i < nslits; ++i) { slit[i].horz = FALSE; slit[i].hide = FALSE; slit[i].hidden = TRUE; slit[i].pos = SlitPos_TopRight; + slit[i].layer = Layer_Top; attrib.event_mask = SLIT_EVENT_MASK; attrib.override_redirect = True;@@ -71,6 +48,8 @@ XSetWindowBorder(ob_display, slit[i].frame, theme_b_color->pixel);
XSetWindowBorderWidth(ob_display, slit[i].frame, theme_bwidth); g_hash_table_insert(slit_map, &slit[i].frame, &slit[i]); + stacking_add(&slit[i]); + stacking_raise(SLIT_AS_WINDOW(&slit[i])); } }@@ -82,6 +61,7 @@ for (i = 0; i < nslits; ++i) {
XDestroyWindow(ob_display, slit[i].frame); appearance_free(slit[i].a_frame); g_hash_table_remove(slit_map, &slit[i].frame); + stacking_remove(&slit[i]); } g_hash_table_destroy(slit_app_map); g_hash_table_destroy(slit_map);
@@ -1,11 +1,52 @@
#ifndef __slit_h #define __slit_h +#include "timer.h" +#include "render/render.h" +#include "window.h" +#include "stacking.h" + #include <glib.h> #include <X11/Xlib.h> #include <X11/Xutil.h> -typedef struct Slit Slit; +typedef enum { + SlitPos_Floating, + SlitPos_TopLeft, + SlitPos_Top, + SlitPos_TopRight, + SlitPos_Right, + SlitPos_BottomRight, + SlitPos_Bottom, + SlitPos_BottomLeft, + SlitPos_Left +} SlitPosition; + +typedef struct Slit { + ObWindow obwin; + + Window frame; + StackLayer layer; + + /* user-requested position stuff */ + SlitPosition pos; + int gravity; + int user_x, user_y; + + /* actual position (when not auto-hidden) */ + int x, y; + int w, h; + + gboolean horz; + gboolean hide; + gboolean hidden; + + Appearance *a_frame; + + Timer *hide_timer; + + GList *slit_apps; +} Slit; typedef struct SlitApp { int ignore_unmaps;@@ -18,18 +59,6 @@ int y;
int w; int h; } SlitApp; - -typedef enum { - SlitPos_Floating, - SlitPos_TopLeft, - SlitPos_Top, - SlitPos_TopRight, - SlitPos_Right, - SlitPos_BottomRight, - SlitPos_Bottom, - SlitPos_BottomLeft, - SlitPos_Left -} SlitPosition; extern GHashTable *slit_map; extern GHashTable *slit_app_map;
@@ -4,28 +4,11 @@ #include "focus.h"
#include "client.h" #include "group.h" #include "frame.h" +#include "window.h" #include <glib.h> GList *stacking_list = NULL; -static Window top_window = None; - -void stacking_startup() -{ - XSetWindowAttributes attrib; - attrib.override_redirect = TRUE; - top_window = XCreateWindow(ob_display, ob_root, - -100, -100, 1, 1, 0, - CopyFromParent, InputOutput, CopyFromParent, - CWOverrideRedirect, &attrib); - XMapWindow(ob_display, top_window); -} - -void stacking_shutdown() -{ - XDestroyWindow(ob_display, top_window); -} - void stacking_set_list() { Window *windows, *win_it;@@ -44,7 +27,8 @@ windows = g_new(Window, size);
win_it = windows; for (it = g_list_last(stacking_list); it != NULL; it = it->prev, ++win_it) - *win_it = ((Client*)it->data)->window; + if (WINDOW_IS_CLIENT(it->data)) + *win_it = window_top(it->data); } else windows = NULL;@@ -67,7 +51,7 @@ return it;
return NULL; } -static void raise_recursive(Client *client) +static void raise_recursive(ObWindow *window) { Window wins[2]; /* only ever restack 2 windows. */ GList *it, *low;@@ -75,21 +59,27 @@ GSList *sit;
g_assert(stacking_list != NULL); /* this would be bad */ - /* remove the client before looking so we can't run into ourselves and our + /* remove the window before looking so we can't run into ourselves and our transients can't either. */ - stacking_list = g_list_remove(stacking_list, client); + stacking_list = g_list_remove(stacking_list, window); /* raise transients first */ - for (sit = client->transients; sit; sit = sit->next) - raise_recursive(sit->data); + if (WINDOW_IS_CLIENT(window)) { + Client *client = WINDOW_AS_CLIENT(window); + for (sit = client->transients; sit; sit = sit->next) + raise_recursive(sit->data); + } /* find 'it' where it is the positiion in the stacking order where - 'client' will be inserted *before* */ + 'window' will be inserted *before* */ - low = find_lowest_transient(client); + if (WINDOW_IS_CLIENT(window)) + low = find_lowest_transient(WINDOW_AS_CLIENT(window)); + else + low = NULL; /* the stacking list is from highest to lowest */ for (it = g_list_last(stacking_list); it; it = it->prev) { - if (it == low || client->layer < ((Client*)it->data)->layer) { + if (it == low || window_layer(window) < window_layer(it->data)) { it = it->next; break; }@@ -104,110 +94,112 @@ */
if (it == stacking_list) wins[0] = focus_backup; else if (it != NULL) - wins[0] = ((Client*)it->prev->data)->frame->window; + wins[0] = window_top(it->prev->data); else - wins[0] = ((Client*)g_list_last(stacking_list)->data)->frame->window; - wins[1] = client->frame->window; + wins[0] = window_top(g_list_last(stacking_list)->data); + wins[1] = window_top(window); - stacking_list = g_list_insert_before(stacking_list, it, client); + stacking_list = g_list_insert_before(stacking_list, it, window); XRestackWindows(ob_display, wins, 2); } -void stacking_raise(Client *client) +void stacking_raise(ObWindow *window) { g_assert(stacking_list != NULL); /* this would be bad */ - /* move up the transient chain as far as possible first */ - while (client->transient_for) { - if (client->transient_for != TRAN_GROUP) { - client = client->transient_for; - } else { - GSList *it; + if (WINDOW_IS_CLIENT(window)) { + Client *client = WINDOW_AS_CLIENT(window); + /* move up the transient chain as far as possible first */ + while (client->transient_for) { + if (client->transient_for != TRAN_GROUP) { + client = client->transient_for; + } else { + GSList *it; - /* the check for TRAN_GROUP is to prevent an infinate loop with - 2 transients of the same group at the head of the group's - members list */ - for (it = client->group->members; it; it = it->next) { - Client *c = it->data; + /* the check for TRAN_GROUP is to prevent an infinate loop with + 2 transients of the same group at the head of the group's + members list */ + for (it = client->group->members; it; it = it->next) { + Client *c = it->data; - if (c != client && c->transient_for != TRAN_GROUP) { - client = it->data; - break; + if (c != client && c->transient_for != TRAN_GROUP) { + client = it->data; + break; + } } + if (it == NULL) break; } - if (it == NULL) break; } + window = CLIENT_AS_WINDOW(client); } - raise_recursive(client); + raise_recursive(window); stacking_set_list(); } -static void lower_recursive(Client *client, Client *above) +static void lower_recursive(ObWindow *window, ObWindow *above) { Window wins[2]; /* only ever restack 2 windows. */ GList *it; GSList *sit; /* find 'it' where 'it' is the position in the stacking_list where the - 'client' will be placed *after* */ + 'window' will be placed *after* */ for (it = g_list_last(stacking_list); it != stacking_list; it = it->prev) - if (client->layer <= ((Client*)it->data)->layer && it->data != above) + if (window_layer(window) <= window_layer(it->data) && + it->data != above) break; - if (it->data != client) { /* not already the bottom */ - wins[0] = ((Client*)it->data)->frame->window; - wins[1] = client->frame->window; + if (it->data != window) { /* not already the bottom */ + wins[0] = window_top(it->data); + wins[1] = window_top(window); - stacking_list = g_list_remove(stacking_list, client); - stacking_list = g_list_insert_before(stacking_list, it->next, client); + stacking_list = g_list_remove(stacking_list, window); + stacking_list = g_list_insert_before(stacking_list, it->next, window); XRestackWindows(ob_display, wins, 2); } - for (sit = client->transients; sit; sit = sit->next) - lower_recursive(sit->data, client); + if (WINDOW_IS_CLIENT(window)) { + Client *client = WINDOW_AS_CLIENT(window); + for (sit = client->transients; sit; sit = sit->next) + lower_recursive(CLIENT_AS_WINDOW(sit->data), window); + } } -void stacking_lower(Client *client) +void stacking_lower(ObWindow *window) { g_assert(stacking_list != NULL); /* this would be bad */ - /* move up the transient chain as far as possible first */ - while (client->transient_for) { - if (client->transient_for != TRAN_GROUP) { - client = client->transient_for; - } else { - GSList *it; + if (WINDOW_IS_CLIENT(window)) { + Client *client = WINDOW_AS_CLIENT(window); + /* move up the transient chain as far as possible first */ + while (client->transient_for) { + if (client->transient_for != TRAN_GROUP) { + client = client->transient_for; + } else { + GSList *it; - /* the check for TRAN_GROUP is to prevent an infinate loop with - 2 transients of the same group at the head of the group's - members list */ - for (it = client->group->members; it; it = it->next) { - Client *c = it->data; + /* the check for TRAN_GROUP is to prevent an infinate loop with + 2 transients of the same group at the head of the group's + members list */ + for (it = client->group->members; it; it = it->next) { + Client *c = it->data; - if (c != client && c->transient_for != TRAN_GROUP) { - client = it->data; - break; + if (c != client && c->transient_for != TRAN_GROUP) { + client = it->data; + break; + } } + if (it == NULL) break; } - if (it == NULL) break; } + window = CLIENT_AS_WINDOW(client); } - lower_recursive(client, NULL); + lower_recursive(window, NULL); stacking_set_list(); } - -void stacking_raise_internal(Window win) -{ - Window wins[2]; /* only ever restack 2 windows. */ - - wins[0] = top_window; - wins[1] = win; - - XRestackWindows(ob_display, wins, 2); -}
@@ -1,46 +1,42 @@
#ifndef __stacking_h #define __stacking_h +#include "window.h" + #include <glib.h> #include <X11/Xlib.h> -struct Client; - /*! The possible stacking layers a client window can be a part of */ typedef enum { - Layer_Icon, /*!< 0 - iconified windows, in any order at all */ - Layer_Desktop, /*!< 1 - desktop windows */ - Layer_Below, /*!< 2 - normal windows w/ below */ - Layer_Normal, /*!< 3 - normal windows */ - Layer_Above, /*!< 4 - normal windows w/ above */ - Layer_Top, /*!< 5 - always-on-top-windows (docks?) */ - Layer_Fullscreen, /*!< 6 - fullscreeen windows */ - Layer_Internal /*!< 7 - openbox windows/menus */ + Layer_Desktop, /*!< 0 - desktop windows */ + Layer_Below, /*!< 1 - normal windows w/ below */ + Layer_Normal, /*!< 2 - normal windows */ + Layer_Above, /*!< 3 - normal windows w/ above */ + Layer_Top, /*!< 4 - always-on-top-windows (docks?) */ + Layer_Fullscreen, /*!< 5 - fullscreeen windows */ + Layer_Internal /*!< 6 - openbox windows/menus */ } StackLayer; -/* list of Client*s in stacking order from highest to lowest */ +/* list of ObWindow*s in stacking order from highest to lowest */ extern GList *stacking_list; -void stacking_startup(); -void stacking_shutdown(); +/*! Sets the window stacking list on the root window from the + stacking_list */ +void stacking_set_list(); -/*! Sets the client stacking list on the root window from the - stacking_clientlist */ -void stacking_set_list(); +#define stacking_add(win) stacking_list = g_list_append(stacking_list, win); +#define stacking_remove(win) stacking_list = g_list_remove(stacking_list, win); -/*! Raises a client window above all others in its stacking layer +/*! Raises a window above all others in its stacking layer raiseWindow has a couple of constraints that lowerWindow does not.<br> - 1) raiseWindow can be called after changing a Client's stack layer, and + 1) raiseWindow can be called after changing a Window's stack layer, and the list will be reorganized properly.<br> 2) raiseWindow guarantees that XRestackWindows() will <i>always</i> be - called for the specified client. + called for the specified window. */ -void stacking_raise(struct Client *client); +void stacking_raise(ObWindow *window); /*! Lowers a client window below all others in its stacking layer */ -void stacking_lower(struct Client *client); - -/*! Raises an internal window (e.g. menus) */ -void stacking_raise_internal(Window win); +void stacking_lower(ObWindow *window); #endif
@@ -0,0 +1,33 @@
+#include "window.h" +#include "menu.h" +#include "slit.h" +#include "client.h" +#include "frame.h" + +Window window_top(ObWindow *self) +{ + switch (self->type) { + case Window_Menu: + return ((Menu*)self)->frame; + case Window_Slit: + return ((Slit*)self)->frame; + case Window_Client: + return ((Client*)self)->frame->window; + } + g_assert_not_reached(); + return None; +} + +Window window_layer(ObWindow *self) +{ + switch (self->type) { + case Window_Menu: + return Layer_Internal; + case Window_Slit: + return ((Slit*)self)->layer; + case Window_Client: + return ((Client*)self)->layer; + } + g_assert_not_reached(); + return None; +}
@@ -0,0 +1,35 @@
+#ifndef __window_h +#define __window_h + +#include <X11/Xlib.h> + +typedef enum { + Window_Menu, + Window_Slit, + Window_Client +} Window_InternalType; + +typedef struct ObWindow { + Window_InternalType type; +} ObWindow; + +#define WINDOW_IS_MENU(win) (((ObWindow*)win)->type == Window_Menu) +#define WINDOW_IS_SLIT(win) (((ObWindow*)win)->type == Window_Slit) +#define WINDOW_IS_CLIENT(win) (((ObWindow*)win)->type == Window_Client) + +struct Menu; +struct Slit; +struct Client; + +#define WINDOW_AS_MENU(win) ((struct Menu*)win) +#define WINDOW_AS_SLIT(win) ((struct Slit*)win) +#define WINDOW_AS_CLIENT(win) ((struct Client*)win) + +#define MENU_AS_WINDOW(menu) ((ObWindow*)menu) +#define SLIT_AS_WINDOW(slit) ((ObWindow*)slit) +#define CLIENT_AS_WINDOW(client) ((ObWindow*)client) + +Window window_top(ObWindow *self); +Window window_layer(ObWindow *self); + +#endif
@@ -65,6 +65,8 @@ for (it = stacking_list; it != NULL; it = it->next) {
Client *target; int tl, tt, tr, tb; /* 1 past the target's edges on each side */ + if (!WINDOW_IS_CLIENT(it->data)) + continue; target = it->data; /* don't snap to self or non-visibles */ if (!target->frame->visible || target == c) continue;