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).
# 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]
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
#include "client.h"
-#include "slit.h"
+#include "dock.h"
#include "startup.h"
#include "screen.h"
#include "moveresize.h"
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);
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()
Window w, *children;
XWMHints *wmhints;
XWindowAttributes attrib;
- Client *active;
XQueryTree(ob_display, ob_root, &w, &w, &children, &nchild);
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);
}
}
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;
/* 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);
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);
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
} Client;
extern GList *client_list;
-extern GHashTable *client_map;
void client_startup();
void client_shutdown();
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)
{
if (!g_ascii_strcasecmp(name, "focusnew")) {
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;
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()
#ifndef __config_h
#define __config_h
+#include "dock.h"
+#include "stacking.h"
+
#include <glib.h>
/*! Should new windows be focused */
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;
--- /dev/null
+#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);
+ }
+}
--- /dev/null
+#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
#include "openbox.h"
-#include "slit.h"
+#include "dock.h"
#include "client.h"
#include "xerror.h"
#include "prop.h"
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);
{
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);
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)
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;
}
}
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)
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);
}
#include "plugin.h"
static GHashTable *menu_hash = NULL;
-GHashTable *menu_map = NULL;
#define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask | \
LeaveWindowMask)
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);
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);
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);
void menu_shutdown()
{
g_hash_table_destroy(menu_hash);
- g_hash_table_destroy(menu_map);
}
static Window createWindow(Window parent, unsigned long mask,
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));
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)
#include <glib.h>
-extern GHashTable *menu_map;
-
struct Menu;
struct MenuEntry;
#include "openbox.h"
-#include "slit.h"
+#include "dock.h"
#include "event.h"
#include "menu.h"
#include "client.h"
g_free(theme);
if (!theme) return 1;
+ window_startup();
menu_startup();
frame_startup();
moveresize_startup();
screen_startup();
group_startup();
client_startup();
- slit_startup();
+ dock_startup();
/* call startup for all the plugins */
plugin_startall();
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();
moveresize_shutdown();
frame_shutdown();
menu_shutdown();
+ window_shutdown();
grab_shutdown();
event_shutdown();
theme_shutdown();
#include "openbox.h"
-#include "slit.h"
+#include "dock.h"
#include "prop.h"
#include "startup.h"
#include "config.h"
if (ob_state == State_Starting)
return;
- slit_configure_all();
+ dock_configure();
screen_update_struts();
for (it = client_list; it; it = it->next)
+++ /dev/null
-#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);
- }
-}
+++ /dev/null
-#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
#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:
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:
#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 {
} 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);