rename "Slit" to "Dock".
authorDana Jansens <danakj@orodu.net>
Fri, 16 May 2003 18:10:10 +0000 (18:10 +0000)
committerDana Jansens <danakj@orodu.net>
Fri, 16 May 2003 18:10:10 +0000 (18:10 +0000)
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).

18 files changed:
data/rc3
openbox/Makefile.am
openbox/client.c
openbox/client.h
openbox/config.c
openbox/config.h
openbox/dock.c [new file with mode: 0644]
openbox/dock.h [new file with mode: 0644]
openbox/event.c
openbox/frame.c
openbox/menu.c
openbox/menu.h
openbox/openbox.c
openbox/screen.c
openbox/slit.c [deleted file]
openbox/slit.h [deleted file]
openbox/window.c
openbox/window.h

index 01c9525..57eec1e 100644 (file)
--- a/data/rc3
+++ b/data/rc3
@@ -53,6 +53,39 @@ names = ("one" "two" "three" "four")
 # 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]
index f33b65d..795b26a 100644 (file)
@@ -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
index 828b158..5f54e64 100644 (file)
@@ -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 @@
                                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 @@ void client_manage_all()
     Window w, *children;
     XWMHints *wmhints;
     XWindowAttributes attrib;
-    Client *active;
 
     XQueryTree(ob_display, ob_root, &w, &w, &children, &nchild);
 
@@ -154,19 +145,28 @@ void client_manage_all()
        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 @@ void client_manage(Window window)
     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 @@ void client_manage(Window window)
 
     /* 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 @@ void client_unmanage(Client *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);
@@ -673,9 +673,10 @@ void client_update_transient_for(Client *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
index 4461377..08a3a88 100644 (file)
@@ -294,7 +294,6 @@ typedef struct Client {
 } Client;
 
 extern GList *client_list;
-extern GHashTable *client_map;
 
 void client_startup();
 void client_shutdown();
index 5624c48..e751f32 100644 (file)
@@ -9,12 +9,20 @@ 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)
 {
     if (!g_ascii_strcasecmp(name, "focusnew")) {
@@ -118,6 +126,81 @@ static void parse_moveresize(char *name, ParseToken *value)
     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 @@ void config_startup()
     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()
index c268503..71aa4e1 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef __config_h
 #define __config_h
 
+#include "dock.h"
+#include "stacking.h"
+
 #include <glib.h>
 
 /*! Should new windows be focused */
@@ -22,6 +25,23 @@ extern gboolean config_opaque_move;
   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;
 
diff --git a/openbox/dock.c b/openbox/dock.c
new file mode 100644 (file)
index 0000000..6e45850
--- /dev/null
@@ -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);
+    }
+}
diff --git a/openbox/dock.h b/openbox/dock.h
new file mode 100644 (file)
index 0000000..ef77076
--- /dev/null
@@ -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
index 230626b..732857e 100644 (file)
@@ -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 @@
 
 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 @@ static void event_process(XEvent *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 @@ void fd_event_handle()
     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;
     }
 }
index d714b69..211a275 100644 (file)
@@ -430,20 +430,20 @@ void frame_grab_client(Frame *self, Client *client)
 
     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 @@ 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);
 }
index 17f96b4..3373616 100644 (file)
@@ -8,7 +8,6 @@
 #include "plugin.h"
 
 static GHashTable *menu_hash = NULL;
-GHashTable *menu_map = NULL;
 
 #define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask | \
                         LeaveWindowMask)
@@ -34,9 +33,9 @@ void menu_destroy_hash_value(Menu *self)
     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 @@ void menu_entry_free(MenuEntry *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);
@@ -73,7 +72,6 @@ void menu_startup()
     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_startup()
 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 @@ Menu *menu_new_full(char *label, char *name, Menu *parent,
     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 @@ void menu_add_entry(Menu *menu, MenuEntry *entry)
 
     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)
index c6b3671..2d811c1 100644 (file)
@@ -7,8 +7,6 @@
 
 #include <glib.h>
 
-extern GHashTable *menu_map;
-
 struct Menu;
 struct MenuEntry;
 
index 505dffb..93e91a5 100644 (file)
@@ -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 @@ int main(int argc, char **argv)
         g_free(theme);
         if (!theme) return 1;
 
+        window_startup();
         menu_startup();
         frame_startup();
         moveresize_startup();
@@ -191,7 +192,7 @@ int main(int argc, char **argv)
        screen_startup();
         group_startup();
        client_startup();
-        slit_startup();
+        dock_startup();
 
         /* call startup for all the plugins */
         plugin_startall();
@@ -204,11 +205,11 @@ int main(int argc, char **argv)
            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 @@ int main(int argc, char **argv)
         moveresize_shutdown();
         frame_shutdown();
         menu_shutdown();
+        window_shutdown();
         grab_shutdown();
        event_shutdown();
         theme_shutdown();
index 6a300d8..0c80827 100644 (file)
@@ -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 @@ void screen_resize(int w, int h)
     if (ob_state == State_Starting)
        return;
 
-    slit_configure_all();
+    dock_configure();
     screen_update_struts();
 
     for (it = client_list; it; it = it->next)
diff --git a/openbox/slit.c b/openbox/slit.c
deleted file mode 100644 (file)
index 81f0b89..0000000
+++ /dev/null
@@ -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);
-    }
-}
diff --git a/openbox/slit.h b/openbox/slit.h
deleted file mode 100644 (file)
index 3cdcb30..0000000
+++ /dev/null
@@ -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
index 11f5e46..ed139b6 100644 (file)
@@ -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 @@ Window window_layer(ObWindow *self)
     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:
index 150323c..b7762ed 100644 (file)
@@ -2,12 +2,14 @@
 #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,24 +24,33 @@ typedef struct InternalWindow {
 } 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);