]> icculus.org git repositories - dana/openbox.git/blob - engines/default/plugin.c
Improve interface by removing display screen and render instance
[dana/openbox.git] / engines / default / plugin.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3  frame_default_plugin.c for the Openbox window manager
4  Copyright (c) 2006        Mikael Magnusson
5  Copyright (c) 2003-2007   Dana Jansens
6
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  GNU General Public License for more details.
16
17  See the COPYING file for a copy of the GNU General Public License.
18  */
19
20 #include "plugin.h"
21 #include "render.h"
22
23 /* Needed for the _() function */
24 #include <gettext.h>
25
26 #include "obt/prop.h"
27 #include "openbox/screen.h"
28
29 /* Needed for the grab_server */
30 #include "openbox/grab.h"
31
32 #include <X11/extensions/shape.h>
33
34 typedef enum
35 {
36     OB_FLAG_MAX = 1 << 0,
37     OB_FLAG_CLOSE = 1 << 1,
38     OB_FLAG_DESK = 1 << 2,
39     OB_FLAG_SHADE = 1 << 3,
40     OB_FLAG_ICONIFY = 1 << 4
41 } ObFrameFlags;
42
43 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
44                          ButtonPressMask | ButtonReleaseMask | \
45                          SubstructureRedirectMask | FocusChangeMask)
46 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
47                            ButtonMotionMask | PointerMotionMask | \
48                            EnterWindowMask | LeaveWindowMask)
49
50 #define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */
51 #define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */
52
53 #define FRAME_HANDLE_Y(f) (f->size.top + f->client_area.height + f->cbwidth_b)
54
55 Display * obp_display;
56 gint obp_screen;
57 RrInstance *ob_rr_inst;
58
59 Window createWindow(Window parent, Visual *visual, gulong mask,
60         XSetWindowAttributes *attrib)
61 {
62     return XCreateWindow(obp_display, parent, 0, 0, 1, 1, 0, (visual ? 32
63             : RrDepth(ob_rr_inst)), InputOutput, (visual ? visual
64             : RrVisual(ob_rr_inst)), mask, attrib);
65
66 }
67
68 Visual *check_32bit_client(ObClient *c)
69 {
70     XWindowAttributes wattrib;
71     Status ret;
72
73     /* we're already running at 32 bit depth, yay. we don't need to use their
74      visual */
75     if (RrDepth(ob_rr_inst) == 32)
76         return NULL;
77
78     ret = XGetWindowAttributes(obp_display, c->window, &wattrib);
79     g_assert(ret != BadDrawable);
80     g_assert(ret != BadWindow);
81
82     if (wattrib.depth == 32)
83         return wattrib.visual;
84     return NULL;
85 }
86
87 /* Not used */
88 gint init(Display * display, gint screen)
89 {
90     ob_rr_inst = RrInstanceNew(display, screen);
91     if (ob_rr_inst == NULL)
92         ob_exit_with_error(_("Failed to initialize the obrender library."));
93     obp_display = display;
94     obp_screen = screen;
95 }
96
97 gpointer frame_new(struct _ObClient * client)
98 {
99     XSetWindowAttributes attrib;
100     gulong mask;
101     ObDefaultFrame *self;
102     Visual *visual;
103
104     self = g_new0(ObDefaultFrame, 1);
105     self->client = client;
106
107     visual = check_32bit_client(client);
108
109     /* create the non-visible decor windows */
110
111     mask = 0;
112     if (visual) {
113         /* client has a 32-bit visual */
114         mask |= CWColormap | CWBackPixel | CWBorderPixel;
115         /* create a colormap with the visual */
116         OBDEFAULTFRAME(self)->colormap = attrib.colormap = XCreateColormap(
117                 obp_display, RootWindow(obp_display,
118                         obp_screen), visual, AllocNone);
119         attrib.background_pixel = BlackPixel(obp_display,
120                 obp_screen);
121         attrib.border_pixel = BlackPixel(obp_display, obp_screen);
122     }
123     self->window = createWindow(
124             RootWindow(obp_display, obp_screen), visual, mask,
125             &attrib);
126
127     /* create the visible decor windows */
128
129     mask = 0;
130     if (visual) {
131         /* client has a 32-bit visual */
132         mask |= CWColormap | CWBackPixel | CWBorderPixel;
133         attrib.colormap = RrColormap(ob_rr_inst);
134     }
135
136     self->backback = createWindow(self->window, NULL, mask, &attrib);
137     self->backfront = createWindow(self->backback, NULL, mask, &attrib);
138
139     mask |= CWEventMask;
140     attrib.event_mask = ELEMENT_EVENTMASK;
141     self->innerleft = createWindow(self->window, NULL, mask, &attrib);
142     self->innertop = createWindow(self->window, NULL, mask, &attrib);
143     self->innerright = createWindow(self->window, NULL, mask, &attrib);
144     self->innerbottom = createWindow(self->window, NULL, mask, &attrib);
145
146     self->innerblb = createWindow(self->innerbottom, NULL, mask, &attrib);
147     self->innerbrb = createWindow(self->innerbottom, NULL, mask, &attrib);
148     self->innerbll = createWindow(self->innerleft, NULL, mask, &attrib);
149     self->innerbrr = createWindow(self->innerright, NULL, mask, &attrib);
150
151     self->title = createWindow(self->window, NULL, mask, &attrib);
152     self->titleleft = createWindow(self->window, NULL, mask, &attrib);
153     self->titletop = createWindow(self->window, NULL, mask, &attrib);
154     self->titletopleft = createWindow(self->window, NULL, mask, &attrib);
155     self->titletopright = createWindow(self->window, NULL, mask, &attrib);
156     self->titleright = createWindow(self->window, NULL, mask, &attrib);
157     self->titlebottom = createWindow(self->window, NULL, mask, &attrib);
158
159     self->topresize = createWindow(self->title, NULL, mask, &attrib);
160     self->tltresize = createWindow(self->title, NULL, mask, &attrib);
161     self->tllresize = createWindow(self->title, NULL, mask, &attrib);
162     self->trtresize = createWindow(self->title, NULL, mask, &attrib);
163     self->trrresize = createWindow(self->title, NULL, mask, &attrib);
164
165     self->left = createWindow(self->window, NULL, mask, &attrib);
166     self->right = createWindow(self->window, NULL, mask, &attrib);
167
168     self->label = createWindow(self->title, NULL, mask, &attrib);
169     self->max = createWindow(self->title, NULL, mask, &attrib);
170     self->close = createWindow(self->title, NULL, mask, &attrib);
171     self->desk = createWindow(self->title, NULL, mask, &attrib);
172     self->shade = createWindow(self->title, NULL, mask, &attrib);
173     self->icon = createWindow(self->title, NULL, mask, &attrib);
174     self->iconify = createWindow(self->title, NULL, mask, &attrib);
175
176     self->handle = createWindow(self->window, NULL, mask, &attrib);
177     self->lgrip = createWindow(self->handle, NULL, mask, &attrib);
178     self->rgrip = createWindow(self->handle, NULL, mask, &attrib);
179
180     self->handleleft = createWindow(self->handle, NULL, mask, &attrib);
181     self->handleright = createWindow(self->handle, NULL, mask, &attrib);
182
183     self->handletop = createWindow(self->window, NULL, mask, &attrib);
184     self->handlebottom = createWindow(self->window, NULL, mask, &attrib);
185     self->lgripleft = createWindow(self->window, NULL, mask, &attrib);
186     self->lgriptop = createWindow(self->window, NULL, mask, &attrib);
187     self->lgripbottom = createWindow(self->window, NULL, mask, &attrib);
188     self->rgripright = createWindow(self->window, NULL, mask, &attrib);
189     self->rgriptop = createWindow(self->window, NULL, mask, &attrib);
190     self->rgripbottom = createWindow(self->window, NULL, mask, &attrib);
191
192     self->stitle = g_strdup("");
193     self->focused = FALSE;
194
195     /* the other stuff is shown based on decor settings */
196     XMapWindow(obp_display, self->label);
197     XMapWindow(obp_display, self->backback);
198     XMapWindow(obp_display, self->backfront);
199
200     self->hover_flag = OB_BUTTON_NONE;
201     self->press_flag = OB_BUTTON_NONE;
202
203     set_theme_statics(self);
204
205     return self;
206 }
207
208 void set_theme_statics(gpointer _self)
209 {
210     ObDefaultFrame * self = (ObDefaultFrame *) _self;
211     /* set colors/appearance/sizes for stuff that doesn't change */
212     XResizeWindow(obp_display, self->max, theme_config.button_size,
213             theme_config.button_size);
214     XResizeWindow(obp_display, self->iconify, theme_config.button_size,
215             theme_config.button_size);
216     XResizeWindow(obp_display, self->icon, theme_config.button_size + 2,
217             theme_config.button_size + 2);
218     XResizeWindow(obp_display, self->close, theme_config.button_size,
219             theme_config.button_size);
220     XResizeWindow(obp_display, self->desk, theme_config.button_size,
221             theme_config.button_size);
222     XResizeWindow(obp_display, self->shade, theme_config.button_size,
223             theme_config.button_size);
224     XResizeWindow(obp_display, self->tltresize, theme_config.grip_width,
225             theme_config.paddingy + 1);
226     XResizeWindow(obp_display, self->trtresize, theme_config.grip_width,
227             theme_config.paddingy + 1);
228     XResizeWindow(obp_display, self->tllresize,
229             theme_config.paddingx + 1, theme_config.title_height);
230     XResizeWindow(obp_display, self->trrresize,
231             theme_config.paddingx + 1, theme_config.title_height);
232
233     /* set up the dynamic appearances */
234     self->a_unfocused_title = RrAppearanceCopy(theme_config.a_unfocused_title);
235     self->a_focused_title = RrAppearanceCopy(theme_config.a_focused_title);
236     self->a_unfocused_label = RrAppearanceCopy(theme_config.a_unfocused_label);
237     self->a_focused_label = RrAppearanceCopy(theme_config.a_focused_label);
238     self->a_unfocused_handle
239             = RrAppearanceCopy(theme_config.a_unfocused_handle);
240     self->a_focused_handle = RrAppearanceCopy(theme_config.a_focused_handle);
241     self->a_icon = RrAppearanceCopy(theme_config.a_icon);
242 }
243
244 void free_theme_statics(gpointer _self)
245 {
246     ObDefaultFrame * self = (ObDefaultFrame *) _self;
247     RrAppearanceFree(self->a_unfocused_title);
248     RrAppearanceFree(self->a_focused_title);
249     RrAppearanceFree(self->a_unfocused_label);
250     RrAppearanceFree(self->a_focused_label);
251     RrAppearanceFree(self->a_unfocused_handle);
252     RrAppearanceFree(self->a_focused_handle);
253     RrAppearanceFree(self->a_icon);
254 }
255
256 void frame_free(gpointer self)
257 {
258     free_theme_statics(OBDEFAULTFRAME(self));
259     XDestroyWindow(obp_display, OBDEFAULTFRAME(self)->window);
260     if (OBDEFAULTFRAME(self)->colormap)
261         XFreeColormap(obp_display, OBDEFAULTFRAME(self)->colormap);
262     
263     g_free(OBDEFAULTFRAME(self)->stitle);
264     g_free(self);
265 }
266
267 void frame_show(gpointer _self)
268 {
269     ObDefaultFrame * self = (ObDefaultFrame *) _self;
270     if (!self->visible) {
271         self->visible = TRUE;
272         frame_update_skin(self);
273         /* Grab the server to make sure that the frame window is mapped before
274          the client gets its MapNotify, i.e. to make sure the client is
275          _visible_ when it gets MapNotify. */
276         grab_server(TRUE);
277         XMapWindow(obp_display, self->client->window);
278         XMapWindow(obp_display, self->window);
279         grab_server(FALSE);
280     }
281 }
282
283 gint frame_hide(gpointer self)
284 {
285     if (OBDEFAULTFRAME(self)->visible) {
286         OBDEFAULTFRAME(self)->visible = FALSE;
287         if (!frame_iconify_animating(self))
288             XUnmapWindow(obp_display, OBDEFAULTFRAME(self)->window);
289         /* we unmap the client itself so that we can get MapRequest
290          events, and because the ICCCM tells us to! */
291         XUnmapWindow(obp_display, OBDEFAULTFRAME(self)->client->window);
292         return 1;
293     }
294     else {
295         return 0;
296     }
297 }
298
299 void frame_adjust_theme(gpointer self)
300 {
301     free_theme_statics(self);
302     set_theme_statics(self);
303 }
304
305 void frame_adjust_shape(gpointer _self)
306 {
307 #ifdef SHAPE
308     ObDefaultFrame * self = (ObDefaultFrame *) _self;
309     gint num;
310     XRectangle xrect[2];
311
312     if (!self->client->shaped)
313     {
314         /* clear the shape on the frame window */
315         XShapeCombineMask(obp_display, self->window, ShapeBounding,
316                 self->size.left,
317                 self->size.top,
318                 None, ShapeSet);
319     }
320     else
321     {
322         /* make the frame's shape match the clients */
323         XShapeCombineShape(obp_display, self->window, ShapeBounding,
324                 self->size.left,
325                 self->size.top,
326                 self->client->window,
327                 ShapeBounding, ShapeSet);
328
329         num = 0;
330         if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
331         {
332             xrect[0].x = 0;
333             xrect[0].y = 0;
334             xrect[0].width = self->area.width;
335             xrect[0].height = self->size.top;
336             ++num;
337         }
338
339         if (self->decorations & OB_FRAME_DECOR_HANDLE &&
340                 theme_config.handle_height> 0)
341         {
342             xrect[1].x = 0;
343             xrect[1].y = FRAME_HANDLE_Y(self);
344             xrect[1].width = self->area.width;
345             xrect[1].height = theme_config.handle_height +
346             self->bwidth * 2;
347             ++num;
348         }
349
350         XShapeCombineRectangles(obp_display, self->window,
351                 ShapeBounding, 0, 0, xrect, num,
352                 ShapeUnion, Unsorted);
353     }
354 #endif
355 }
356
357 void frame_grab(gpointer _self, GHashTable * window_map)
358 {
359     ObDefaultFrame * self = (ObDefaultFrame *) _self;
360     /* DO NOT map the client window here. we used to do that, but it is bogus.
361      we need to set up the client's dimensions and everything before we
362      send a mapnotify or we create race conditions.
363      */
364
365     /* reparent the client to the frame */
366     XReparentWindow(obp_display, self->client->window, self->window, 0, 0);
367
368     /*
369      When reparenting the client window, it is usually not mapped yet, since
370      this occurs from a MapRequest. However, in the case where Openbox is
371      starting up, the window is already mapped, so we'll see an unmap event
372      for it.
373      */
374     if (ob_state() == OB_STATE_STARTING)
375         ++self->client->ignore_unmaps;
376
377     /* select the event mask on the client's parent (to receive config/map
378      req's) the ButtonPress is to catch clicks on the client border */
379     XSelectInput(obp_display, self->window, FRAME_EVENTMASK);
380
381     /* set all the windows for the frame in the window_map */
382     g_hash_table_insert(window_map, &self->window, self->client);
383     g_hash_table_insert(window_map, &self->backback, self->client);
384     g_hash_table_insert(window_map, &self->backfront, self->client);
385     g_hash_table_insert(window_map, &self->innerleft, self->client);
386     g_hash_table_insert(window_map, &self->innertop, self->client);
387     g_hash_table_insert(window_map, &self->innerright, self->client);
388     g_hash_table_insert(window_map, &self->innerbottom, self->client);
389     g_hash_table_insert(window_map, &self->title, self->client);
390     g_hash_table_insert(window_map, &self->label, self->client);
391     g_hash_table_insert(window_map, &self->max, self->client);
392     g_hash_table_insert(window_map, &self->close, self->client);
393     g_hash_table_insert(window_map, &self->desk, self->client);
394     g_hash_table_insert(window_map, &self->shade, self->client);
395     g_hash_table_insert(window_map, &self->icon, self->client);
396     g_hash_table_insert(window_map, &self->iconify, self->client);
397     g_hash_table_insert(window_map, &self->handle, self->client);
398     g_hash_table_insert(window_map, &self->lgrip, self->client);
399     g_hash_table_insert(window_map, &self->rgrip, self->client);
400     g_hash_table_insert(window_map, &self->topresize, self->client);
401     g_hash_table_insert(window_map, &self->tltresize, self->client);
402     g_hash_table_insert(window_map, &self->tllresize, self->client);
403     g_hash_table_insert(window_map, &self->trtresize, self->client);
404     g_hash_table_insert(window_map, &self->trrresize, self->client);
405     g_hash_table_insert(window_map, &self->left, self->client);
406     g_hash_table_insert(window_map, &self->right, self->client);
407     g_hash_table_insert(window_map, &self->titleleft, self->client);
408     g_hash_table_insert(window_map, &self->titletop, self->client);
409     g_hash_table_insert(window_map, &self->titletopleft, self->client);
410     g_hash_table_insert(window_map, &self->titletopright, self->client);
411     g_hash_table_insert(window_map, &self->titleright, self->client);
412     g_hash_table_insert(window_map, &self->titlebottom, self->client);
413     g_hash_table_insert(window_map, &self->handleleft, self->client);
414     g_hash_table_insert(window_map, &self->handletop, self->client);
415     g_hash_table_insert(window_map, &self->handleright, self->client);
416     g_hash_table_insert(window_map, &self->handlebottom, self->client);
417     g_hash_table_insert(window_map, &self->lgripleft, self->client);
418     g_hash_table_insert(window_map, &self->lgriptop, self->client);
419     g_hash_table_insert(window_map, &self->lgripbottom, self->client);
420     g_hash_table_insert(window_map, &self->rgripright, self->client);
421     g_hash_table_insert(window_map, &self->rgriptop, self->client);
422     g_hash_table_insert(window_map, &self->rgripbottom, self->client);
423 }
424
425 void frame_ungrab(gpointer _self, GHashTable * window_map)
426 {
427     ObDefaultFrame * self = (ObDefaultFrame *) _self;
428     XEvent ev;
429     gboolean reparent = TRUE;
430
431     /* if there was any animation going on, kill it */
432     obt_main_loop_timeout_remove_data(plugin.ob_main_loop,
433             frame_animate_iconify, self, FALSE);
434
435     /* check if the app has already reparented its window away */
436     while (XCheckTypedWindowEvent(obp_display, self->client->window,
437             ReparentNotify, &ev)) {
438         /* This check makes sure we don't catch our own reparent action to
439          our frame window. This doesn't count as the app reparenting itself
440          away of course.
441
442          Reparent events that are generated by us are just discarded here.
443          They are of no consequence to us anyhow.
444          */
445         if (ev.xreparent.parent != self->window) {
446             reparent = FALSE;
447             XPutBackEvent(obp_display, &ev);
448             break;
449         }
450     }
451
452     if (reparent) {
453         /* according to the ICCCM - if the client doesn't reparent itself,
454          then we will reparent the window to root for them */
455         XReparentWindow(obp_display, self->client->window, RootWindow(
456                 obp_display, obp_screen), self->client_area.x,
457                 self->client_area.y);
458     }
459
460     /* remove all the windows for the frame from the window_map */
461     g_hash_table_remove(window_map, &self->window);
462     g_hash_table_remove(window_map, &self->backback);
463     g_hash_table_remove(window_map, &self->backfront);
464     g_hash_table_remove(window_map, &self->innerleft);
465     g_hash_table_remove(window_map, &self->innertop);
466     g_hash_table_remove(window_map, &self->innerright);
467     g_hash_table_remove(window_map, &self->innerbottom);
468     g_hash_table_remove(window_map, &self->title);
469     g_hash_table_remove(window_map, &self->label);
470     g_hash_table_remove(window_map, &self->max);
471     g_hash_table_remove(window_map, &self->close);
472     g_hash_table_remove(window_map, &self->desk);
473     g_hash_table_remove(window_map, &self->shade);
474     g_hash_table_remove(window_map, &self->icon);
475     g_hash_table_remove(window_map, &self->iconify);
476     g_hash_table_remove(window_map, &self->handle);
477     g_hash_table_remove(window_map, &self->lgrip);
478     g_hash_table_remove(window_map, &self->rgrip);
479     g_hash_table_remove(window_map, &self->topresize);
480     g_hash_table_remove(window_map, &self->tltresize);
481     g_hash_table_remove(window_map, &self->tllresize);
482     g_hash_table_remove(window_map, &self->trtresize);
483     g_hash_table_remove(window_map, &self->trrresize);
484     g_hash_table_remove(window_map, &self->left);
485     g_hash_table_remove(window_map, &self->right);
486     g_hash_table_remove(window_map, &self->titleleft);
487     g_hash_table_remove(window_map, &self->titletop);
488     g_hash_table_remove(window_map, &self->titletopleft);
489     g_hash_table_remove(window_map, &self->titletopright);
490     g_hash_table_remove(window_map, &self->titleright);
491     g_hash_table_remove(window_map, &self->titlebottom);
492     g_hash_table_remove(window_map, &self->handleleft);
493     g_hash_table_remove(window_map, &self->handletop);
494     g_hash_table_remove(window_map, &self->handleright);
495     g_hash_table_remove(window_map, &self->handlebottom);
496     g_hash_table_remove(window_map, &self->lgripleft);
497     g_hash_table_remove(window_map, &self->lgriptop);
498     g_hash_table_remove(window_map, &self->lgripbottom);
499     g_hash_table_remove(window_map, &self->rgripright);
500     g_hash_table_remove(window_map, &self->rgriptop);
501     g_hash_table_remove(window_map, &self->rgripbottom);
502
503     obt_main_loop_timeout_remove_data(plugin.ob_main_loop, flash_timeout, self,
504             TRUE);
505 }
506
507 ObFrameContext frame_context(gpointer _self, Window win, gint x, gint y)
508 {
509     ObDefaultFrame * self = OBDEFAULTFRAME(_self);
510
511     /* when the user clicks in the corners of the titlebar and the client
512      is fully maximized, then treat it like they clicked in the
513      button that is there */
514     if (self->max_horz && self->max_vert && (win == self->title || win
515             == self->titletop || win == self->titleleft || win
516             == self->titletopleft || win == self->titleright || win
517             == self->titletopright)) {
518         /* get the mouse coords in reference to the whole frame */
519         gint fx = x;
520         gint fy = y;
521
522         /* these windows are down a border width from the top of the frame */
523         if (win == self->title || win == self->titleleft || win
524                 == self->titleright)
525             fy += self->bwidth;
526
527         /* title is a border width in from the edge */
528         if (win == self->title)
529             fx += self->bwidth;
530         /* titletop is a bit to the right */
531         else if (win == self->titletop)
532             fx += theme_config.grip_width + self->bwidth;
533         /* titletopright is way to the right edge */
534         else if (win == self->titletopright)
535             fx += self->area.width - (theme_config.grip_width + self->bwidth);
536         /* titleright is even more way to the right edge */
537         else if (win == self->titleright)
538             fx += self->area.width - self->bwidth;
539
540         /* figure out if we're over the area that should be considered a
541          button */
542         if (fy < self->bwidth + theme_config.paddingy + 1
543                 + theme_config.button_size) {
544             if (fx < (self->bwidth + theme_config.paddingx + 1
545                     + theme_config.button_size)) {
546                 if (self->leftmost != OB_FRAME_CONTEXT_NONE)
547                     return self->leftmost;
548             }
549             else if (fx >= (self->area.width - (self->bwidth
550                     + theme_config.paddingx + 1 + theme_config.button_size))) {
551                 if (self->rightmost != OB_FRAME_CONTEXT_NONE)
552                     return self->rightmost;
553             }
554         }
555
556         /* there is no resizing maximized windows so make them the titlebar
557          context */
558         return OB_FRAME_CONTEXT_TITLEBAR;
559     }
560     else if (self->max_vert
561             && (win == self->titletop || win == self->topresize))
562         /* can't resize vertically when max vert */
563         return OB_FRAME_CONTEXT_TITLEBAR;
564     else if (self->shaded && (win == self->titletop || win == self->topresize))
565         /* can't resize vertically when shaded */
566         return OB_FRAME_CONTEXT_TITLEBAR;
567
568     if (win == self->window)
569         return OB_FRAME_CONTEXT_FRAME;
570     if (win == self->label)
571         return OB_FRAME_CONTEXT_TITLEBAR;
572     if (win == self->handle)
573         return OB_FRAME_CONTEXT_BOTTOM;
574     if (win == self->handletop)
575         return OB_FRAME_CONTEXT_BOTTOM;
576     if (win == self->handlebottom)
577         return OB_FRAME_CONTEXT_BOTTOM;
578     if (win == self->handleleft)
579         return OB_FRAME_CONTEXT_BLCORNER;
580     if (win == self->lgrip)
581         return OB_FRAME_CONTEXT_BLCORNER;
582     if (win == self->lgripleft)
583         return OB_FRAME_CONTEXT_BLCORNER;
584     if (win == self->lgriptop)
585         return OB_FRAME_CONTEXT_BLCORNER;
586     if (win == self->lgripbottom)
587         return OB_FRAME_CONTEXT_BLCORNER;
588     if (win == self->handleright)
589         return OB_FRAME_CONTEXT_BRCORNER;
590     if (win == self->rgrip)
591         return OB_FRAME_CONTEXT_BRCORNER;
592     if (win == self->rgripright)
593         return OB_FRAME_CONTEXT_BLCORNER;
594     if (win == self->rgriptop)
595         return OB_FRAME_CONTEXT_BLCORNER;
596     if (win == self->rgripbottom)
597         return OB_FRAME_CONTEXT_BLCORNER;
598     if (win == self->title)
599         return OB_FRAME_CONTEXT_TITLEBAR;
600     if (win == self->titlebottom)
601         return OB_FRAME_CONTEXT_TITLEBAR;
602     if (win == self->titleleft)
603         return OB_FRAME_CONTEXT_TLCORNER;
604     if (win == self->titletopleft)
605         return OB_FRAME_CONTEXT_TLCORNER;
606     if (win == self->titleright)
607         return OB_FRAME_CONTEXT_TRCORNER;
608     if (win == self->titletopright)
609         return OB_FRAME_CONTEXT_TRCORNER;
610     if (win == self->titletop)
611         return OB_FRAME_CONTEXT_TOP;
612     if (win == self->topresize)
613         return OB_FRAME_CONTEXT_TOP;
614     if (win == self->tltresize)
615         return OB_FRAME_CONTEXT_TLCORNER;
616     if (win == self->tllresize)
617         return OB_FRAME_CONTEXT_TLCORNER;
618     if (win == self->trtresize)
619         return OB_FRAME_CONTEXT_TRCORNER;
620     if (win == self->trrresize)
621         return OB_FRAME_CONTEXT_TRCORNER;
622     if (win == self->left)
623         return OB_FRAME_CONTEXT_LEFT;
624     if (win == self->right)
625         return OB_FRAME_CONTEXT_RIGHT;
626     if (win == self->innertop)
627         return OB_FRAME_CONTEXT_TITLEBAR;
628     if (win == self->innerleft)
629         return OB_FRAME_CONTEXT_LEFT;
630     if (win == self->innerbottom)
631         return OB_FRAME_CONTEXT_BOTTOM;
632     if (win == self->innerright)
633         return OB_FRAME_CONTEXT_RIGHT;
634     if (win == self->max)
635         return OB_FRAME_CONTEXT_MAXIMIZE;
636     if (win == self->iconify)
637         return OB_FRAME_CONTEXT_ICONIFY;
638     if (win == self->close)
639         return OB_FRAME_CONTEXT_CLOSE;
640     if (win == self->icon)
641         return OB_FRAME_CONTEXT_ICON;
642     if (win == self->desk)
643         return OB_FRAME_CONTEXT_ALLDESKTOPS;
644     if (win == self->shade)
645         return OB_FRAME_CONTEXT_SHADE;
646
647     return OB_FRAME_CONTEXT_NONE;
648 }
649
650 void frame_set_is_visible(gpointer self, gboolean b)
651 {
652     OBDEFAULTFRAME(self)->visible = b;
653 }
654
655 void frame_set_is_focus(gpointer self, gboolean b)
656 {
657     OBDEFAULTFRAME(self)->focused = b;
658 }
659
660 void frame_set_is_max_vert(gpointer self, gboolean b)
661 {
662     OBDEFAULTFRAME(self)->max_vert = b;
663 }
664
665 void frame_set_is_max_horz(gpointer self, gboolean b)
666 {
667     OBDEFAULTFRAME(self)->max_horz = b;
668 }
669
670 void frame_set_is_shaded(gpointer self, gboolean b)
671 {
672     OBDEFAULTFRAME(self)->shaded = b;
673 }
674
675 void frame_unfocus(gpointer self)
676 {
677     OBDEFAULTFRAME(self)->focused = FALSE;
678 }
679
680 void frame_flash_start(gpointer _self)
681 {
682     ObDefaultFrame * self = (ObDefaultFrame *) _self;
683     self->flash_on = self->focused;
684
685     if (!self->flashing)
686         obt_main_loop_timeout_add(plugin.ob_main_loop, G_USEC_PER_SEC * 0.6,
687                 flash_timeout, self, g_direct_equal, flash_done);
688     g_get_current_time(&self->flash_end);
689     g_time_val_add(&self->flash_end, G_USEC_PER_SEC * 5);
690
691     self->flashing = TRUE;
692 }
693
694 void frame_flash_stop(gpointer _self)
695 {
696     ObDefaultFrame * self = (ObDefaultFrame *) _self;
697     self->flashing = FALSE;
698 }
699
700 void frame_begin_iconify_animation(gpointer _self, gboolean iconifying)
701 {
702     ObDefaultFrame * self = (ObDefaultFrame *) _self;
703     gulong time;
704     gboolean new_anim = FALSE;
705     gboolean set_end = TRUE;
706     GTimeVal now;
707
708     /* if there is no titlebar, just don't animate for now
709      XXX it would be nice tho.. */
710     if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR))
711         return;
712
713     /* get the current time */
714     g_get_current_time(&now);
715
716     /* get how long until the end */
717     time = FRAME_ANIMATE_ICONIFY_TIME;
718     if (self->iconify_animation_going) {
719         if (!!iconifying != (self->iconify_animation_going > 0)) {
720             /* animation was already going on in the opposite direction */
721             time = time - frame_animate_iconify_time_left(_self, &now);
722         }
723         else
724             /* animation was already going in the same direction */
725             set_end = FALSE;
726     }
727     else
728         new_anim = TRUE;
729     self->iconify_animation_going = iconifying ? 1 : -1;
730
731     /* set the ending time */
732     if (set_end) {
733         self->iconify_animation_end.tv_sec = now.tv_sec;
734         self->iconify_animation_end.tv_usec = now.tv_usec;
735         g_time_val_add(&self->iconify_animation_end, time);
736     }
737
738     if (new_anim) {
739         obt_main_loop_timeout_remove_data(plugin.ob_main_loop,
740                 frame_animate_iconify, self, FALSE);
741         obt_main_loop_timeout_add(plugin.ob_main_loop, 
742         FRAME_ANIMATE_ICONIFY_STEP_TIME, frame_animate_iconify, self,
743                 g_direct_equal, NULL);
744
745         /* do the first step */
746         frame_animate_iconify(self);
747
748         /* show it during the animation even if it is not "visible" */
749         if (!self->visible)
750             XMapWindow(obp_display, self->window);
751     }
752 }
753
754 void frame_end_iconify_animation(gpointer _self)
755 {
756     ObDefaultFrame * self = (ObDefaultFrame *) _self;
757     /* see if there is an animation going */
758     if (self->iconify_animation_going == 0)
759         return;
760
761     if (!self->visible)
762         XUnmapWindow(obp_display, self->window);
763     else {
764         /* Send a ConfigureNotify when the animation is done, this fixes
765          KDE's pager showing the window in the wrong place.  since the
766          window is mapped at a different location and is then moved, we
767          need to send the synthetic configurenotify, since apps may have
768          read the position when the client mapped, apparently. */
769         client_reconfigure(self->client, TRUE);
770     }
771
772     /* we're not animating any more ! */
773     self->iconify_animation_going = 0;
774
775     XMoveResizeWindow(obp_display, self->window, self->area.x,
776             self->area.y, self->area.width, self->area.height);
777     /* we delay re-rendering until after we're done animating */
778     frame_update_skin(self);
779     XFlush(obp_display);
780 }
781
782 gboolean frame_iconify_animating(gpointer _self)
783 {
784     ObDefaultFrame * self = (ObDefaultFrame *) _self;
785     return self->iconify_animation_going != 0;
786 }
787
788 void frame_set_decorations(gpointer self, ObFrameDecorations d)
789 {
790     OBDEFAULTFRAME(self)->decorations = d;
791 }
792
793 Rect frame_get_window_area(gpointer self)
794 {
795     return OBDEFAULTFRAME(self)->area;
796 }
797 void frame_set_client_area(gpointer self, Rect r)
798 {
799     OBDEFAULTFRAME(self)->client_area = r;
800 }
801
802 void frame_update_layout(gpointer _self, gboolean is_resize, gboolean is_fake)
803 {
804     ObDefaultFrame * self = (ObDefaultFrame *) _self;
805     Strut oldsize;
806
807     oldsize = self->size;
808     self->area = self->client_area;
809
810     /* do this before changing the frame's status like max_horz max_vert */
811     frame_adjust_cursors(self);
812
813     if (self->decorations & OB_FRAME_DECOR_BORDER
814             || (plugin.config_theme_keepborder)) {
815         self->bwidth = theme_config.fbwidth;
816     }
817     else {
818         self->bwidth = 0;
819     }
820
821     if (self->decorations & OB_FRAME_DECOR_BORDER) {
822         self->cbwidth_l = theme_config.cbwidthx;
823         self->cbwidth_r = theme_config.cbwidthx;
824         self->cbwidth_t = theme_config.cbwidthy;
825         self->cbwidth_b = theme_config.cbwidthy;
826     }
827     else {
828         self->cbwidth_l = 0;
829         self->cbwidth_t = 0;
830         self->cbwidth_r = 0;
831         self->cbwidth_b = 0;
832     }
833
834     if (self->max_horz) {
835         self->cbwidth_l = 0;
836         self->cbwidth_r = 0;
837         self->width = self->client_area.width;
838         if (self->max_vert)
839             self->cbwidth_b = 0;
840     }
841     else {
842         self->width = self->client_area.width + self->cbwidth_l
843                 + self->cbwidth_r;
844     }
845
846     /* some elements are sized based of the width, so don't let them have
847      negative values */
848     self->width = MAX(self->width, (theme_config.grip_width + self->bwidth) * 2
849             + 1);
850
851     STRUT_SET(self->size, self->cbwidth_l
852             + (!self->max_horz ? self->bwidth : 0), self->cbwidth_t
853             + self->bwidth, self->cbwidth_r + (!self->max_horz ? self->bwidth
854             : 0), self->cbwidth_b
855             + (!self->max_horz || !self->max_vert ? self->bwidth : 0));
856
857     if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
858         self->size.top += theme_config.title_height + self->bwidth;
859     if (self->decorations & OB_FRAME_DECOR_HANDLE && theme_config.handle_height
860             > 0) {
861         self->size.bottom += theme_config.handle_height + self->bwidth;
862     }
863
864     /* position/size and map/unmap all the windows */
865     if (!is_fake) {
866         gint innercornerheight = theme_config.grip_width - self->size.bottom;
867
868         if (self->cbwidth_l) {
869             XMoveResizeWindow(obp_display, self->innerleft,
870                     self->size.left - self->cbwidth_l, self->size.top,
871                     self->cbwidth_l, self->client_area.height);
872
873             XMapWindow(obp_display, self->innerleft);
874         }
875         else
876             XUnmapWindow(obp_display, self->innerleft);
877
878         if (self->cbwidth_l && innercornerheight > 0) {
879             XMoveResizeWindow(obp_display, self->innerbll, 0,
880                     self->client_area.height - (theme_config.grip_width
881                             - self->size.bottom), self->cbwidth_l,
882                     theme_config.grip_width - self->size.bottom);
883
884             XMapWindow(obp_display, self->innerbll);
885         }
886         else
887             XUnmapWindow(obp_display, self->innerbll);
888
889         if (self->cbwidth_r) {
890             XMoveResizeWindow(obp_display, self->innerright,
891                     self->size.left + self->client_area.width, self->size.top,
892                     self->cbwidth_r, self->client_area.height);
893
894             XMapWindow(obp_display, self->innerright);
895         }
896         else
897             XUnmapWindow(obp_display, self->innerright);
898
899         if (self->cbwidth_r && innercornerheight > 0) {
900             XMoveResizeWindow(obp_display, self->innerbrr, 0,
901                     self->client_area.height - (theme_config.grip_width
902                             - self->size.bottom), self->cbwidth_r,
903                     theme_config.grip_width - self->size.bottom);
904
905             XMapWindow(obp_display, self->innerbrr);
906         }
907         else
908             XUnmapWindow(obp_display, self->innerbrr);
909
910         if (self->cbwidth_t) {
911             XMoveResizeWindow(obp_display, self->innertop,
912                     self->size.left - self->cbwidth_l, self->size.top
913                             - self->cbwidth_t, self->client_area.width
914                             + self->cbwidth_l + self->cbwidth_r,
915                     self->cbwidth_t);
916
917             XMapWindow(obp_display, self->innertop);
918         }
919         else
920             XUnmapWindow(obp_display, self->innertop);
921
922         if (self->cbwidth_b) {
923             XMoveResizeWindow(obp_display, self->innerbottom,
924                     self->size.left - self->cbwidth_l, self->size.top
925                             + self->client_area.height, self->client_area.width
926                             + self->cbwidth_l + self->cbwidth_r,
927                     self->cbwidth_b);
928
929             XMoveResizeWindow(obp_display, self->innerblb, 0, 0,
930                     theme_config.grip_width + self->bwidth, self->cbwidth_b);
931             XMoveResizeWindow(obp_display, self->innerbrb,
932                     self->client_area.width + self->cbwidth_l + self->cbwidth_r
933                             - (theme_config.grip_width + self->bwidth), 0,
934                     theme_config.grip_width + self->bwidth, self->cbwidth_b);
935
936             XMapWindow(obp_display, self->innerbottom);
937             XMapWindow(obp_display, self->innerblb);
938             XMapWindow(obp_display, self->innerbrb);
939         }
940         else {
941             XUnmapWindow(obp_display, self->innerbottom);
942             XUnmapWindow(obp_display, self->innerblb);
943             XUnmapWindow(obp_display, self->innerbrb);
944         }
945
946         if (self->bwidth) {
947             gint titlesides;
948
949             /* height of titleleft and titleright */
950             titlesides = (!self->max_horz ? theme_config.grip_width : 0);
951
952             XMoveResizeWindow(obp_display, self->titletop,
953                     theme_config.grip_width + self->bwidth, 0,
954                     /* width + bwidth*2 - bwidth*2 - grips*2 */
955                     self->width - theme_config.grip_width * 2, self->bwidth);
956             XMoveResizeWindow(obp_display, self->titletopleft, 0, 0,
957                     theme_config.grip_width + self->bwidth, self->bwidth);
958             XMoveResizeWindow(obp_display, self->titletopright,
959                     self->client_area.width + self->size.left
960                             + self->size.right - theme_config.grip_width
961                             - self->bwidth, 0, theme_config.grip_width
962                             + self->bwidth, self->bwidth);
963
964             if (titlesides > 0) {
965                 XMoveResizeWindow(obp_display, self->titleleft, 0,
966                         self->bwidth, self->bwidth, titlesides);
967                 XMoveResizeWindow(obp_display, self->titleright,
968                         self->client_area.width + self->size.left
969                                 + self->size.right - self->bwidth,
970                         self->bwidth, self->bwidth, titlesides);
971
972                 XMapWindow(obp_display, self->titleleft);
973                 XMapWindow(obp_display, self->titleright);
974             }
975             else {
976                 XUnmapWindow(obp_display, self->titleleft);
977                 XUnmapWindow(obp_display, self->titleright);
978             }
979
980             XMapWindow(obp_display, self->titletop);
981             XMapWindow(obp_display, self->titletopleft);
982             XMapWindow(obp_display, self->titletopright);
983
984             if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
985                 XMoveResizeWindow(obp_display, self->titlebottom,
986                         (self->max_horz ? 0 : self->bwidth),
987                         theme_config.title_height + self->bwidth, self->width,
988                         self->bwidth);
989
990                 XMapWindow(obp_display, self->titlebottom);
991             }
992             else
993                 XUnmapWindow(obp_display, self->titlebottom);
994         }
995         else {
996             XUnmapWindow(obp_display, self->titlebottom);
997
998             XUnmapWindow(obp_display, self->titletop);
999             XUnmapWindow(obp_display, self->titletopleft);
1000             XUnmapWindow(obp_display, self->titletopright);
1001             XUnmapWindow(obp_display, self->titleleft);
1002             XUnmapWindow(obp_display, self->titleright);
1003         }
1004
1005         if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
1006             XMoveResizeWindow(obp_display, self->title,
1007                     (self->max_horz ? 0 : self->bwidth), self->bwidth,
1008                     self->width, theme_config.title_height);
1009
1010             XMapWindow(obp_display, self->title);
1011
1012             if (self->decorations & OB_FRAME_DECOR_GRIPS) {
1013                 XMoveResizeWindow(obp_display, self->topresize,
1014                         theme_config.grip_width, 0, self->width
1015                                 - theme_config.grip_width *2,
1016                         theme_config.paddingy + 1);
1017
1018                 XMoveWindow(obp_display, self->tltresize, 0, 0);
1019                 XMoveWindow(obp_display, self->tllresize, 0, 0);
1020                 XMoveWindow(obp_display, self->trtresize, self->width
1021                         - theme_config.grip_width, 0);
1022                 XMoveWindow(obp_display, self->trrresize, self->width
1023                         - theme_config.paddingx - 1, 0);
1024
1025                 XMapWindow(obp_display, self->topresize);
1026                 XMapWindow(obp_display, self->tltresize);
1027                 XMapWindow(obp_display, self->tllresize);
1028                 XMapWindow(obp_display, self->trtresize);
1029                 XMapWindow(obp_display, self->trrresize);
1030             }
1031             else {
1032                 XUnmapWindow(obp_display, self->topresize);
1033                 XUnmapWindow(obp_display, self->tltresize);
1034                 XUnmapWindow(obp_display, self->tllresize);
1035                 XUnmapWindow(obp_display, self->trtresize);
1036                 XUnmapWindow(obp_display, self->trrresize);
1037             }
1038         }
1039         else
1040             XUnmapWindow(obp_display, self->title);
1041     }
1042
1043     if ((self->decorations & OB_FRAME_DECOR_TITLEBAR))
1044         /* layout the title bar elements */
1045         layout_title(self);
1046
1047     if (!is_fake) {
1048         gint sidebwidth = self->max_horz ? 0 : self->bwidth;
1049
1050         if (self->bwidth && self->size.bottom) {
1051             XMoveResizeWindow(obp_display, self->handlebottom,
1052                     theme_config.grip_width + self->bwidth + sidebwidth,
1053                     self->size.top + self->client_area.height
1054                             + self->size.bottom - self->bwidth, self->width
1055                             - (theme_config.grip_width + sidebwidth) * 2,
1056                     self->bwidth);
1057
1058             if (sidebwidth) {
1059                 XMoveResizeWindow(obp_display, self->lgripleft, 0,
1060                         self->size.top + self->client_area.height
1061                                 + self->size.bottom
1062                                 - (!self->max_horz ? theme_config.grip_width
1063                                         : self->size.bottom - self->cbwidth_b),
1064                         self->bwidth,
1065                         (!self->max_horz ? theme_config.grip_width
1066                                 : self->size.bottom - self->cbwidth_b));
1067                 XMoveResizeWindow(obp_display, self->rgripright,
1068                         self->size.left + self->client_area.width
1069                                 + self->size.right - self->bwidth,
1070                         self->size.top + self->client_area.height
1071                                 + self->size.bottom
1072                                 - (!self->max_horz ? theme_config.grip_width
1073                                         : self->size.bottom - self->cbwidth_b),
1074                         self->bwidth,
1075                         (!self->max_horz ? theme_config.grip_width
1076                                 : self->size.bottom - self->cbwidth_b));
1077
1078                 XMapWindow(obp_display, self->lgripleft);
1079                 XMapWindow(obp_display, self->rgripright);
1080             }
1081             else {
1082                 XUnmapWindow(obp_display, self->lgripleft);
1083                 XUnmapWindow(obp_display, self->rgripright);
1084             }
1085
1086             XMoveResizeWindow(obp_display, self->lgripbottom, sidebwidth,
1087                     self->size.top + self->client_area.height
1088                             + self->size.bottom - self->bwidth,
1089                     theme_config.grip_width + self->bwidth, self->bwidth);
1090             XMoveResizeWindow(obp_display, self->rgripbottom,
1091                     self->size.left + self->client_area.width
1092                             + self->size.right - self->bwidth - sidebwidth
1093                             - theme_config.grip_width, self->size.top
1094                             + self->client_area.height + self->size.bottom
1095                             - self->bwidth, theme_config.grip_width
1096                             + self->bwidth, self->bwidth);
1097
1098             XMapWindow(obp_display, self->handlebottom);
1099             XMapWindow(obp_display, self->lgripbottom);
1100             XMapWindow(obp_display, self->rgripbottom);
1101
1102             if (self->decorations & OB_FRAME_DECOR_HANDLE
1103                     && theme_config.handle_height > 0) {
1104                 XMoveResizeWindow(obp_display, self->handletop,
1105                         theme_config.grip_width + self->bwidth + sidebwidth, 
1106                         FRAME_HANDLE_Y(self), self->width - (theme_config.grip_width
1107                                 + sidebwidth) * 2, self->bwidth);
1108                 XMapWindow(obp_display, self->handletop);
1109
1110                 if (self->decorations & OB_FRAME_DECOR_GRIPS) {
1111                     XMoveResizeWindow(obp_display, self->handleleft,
1112                             theme_config.grip_width, 0, self->bwidth,
1113                             theme_config.handle_height);
1114                     XMoveResizeWindow(obp_display, self->handleright,
1115                             self->width - theme_config.grip_width
1116                                     - self->bwidth, 0, self->bwidth,
1117                             theme_config.handle_height);
1118
1119                     XMoveResizeWindow(obp_display, self->lgriptop,
1120                             sidebwidth, 
1121                             FRAME_HANDLE_Y(self), theme_config.grip_width
1122                                     + self->bwidth, self->bwidth);
1123                     XMoveResizeWindow(obp_display, self->rgriptop,
1124                             self->size.left + self->client_area.width
1125                                     + self->size.right - self->bwidth
1126                                     - sidebwidth - theme_config.grip_width, 
1127                             FRAME_HANDLE_Y(self), theme_config.grip_width
1128                                     + self->bwidth, self->bwidth);
1129
1130                     XMapWindow(obp_display, self->handleleft);
1131                     XMapWindow(obp_display, self->handleright);
1132                     XMapWindow(obp_display, self->lgriptop);
1133                     XMapWindow(obp_display, self->rgriptop);
1134                 }
1135                 else {
1136                     XUnmapWindow(obp_display, self->handleleft);
1137                     XUnmapWindow(obp_display, self->handleright);
1138                     XUnmapWindow(obp_display, self->lgriptop);
1139                     XUnmapWindow(obp_display, self->rgriptop);
1140                 }
1141             }
1142             else {
1143                 XUnmapWindow(obp_display, self->handleleft);
1144                 XUnmapWindow(obp_display, self->handleright);
1145                 XUnmapWindow(obp_display, self->lgriptop);
1146                 XUnmapWindow(obp_display, self->rgriptop);
1147
1148                 XUnmapWindow(obp_display, self->handletop);
1149             }
1150         }
1151         else {
1152             XUnmapWindow(obp_display, self->handleleft);
1153             XUnmapWindow(obp_display, self->handleright);
1154             XUnmapWindow(obp_display, self->lgriptop);
1155             XUnmapWindow(obp_display, self->rgriptop);
1156
1157             XUnmapWindow(obp_display, self->handletop);
1158
1159             XUnmapWindow(obp_display, self->handlebottom);
1160             XUnmapWindow(obp_display, self->lgripleft);
1161             XUnmapWindow(obp_display, self->rgripright);
1162             XUnmapWindow(obp_display, self->lgripbottom);
1163             XUnmapWindow(obp_display, self->rgripbottom);
1164         }
1165
1166         if (self->decorations & OB_FRAME_DECOR_HANDLE
1167                 && theme_config.handle_height > 0) {
1168             XMoveResizeWindow(obp_display, self->handle, sidebwidth, 
1169             FRAME_HANDLE_Y(self) + self->bwidth, self->width,
1170                     theme_config.handle_height);
1171             XMapWindow(obp_display, self->handle);
1172
1173             if (self->decorations & OB_FRAME_DECOR_GRIPS) {
1174                 XMoveResizeWindow(obp_display, self->lgrip, 0, 0,
1175                         theme_config.grip_width, theme_config.handle_height);
1176                 XMoveResizeWindow(obp_display, self->rgrip, self->width
1177                         - theme_config.grip_width, 0, theme_config.grip_width,
1178                         theme_config.handle_height);
1179
1180                 XMapWindow(obp_display, self->lgrip);
1181                 XMapWindow(obp_display, self->rgrip);
1182             }
1183             else {
1184                 XUnmapWindow(obp_display, self->lgrip);
1185                 XUnmapWindow(obp_display, self->rgrip);
1186             }
1187         }
1188         else {
1189             XUnmapWindow(obp_display, self->lgrip);
1190             XUnmapWindow(obp_display, self->rgrip);
1191
1192             XUnmapWindow(obp_display, self->handle);
1193         }
1194
1195         if (self->bwidth && !self->max_horz && (self->client_area.height
1196                 + self->size.top + self->size.bottom) > theme_config.grip_width
1197                 * 2) {
1198             XMoveResizeWindow(obp_display, self->left, 0, self->bwidth
1199                     + theme_config.grip_width, self->bwidth,
1200                     self->client_area.height + self->size.top
1201                             + self->size.bottom - theme_config.grip_width * 2);
1202
1203             XMapWindow(obp_display, self->left);
1204         }
1205         else
1206             XUnmapWindow(obp_display, self->left);
1207
1208         if (self->bwidth && !self->max_horz && (self->client_area.height
1209                 + self->size.top + self->size.bottom) > theme_config.grip_width
1210                 * 2) {
1211             XMoveResizeWindow(obp_display, self->right,
1212                     self->client_area.width + self->cbwidth_l + self->cbwidth_r
1213                             + self->bwidth, self->bwidth
1214                             + theme_config.grip_width, self->bwidth,
1215                     self->client_area.height + self->size.top
1216                             + self->size.bottom - theme_config.grip_width * 2);
1217
1218             XMapWindow(obp_display, self->right);
1219         }
1220         else
1221             XUnmapWindow(obp_display, self->right);
1222
1223         XMoveResizeWindow(obp_display, self->backback, self->size.left,
1224                 self->size.top, self->client_area.width,
1225                 self->client_area.height);
1226     }
1227
1228     /* shading can change without being moved or resized */
1229     RECT_SET_SIZE(self->area, self->client_area.width + self->size.left
1230             + self->size.right, (self->shaded ? theme_config.title_height
1231             + self->bwidth * 2 : self->client_area.height + self->size.top
1232             + self->size.bottom));
1233
1234     if ((is_resize) && !is_fake) {
1235         /* find the new coordinates, done after setting the frame.size, for
1236          frame_client_gravity. */
1237         self->area.x = self->client_area.x;
1238         self->area.y = self->client_area.y;
1239         frame_client_gravity(OBDEFAULTFRAME(_self)->client, &self->area.x, &self->area.y);
1240     }
1241
1242     if (!is_fake) {
1243         if (!frame_iconify_animating(self))
1244             /* move and resize the top level frame.
1245              shading can change without being moved or resized.
1246
1247              but don't do this during an iconify animation. it will be
1248              reflected afterwards.
1249              */
1250             XMoveResizeWindow(obp_display, self->window, self->area.x,
1251                     self->area.y, self->area.width, self->area.height);
1252
1253         /* when the client has StaticGravity, it likes to move around.
1254          also this correctly positions the client when it maps.
1255          this also needs to be run when the frame's decorations sizes change!
1256          */
1257         if (!is_resize)
1258             XMoveResizeWindow(obp_display, self->client->window,
1259                     self->size.left, self->size.top, self->client_area.width,
1260                     self->client_area.height);
1261
1262         if (is_resize) {
1263             self->need_render = TRUE;
1264             frame_update_skin(self);
1265             frame_adjust_shape(self);
1266         }
1267
1268         if (!STRUT_EQUAL(self->size, oldsize)) {
1269             gulong vals[4];
1270             vals[0] = self->size.left;
1271             vals[1] = self->size.right;
1272             vals[2] = self->size.top;
1273             vals[3] = self->size.bottom;
1274             OBT_PROP_SETA32(self->client->window, NET_FRAME_EXTENTS, CARDINAL,
1275                     vals, 4);
1276             OBT_PROP_SETA32(self->client->window, KDE_NET_WM_FRAME_STRUT,
1277                     CARDINAL, vals, 4);
1278         }
1279
1280         /* if this occurs while we are focus cycling, the indicator needs to
1281          match the changes */
1282         if (plugin.focus_cycle_target == self->client)
1283             focus_cycle_draw_indicator(self->client);
1284     }
1285     if (is_resize && (self->decorations & OB_FRAME_DECOR_TITLEBAR))
1286         XResizeWindow(obp_display, self->label, self->label_width,
1287                 theme_config.label_height);
1288 }
1289
1290 void frame_set_hover_flag(gpointer self, ObFrameButton button)
1291 {
1292     if (OBDEFAULTFRAME(self)->hover_flag != button) {
1293         OBDEFAULTFRAME(self)->hover_flag = button;
1294         frame_update_skin(self);
1295     }
1296 }
1297
1298 void frame_set_press_flag(gpointer self, ObFrameButton button)
1299 {
1300     if (OBDEFAULTFRAME(self)->press_flag != button) {
1301         OBDEFAULTFRAME(self)->press_flag = button;
1302         frame_update_skin(self);
1303     }
1304 }
1305
1306 Window frame_get_window(gpointer self)
1307 {
1308     return OBDEFAULTFRAME(self)->window;
1309 }
1310
1311 Strut frame_get_size(gpointer self)
1312 {
1313     return OBDEFAULTFRAME(self)->size;
1314 }
1315
1316 gint frame_get_decorations(gpointer self)
1317 {
1318     return OBDEFAULTFRAME(self)->decorations;
1319 }
1320
1321 void frame_update_title (gpointer self, const gchar * src)
1322 {
1323     g_free(OBDEFAULTFRAME(self)->stitle);
1324     OBDEFAULTFRAME(self)->stitle = g_strdup(src);
1325 }
1326
1327 gboolean frame_is_visible(gpointer self)
1328 {
1329     return OBDEFAULTFRAME(self)->visible;
1330 }
1331
1332 gboolean frame_is_max_horz(gpointer self)
1333 {
1334     return OBDEFAULTFRAME(self)->max_horz;
1335 }
1336
1337 gboolean frame_is_max_vert(gpointer self)
1338 {
1339     return OBDEFAULTFRAME(self)->max_vert;
1340 }
1341
1342 gulong frame_animate_iconify_time_left(gpointer _self, const GTimeVal *now)
1343 {
1344     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1345     glong sec, usec;
1346     sec = self->iconify_animation_end.tv_sec - now->tv_sec;
1347     usec = self->iconify_animation_end.tv_usec - now->tv_usec;
1348     if (usec < 0) {
1349         usec += G_USEC_PER_SEC;
1350         sec--;
1351     }
1352     /* no negative values */
1353     return MAX(sec * G_USEC_PER_SEC + usec, 0);
1354 }
1355
1356 gboolean frame_animate_iconify(gpointer p)
1357 {
1358     ObDefaultFrame *self = p;
1359     gint x, y, w, h;
1360     gint iconx, icony, iconw;
1361     GTimeVal now;
1362     gulong time;
1363     gboolean iconifying;
1364
1365     if (self->client->icon_geometry.width == 0) {
1366         /* there is no icon geometry set so just go straight down */
1367         Rect *a =
1368                 screen_physical_area_monitor(screen_find_monitor(&self->area));
1369         iconx = self->area.x + self->area.width / 2 + 32;
1370         icony = a->y + a->width;
1371         iconw = 64;
1372         g_free(a);
1373     }
1374     else {
1375         iconx = self->client->icon_geometry.x;
1376         icony = self->client->icon_geometry.y;
1377         iconw = self->client->icon_geometry.width;
1378     }
1379
1380     iconifying = self->iconify_animation_going > 0;
1381
1382     /* how far do we have left to go ? */
1383     g_get_current_time(&now);
1384     time = frame_animate_iconify_time_left(self, &now);
1385
1386     if (time == 0 || iconifying) {
1387         /* start where the frame is supposed to be */
1388         x = self->area.x;
1389         y = self->area.y;
1390         w = self->area.width;
1391         h = self->area.height;
1392     }
1393     else {
1394         /* start at the icon */
1395         x = iconx;
1396         y = icony;
1397         w = iconw;
1398         h = self->size.top; /* just the titlebar */
1399     }
1400
1401     if (time > 0) {
1402         glong dx, dy, dw;
1403         glong elapsed;
1404
1405         dx = self->area.x - iconx;
1406         dy = self->area.y - icony;
1407         dw = self->area.width - self->bwidth * 2 - iconw;
1408         /* if restoring, we move in the opposite direction */
1409         if (!iconifying) {
1410             dx = -dx;
1411             dy = -dy;
1412             dw = -dw;
1413         }
1414
1415         elapsed = FRAME_ANIMATE_ICONIFY_TIME - time;
1416         x = x - (dx * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
1417         y = y - (dy * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
1418         w = w - (dw * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
1419         h = self->size.top; /* just the titlebar */
1420     }
1421
1422     if (time == 0)
1423         frame_end_iconify_animation(self);
1424     else {
1425         XMoveResizeWindow(obp_display, self->window, x, y, w, h);
1426         XFlush(obp_display);
1427     }
1428
1429     return time > 0; /* repeat until we're out of time */
1430 }
1431
1432 void frame_adjust_cursors(gpointer _self)
1433 {
1434     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1435     if ((self->functions & OB_CLIENT_FUNC_RESIZE) != (self->functions
1436             & OB_CLIENT_FUNC_RESIZE) || self->max_horz != self->max_horz
1437             || self->max_vert != self->max_vert || self->shaded != self->shaded) {
1438         gboolean r = (self->functions & OB_CLIENT_FUNC_RESIZE)
1439                 && !(self->max_horz && self->max_vert);
1440         gboolean topbot = !self->max_vert;
1441         gboolean sh = self->shaded;
1442         XSetWindowAttributes a;
1443
1444         /* these ones turn off when max vert, and some when shaded */
1445         a.cursor = ob_cursor(r && topbot && !sh ? OB_CURSOR_NORTH
1446                 : OB_CURSOR_NONE);
1447         XChangeWindowAttributes(obp_display, self->topresize, CWCursor,
1448                 &a);
1449         XChangeWindowAttributes(obp_display, self->titletop, CWCursor, &a);
1450         a.cursor = ob_cursor(r && topbot ? OB_CURSOR_SOUTH : OB_CURSOR_NONE);
1451         XChangeWindowAttributes(obp_display, self->handle, CWCursor, &a);
1452         XChangeWindowAttributes(obp_display, self->handletop, CWCursor,
1453                 &a);
1454         XChangeWindowAttributes(obp_display, self->handlebottom,
1455                 CWCursor, &a);
1456         XChangeWindowAttributes(obp_display, self->innerbottom, CWCursor,
1457                 &a);
1458
1459         /* these ones change when shaded */
1460         a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_WEST : OB_CURSOR_NORTHWEST)
1461                 : OB_CURSOR_NONE);
1462         XChangeWindowAttributes(obp_display, self->titleleft, CWCursor,
1463                 &a);
1464         XChangeWindowAttributes(obp_display, self->tltresize, CWCursor,
1465                 &a);
1466         XChangeWindowAttributes(obp_display, self->tllresize, CWCursor,
1467                 &a);
1468         XChangeWindowAttributes(obp_display, self->titletopleft,
1469                 CWCursor, &a);
1470         a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_EAST : OB_CURSOR_NORTHEAST)
1471                 : OB_CURSOR_NONE);
1472         XChangeWindowAttributes(obp_display, self->titleright, CWCursor,
1473                 &a);
1474         XChangeWindowAttributes(obp_display, self->trtresize, CWCursor,
1475                 &a);
1476         XChangeWindowAttributes(obp_display, self->trrresize, CWCursor,
1477                 &a);
1478         XChangeWindowAttributes(obp_display, self->titletopright,
1479                 CWCursor, &a);
1480
1481         /* these ones are pretty static */
1482         a.cursor = ob_cursor(r ? OB_CURSOR_WEST : OB_CURSOR_NONE);
1483         XChangeWindowAttributes(obp_display, self->left, CWCursor, &a);
1484         XChangeWindowAttributes(obp_display, self->innerleft, CWCursor,
1485                 &a);
1486         a.cursor = ob_cursor(r ? OB_CURSOR_EAST : OB_CURSOR_NONE);
1487         XChangeWindowAttributes(obp_display, self->right, CWCursor, &a);
1488         XChangeWindowAttributes(obp_display, self->innerright, CWCursor,
1489                 &a);
1490         a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHWEST : OB_CURSOR_NONE);
1491         XChangeWindowAttributes(obp_display, self->lgrip, CWCursor, &a);
1492         XChangeWindowAttributes(obp_display, self->handleleft, CWCursor,
1493                 &a);
1494         XChangeWindowAttributes(obp_display, self->lgripleft, CWCursor,
1495                 &a);
1496         XChangeWindowAttributes(obp_display, self->lgriptop, CWCursor, &a);
1497         XChangeWindowAttributes(obp_display, self->lgripbottom, CWCursor,
1498                 &a);
1499         XChangeWindowAttributes(obp_display, self->innerbll, CWCursor, &a);
1500         XChangeWindowAttributes(obp_display, self->innerblb, CWCursor, &a);
1501         a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHEAST : OB_CURSOR_NONE);
1502         XChangeWindowAttributes(obp_display, self->rgrip, CWCursor, &a);
1503         XChangeWindowAttributes(obp_display, self->handleright, CWCursor,
1504                 &a);
1505         XChangeWindowAttributes(obp_display, self->rgripright, CWCursor,
1506                 &a);
1507         XChangeWindowAttributes(obp_display, self->rgriptop, CWCursor, &a);
1508         XChangeWindowAttributes(obp_display, self->rgripbottom, CWCursor,
1509                 &a);
1510         XChangeWindowAttributes(obp_display, self->innerbrr, CWCursor, &a);
1511         XChangeWindowAttributes(obp_display, self->innerbrb, CWCursor, &a);
1512     }
1513 }
1514
1515 void frame_adjust_client_area(gpointer _self)
1516 {
1517     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1518     /* adjust the window which is there to prevent flashing on unmap */
1519     XMoveResizeWindow(obp_display, self->backfront, 0, 0,
1520             self->client_area.width, self->client_area.height);
1521 }
1522
1523 void frame_adjust_state(gpointer _self)
1524 {
1525     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1526     self->need_render = TRUE;
1527     frame_update_skin(self);
1528 }
1529
1530 void frame_adjust_focus(gpointer _self, gboolean hilite)
1531 {
1532     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1533     self->focused = hilite;
1534     self->need_render = TRUE;
1535     frame_update_skin(self);
1536     XFlush(obp_display);
1537 }
1538
1539 void frame_adjust_title(gpointer _self)
1540 {
1541     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1542     self->need_render = TRUE;
1543     frame_update_skin(self);
1544 }
1545
1546 void frame_adjust_icon(gpointer _self)
1547 {
1548     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1549     self->need_render = TRUE;
1550     frame_update_skin(self);
1551 }
1552
1553 /* is there anything present between us and the label? */
1554 static gboolean is_button_present(ObDefaultFrame *_self, const gchar *lc,
1555         gint dir)
1556 {
1557     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1558     for (; *lc != '\0' && lc >= plugin.config_title_layout; lc += dir) {
1559         if (*lc == ' ')
1560             continue; /* it was invalid */
1561         if (*lc == 'N' && self->decorations & OB_FRAME_DECOR_ICON)
1562             return TRUE;
1563         if (*lc == 'D' && self->decorations & OB_FRAME_DECOR_ALLDESKTOPS)
1564             return TRUE;
1565         if (*lc == 'S' && self->decorations & OB_FRAME_DECOR_SHADE)
1566             return TRUE;
1567         if (*lc == 'I' && self->decorations & OB_FRAME_DECOR_ICONIFY)
1568             return TRUE;
1569         if (*lc == 'M' && self->decorations & OB_FRAME_DECOR_MAXIMIZE)
1570             return TRUE;
1571         if (*lc == 'C' && self->decorations & OB_FRAME_DECOR_CLOSE)
1572             return TRUE;
1573         if (*lc == 'L')
1574             return FALSE;
1575     }
1576     return FALSE;
1577 }
1578
1579 void flash_done(gpointer data)
1580 {
1581     ObDefaultFrame *self = data;
1582
1583     if (self->focused != self->flash_on)
1584         frame_adjust_focus(self, self->focused);
1585 }
1586
1587 gboolean flash_timeout(gpointer data)
1588 {
1589     ObDefaultFrame *self = data;
1590     GTimeVal now;
1591
1592     g_get_current_time(&now);
1593     if (now.tv_sec > self->flash_end.tv_sec
1594             || (now.tv_sec == self->flash_end.tv_sec && now.tv_usec
1595                     >= self->flash_end.tv_usec))
1596         self->flashing = FALSE;
1597
1598     if (!self->flashing)
1599         return FALSE; /* we are done */
1600
1601     self->flash_on = !self->flash_on;
1602     if (!self->focused) {
1603         frame_adjust_focus(self, self->flash_on);
1604         self->focused = FALSE;
1605     }
1606
1607     return TRUE; /* go again */
1608 }
1609
1610 void layout_title(ObDefaultFrame * self)
1611 {
1612     gchar *lc;
1613     gint i;
1614
1615     const gint bwidth = theme_config.button_size + theme_config.paddingx + 1;
1616     /* position of the left most button */
1617     const gint left = theme_config.paddingx + 1;
1618     /* position of the right most button */
1619     const gint right = self->width;
1620
1621     /* turn them all off */
1622     self->icon_on = self->desk_on = self->shade_on = self->iconify_on
1623             = self->max_on = self->close_on = self->label_on = FALSE;
1624     self->label_width = self->width - (theme_config.paddingx + 1) * 2;
1625     self->leftmost = self->rightmost = OB_FRAME_CONTEXT_NONE;
1626
1627     /* figure out what's being show, find each element's position, and the
1628      width of the label
1629
1630      do the ones before the label, then after the label,
1631      i will be +1 the first time through when working to the left,
1632      and -1 the second time through when working to the right */
1633     for (i = 1; i >= -1; i-=2) {
1634         gint x;
1635         ObFrameContext *firstcon;
1636
1637         if (i > 0) {
1638             x = left;
1639             lc = plugin.config_title_layout;
1640             firstcon = &self->leftmost;
1641         }
1642         else {
1643             x = right;
1644             lc = plugin.config_title_layout
1645                     + strlen(plugin.config_title_layout)-1;
1646             firstcon = &self->rightmost;
1647         }
1648
1649         /* stop at the end of the string (or the label, which calls break) */
1650         for (; *lc != '\0' && lc >= plugin.config_title_layout; lc+=i) {
1651             if (*lc == 'L') {
1652                 if (i > 0) {
1653                     self->label_on = TRUE;
1654                     self->label_x = x;
1655                 }
1656                 break; /* break the for loop, do other side of label */
1657             }
1658             else if (*lc == 'N') {
1659                 if (firstcon)
1660                     *firstcon = OB_FRAME_CONTEXT_ICON;
1661                 if ((self->icon_on = is_button_present(self, lc, i))) {
1662                     /* icon is bigger than buttons */
1663                     self->label_width -= bwidth + 2;
1664                     if (i > 0)
1665                         self->icon_x = x;
1666                     x += i * (bwidth + 2);
1667                     if (i < 0)
1668                         self->icon_x = x;
1669                 }
1670             }
1671             else if (*lc == 'D') {
1672                 if (firstcon)
1673                     *firstcon = OB_FRAME_CONTEXT_ALLDESKTOPS;
1674                 if ((self->desk_on = is_button_present(self, lc, i))) {
1675                     self->label_width -= bwidth;
1676                     if (i > 0)
1677                         self->desk_x = x;
1678                     x += i * bwidth;
1679                     if (i < 0)
1680                         self->desk_x = x;
1681                 }
1682             }
1683             else if (*lc == 'S') {
1684                 if (firstcon)
1685                     *firstcon = OB_FRAME_CONTEXT_SHADE;
1686                 if ((self->shade_on = is_button_present(self, lc, i))) {
1687                     self->label_width -= bwidth;
1688                     if (i > 0)
1689                         self->shade_x = x;
1690                     x += i * bwidth;
1691                     if (i < 0)
1692                         self->shade_x = x;
1693                 }
1694             }
1695             else if (*lc == 'I') {
1696                 if (firstcon)
1697                     *firstcon = OB_FRAME_CONTEXT_ICONIFY;
1698                 if ((self->iconify_on = is_button_present(self, lc, i))) {
1699                     self->label_width -= bwidth;
1700                     if (i > 0)
1701                         self->iconify_x = x;
1702                     x += i * bwidth;
1703                     if (i < 0)
1704                         self->iconify_x = x;
1705                 }
1706             }
1707             else if (*lc == 'M') {
1708                 if (firstcon)
1709                     *firstcon = OB_FRAME_CONTEXT_MAXIMIZE;
1710                 if ((self->max_on = is_button_present(self, lc, i))) {
1711                     self->label_width -= bwidth;
1712                     if (i > 0)
1713                         self->max_x = x;
1714                     x += i * bwidth;
1715                     if (i < 0)
1716                         self->max_x = x;
1717                 }
1718             }
1719             else if (*lc == 'C') {
1720                 if (firstcon)
1721                     *firstcon = OB_FRAME_CONTEXT_CLOSE;
1722                 if ((self->close_on = is_button_present(self, lc, i))) {
1723                     self->label_width -= bwidth;
1724                     if (i > 0)
1725                         self->close_x = x;
1726                     x += i * bwidth;
1727                     if (i < 0)
1728                         self->close_x = x;
1729                 }
1730             }
1731             else
1732                 continue; /* don't set firstcon */
1733             firstcon = NULL;
1734         }
1735     }
1736
1737     /* position and map the elements */
1738     if (self->icon_on) {
1739         XMapWindow(obp_display, self->icon);
1740         XMoveWindow(obp_display, self->icon, self->icon_x,
1741                 theme_config.paddingy);
1742     }
1743     else
1744         XUnmapWindow(obp_display, self->icon);
1745
1746     if (self->desk_on) {
1747         XMapWindow(obp_display, self->desk);
1748         XMoveWindow(obp_display, self->desk, self->desk_x,
1749                 theme_config.paddingy + 1);
1750     }
1751     else
1752         XUnmapWindow(obp_display, self->desk);
1753
1754     if (self->shade_on) {
1755         XMapWindow(obp_display, self->shade);
1756         XMoveWindow(obp_display, self->shade, self->shade_x,
1757                 theme_config.paddingy + 1);
1758     }
1759     else
1760         XUnmapWindow(obp_display, self->shade);
1761
1762     if (self->iconify_on) {
1763         XMapWindow(obp_display, self->iconify);
1764         XMoveWindow(obp_display, self->iconify, self->iconify_x,
1765                 theme_config.paddingy + 1);
1766     }
1767     else
1768         XUnmapWindow(obp_display, self->iconify);
1769
1770     if (self->max_on) {
1771         XMapWindow(obp_display, self->max);
1772         XMoveWindow(obp_display, self->max, self->max_x,
1773                 theme_config.paddingy + 1);
1774     }
1775     else
1776         XUnmapWindow(obp_display, self->max);
1777
1778     if (self->close_on) {
1779         XMapWindow(obp_display, self->close);
1780         XMoveWindow(obp_display, self->close, self->close_x,
1781                 theme_config.paddingy + 1);
1782     }
1783     else
1784         XUnmapWindow(obp_display, self->close);
1785
1786     if (self->label_on) {
1787         self->label_width = MAX(1, self->label_width); /* no lower than 1 */
1788         XMapWindow(obp_display, self->label);
1789         XMoveWindow(obp_display, self->label, self->label_x,
1790                 theme_config.paddingy);
1791     }
1792     else
1793         XUnmapWindow(obp_display, self->label);
1794 }
1795
1796 void trigger_none (gpointer self) {}
1797 void trigger_iconify(gpointer self) {}
1798 void trigger_uniconnity(gpointer self) {}
1799 void trigger_iconify_toggle(gpointer self) {}
1800 void trigger_shade(gpointer self) {}
1801 void trigger_unshade(gpointer self) {}
1802 void trigger_shade_toggle(gpointer self) {}
1803 void trigger_max(gpointer self) {}
1804 void trigger_unmax(gpointer self) {}
1805 void trigger_max_troggle(gpointer self) {}
1806 void trigger_max_vert(gpointer self) {OBDEFAULTFRAME(self)->max_vert = TRUE;}
1807 void trigger_unmax_vert(gpointer self) {OBDEFAULTFRAME(self)->max_vert = FALSE;}
1808 void trigger_max_toggle(gpointer self) {}
1809 void trigger_max_horz(gpointer self) {OBDEFAULTFRAME(self)->max_horz = TRUE;}
1810 void trigger_unmax_horz(gpointer self) {OBDEFAULTFRAME(self)->max_horz = FALSE;}
1811 void trigger_max_horz_toggle(gpointer self) {}
1812 void trigger_plugin1(gpointer self) {}
1813 void trigger_plugin2(gpointer self) {}
1814 void trigger_plugin3(gpointer self) {}
1815 void trigger_plugin4(gpointer self) {}
1816 void trigger_plugin5(gpointer self) {}
1817 void trigger_plugin6(gpointer self) {}
1818 void trigger_plugin7(gpointer self) {}
1819 void trigger_plugin8(gpointer self) {}
1820 void trigger_plugin9(gpointer self) {}
1821
1822 void frame_trigger(gpointer self, ObFrameTrigger trigger_name)
1823 {
1824
1825     static void (*trigger_func[64])(gpointer) = { 
1826             trigger_none,
1827             trigger_iconify,
1828             trigger_uniconnity,
1829             trigger_iconify_toggle,
1830             trigger_shade,
1831             trigger_unshade,
1832             trigger_shade_toggle,
1833             trigger_max,
1834             trigger_unmax,
1835             trigger_max_troggle,
1836             trigger_max_vert,
1837             trigger_unmax_vert,
1838             trigger_max_toggle,
1839             trigger_max_horz,
1840             trigger_unmax_horz,
1841             trigger_max_horz_toggle,
1842             trigger_plugin1,
1843             trigger_plugin2,
1844             trigger_plugin3,
1845             trigger_plugin4,
1846             trigger_plugin5,
1847             trigger_plugin6,
1848             trigger_plugin7,
1849             trigger_plugin8,
1850             trigger_plugin9,
1851             NULL,
1852     };
1853     
1854     void (*call_trigger_func)(gpointer) = trigger_func[trigger_name];
1855     if(!call_trigger_func)
1856     {
1857         call_trigger_func (self);
1858     }
1859 }
1860
1861 ObFramePlugin plugin = {
1862         0, /* gpointer handler */
1863         "libdefault.la", /* gchar * filename */
1864         "Default", /* gchar * name */
1865         init, //gint (*init) (Display * display, gint screen);
1866         0, /* */
1867         frame_new, //gpointer (*frame_new) (struct _ObClient *c);
1868         frame_free, //void (*frame_free) (gpointer self);
1869         frame_show, //void (*frame_show) (gpointer self);
1870         frame_hide, //void (*frame_hide) (gpointer self);
1871         frame_adjust_theme, //void (*frame_adjust_theme) (gpointer self);
1872         frame_adjust_shape, //void (*frame_adjust_shape) (gpointer self);
1873         frame_grab, //void (*frame_adjust_area) (gpointer self, gboolean moved, gboolean resized, gboolean fake);
1874         frame_ungrab, frame_context, //void (*frame_adjust_state) (gpointer self);
1875         frame_set_is_visible, /* */
1876         frame_set_is_focus, /* */
1877         frame_set_is_max_vert, /* */
1878         frame_set_is_max_horz, /* */
1879         frame_set_is_shaded, /* */
1880
1881         frame_flash_start, /* */
1882         frame_flash_stop, /* */
1883         frame_begin_iconify_animation, /* */
1884         frame_end_iconify_animation, /* */
1885         frame_iconify_animating, /* */
1886
1887         frame_set_decorations, /* */
1888         
1889         frame_update_title, /* */
1890         /* This give the window area */
1891         frame_get_window_area, /* */
1892         frame_set_client_area, /* */
1893         /* Draw the frame */
1894         frame_update_layout, /* */
1895         frame_update_skin, /* */
1896
1897         frame_set_hover_flag, /* */
1898         frame_set_press_flag, /* */
1899
1900         frame_get_window,/* */
1901
1902         frame_get_size, /* */
1903         frame_get_decorations, /* */
1904
1905         frame_is_visible, /* */
1906         frame_is_max_horz, /* */
1907         frame_is_max_vert, /* */
1908
1909         frame_trigger, /* */
1910
1911         load_theme_config, /* */
1912
1913         /* This fields are fill by openbox. */
1914         //0, //Display * ob_display;
1915         //0, //gint ob_screen;
1916         //0, //RrInstance *ob_rr_inst;
1917         0, //gboolean config_theme_keepborder;
1918         0, //struct _ObClient *focus_cycle_target;
1919         0, //gchar *config_title_layout;
1920         FALSE, //gboolean moveresize_in_progress;
1921         0, //struct _ObMainLoop *ob_main_loop;
1922 };
1923
1924 ObFramePlugin * get_info()
1925 {
1926     return &plugin;
1927 }