all repos — openbox @ b77e40e1c7710323aa59a778338d8e18b591f718

openbox fork - make it a bit more like ryudo

rename "Slit" to "Dock".
add config options to the rc3 for the dock.
create a window_map, add DockApps to the ObWindow types, use the window_map for translating windows into objects for event handling (only one lookup now) and remove the old maps (client_map, menu_map).
Dana Jansens danakj@orodu.net
commit

b77e40e1c7710323aa59a778338d8e18b591f718

parent

6e42b65bda1706887f3b2a7f9d79ba20f7611a06

M data/rc3data/rc3

@@ -53,6 +53,39 @@

# the theme to display #theme = "operation" +[dock] +# The position on the screen to place the dock. Options are: +# Floating - uses the floatingX and floatingY options to position itself +# TopLeft, Top, TopRight, Right, BottomRight, Bottom, BottomLeft, Left +# - the appropriate corner/edge of the screen +#position = "TopLeft" + +# When position is "Floating", this specifies the x-coordinate to place the +# the dock at. +#floatingx = 0 + +# When position is "Floating", this specifies the y-coordinate to place the +# the dock at. +#floatingy = 0 + +# The stacking layer that the dock will be in. Options are: +# Top - above all normal windows, same layer as panels +# Normal - can be above and below normal windows +# Bottom - below all normal windows +#stacking = "Top" + +# When true, the dock will grow horizontally when dock apps are added to it, +# otherwise it will grow vertically. +#horizontal = no + +# When true, the dock will hide itself while the pointer is not over it, and +# will show itself when the pointer is. +#autoHide = no + +# The number of milliseconds to wait before hiding the dock when the pointer +# leaves it, if the autoHide option is on. +#hideTimeout = 3000 + [keyboard] #kbind (Key [Key...]) Action [Parameter]
M openbox/Makefile.amopenbox/Makefile.am

@@ -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 window.c + moveresize.c startup.c popup.c dock.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 window.h + dock.h window.h # kill the implicit .c.y rule %.c: %.y
M openbox/client.copenbox/client.c

@@ -1,5 +1,5 @@

#include "client.h" -#include "slit.h" +#include "dock.h" #include "startup.h" #include "screen.h" #include "moveresize.h"

@@ -26,7 +26,6 @@ #define CLIENT_NOPROPAGATEMASK (ButtonPressMask | ButtonReleaseMask | \

ButtonMotionMask) GList *client_list = NULL; -GHashTable *client_map = NULL; static void client_get_all(Client *self); static void client_toggle_border(Client *self, gboolean show);

@@ -41,20 +40,13 @@ static void client_change_allowed_actions(Client *self);

static void client_change_state(Client *self); static void client_apply_startup_state(Client *self); -static guint map_hash(Window *w) { return *w; } -static gboolean map_key_comp(Window *w1, Window *w2) { return *w1 == *w2; } - void client_startup() { - client_map = g_hash_table_new((GHashFunc)map_hash, - (GEqualFunc)map_key_comp); - client_set_list(); } void client_shutdown() { - g_hash_table_destroy(client_map); } void client_set_list()

@@ -117,7 +109,6 @@ unsigned int i, j, nchild;

Window w, *children; XWMHints *wmhints; XWindowAttributes attrib; - Client *active; XQueryTree(ob_display, ob_root, &w, &w, &children, &nchild);

@@ -154,19 +145,28 @@ why with stacking_lower? Why, because then windows who aren't in the

stacking list are on the top where you can see them instead of buried at the bottom! */ for (i = startup_stack_size; i > 0; --i) { - Client *c; + ObWindow *obw; w = startup_stack_order[i-1]; - c = g_hash_table_lookup(client_map, &w); - if (c) stacking_lower(CLIENT_AS_WINDOW(c)); + obw = g_hash_table_lookup(window_map, &w); + if (obw) { + g_assert(WINDOW_IS_CLIENT(obw)); + stacking_lower(CLIENT_AS_WINDOW(obw)); + } } g_free(startup_stack_order); startup_stack_order = NULL; startup_stack_size = 0; if (config_focus_new) { - active = g_hash_table_lookup(client_map, &startup_active); - if (!(active && client_focus(active))) + ObWindow *active; + + active = g_hash_table_lookup(window_map, &startup_active); + if (active) { + g_assert(WINDOW_IS_CLIENT(active)); + if (!client_focus(WINDOW_AS_CLIENT(active))) + focus_fallback(Fallback_NoFocus); + } else focus_fallback(Fallback_NoFocus); } }

@@ -203,7 +203,7 @@ /* is the window a docking app */

