From: Dana Jansens Date: Fri, 9 May 2003 19:58:08 +0000 (+0000) Subject: add shit that i made in the last week! X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=bccb90b01da9d3f3b483e690444ebfbca914aa02;p=chaz%2Fopenbox add shit that i made in the last week! --- diff --git a/openbox/openbox.c b/openbox/openbox.c index 304d52c6..8c599c4a 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -271,7 +271,8 @@ void signal_handler(const ObEvent *e, void *data) case SIGFPE: case SIGSEGV: - g_error("Caught signal %d. Aborting and dumping core.", s); + g_message("Caught signal %d. Aborting and dumping core.", s); + abort(); } } diff --git a/openbox/popup.c b/openbox/popup.c new file mode 100644 index 00000000..f20aa006 --- /dev/null +++ b/openbox/popup.c @@ -0,0 +1,215 @@ +#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); +} diff --git a/openbox/popup.h b/openbox/popup.h new file mode 100644 index 00000000..f26bedd9 --- /dev/null +++ b/openbox/popup.h @@ -0,0 +1,25 @@ +#ifndef __popup_h +#define __popup_h + +#include "frame.h" + +typedef struct Popup Popup; + +Popup *popup_new(gboolean hasicon); +void popup_free(Popup *self); + +/*! Position the popup. The gravity rules are not the same X uses for windows, + instead of the position being the top-left of the window, the gravity + specifies which corner of the popup will be placed at the given coords. + Static and Forget gravity are equivilent to NorthWest. +*/ +void popup_position(Popup *self, int gravity, int x, int y); +/*! Set the sizes for the popup. When set to 0, the size will be based on + the text size. */ +void popup_size(Popup *self, int w, int h); +void popup_size_to_string(Popup *self, char *text); + +void popup_show(Popup *self, char *text, Icon *icon); +void popup_hide(Popup *self); + +#endif diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 00000000..a66187c7 --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = slit diff --git a/tools/slit/Makefile.am b/tools/slit/Makefile.am new file mode 100644 index 00000000..b9aa5058 --- /dev/null +++ b/tools/slit/Makefile.am @@ -0,0 +1,17 @@ +rcdir=$(datadir)/openbox + +INCLUDES=-I../.. + +CPPFLAGS=$(X_CFLAGS) $(XFT_CFLAGS) $(GLIB_CFLAGS) @CPPFLAGS@ \ + -DRCDIR=\"$(rcdir)\" \ + -DG_LOG_DOMAIN=\"ObSlit\" +LIBS=$(X_LIBS) $(XFT_LIBS) $(GLIB_LIBS) @LIBS@ @LIBINTL@ + +bin_PROGRAMS=obslit + +obslit_LDADD=-lobrender -L../../render +obslit_SOURCES=slit.c +MAINTAINERCLEANFILES=Makefile.in + +distclean-local: + $(RM) *\~ *.orig *.rej .\#* diff --git a/tools/slit/slit.c b/tools/slit/slit.c new file mode 100644 index 00000000..28d9303e --- /dev/null +++ b/tools/slit/slit.c @@ -0,0 +1,634 @@ +#include "render/render.h" +#include "render/theme.h" + +#include +#include +#include +#ifdef HAVE_SIGNAL_H +# include +#endif +#ifdef HAVE_SYS_SELECT_H +# include +#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); + } +}