--- /dev/null
+#include "openbox.h"
+#include "frame.h"
+#include "render/render.h"
+#include "render/theme.h"
+
+typedef struct Popup {
+ gboolean hasicon;
+ Window bg;
+ Window icon;
+ Window text;
+ Appearance *a_bg;
+ Appearance *a_icon;
+ Appearance *a_text;
+ int gravity;
+ int x;
+ int y;
+ int w;
+ int h;
+} Popup;
+
+Popup *popup_new(gboolean hasicon)
+{
+ Popup *self = g_new(Popup, 1);
+ self->hasicon = hasicon;
+ self->bg = None;
+ self->a_text = NULL;
+ self->gravity = NorthWestGravity;
+ self->x = self->y = self->w = self->h = 0;
+ return self;
+}
+
+void popup_free(Popup *self)
+{
+ if (self->bg) {
+ XDestroyWindow(ob_display, self->bg);
+ XDestroyWindow(ob_display, self->text);
+ XDestroyWindow(ob_display, self->icon);
+ appearance_free(self->a_bg);
+ if (self->hasicon)
+ appearance_free(self->a_icon);
+ }
+ if (self->a_text)
+ appearance_free(self->a_text);
+ g_free(self);
+}
+
+void popup_position(Popup *self, int gravity, int x, int y)
+{
+ self->gravity = gravity;
+ self->x = x;
+ self->y = y;
+}
+
+void popup_size(Popup *self, int w, int h)
+{
+ self->w = w;
+ self->h = h;
+}
+
+void popup_size_to_string(Popup *self, char *text)
+{
+ int textw, texth;
+ int iconw;
+
+ if (!self->a_text)
+ self->a_text = appearance_copy(theme_app_hilite_label);
+
+ self->a_text->texture[0].data.text.string = text;
+ appearance_minsize(self->a_text, &textw, &texth);
+ textw += theme_bevel * 2;
+ texth += theme_bevel * 2;
+
+ self->h = texth + theme_bevel * 2;
+ iconw = (self->hasicon ? texth : 0);
+ self->w = textw + iconw + theme_bevel * 3;
+}
+
+void popup_show(Popup *self, char *text, Icon *icon)
+{
+ XSetWindowAttributes attrib;
+ int x, y, w, h;
+ int textw, texth;
+ int iconw;
+
+ /* create the shit if needed */
+ if (!self->bg) {
+ attrib.override_redirect = True;
+ self->bg = XCreateWindow(ob_display, ob_root,
+ 0, 0, 1, 1, 0, render_depth, InputOutput,
+ render_visual, CWOverrideRedirect, &attrib);
+
+ XSetWindowBorderWidth(ob_display, self->bg, theme_bwidth);
+ XSetWindowBorder(ob_display, self->bg, theme_b_color->pixel);
+
+ self->text = XCreateWindow(ob_display, self->bg,
+ 0, 0, 1, 1, 0, render_depth, InputOutput,
+ render_visual, 0, NULL);
+ if (self->hasicon)
+ self->icon = XCreateWindow(ob_display, self->bg,
+ 0, 0, 1, 1, 0,
+ render_depth, InputOutput,
+ render_visual, 0, NULL);
+
+ XMapWindow(ob_display, self->text);
+ XMapWindow(ob_display, self->icon);
+
+ self->a_bg = appearance_copy(theme_app_hilite_bg);
+ if (self->hasicon)
+ self->a_icon = appearance_copy(theme_app_icon);
+ }
+ if (!self->a_text)
+ self->a_text = appearance_copy(theme_app_hilite_label);
+
+ /* set up the textures */
+ self->a_text->texture[0].data.text.string = text;
+ if (self->hasicon) {
+ if (icon) {
+ self->a_icon->texture[0].type = RGBA;
+ self->a_icon->texture[0].data.rgba.width = icon->width;
+ self->a_icon->texture[0].data.rgba.height = icon->height;
+ self->a_icon->texture[0].data.rgba.data = icon->data;
+ } else
+ self->a_icon->texture[0].type = NoTexture;
+ }
+
+ /* measure the shit out */
+ appearance_minsize(self->a_text, &textw, &texth);
+ textw += theme_bevel * 2;
+ texth += theme_bevel * 2;
+
+ /* set the sizes up and reget the text sizes from the calculated
+ outer sizes */
+ if (self->h) {
+ h = self->h;
+ texth = h - (theme_bevel * 2);
+ } else
+ h = texth + theme_bevel * 2;
+ iconw = (self->hasicon ? texth : 0);
+ if (self->w) {
+ w = self->w;
+ textw = w - (iconw + theme_bevel * 3);
+ } else
+ w = textw + iconw + theme_bevel * 3;
+ /* sanity checks to avoid crashes! */
+ if (w < 1) w = 1;
+ if (h < 1) h = 1;
+ if (textw < 1) textw = 1;
+ if (texth < 1) texth = 1;
+
+ /* set up the x coord */
+ x = self->x;
+ switch (self->gravity) {
+ case NorthGravity:
+ case CenterGravity:
+ case SouthGravity:
+ x -= w / 2;
+ break;
+ case NorthEastGravity:
+ case EastGravity:
+ case SouthEastGravity:
+ x -= w;
+ break;
+ }
+
+ /* set up the y coord */
+ y = self->y;
+ switch (self->gravity) {
+ case WestGravity:
+ case CenterGravity:
+ case EastGravity:
+ y -= h / 2;
+ break;
+ case SouthWestGravity:
+ case SouthGravity:
+ case SouthEastGravity:
+ y -= h;
+ break;
+ }
+
+ /* set the windows/appearances up */
+ RECT_SET(self->a_bg->area, 0, 0, w, h);
+ XMoveResizeWindow(ob_display, self->bg, x, y, w, h);
+
+ RECT_SET(self->a_text->area, 0, 0, textw, texth);
+ RECT_SET(self->a_text->texture[0].position, theme_bevel, theme_bevel,
+ textw - theme_bevel * 2, texth - theme_bevel * 2);
+ self->a_text->surface.data.planar.parent = self->a_bg;
+ self->a_text->surface.data.planar.parentx = iconw + theme_bevel * 2;
+ self->a_text->surface.data.planar.parenty = theme_bevel;
+ XMoveResizeWindow(ob_display, self->text,
+ iconw + theme_bevel * 2, theme_bevel, textw, texth);
+
+ if (self->hasicon) {
+ if (iconw < 1) iconw = 1; /* sanity check for crashes */
+ RECT_SET(self->a_icon->area, 0, 0, iconw, texth);
+ RECT_SET(self->a_icon->texture[0].position, 0, 0, iconw, texth);
+ self->a_icon->surface.data.planar.parent = self->a_bg;
+ self->a_icon->surface.data.planar.parentx = theme_bevel;
+ self->a_icon->surface.data.planar.parenty = theme_bevel;
+ XMoveResizeWindow(ob_display, self->icon,
+ theme_bevel, theme_bevel, iconw, texth);
+ }
+
+ paint(self->bg, self->a_bg);
+ paint(self->text, self->a_text);
+ if (self->hasicon)
+ paint(self->icon, self->a_icon);
+
+ XMapWindow(ob_display, self->bg);
+}
+
+void popup_hide(Popup *self)
+{
+ XUnmapWindow(ob_display, self->bg);
+}
--- /dev/null
+#include "render/render.h"
+#include "render/theme.h"
+
+#include <X11/Xlib.h>
+#include <stdlib.h>
+#include <glib.h>
+#ifdef HAVE_SIGNAL_H
+# include <signal.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+
+#define TITLE_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | \
+ ButtonMotionMask)
+#define ROOT_EVENT_MASK (PropertyChangeMask | StructureNotifyMask | \
+ SubstructureNotifyMask)
+#define SLITAPP_EVENT_MASK (StructureNotifyMask)
+
+Display *ob_display;
+Window ob_root;
+int ob_screen;
+
+static struct Slit {
+ Window frame;
+ Window title;
+
+ /* user-requested position stuff */
+ int gravity;
+ int user_x, user_y;
+
+ /* actual position (when not auto-hidden) */
+ int x, y;
+ int w, h;
+
+ gboolean horz;
+
+ Appearance *a_frame;
+ Appearance *a_title;
+
+ GList *slit_apps;
+} *slit;
+static int nslits;
+
+struct SlitApp {
+ Window icon_win;
+ Window win;
+ int x;
+ int y;
+ int w;
+ int h;
+};
+
+static Atom atom_atom;
+static Atom atom_card;
+static Atom atom_theme;
+static Atom atom_type;
+static Atom atom_type_dock;
+static Atom atom_desktop;
+static Atom atom_state;
+static Atom atom_strut;
+
+static gboolean quit = FALSE;
+static gboolean reconfig = FALSE;
+
+void slit_read_theme();
+void slit_configure();
+void event_handle(XEvent *e);
+void slit_add_existing();
+void slit_add_app(Window win);
+void slit_remove_app(struct Slit *slit, struct SlitApp *app,gboolean reparent);
+
+void sighandler(int signal)
+{
+ if (signal == SIGUSR1)
+ reconfig =TRUE;
+ else
+ quit = TRUE;
+}
+
+int xerrorhandler(Display *d, XErrorEvent *e)
+{
+ char errtxt[128];
+ XGetErrorText(d, e->error_code, errtxt, 127);
+ g_error("X Error: %s", errtxt);
+ return 0;
+}
+
+int main()
+{
+ int i;
+ guint desk = 0xffffffff;
+ XEvent e;
+ XSetWindowAttributes attrib;
+ struct sigaction action;
+ sigset_t sigset;
+ int xfd;
+ fd_set selset;
+
+ /* set up signal handler */
+ sigemptyset(&sigset);
+ action.sa_handler = sighandler;
+ action.sa_mask = sigset;
+ action.sa_flags = SA_NOCLDSTOP;
+ sigaction(SIGUSR1, &action, (struct sigaction *) NULL);
+ sigaction(SIGPIPE, &action, (struct sigaction *) NULL);
+ sigaction(SIGSEGV, &action, (struct sigaction *) NULL);
+ sigaction(SIGFPE, &action, (struct sigaction *) NULL);
+ sigaction(SIGTERM, &action, (struct sigaction *) NULL);
+ sigaction(SIGINT, &action, (struct sigaction *) NULL);
+ sigaction(SIGHUP, &action, (struct sigaction *) NULL);
+
+ ob_display = XOpenDisplay(NULL);
+ ob_screen = DefaultScreen(ob_display);
+ ob_root = RootWindow(ob_display, ob_screen);
+
+ XSetErrorHandler(xerrorhandler);
+
+ render_startup();
+ theme_startup();
+
+ atom_atom = XInternAtom(ob_display, "ATOM", False);
+ atom_card = XInternAtom(ob_display, "CARDINAL", False);
+ atom_theme = XInternAtom(ob_display, "_OPENBOX_THEME", False);
+ atom_type = XInternAtom(ob_display, "_NET_WM_WINDOW_TYPE", False);
+ atom_type_dock = XInternAtom(ob_display, "_NET_WM_WINDOW_TYPE_DOCK",False);
+ atom_desktop =XInternAtom(ob_display, "_NET_WM_DESKTOP", False);
+ atom_state = XInternAtom(ob_display, "WM_STATE", False);
+ atom_strut = XInternAtom(ob_display, "_NET_WM_STRUT", False);
+
+ nslits = 1;
+ slit = g_new0(struct Slit, nslits);
+
+ for (i = 0; i < nslits; ++i) {
+ slit[i].horz = TRUE;
+
+ slit[i].frame = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
+ render_depth, InputOutput, render_visual,
+ 0, NULL);
+ attrib.event_mask = TITLE_EVENT_MASK;
+ slit[i].title = XCreateWindow(ob_display, slit[i].frame, 0, 0, 1, 1, 0,
+ render_depth, InputOutput, render_visual,
+ CWEventMask, &attrib);
+ XMapWindow(ob_display, slit[i].title);
+
+ XChangeProperty(ob_display, slit[i].frame, atom_type, atom_atom,
+ 32, PropModeReplace, (guchar*)&atom_type_dock, 1);
+
+ XChangeProperty(ob_display, slit[i].frame, atom_desktop, atom_card,
+ 32, PropModeReplace, (guchar*)&desk, 1);
+ }
+
+ slit_read_theme();
+
+ XSelectInput(ob_display, ob_root, ROOT_EVENT_MASK);
+
+ slit_add_existing();
+
+ xfd = ConnectionNumber(ob_display);
+ FD_ZERO(&selset);
+ FD_SET(xfd, &selset);
+ while (!quit) {
+ gboolean hadevent = FALSE;
+ while (XPending(ob_display)) {
+ XNextEvent(ob_display, &e);
+ event_handle(&e);
+ hadevent = TRUE;
+ }
+ if (!hadevent) {
+ if (reconfig)
+ slit_read_theme();
+
+ if (!quit)
+ select(xfd + 1, &selset, NULL, NULL, NULL);
+ }
+ }
+
+ for (i = 0; i < nslits; ++i) {
+ while (slit[i].slit_apps)
+ slit_remove_app(&slit[i], slit[i].slit_apps->data, TRUE);
+
+ XDestroyWindow(ob_display, slit[i].title);
+ XDestroyWindow(ob_display, slit[i].frame);
+
+ appearance_free(slit[i].a_frame);
+ appearance_free(slit[i].a_title);
+ }
+
+ theme_shutdown();
+ render_shutdown();
+ XCloseDisplay(ob_display);
+ return 0;
+}
+
+Window find_client(Window win)
+{
+ Window r, *children;
+ unsigned int n, i;
+ Atom ret_type;
+ int ret_format;
+ unsigned long ret_items, ret_bytesleft;
+ unsigned long *prop_return;
+
+ XQueryTree(ob_display, win, &r, &r, &children, &n);
+ for (i = 0; i < n; ++i) {
+ Window w = find_client(children[i]);
+ if (w) return w;
+ }
+
+ /* try me */
+ XGetWindowProperty(ob_display, win, atom_state, 0, 1,
+ False, atom_state, &ret_type, &ret_format,
+ &ret_items, &ret_bytesleft,
+ (unsigned char**) &prop_return);
+ if (ret_type == None || ret_items < 1)
+ return None;
+ return win; /* found it! */
+}
+
+void event_handle(XEvent *e)
+{
+ int i;
+ Window win;
+ static guint button = 0;
+ int sw, sh;
+ int xpos, ypos;
+ int x, y, g;
+
+ switch (e->type) {
+ case ButtonPress:
+ if (!button) {
+ button = e->xbutton.button;
+ }
+ break;
+ case ButtonRelease:
+ if (button == e->xbutton.button)
+ button = 0;
+ break;
+ case MotionNotify:
+ if (button == 1) {
+ for (i = 0; i < nslits; ++i)
+ if (slit[i].title == e->xmotion.window) {
+ /* pick a corner and move it */
+ sw = WidthOfScreen(ScreenOfDisplay(ob_display, ob_screen));
+ sh = HeightOfScreen(ScreenOfDisplay(ob_display,ob_screen));
+
+ if (e->xmotion.x_root < sw / 3) /* left edge */
+ xpos = 0;
+ else if (e->xmotion.x_root < sw / 3 * 2) /* middle */
+ xpos = 1;
+ else /* right edge */
+ xpos = 2;
+ if (e->xmotion.y_root < sh / 3) /* top edge */
+ ypos = 0;
+ else if (e->xmotion.y_root < sh / 3 * 2) /* middle */
+ ypos = 1;
+ else /* bottom edge */
+ ypos = 2;
+
+ if (xpos == 1 && ypos == 1)
+ return; /* cant go in middle middle */
+
+ if (xpos == 0) {
+ if (ypos == 0) {
+ x = 0;
+ y = 0;
+ g = NorthWestGravity;
+ } else if (ypos == 1) {
+ x = 0;
+ y = sh / 2;
+ g = WestGravity;
+ } else {
+ x = 0;
+ y = sh;
+ g = SouthWestGravity;
+ }
+ } else if (xpos == 1) {
+ if (ypos == 0) {
+ x = sw / 2;
+ y = 0;
+ g = NorthGravity;
+ } else {
+ x = sw / 2;
+ y = sh;
+ g = SouthGravity;
+ }
+ } else {
+ if (ypos == 0) {
+ x = sw;
+ y = 0;
+ g = NorthEastGravity;
+ } else if (ypos == 1) {
+ x = sw;
+ y = sh / 2;
+ g = EastGravity;
+ } else {
+ x = sw;
+ y = sh;
+ g = SouthEastGravity;
+ }
+ }
+ if (x != slit[i].x || y != slit[i].y ||
+ g != slit[i].gravity) {
+ slit[i].user_x = x;
+ slit[i].user_y = y;
+ slit[i].gravity = g;
+ slit_configure();
+ }
+ }
+ }
+ break;
+ case PropertyNotify:
+ g_message("PropertyNotify on 0x%lx", e->xproperty.window);
+ if (e->xproperty.window == ob_root) {
+ if (e->xproperty.atom == atom_theme)
+ slit_read_theme();
+ }
+ break;
+ case ConfigureNotify:
+ g_message("ConfigureNotify on 0x%lx", e->xconfigure.window);
+ if (e->xconfigure.window == ob_root) {
+ slit_configure();
+ return;
+ }
+
+ /* an owned slitapp? */
+ for (i = 0; i < nslits; ++i) {
+ GList *it;
+
+ for (it = slit[i].slit_apps; it; it = it->next) {
+ struct SlitApp *app = it->data;
+ if (e->xconfigure.window == app->icon_win) {
+ if (app->w != e->xconfigure.width ||
+ app->h != e->xconfigure.height) {
+ g_message("w %d h %d w %d h %d",
+ app->w, e->xconfigure.width,
+ app->h, e->xconfigure.height);
+ app->w = e->xconfigure.width;
+ app->h = e->xconfigure.height;
+ slit_configure();
+ }
+ return;
+ }
+ }
+ }
+ break;
+ case MapNotify:
+ g_message("MapNotify on 0x%lx", e->xmap.window);
+
+ win = find_client(e->xmap.window);
+ if (!win) return;
+
+ for (i = 0; i < nslits; ++i)
+ if (win == slit[i].frame)
+ return;
+
+ slit_add_app(win);
+ break;
+ case UnmapNotify:
+ g_message("UnmapNotify on 0x%lx", e->xunmap.window);
+ for (i = 0; i < nslits; ++i) {
+ GList *it;
+
+ for (it = slit[i].slit_apps; it; it = it->next) {
+ struct SlitApp *app = it->data;
+ if (e->xunmap.window == app->icon_win) {
+ gboolean r;
+ XEvent e;
+
+ r = !XCheckTypedWindowEvent(ob_display, app->icon_win,
+ DestroyNotify, &e);
+ if (r) {
+ if (XCheckTypedWindowEvent(ob_display, app->icon_win,
+ ReparentNotify, &e)) {
+ XPutBackEvent(ob_display, &e);
+ r = FALSE;
+ }
+ }
+ slit_remove_app(&slit[i], app, r);
+ break;
+ }
+ }
+ }
+ break;
+ case ReparentNotify:
+ g_message("ReparentNotify on 0x%lx", e->xdestroywindow.window);
+ for (i = 0; i < nslits; ++i) {
+ GList *it;
+
+ for (it = slit[i].slit_apps; it; it = it->next) {
+ struct SlitApp *app = it->data;
+ if (e->xdestroywindow.window == app->icon_win) {
+ slit_remove_app(&slit[i], app, FALSE);
+ break;
+ }
+ }
+ }
+ case DestroyNotify:
+ g_message("DestroyNotify on 0x%lx", e->xdestroywindow.window);
+ for (i = 0; i < nslits; ++i) {
+ GList *it;
+
+ for (it = slit[i].slit_apps; it; it = it->next) {
+ struct SlitApp *app = it->data;
+ if (e->xdestroywindow.window == app->icon_win) {
+ slit_remove_app(&slit[i], app, FALSE);
+ break;
+ }
+ }
+ }
+ break;
+ }
+}
+
+void slit_add_existing()
+{
+ unsigned int i, nchild;
+ int j;
+ Window w, *children;
+ XWindowAttributes attrib;
+
+ XQueryTree(ob_display, ob_root, &w, &w, &children, &nchild);
+
+ for (i = 0; i < nchild; ++i) {
+ for (j = 0; j < nslits; ++j)
+ if (children[i] == slit[j].frame)
+ continue;
+ if (children[i] == None)
+ continue;
+ if ((children[i] = find_client(children[i])) == None)
+ continue;
+ if (XGetWindowAttributes(ob_display, children[i], &attrib)) {
+ if (attrib.override_redirect) continue;
+
+ slit_add_app(children[i]);
+ }
+ }
+ XFree(children);
+}
+
+void slit_add_app(Window win)
+{
+ int i;
+ XWMHints *h;
+ XWindowAttributes attrib;
+ struct Slit *s;
+
+ s = &slit[0];
+
+ if ((h = XGetWMHints(ob_display, win))) {
+ if (h->flags & StateHint && h->initial_state == WithdrawnState) {
+ struct SlitApp *app = g_new(struct SlitApp, 1);
+
+ app->win = win;
+ app->icon_win = (h->flags & IconWindowHint) ?
+ h->icon_window : win;
+
+ XFree(h);
+
+ for (i = 0; i < nslits; ++i) {
+ GList *it;
+ for (it = slit[i].slit_apps; it; it = it->next)
+ if (app->icon_win ==
+ ((struct SlitApp*)it->data)->icon_win)
+ /* already managed! */
+ return;
+ }
+
+ if (XGetWindowAttributes(ob_display, app->icon_win, &attrib)) {
+ app->w = attrib.width;
+ app->h = attrib.height;
+ } else {
+ g_free(app);
+ app = NULL;
+ }
+
+ if (app) {
+ s->slit_apps = g_list_append(s->slit_apps, app);
+ slit_configure();
+ XReparentWindow(ob_display, app->icon_win,
+ s->frame, app->x, app->y);
+/* if (app->win != app->icon_win)
+ XUnmapWindow(ob_display, app->win);*/
+ XSync(ob_display, False);
+ XSelectInput(ob_display, app->icon_win,
+ SLITAPP_EVENT_MASK);
+ }
+ g_message("Managed: 0x%lx", app->icon_win);
+ } else
+ XFree(h);
+ }
+}
+
+void slit_remove_app(struct Slit *slit, struct SlitApp *app, gboolean reparent)
+{
+
+ XSelectInput(ob_display, app->icon_win, NoEventMask);
+ XSync(ob_display, False);
+ if (reparent) {
+ g_message("reparenting");
+/* if (app->win != app->icon_win)
+ XMapWindow(ob_display, app->win);*/
+ XReparentWindow(ob_display, app->icon_win, ob_root, 0, 0);
+ }
+
+ g_free(app);
+ slit->slit_apps = g_list_remove(slit->slit_apps, app);
+ slit_configure();
+}
+
+void slit_read_theme()
+{
+ XTextProperty prop;
+ int i;
+ char *theme = NULL;
+
+ if (XGetTextProperty(ob_display, ob_root, &prop,
+ XInternAtom(ob_display, "_OPENBOX_THEME", False))) {
+ theme = theme_load((char*)prop.value);
+ XFree(prop.value);
+ } else
+ theme = theme_load(NULL);
+
+ g_free(theme);
+ if (!theme) exit(EXIT_FAILURE);
+
+ for (i = 0; i < nslits; ++i) {
+ appearance_free(slit[i].a_frame);
+ appearance_free(slit[i].a_title);
+
+ slit[i].a_frame = appearance_copy(theme_a_unfocused_title);
+ slit[i].a_title = appearance_copy(theme_a_unfocused_title);
+
+ XSetWindowBorder(ob_display, slit[i].frame, theme_b_color->pixel);
+ XSetWindowBorderWidth(ob_display, slit[i].frame, theme_bwidth);
+ XSetWindowBorder(ob_display, slit[i].frame, BlackPixel(ob_display, ob_screen));
+ XSetWindowBorderWidth(ob_display, slit[i].frame, 30);
+ }
+
+ slit_configure();
+}
+
+void slit_configure()
+{
+ int i;
+ int titleh;
+ GList *it;
+ int spot;
+
+ titleh = 4;
+
+ for (i = 0; i < nslits; ++i) {
+ if (slit[i].horz) {
+ slit[i].w = titleh;
+ slit[i].h = 0;
+ } else {
+ slit[i].w = 0;
+ slit[i].h = titleh;
+ }
+ spot = titleh;
+
+ for (it = slit[i].slit_apps; it; it = it->next) {
+ struct SlitApp *app = it->data;
+ if (slit[i].horz) {
+ g_message("%d", spot);
+ app->x = spot;
+ app->y = 0;
+ slit[i].w += app->w;
+ slit[i].h = MAX(slit[i].h, app->h);
+ spot += app->w;
+ } else {
+ app->x = 0;
+ app->y = spot;
+ slit[i].w = MAX(slit[i].h, app->w);
+ slit[i].h += app->h;
+ spot += app->h;
+ }
+
+ XMoveWindow(ob_display, app->icon_win, app->x, app->y);
+ }
+
+ /* calculate position */
+ slit[i].x = slit[i].user_x;
+ slit[i].y = slit[i].user_y;
+
+ switch(slit[i].gravity) {
+ case NorthGravity:
+ case CenterGravity:
+ case SouthGravity:
+ slit[i].x -= slit[i].w / 2;
+ break;
+ case NorthEastGravity:
+ case EastGravity:
+ case SouthEastGravity:
+ slit[i].x -= slit[i].w;
+ break;
+ }
+ switch(slit[i].gravity) {
+ case WestGravity:
+ case CenterGravity:
+ case EastGravity:
+ slit[i].y -= slit[i].h / 2;
+ break;
+ case SouthWestGravity:
+ case SouthGravity:
+ case SouthEastGravity:
+ slit[i].y -= slit[i].h;
+ break;
+ }
+
+ if (slit[i].w > 0 && slit[i].h > 0) {
+ RECT_SET(slit[i].a_frame->area, 0, 0, slit[i].w, slit[i].h);
+ XMoveResizeWindow(ob_display, slit[i].frame,
+ slit[i].x - theme_bwidth,
+ slit[i].y - theme_bwidth,
+ slit[i].w, slit[i].h);
+
+ if (slit[i].horz) {
+ RECT_SET(slit[i].a_title->area, 0, 0, titleh, slit[i].h);
+ XMoveResizeWindow(ob_display, slit[i].title, 0, 0,
+ titleh, slit[i].h);
+ } else {
+ RECT_SET(slit[i].a_title->area, 0, 0, slit[i].w, titleh);
+ XMoveResizeWindow(ob_display, slit[i].title, 0, 0,
+ slit[i].w, titleh);
+ }
+
+ paint(slit[i].frame, slit[i].a_frame);
+ paint(slit[i].title, slit[i].a_title);
+ XMapWindow(ob_display, slit[i].frame);
+ } else
+ XUnmapWindow(ob_display, slit[i].frame);
+ }
+}