if ((wmhint = XGetWMHints(ob_display, window))) { if ((wmhint->flags & StateHint) && wmhint->initial_state == WithdrawnState) { - slit_add(window, wmhint); + dock_add(window, wmhint); grab_server(FALSE); XFree(wmhint); return;

@@ -245,7 +245,7 @@ grab_server(FALSE);

/* add to client list/map */ client_list = g_list_append(client_list, self); - g_hash_table_insert(client_map, &self->window, self); + g_hash_table_insert(window_map, &self->window, self); /* update the focus lists */ focus_order_add_new(self);

@@ -330,7 +330,7 @@ frame_hide(self->frame);

client_list = g_list_remove(client_list, self); stacking_remove(self); - g_hash_table_remove(client_map, &self->window); + g_hash_table_remove(window_map, &self->window); /* update the focus lists */ focus_order_remove(self);

@@ -673,9 +673,10 @@

if (XGetTransientForHint(ob_display, self->window, &t)) { self->transient = TRUE; if (t != self->window) { /* cant be transient to itself! */ - c = g_hash_table_lookup(client_map, &t); + c = g_hash_table_lookup(window_map, &t); /* if this happens then we need to check for it*/ g_assert(c != self); + g_assert(!c || WINDOW_IS_CLIENT(c)); if (!c && self->group) { /* not transient to a client, see if it is transient for a
M openbox/client.hopenbox/client.h

@@ -294,7 +294,6 @@ Pixmap pixmap_icon_mask;

} Client; extern GList *client_list; -extern GHashTable *client_map; void client_startup(); void client_shutdown();
M openbox/config.copenbox/config.c

@@ -9,11 +9,19 @@ gboolean config_focus_popup;

char *config_theme; -int config_desktops_num; +int config_desktops_num; GSList *config_desktops_names; gboolean config_opaque_move; gboolean config_opaque_resize; + +StackLayer config_dock_layer; +DockPosition config_dock_pos; +int config_dock_x; +int config_dock_y; +gboolean config_dock_horz; +gboolean config_dock_hide; +guint config_dock_hide_timeout; static void parse_focus(char *name, ParseToken *value) {

@@ -118,6 +126,81 @@ yyerror("invalid option");

parse_free_token(value); } +static void parse_dock(char *name, ParseToken *value) +{ + if (!g_ascii_strcasecmp(name, "stacking")) { + if (value->type != TOKEN_STRING) + yyerror("invalid value"); + else { + if (!g_ascii_strcasecmp(value->data.string, "bottom")) + config_dock_layer = Layer_Below; + else if (!g_ascii_strcasecmp(value->data.string, "normal")) + config_dock_layer = Layer_Normal; + else if (!g_ascii_strcasecmp(value->data.string, "top")) + config_dock_layer = Layer_Top; + else + yyerror("invalid layer"); + } + } else if (!g_ascii_strcasecmp(name, "position")) { + if (value->type != TOKEN_STRING) + yyerror("invalid value"); + else { + if (!g_ascii_strcasecmp(value->data.string, "topleft")) + config_dock_pos = DockPos_TopLeft; + else if (!g_ascii_strcasecmp(value->data.string, "top")) + config_dock_pos = DockPos_Top; + else if (!g_ascii_strcasecmp(value->data.string, "topright")) + config_dock_pos = DockPos_TopRight; + else if (!g_ascii_strcasecmp(value->data.string, "right")) + config_dock_pos = DockPos_Right; + else if (!g_ascii_strcasecmp(value->data.string, "bottomright")) + config_dock_pos = DockPos_BottomRight; + else if (!g_ascii_strcasecmp(value->data.string, "bottom")) + config_dock_pos = DockPos_Bottom; + else if (!g_ascii_strcasecmp(value->data.string, "bottomleft")) + config_dock_pos = DockPos_BottomLeft; + else if (!g_ascii_strcasecmp(value->data.string, "left")) + config_dock_pos = DockPos_Left; + else if (!g_ascii_strcasecmp(value->data.string, "floating")) + config_dock_pos = DockPos_Floating; + else + yyerror("invalid position"); + } + } else if (!g_ascii_strcasecmp(name, "floatingx")) { + if (value->type != TOKEN_INTEGER) + yyerror("invalid value"); + else { + config_dock_x = value->data.integer; + } + } else if (!g_ascii_strcasecmp(name, "floatingy")) { + if (value->type != TOKEN_INTEGER) + yyerror("invalid value"); + else { + config_dock_y = value->data.integer; + } + } else if (!g_ascii_strcasecmp(name, "horizontal")) { + if (value->type != TOKEN_BOOL) + yyerror("invalid value"); + else { + config_dock_horz = value->data.bool; + } + } else if (!g_ascii_strcasecmp(name, "autohide")) { + if (value->type != TOKEN_BOOL) + yyerror("invalid value"); + else { + config_dock_hide = value->data.bool; + } + } else if (!g_ascii_strcasecmp(name, "hidetimeout")) { + if (value->type != TOKEN_INTEGER) + yyerror("invalid value"); + else { + config_dock_hide_timeout = value->data.integer; + } + } else + yyerror("invalid option"); + parse_free_token(value); +} + void config_startup() { config_focus_new = TRUE;

@@ -141,6 +224,16 @@ config_opaque_move = TRUE;

config_opaque_resize = TRUE; parse_reg_section("moveresize", NULL, parse_moveresize); + + config_dock_layer = Layer_Top; + config_dock_pos = DockPos_TopRight; + config_dock_x = 0; + config_dock_y = 0; + config_dock_horz = FALSE; + config_dock_hide = FALSE; + config_dock_hide_timeout = 3000; + + parse_reg_section("dock", NULL, parse_dock); } void config_shutdown()
M openbox/config.hopenbox/config.h

@@ -1,6 +1,9 @@

#ifndef __config_h #define __config_h +#include "dock.h" +#include "stacking.h" + #include <glib.h> /*! Should new windows be focused */

@@ -21,6 +24,23 @@ extern gboolean config_opaque_move;

/*! When true windows are resize opaquely, when false just an outline is shown while they are resize */ extern gboolean config_opaque_resize; + +/*! The stacking layer the dock will reside in */ +extern StackLayer config_dock_layer; +/*! The position at which to place the dock */ +extern DockPosition config_dock_pos; +/*! If config_dock_pos is DockPos_Floating, this is the top-left corner's + position */ +extern int config_dock_x; +/*! If config_dock_pos is DockPos_Floating, this is the top-left corner's + position */ +extern int config_dock_y; +/*! Whether the dock places the dockapps in it horizontally or vertically */ +extern gboolean config_dock_horz; +/*! Whether to auto-hide the dock when the pointer is not over it */ +extern gboolean config_dock_hide; +/*! The number of milliseconds to wait before hiding the dock */ +extern guint config_dock_hide_timeout; /* The name of the theme */ char *config_theme;
A openbox/dock.c

@@ -0,0 +1,382 @@

+#include "dock.h" +#include "screen.h" +#include "config.h" +#include "grab.h" +#include "openbox.h" +#include "render/theme.h" + +#define DOCK_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \ + EnterWindowMask | LeaveWindowMask) +#define DOCKAPP_EVENT_MASK (StructureNotifyMask) + +static Dock *dock; + +void dock_startup() +{ + XSetWindowAttributes attrib; + int i; + + dock = g_new0(struct Dock, 1); + dock->obwin.type = Window_Dock; + + dock->hidden = TRUE; + + attrib.event_mask = DOCK_EVENT_MASK; + attrib.override_redirect = True; + dock->frame = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0, + render_depth, InputOutput, render_visual, + CWOverrideRedirect | CWEventMask, + &attrib); + dock->a_frame = appearance_copy(theme_a_unfocused_title); + XSetWindowBorder(ob_display, dock->frame, theme_b_color->pixel); + XSetWindowBorderWidth(ob_display, dock->frame, theme_bwidth); + + g_hash_table_insert(window_map, &dock->frame, dock); + stacking_add(DOCK_AS_WINDOW(&dock[i])); + stacking_raise(DOCK_AS_WINDOW(&dock[i])); +} + +void dock_shutdown() +{ + XDestroyWindow(ob_display, dock->frame); + appearance_free(dock->a_frame); + g_hash_table_remove(window_map, &dock->frame); + stacking_remove(dock); +} + +void dock_add(Window win, XWMHints *wmhints) +{ + DockApp *app; + XWindowAttributes attrib; + + app = g_new0(DockApp, 1); + app->win = win; + app->icon_win = (wmhints->flags & IconWindowHint) ? + wmhints->icon_window : win; + + if (XGetWindowAttributes(ob_display, app->icon_win, &attrib)) { + app->w = attrib.width; + app->h = attrib.height; + } else { + app->w = app->h = 64; + } + + dock->dock_apps = g_list_append(dock->dock_apps, app); + dock_configure(); + + XReparentWindow(ob_display, app->icon_win, dock->frame, app->x, app->y); + /* + This is the same case as in frame.c for client windows. When Openbox is + starting, the window is already mapped so we see unmap events occur for + it. There are 2 unmap events generated that we see, one with the 'event' + member set the root window, and one set to the client, but both get + handled and need to be ignored. + */ + if (ob_state == State_Starting) + app->ignore_unmaps += 2; + + if (app->win != app->icon_win) { + /* have to map it so that it can be re-managed on a restart */ + XMoveWindow(ob_display, app->win, -1000, -1000); + XMapWindow(ob_display, app->win); + } + XMapWindow(ob_display, app->icon_win); + XSync(ob_display, False); + + /* specify that if we exit, the window should not be destroyed and should + be reparented back to root automatically */ + XChangeSaveSet(ob_display, app->icon_win, SetModeInsert); + XSelectInput(ob_display, app->icon_win, DOCKAPP_EVENT_MASK); + + grab_button_full(2, 0, app->icon_win, + ButtonPressMask | ButtonReleaseMask | ButtonMotionMask, + GrabModeAsync, ob_cursors.move); + + g_hash_table_insert(window_map, &app->icon_win, app); + + g_message("Managed Dock App: 0x%lx", app->icon_win); +} + +void dock_remove_all() +{ + while (dock->dock_apps) + dock_remove(dock->dock_apps->data, TRUE); +} + +void dock_remove(DockApp *app, gboolean reparent) +{ + ungrab_button(2, 0, app->icon_win); + XSelectInput(ob_display, app->icon_win, NoEventMask); + /* remove the window from our save set */ + XChangeSaveSet(ob_display, app->icon_win, SetModeDelete); + XSync(ob_display, False); + + g_hash_table_remove(window_map, &app->icon_win); + + if (reparent) + XReparentWindow(ob_display, app->icon_win, ob_root, app->x, app->y); + + dock->dock_apps = g_list_remove(dock->dock_apps, app); + dock_configure(); + + g_message("Unmanaged Dock App: 0x%lx", app->icon_win); + + g_free(app); +} + +void dock_configure() +{ + GList *it; + int spot; + int gravity; + + dock->w = dock->h = spot = 0; + + for (it = dock->dock_apps; it; it = it->next) { + struct DockApp *app = it->data; + if (config_dock_horz) { + app->x = spot; + app->y = 0; + dock->w += app->w; + dock->h = MAX(dock->h, app->h); + spot += app->w; + } else { + app->x = 0; + app->y = spot; + dock->w = MAX(dock->w, app->w); + dock->h += app->h; + spot += app->h; + } + + XMoveWindow(ob_display, app->icon_win, app->x, app->y); + } + + /* used for calculating offsets */ + dock->w += theme_bwidth * 2; + dock->h += theme_bwidth * 2; + + /* calculate position */ + switch (config_dock_pos) { + case DockPos_Floating: + dock->x = config_dock_x; + dock->y = config_dock_y; + gravity = NorthWestGravity; + break; + case DockPos_TopLeft: + dock->x = 0; + dock->y = 0; + gravity = NorthWestGravity; + break; + case DockPos_Top: + dock->x = screen_physical_size.width / 2; + dock->y = 0; + gravity = NorthGravity; + break; + case DockPos_TopRight: + dock->x = screen_physical_size.width; + dock->y = 0; + gravity = NorthEastGravity; + break; + case DockPos_Left: + dock->x = 0; + dock->y = screen_physical_size.height / 2; + gravity = WestGravity; + break; + case DockPos_Right: + dock->x = screen_physical_size.width; + dock->y = screen_physical_size.height / 2; + gravity = EastGravity; + break; + case DockPos_BottomLeft: + dock->x = 0; + dock->y = screen_physical_size.height; + gravity = SouthWestGravity; + break; + case DockPos_Bottom: + dock->x = screen_physical_size.width / 2; + dock->y = screen_physical_size.height; + gravity = SouthGravity; + break; + case DockPos_BottomRight: + dock->x = screen_physical_size.width; + dock->y = screen_physical_size.height; + gravity = SouthEastGravity; + break; + } + + switch(gravity) { + case NorthGravity: + case CenterGravity: + case SouthGravity: + dock->x -= dock->w / 2; + break; + case NorthEastGravity: + case EastGravity: + case SouthEastGravity: + dock->x -= dock->w; + break; + } + switch(gravity) { + case WestGravity: + case CenterGravity: + case EastGravity: + dock->y -= dock->h / 2; + break; + case SouthWestGravity: + case SouthGravity: + case SouthEastGravity: + dock->y -= dock->h; + break; + } + + if (config_dock_hide && dock->hidden) { + switch (config_dock_pos) { + case DockPos_Floating: + break; + case DockPos_TopLeft: + if (config_dock_horz) + dock->y -= dock->h - theme_bwidth; + else + dock->x -= dock->w - theme_bwidth; + break; + case DockPos_Top: + dock->y -= dock->h - theme_bwidth; + break; + case DockPos_TopRight: + if (config_dock_horz) + dock->y -= dock->h - theme_bwidth; + else + dock->x += dock->w - theme_bwidth; + break; + case DockPos_Left: + dock->x -= dock->w - theme_bwidth; + break; + case DockPos_Right: + dock->x += dock->w - theme_bwidth; + break; + case DockPos_BottomLeft: + if (config_dock_horz) + dock->y += dock->h - theme_bwidth; + else + dock->x -= dock->w - theme_bwidth; + break; + case DockPos_Bottom: + dock->y += dock->h - theme_bwidth; + break; + case DockPos_BottomRight: + if (config_dock_horz) + dock->y += dock->h - theme_bwidth; + else + dock->x += dock->w - theme_bwidth; + break; + } + } + + /* not used for actually sizing shit */ + dock->w -= theme_bwidth * 2; + dock->h -= theme_bwidth * 2; + + if (dock->w > 0 && dock->h > 0) { + RECT_SET(dock->a_frame->area, 0, 0, dock->w, dock->h); + XMoveResizeWindow(ob_display, dock->frame, + dock->x, dock->y, dock->w, dock->h); + + paint(dock->frame, dock->a_frame); + XMapWindow(ob_display, dock->frame); + } else + XUnmapWindow(ob_display, dock->frame); + + /* but they are useful outside of this function! */ + dock->w += theme_bwidth * 2; + dock->h += theme_bwidth * 2; +} + +void dock_app_configure(DockApp *app, int w, int h) +{ + app->w = w; + app->h = h; + dock_configure(); +} + +void dock_app_drag(DockApp *app, XMotionEvent *e) +{ + DockApp *over = NULL; + GList *it; + int x, y; + gboolean after; + + x = e->x_root; + y = e->y_root; + + /* are we on top of the dock? */ + if (!(x >= dock->x && + y >= dock->y && + x < dock->x + dock->w && + y < dock->y + dock->h)) + return; + + x -= dock->x; + y -= dock->y; + + /* which dock app are we on top of? */ + for (it = dock->dock_apps; it; it = it->next) { + over = it->data; + if (config_dock_horz) { + if (x >= over->x && x < over->x + over->w) + break; + } else { + if (y >= over->y && y < over->y + over->h) + break; + } + } + if (!it || app == over) return; + + x -= over->x; + y -= over->y; + + if (config_dock_horz) + after = (x > over->w / 2); + else + after = (y > over->h / 2); + + /* remove before doing the it->next! */ + dock->dock_apps = g_list_remove(dock->dock_apps, app); + + if (after) it = it->next; + + dock->dock_apps = g_list_insert_before(dock->dock_apps, it, app); + dock_configure(); +} + +static void hide_timeout(void *n) +{ + /* dont repeat */ + timer_stop(dock->hide_timer); + dock->hide_timer = NULL; + + /* hide */ + dock->hidden = TRUE; + dock_configure(); +} + +void dock_hide(gboolean hide) +{ + if (dock->hidden == hide || !config_dock_hide) + return; + if (!hide) { + /* show */ + dock->hidden = FALSE; + dock_configure(); + + /* if was hiding, stop it */ + if (dock->hide_timer) { + timer_stop(dock->hide_timer); + dock->hide_timer = NULL; + } + } else { + g_assert(!dock->hide_timer); + dock->hide_timer = timer_start(config_dock_hide_timeout * 1000, + (TimeoutHandler)hide_timeout, + NULL); + } +}
A openbox/dock.h

@@ -0,0 +1,66 @@

+#ifndef __dock_h +#define __dock_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 enum { + DockPos_Floating, + DockPos_TopLeft, + DockPos_Top, + DockPos_TopRight, + DockPos_Right, + DockPos_BottomRight, + DockPos_Bottom, + DockPos_BottomLeft, + DockPos_Left +} DockPosition; + +typedef struct Dock { + ObWindow obwin; + + Window frame; + Appearance *a_frame; + + /* actual position (when not auto-hidden) */ + int x, y; + int w, h; + + gboolean hidden; + Timer *hide_timer; + + GList *dock_apps; +} Dock; + +typedef struct DockApp { + int ignore_unmaps; + + Window icon_win; + Window win; + int x; + int y; + int w; + int h; +} DockApp; + +void dock_startup(); +void dock_shutdown(); + +void dock_configure(); +void dock_hide(gboolean hide); + +void dock_add(Window win, XWMHints *wmhints); + +void dock_remove_all(); +void dock_remove(DockApp *app, gboolean reparent); + +void dock_app_drag(DockApp *app, XMotionEvent *e); +void dock_app_configure(DockApp *app, int w, int h); + +#endif
M openbox/event.copenbox/event.c

@@ -1,5 +1,5 @@

#include "openbox.h" -#include "slit.h" +#include "dock.h" #include "client.h" #include "xerror.h" #include "prop.h"

@@ -27,8 +27,8 @@ #endif

static void event_process(XEvent *e); static void event_handle_root(XEvent *e); -static void event_handle_slit(Slit *s, XEvent *e); -static void event_handle_slitapp(SlitApp *app, XEvent *e); +static void event_handle_dock(Dock *s, XEvent *e); +static void event_handle_dockapp(DockApp *app, XEvent *e); static void event_handle_client(Client *c, XEvent *e); static void event_handle_menu(Menu *menu, XEvent *e);

@@ -394,15 +394,32 @@ static void event_process(XEvent *e)

{ Window window; Client *client = NULL; - Slit *slit = NULL; - SlitApp *slitapp = NULL; + Dock *dock = NULL; + DockApp *dockapp = NULL; Menu *menu = NULL; + ObWindow *obwin = NULL; window = event_get_window(e); - if (!(client = g_hash_table_lookup(client_map, &window))) - if (!(slitapp = g_hash_table_lookup(slit_app_map, &window))) - if (!(slit = g_hash_table_lookup(slit_map, &window))) - menu = g_hash_table_lookup(menu_map, &window); + if ((obwin = g_hash_table_lookup(window_map, &window))) { + switch (obwin->type) { + case Window_Dock: + dock = WINDOW_AS_DOCK(obwin); + break; + case Window_DockApp: + dockapp = WINDOW_AS_DOCKAPP(obwin); + break; + case Window_Menu: + menu = WINDOW_AS_MENU(obwin); + break; + case Window_Client: + client = WINDOW_AS_CLIENT(obwin); + break; + case Window_Internal: + /* not to be used for events */ + g_assert_not_reached(); + break; + } + } event_set_lasttime(e); event_hack_mods(e);

@@ -415,10 +432,10 @@ event_handle_menu(menu, e);

return; } else if (client) event_handle_client(client, e); - else if (slitapp) - event_handle_slitapp(slitapp, e); - else if (slit) - event_handle_slit(slit, e); + else if (dockapp) + event_handle_dockapp(dockapp, e); + else if (dock) + event_handle_dock(dock, e); else if (window == ob_root) event_handle_root(e); else if (e->type == MapRequest)

@@ -969,41 +986,41 @@ {

g_datalist_foreach(&fd_handler_list, fd_event_handle_foreach, NULL); } -static void event_handle_slit(Slit *s, XEvent *e) +static void event_handle_dock(Dock *s, XEvent *e) { switch (e->type) { case ButtonPress: - stacking_raise(SLIT_AS_WINDOW(s)); + stacking_raise(DOCK_AS_WINDOW(s)); case EnterNotify: - slit_hide(s, FALSE); + dock_hide(FALSE); break; case LeaveNotify: - slit_hide(s, TRUE); + dock_hide(TRUE); break; } } -static void event_handle_slitapp(SlitApp *app, XEvent *e) +static void event_handle_dockapp(DockApp *app, XEvent *e) { switch (e->type) { case MotionNotify: - slit_app_drag(app, &e->xmotion); + dock_app_drag(app, &e->xmotion); break; case UnmapNotify: if (app->ignore_unmaps) { app->ignore_unmaps--; break; } - slit_remove(app, TRUE); + dock_remove(app, TRUE); break; case DestroyNotify: - slit_remove(app, FALSE); + dock_remove(app, FALSE); break; case ReparentNotify: - slit_remove(app, FALSE); + dock_remove(app, FALSE); break; case ConfigureNotify: - slit_app_configure(app, e->xconfigure.width, e->xconfigure.height); + dock_app_configure(app, e->xconfigure.width, e->xconfigure.height); break; } }
M openbox/frame.copenbox/frame.c

@@ -430,20 +430,20 @@ XMapWindow(ob_display, client->window);

frame_adjust_area(self, TRUE, TRUE); - /* set all the windows for the frame in the client_map */ - g_hash_table_insert(client_map, &self->window, client); - g_hash_table_insert(client_map, &self->plate, client); - g_hash_table_insert(client_map, &self->title, client); - g_hash_table_insert(client_map, &self->label, client); - g_hash_table_insert(client_map, &self->max, client); - g_hash_table_insert(client_map, &self->close, client); - g_hash_table_insert(client_map, &self->desk, client); - g_hash_table_insert(client_map, &self->shade, client); - g_hash_table_insert(client_map, &self->icon, client); - g_hash_table_insert(client_map, &self->iconify, client); - g_hash_table_insert(client_map, &self->handle, client); - g_hash_table_insert(client_map, &self->lgrip, client); - g_hash_table_insert(client_map, &self->rgrip, client); + /* set all the windows for the frame in the window_map */ + g_hash_table_insert(window_map, &self->window, client); + g_hash_table_insert(window_map, &self->plate, client); + g_hash_table_insert(window_map, &self->title, client); + g_hash_table_insert(window_map, &self->label, client); + g_hash_table_insert(window_map, &self->max, client); + g_hash_table_insert(window_map, &self->close, client); + g_hash_table_insert(window_map, &self->desk, client); + g_hash_table_insert(window_map, &self->shade, client); + g_hash_table_insert(window_map, &self->icon, client); + g_hash_table_insert(window_map, &self->iconify, client); + g_hash_table_insert(window_map, &self->handle, client); + g_hash_table_insert(window_map, &self->lgrip, client); + g_hash_table_insert(window_map, &self->rgrip, client); } void frame_release_client(Frame *self, Client *client)

@@ -470,20 +470,20 @@ client->area.x,

client->area.y); } - /* remove all the windows for the frame from the client_map */ - g_hash_table_remove(client_map, &self->window); - g_hash_table_remove(client_map, &self->plate); - g_hash_table_remove(client_map, &self->title); - g_hash_table_remove(client_map, &self->label); - g_hash_table_remove(client_map, &self->max); - g_hash_table_remove(client_map, &self->close); - g_hash_table_remove(client_map, &self->desk); - g_hash_table_remove(client_map, &self->shade); - g_hash_table_remove(client_map, &self->icon); - g_hash_table_remove(client_map, &self->iconify); - g_hash_table_remove(client_map, &self->handle); - g_hash_table_remove(client_map, &self->lgrip); - g_hash_table_remove(client_map, &self->rgrip); + /* remove all the windows for the frame from the window_map */ + g_hash_table_remove(window_map, &self->window); + g_hash_table_remove(window_map, &self->plate); + g_hash_table_remove(window_map, &self->title); + g_hash_table_remove(window_map, &self->label); + g_hash_table_remove(window_map, &self->max); + g_hash_table_remove(window_map, &self->close); + g_hash_table_remove(window_map, &self->desk); + g_hash_table_remove(window_map, &self->shade); + g_hash_table_remove(window_map, &self->icon); + g_hash_table_remove(window_map, &self->iconify); + g_hash_table_remove(window_map, &self->handle); + g_hash_table_remove(window_map, &self->lgrip); + g_hash_table_remove(window_map, &self->rgrip); frame_free(self); }
M openbox/menu.copenbox/menu.c

@@ -8,7 +8,6 @@ #include "geom.h"

#include "plugin.h" static GHashTable *menu_hash = NULL; -GHashTable *menu_map = NULL; #define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask | \ LeaveWindowMask)

@@ -34,9 +33,9 @@

g_free(self->label); g_free(self->name); - g_hash_table_remove(menu_map, &self->title); - g_hash_table_remove(menu_map, &self->frame); - g_hash_table_remove(menu_map, &self->items); + g_hash_table_remove(window_map, &self->title); + g_hash_table_remove(window_map, &self->frame); + g_hash_table_remove(window_map, &self->items); stacking_remove(self);

@@ -53,7 +52,7 @@ {

g_free(self->label); action_free(self->action); - g_hash_table_remove(menu_map, &self->item); + g_hash_table_remove(window_map, &self->item); appearance_free(self->a_item); appearance_free(self->a_disabled);

@@ -73,7 +72,6 @@

menu_hash = g_hash_table_new_full(g_str_hash, g_str_equal, menu_destroy_hash_key, (GDestroyNotify)menu_destroy_hash_value); - menu_map = g_hash_table_new(g_int_hash, g_int_equal); m = menu_new(NULL, "root", NULL);

@@ -137,7 +135,6 @@

void menu_shutdown() { g_hash_table_destroy(menu_hash); - g_hash_table_destroy(menu_map); } static Window createWindow(Window parent, unsigned long mask,

@@ -195,9 +192,9 @@

self->a_title = appearance_copy(theme_a_menu_title); self->a_items = appearance_copy(theme_a_menu); - g_hash_table_insert(menu_map, &self->frame, self); - g_hash_table_insert(menu_map, &self->title, self); - g_hash_table_insert(menu_map, &self->items, self); + g_hash_table_insert(window_map, &self->frame, self); + g_hash_table_insert(window_map, &self->title, self); + g_hash_table_insert(window_map, &self->items, self); g_hash_table_insert(menu_hash, g_strdup(name), self); stacking_add(MENU_AS_WINDOW(self));

@@ -259,7 +256,7 @@ entry->a_hilite = appearance_copy(theme_a_menu_hilite);

menu->invalid = TRUE; - g_hash_table_insert(menu_map, &entry->item, menu); + g_hash_table_insert(window_map, &entry->item, menu); } void menu_show(char *name, int x, int y, Client *client)
M openbox/menu.hopenbox/menu.h

@@ -7,8 +7,6 @@ #include "geom.h"

#include <glib.h> -extern GHashTable *menu_map; - struct Menu; struct MenuEntry;
M openbox/openbox.copenbox/openbox.c

@@ -1,5 +1,5 @@

#include "openbox.h" -#include "slit.h" +#include "dock.h" #include "event.h" #include "menu.h" #include "client.h"

@@ -184,6 +184,7 @@ theme = theme_load(config_theme);

g_free(theme); if (!theme) return 1; + window_startup(); menu_startup(); frame_startup(); moveresize_startup();

@@ -191,7 +192,7 @@ focus_startup();

screen_startup(); group_startup(); client_startup(); - slit_startup(); + dock_startup(); /* call startup for all the plugins */ plugin_startall();

@@ -204,11 +205,11 @@ while (!ob_shutdown)

event_loop(); ob_state = State_Exiting; - slit_remove_all(); + dock_remove_all(); client_unmanage_all(); plugin_shutdown(); /* calls all the plugins' shutdown functions */ - slit_shutdown(); + dock_shutdown(); client_shutdown(); group_shutdown(); screen_shutdown();

@@ -216,6 +217,7 @@ focus_shutdown();

moveresize_shutdown(); frame_shutdown(); menu_shutdown(); + window_shutdown(); grab_shutdown(); event_shutdown(); theme_shutdown();
M openbox/screen.copenbox/screen.c

@@ -1,5 +1,5 @@

#include "openbox.h" -#include "slit.h" +#include "dock.h" #include "prop.h" #include "startup.h" #include "config.h"

@@ -219,7 +219,7 @@

if (ob_state == State_Starting) return; - slit_configure_all(); + dock_configure(); screen_update_struts(); for (it = client_list; it; it = it->next)
D openbox/slit.c

@@ -1,424 +0,0 @@

-#include "slit.h" -#include "screen.h" -#include "grab.h" -#include "openbox.h" -#include "render/theme.h" - -#define SLIT_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \ - EnterWindowMask | LeaveWindowMask) -#define SLITAPP_EVENT_MASK (StructureNotifyMask) - -GHashTable *slit_map = NULL; -GHashTable *slit_app_map = NULL; - -static Slit *slit; -static int nslits; - -static guint slit_hide_timeout = 3000; /* XXX make a config option */ - -static void slit_configure(Slit *self); - -void slit_startup() -{ - XSetWindowAttributes attrib; - int i; - - slit_map = g_hash_table_new(g_int_hash, g_int_equal); - 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; - slit[i].frame = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0, - render_depth, InputOutput, render_visual, - CWOverrideRedirect | CWEventMask, - &attrib); - slit[i].a_frame = appearance_copy(theme_a_unfocused_title); - 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_AS_WINDOW(&slit[i])); - stacking_raise(SLIT_AS_WINDOW(&slit[i])); - } -} - -void slit_shutdown() -{ - int i; - - 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); -} - -void slit_add(Window win, XWMHints *wmhints) -{ - Slit *s; - SlitApp *app; - XWindowAttributes attrib; - - /* XXX pick a slit */ - s = &slit[0]; - - app = g_new0(SlitApp, 1); - app->slit = s; - app->win = win; - app->icon_win = (wmhints->flags & IconWindowHint) ? - wmhints->icon_window : win; - - if (XGetWindowAttributes(ob_display, app->icon_win, &attrib)) { - app->w = attrib.width; - app->h = attrib.height; - } else { - app->w = app->h = 64; - } - - s->slit_apps = g_list_append(s->slit_apps, app); - slit_configure(s); - - XReparentWindow(ob_display, app->icon_win, s->frame, app->x, app->y); - /* - This is the same case as in frame.c for client windows. When Openbox is - starting, the window is already mapped so we see unmap events occur for - it. There are 2 unmap events generated that we see, one with the 'event' - member set the root window, and one set to the client, but both get - handled and need to be ignored. - */ - if (ob_state == State_Starting) - app->ignore_unmaps += 2; - - if (app->win != app->icon_win) { - /* have to map it so that it can be re-managed on a restart */ - XMoveWindow(ob_display, app->win, -1000, -1000); - XMapWindow(ob_display, app->win); - } - XMapWindow(ob_display, app->icon_win); - XSync(ob_display, False); - - /* specify that if we exit, the window should not be destroyed and should - be reparented back to root automatically */ - XChangeSaveSet(ob_display, app->icon_win, SetModeInsert); - XSelectInput(ob_display, app->icon_win, SLITAPP_EVENT_MASK); - - grab_button_full(2, 0, app->icon_win, - ButtonPressMask | ButtonReleaseMask | ButtonMotionMask, - GrabModeAsync, ob_cursors.move); - - g_hash_table_insert(slit_app_map, &app->icon_win, app); - - g_message("Managed Slit App: 0x%lx", app->icon_win); -} - -void slit_remove_all() -{ - int i; - - for (i = 0; i < nslits; ++i) - while (slit[i].slit_apps) - slit_remove(slit[i].slit_apps->data, TRUE); -} - -void slit_remove(SlitApp *app, gboolean reparent) -{ - ungrab_button(2, 0, app->icon_win); - XSelectInput(ob_display, app->icon_win, NoEventMask); - /* remove the window from our save set */ - XChangeSaveSet(ob_display, app->icon_win, SetModeDelete); - XSync(ob_display, False); - - g_hash_table_remove(slit_app_map, &app->icon_win); - - if (reparent) - XReparentWindow(ob_display, app->icon_win, ob_root, app->x, app->y); - - app->slit->slit_apps = g_list_remove(app->slit->slit_apps, app); - slit_configure(app->slit); - - g_message("Unmanaged Slit App: 0x%lx", app->icon_win); - - g_free(app); -} - -void slit_configure_all() -{ - int i; for (i = 0; i < nslits; ++i) slit_configure(&slit[i]); -} - -static void slit_configure(Slit *self) -{ - GList *it; - int spot; - - self->w = self->h = spot = 0; - - for (it = self->slit_apps; it; it = it->next) { - struct SlitApp *app = it->data; - if (self->horz) { - app->x = spot; - app->y = 0; - self->w += app->w; - self->h = MAX(self->h, app->h); - spot += app->w; - } else { - app->x = 0; - app->y = spot; - self->w = MAX(self->w, app->w); - self->h += app->h; - spot += app->h; - } - - XMoveWindow(ob_display, app->icon_win, app->x, app->y); - } - - /* used for calculating offsets */ - self->w += theme_bwidth * 2; - self->h += theme_bwidth * 2; - - /* calculate position */ - switch (self->pos) { - case SlitPos_Floating: - self->x = self->user_x; - self->y = self->user_y; - break; - case SlitPos_TopLeft: - self->x = 0; - self->y = 0; - self->gravity = NorthWestGravity; - break; - case SlitPos_Top: - self->x = screen_physical_size.width / 2; - self->y = 0; - self->gravity = NorthGravity; - break; - case SlitPos_TopRight: - self->x = screen_physical_size.width; - self->y = 0; - self->gravity = NorthEastGravity; - break; - case SlitPos_Left: - self->x = 0; - self->y = screen_physical_size.height / 2; - self->gravity = WestGravity; - break; - case SlitPos_Right: - self->x = screen_physical_size.width; - self->y = screen_physical_size.height / 2; - self->gravity = EastGravity; - break; - case SlitPos_BottomLeft: - self->x = 0; - self->y = screen_physical_size.height; - self->gravity = SouthWestGravity; - break; - case SlitPos_Bottom: - self->x = screen_physical_size.width / 2; - self->y = screen_physical_size.height; - self->gravity = SouthGravity; - break; - case SlitPos_BottomRight: - self->x = screen_physical_size.width; - self->y = screen_physical_size.height; - self->gravity = SouthEastGravity; - break; - } - - switch(self->gravity) { - case NorthGravity: - case CenterGravity: - case SouthGravity: - self->x -= self->w / 2; - break; - case NorthEastGravity: - case EastGravity: - case SouthEastGravity: - self->x -= self->w; - break; - } - switch(self->gravity) { - case WestGravity: - case CenterGravity: - case EastGravity: - self->y -= self->h / 2; - break; - case SouthWestGravity: - case SouthGravity: - case SouthEastGravity: - self->y -= self->h; - break; - } - - if (self->hide && self->hidden) { - g_message("hidden"); - switch (self->pos) { - case SlitPos_Floating: - break; - case SlitPos_TopLeft: - if (self->horz) - self->y -= self->h - theme_bwidth; - else - self->x -= self->w - theme_bwidth; - break; - case SlitPos_Top: - self->y -= self->h - theme_bwidth; - break; - case SlitPos_TopRight: - if (self->horz) - self->y -= self->h - theme_bwidth; - else - self->x += self->w - theme_bwidth; - break; - case SlitPos_Left: - self->x -= self->w - theme_bwidth; - break; - case SlitPos_Right: - self->x += self->w - theme_bwidth; - break; - case SlitPos_BottomLeft: - if (self->horz) - self->y += self->h - theme_bwidth; - else - self->x -= self->w - theme_bwidth; - break; - case SlitPos_Bottom: - self->y += self->h - theme_bwidth; - break; - case SlitPos_BottomRight: - if (self->horz) - self->y += self->h - theme_bwidth; - else - self->x += self->w - theme_bwidth; - break; - } - } - - /* not used for actually sizing shit */ - self->w -= theme_bwidth * 2; - self->h -= theme_bwidth * 2; - - if (self->w > 0 && self->h > 0) { - RECT_SET(self->a_frame->area, 0, 0, self->w, self->h); - XMoveResizeWindow(ob_display, self->frame, - self->x, self->y, self->w, self->h); - - paint(self->frame, self->a_frame); - XMapWindow(ob_display, self->frame); - } else - XUnmapWindow(ob_display, self->frame); - - /* but they are useful outside of this function! */ - self->w += theme_bwidth * 2; - self->h += theme_bwidth * 2; -} - -void slit_app_configure(SlitApp *app, int w, int h) -{ - app->w = w; - app->h = h; - slit_configure(app->slit); -} - -void slit_app_drag(SlitApp *app, XMotionEvent *e) -{ - Slit *src, *dest = NULL; - SlitApp *over = NULL; - GList *it; - int i; - int x, y; - gboolean after; - - src = app->slit; - x = e->x_root; - y = e->y_root; - - /* which slit are we on top of? */ - for (i = 0; i < nslits; ++i) - if (x >= slit[i].x && - y >= slit[i].y && - x < slit[i].x + slit[i].w && - y < slit[i].y + slit[i].h) { - dest = &slit[i]; - break; - } - if (!dest) return; - - x -= dest->x; - y -= dest->y; - - /* which slit app are we on top of? */ - for (it = dest->slit_apps; it; it = it->next) { - over = it->data; - if (dest->horz) { - if (x >= over->x && x < over->x + over->w) - break; - } else { - if (y >= over->y && y < over->y + over->h) - break; - } - } - if (!it || app == over) return; - - x -= over->x; - y -= over->y; - - if (dest->horz) - after = (x > over->w / 2); - else - after = (y > over->h / 2); - - /* remove before doing the it->next! */ - src->slit_apps = g_list_remove(src->slit_apps, app); - if (src != dest) slit_configure(src); - - if (after) it = it->next; - - dest->slit_apps = g_list_insert_before(dest->slit_apps, it, app); - slit_configure(dest); -} - -static void hide_timeout(Slit *self) -{ - /* dont repeat */ - timer_stop(self->hide_timer); - self->hide_timer = NULL; - - /* hide */ - self->hidden = TRUE; - slit_configure(self); -} - -void slit_hide(Slit *self, gboolean hide) -{ - if (self->hidden == hide || !self->hide) - return; - if (!hide) { - /* show */ - self->hidden = FALSE; - slit_configure(self); - - /* if was hiding, stop it */ - if (self->hide_timer) { - timer_stop(self->hide_timer); - self->hide_timer = NULL; - } - } else { - g_assert(!self->hide_timer); - self->hide_timer = timer_start(slit_hide_timeout * 1000, - (TimeoutHandler)hide_timeout, self); - } -}
D openbox/slit.h

@@ -1,80 +0,0 @@

-#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 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; - - Slit *slit; - Window icon_win; - Window win; - int x; - int y; - int w; - int h; -} SlitApp; - -extern GHashTable *slit_map; -extern GHashTable *slit_app_map; - -void slit_startup(); -void slit_shutdown(); - -void slit_configure_all(); -void slit_hide(Slit *self, gboolean hide); - -void slit_add(Window win, XWMHints *wmhints); - -void slit_remove_all(); -void slit_remove(SlitApp *app, gboolean reparent); - -void slit_app_drag(SlitApp *app, XMotionEvent *e); -void slit_app_configure(SlitApp *app, int w, int h); - -#endif
M openbox/window.copenbox/window.c

@@ -1,16 +1,33 @@

#include "window.h" #include "menu.h" -#include "slit.h" +#include "config.h" +#include "dock.h" #include "client.h" #include "frame.h" +GHashTable *window_map; + +void window_startup() +{ + window_map = g_hash_table_new(g_int_hash, g_int_equal); +} + +void window_shutdown() +{ + g_hash_table_destroy(window_map); +} + Window window_top(ObWindow *self) { switch (self->type) { case Window_Menu: return ((Menu*)self)->frame; - case Window_Slit: - return ((Slit*)self)->frame; + case Window_Dock: + return ((Dock*)self)->frame; + case Window_DockApp: + /* not to be used for stacking */ + g_assert_not_reached(); + break; case Window_Client: return ((Client*)self)->frame->window; case Window_Internal:

@@ -25,8 +42,12 @@ {

switch (self->type) { case Window_Menu: return Layer_Internal; - case Window_Slit: - return ((Slit*)self)->layer; + case Window_Dock: + return config_dock_layer; + case Window_DockApp: + /* not to be used for stacking */ + g_assert_not_reached(); + break; case Window_Client: return ((Client*)self)->layer; case Window_Internal:
M openbox/window.hopenbox/window.h

@@ -2,12 +2,14 @@ #ifndef __window_h

#define __window_h #include <X11/Xlib.h> +#include <glib.h> typedef enum { Window_Menu, - Window_Slit, + Window_Dock, + Window_DockApp, /* used for events but not stacking */ Window_Client, - Window_Internal + Window_Internal /* used for stacking but not events */ } Window_InternalType; typedef struct ObWindow {

@@ -22,23 +24,32 @@ Window win;

} InternalWindow; #define WINDOW_IS_MENU(win) (((ObWindow*)win)->type == Window_Menu) -#define WINDOW_IS_SLIT(win) (((ObWindow*)win)->type == Window_Slit) +#define WINDOW_IS_DOCK(win) (((ObWindow*)win)->type == Window_Dock) +#define WINDOW_IS_DOCKAPP(win) (((ObWindow*)win)->type == Window_DockApp) #define WINDOW_IS_CLIENT(win) (((ObWindow*)win)->type == Window_Client) #define WINDOW_IS_INTERNAL(win) (((ObWindow*)win)->type == Window_Internal) struct Menu; -struct Slit; +struct Dock; +struct DockApp; struct Client; #define WINDOW_AS_MENU(win) ((struct Menu*)win) -#define WINDOW_AS_SLIT(win) ((struct Slit*)win) +#define WINDOW_AS_DOCK(win) ((struct Dock*)win) +#define WINDOW_AS_DOCKAPP(win) ((struct DockApp*)win) #define WINDOW_AS_CLIENT(win) ((struct Client*)win) #define WINDOW_AS_INTERNAL(win) ((struct InternalWindow*)win) #define MENU_AS_WINDOW(menu) ((ObWindow*)menu) -#define SLIT_AS_WINDOW(slit) ((ObWindow*)slit) +#define DOCK_AS_WINDOW(dock) ((ObWindow*)dock) +#define DOCKAPP_AS_WINDOW(dockapp) ((ObWindow*)dockapp) #define CLIENT_AS_WINDOW(client) ((ObWindow*)client) #define INTERNAL_AS_WINDOW(intern) ((ObWindow*)intern) + +extern GHashTable *window_map; + +void window_startup(); +void window_shutdown(); Window window_top(ObWindow *self); Window window_layer(ObWindow *self);