]> icculus.org git repositories - mikachu/openbox.git/blob - engines/default/plugin.c
Flashing is now a part of obclient
[mikachu/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 #include "openbox/config.h"
24 #include "openbox/openbox.h"
25
26 /* Needed for the _() function */
27 #include <gettext.h>
28
29 #include "obt/prop.h"
30 #include "openbox/screen.h"
31
32 /* Needed for the grab_server */
33 #include "openbox/grab.h"
34
35 #include <X11/extensions/shape.h>
36
37 typedef enum
38 {
39     OB_FLAG_MAX = 1 << 0,
40     OB_FLAG_CLOSE = 1 << 1,
41     OB_FLAG_DESK = 1 << 2,
42     OB_FLAG_SHADE = 1 << 3,
43     OB_FLAG_ICONIFY = 1 << 4
44 } ObFrameFlags;
45
46 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
47                          ButtonPressMask | ButtonReleaseMask | \
48                          SubstructureRedirectMask | FocusChangeMask)
49 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
50                            ButtonMotionMask | PointerMotionMask | \
51                            EnterWindowMask | LeaveWindowMask)
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->w_client, &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, Window w_client, Window w_frame)
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, obp_screen), visual,
118                 AllocNone);
119         attrib.background_pixel = BlackPixel(obp_display, obp_screen);
120         attrib.border_pixel = BlackPixel(obp_display, obp_screen);
121     }
122     self->window = w_frame;
123
124     /* create the visible decor windows */
125
126     mask = 0;
127     if (visual) {
128         /* client has a 32-bit visual */
129         mask |= CWColormap | CWBackPixel | CWBorderPixel;
130         attrib.colormap = RrColormap(ob_rr_inst);
131     }
132
133     self->backback = createWindow(self->window, NULL, mask, &attrib);
134     self->backfront = createWindow(self->backback, NULL, mask, &attrib);
135
136     mask |= CWEventMask;
137     attrib.event_mask = ELEMENT_EVENTMASK;
138     self->innerleft = createWindow(self->window, NULL, mask, &attrib);
139     self->innertop = createWindow(self->window, NULL, mask, &attrib);
140     self->innerright = createWindow(self->window, NULL, mask, &attrib);
141     self->innerbottom = createWindow(self->window, NULL, mask, &attrib);
142
143     self->innerblb = createWindow(self->innerbottom, NULL, mask, &attrib);
144     self->innerbrb = createWindow(self->innerbottom, NULL, mask, &attrib);
145     self->innerbll = createWindow(self->innerleft, NULL, mask, &attrib);
146     self->innerbrr = createWindow(self->innerright, NULL, mask, &attrib);
147
148     self->title = createWindow(self->window, NULL, mask, &attrib);
149     self->titleleft = createWindow(self->window, NULL, mask, &attrib);
150     self->titletop = createWindow(self->window, NULL, mask, &attrib);
151     self->titletopleft = createWindow(self->window, NULL, mask, &attrib);
152     self->titletopright = createWindow(self->window, NULL, mask, &attrib);
153     self->titleright = createWindow(self->window, NULL, mask, &attrib);
154     self->titlebottom = createWindow(self->window, NULL, mask, &attrib);
155
156     self->topresize = createWindow(self->title, NULL, mask, &attrib);
157     self->tltresize = createWindow(self->title, NULL, mask, &attrib);
158     self->tllresize = createWindow(self->title, NULL, mask, &attrib);
159     self->trtresize = createWindow(self->title, NULL, mask, &attrib);
160     self->trrresize = createWindow(self->title, NULL, mask, &attrib);
161
162     self->left = createWindow(self->window, NULL, mask, &attrib);
163     self->right = createWindow(self->window, NULL, mask, &attrib);
164
165     self->label = createWindow(self->title, NULL, mask, &attrib);
166     self->max = createWindow(self->title, NULL, mask, &attrib);
167     self->close = createWindow(self->title, NULL, mask, &attrib);
168     self->desk = createWindow(self->title, NULL, mask, &attrib);
169     self->shade = createWindow(self->title, NULL, mask, &attrib);
170     self->icon = createWindow(self->title, NULL, mask, &attrib);
171     self->iconify = createWindow(self->title, NULL, mask, &attrib);
172
173     self->handle = createWindow(self->window, NULL, mask, &attrib);
174     self->lgrip = createWindow(self->handle, NULL, mask, &attrib);
175     self->rgrip = createWindow(self->handle, NULL, mask, &attrib);
176
177     self->handleleft = createWindow(self->handle, NULL, mask, &attrib);
178     self->handleright = createWindow(self->handle, NULL, mask, &attrib);
179
180     self->handletop = createWindow(self->window, NULL, mask, &attrib);
181     self->handlebottom = createWindow(self->window, NULL, mask, &attrib);
182     self->lgripleft = createWindow(self->window, NULL, mask, &attrib);
183     self->lgriptop = createWindow(self->window, NULL, mask, &attrib);
184     self->lgripbottom = createWindow(self->window, NULL, mask, &attrib);
185     self->rgripright = createWindow(self->window, NULL, mask, &attrib);
186     self->rgriptop = createWindow(self->window, NULL, mask, &attrib);
187     self->rgripbottom = createWindow(self->window, NULL, mask, &attrib);
188
189     self->stitle = g_strdup("");
190     self->focused = FALSE;
191
192     /* the other stuff is shown based on decor settings */
193     XMapWindow(obp_display, self->label);
194     XMapWindow(obp_display, self->backback);
195     XMapWindow(obp_display, self->backfront);
196
197     self->hover_flag = OB_BUTTON_NONE;
198     self->press_flag = OB_BUTTON_NONE;
199
200     set_theme_statics(self);
201
202     return self;
203 }
204
205 void set_theme_statics(gpointer _self)
206 {
207     ObDefaultFrame * self = (ObDefaultFrame *) _self;
208     /* set colors/appearance/sizes for stuff that doesn't change */
209     XResizeWindow(obp_display, self->max, theme_config.button_size,
210             theme_config.button_size);
211     XResizeWindow(obp_display, self->iconify, theme_config.button_size,
212             theme_config.button_size);
213     XResizeWindow(obp_display, self->icon, theme_config.button_size + 2,
214             theme_config.button_size + 2);
215     XResizeWindow(obp_display, self->close, theme_config.button_size,
216             theme_config.button_size);
217     XResizeWindow(obp_display, self->desk, theme_config.button_size,
218             theme_config.button_size);
219     XResizeWindow(obp_display, self->shade, theme_config.button_size,
220             theme_config.button_size);
221     XResizeWindow(obp_display, self->tltresize, theme_config.grip_width,
222             theme_config.paddingy + 1);
223     XResizeWindow(obp_display, self->trtresize, theme_config.grip_width,
224             theme_config.paddingy + 1);
225     XResizeWindow(obp_display, self->tllresize, theme_config.paddingx + 1,
226             theme_config.title_height);
227     XResizeWindow(obp_display, self->trrresize, theme_config.paddingx + 1,
228             theme_config.title_height);
229
230     /* set up the dynamic appearances */
231     self->a_unfocused_title = RrAppearanceCopy(theme_config.a_unfocused_title);
232     self->a_focused_title = RrAppearanceCopy(theme_config.a_focused_title);
233     self->a_unfocused_label = RrAppearanceCopy(theme_config.a_unfocused_label);
234     self->a_focused_label = RrAppearanceCopy(theme_config.a_focused_label);
235     self->a_unfocused_handle
236             = RrAppearanceCopy(theme_config.a_unfocused_handle);
237     self->a_focused_handle = RrAppearanceCopy(theme_config.a_focused_handle);
238     self->a_icon = RrAppearanceCopy(theme_config.a_icon);
239 }
240
241 void free_theme_statics(gpointer _self)
242 {
243     ObDefaultFrame * self = (ObDefaultFrame *) _self;
244     RrAppearanceFree(self->a_unfocused_title);
245     RrAppearanceFree(self->a_focused_title);
246     RrAppearanceFree(self->a_unfocused_label);
247     RrAppearanceFree(self->a_focused_label);
248     RrAppearanceFree(self->a_unfocused_handle);
249     RrAppearanceFree(self->a_focused_handle);
250     RrAppearanceFree(self->a_icon);
251 }
252
253 void frame_free(gpointer self)
254 {
255     free_theme_statics(OBDEFAULTFRAME(self));
256     XDestroyWindow(obp_display, OBDEFAULTFRAME(self)->window);
257     if (OBDEFAULTFRAME(self)->colormap)
258         XFreeColormap(obp_display, OBDEFAULTFRAME(self)->colormap);
259
260     g_free(OBDEFAULTFRAME(self)->stitle);
261     g_free(self);
262 }
263
264 void frame_adjust_theme(gpointer self)
265 {
266     free_theme_statics(self);
267     set_theme_statics(self);
268 }
269
270 void frame_adjust_shape(gpointer _self)
271 {
272 #ifdef SHAPE
273     ObDefaultFrame * self = (ObDefaultFrame *) _self;
274     gint num;
275     XRectangle xrect[2];
276
277     if (!self->client->shaped)
278     {
279         /* clear the shape on the frame window */
280         XShapeCombineMask(obp_display, self->window, ShapeBounding,
281                 self->size.left,
282                 self->size.top,
283                 None, ShapeSet);
284     }
285     else
286     {
287         /* make the frame's shape match the clients */
288         XShapeCombineShape(obp_display, self->window, ShapeBounding,
289                 self->size.left,
290                 self->size.top,
291                 self->client->w_client,
292                 ShapeBounding, ShapeSet);
293
294         num = 0;
295         if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
296         {
297             xrect[0].x = 0;
298             xrect[0].y = 0;
299             xrect[0].width = self->area.width;
300             xrect[0].height = self->size.top;
301             ++num;
302         }
303
304         if (self->decorations & OB_FRAME_DECOR_HANDLE &&
305                 theme_config.handle_height> 0)
306         {
307             xrect[1].x = 0;
308             xrect[1].y = FRAME_HANDLE_Y(self);
309             xrect[1].width = self->area.width;
310             xrect[1].height = theme_config.handle_height +
311             self->bwidth * 2;
312             ++num;
313         }
314
315         XShapeCombineRectangles(obp_display, self->window,
316                 ShapeBounding, 0, 0, xrect, num,
317                 ShapeUnion, Unsorted);
318     }
319 #endif
320 }
321
322 void frame_grab(gpointer _self, GHashTable * window_map)
323 {
324     ObDefaultFrame * self = (ObDefaultFrame *) _self;
325     /* DO NOT map the client window here. we used to do that, but it is bogus.
326      we need to set up the client's dimensions and everything before we
327      send a mapnotify or we create race conditions.
328      */
329
330     /* set all the windows for the frame in the window_map */
331     g_hash_table_insert(window_map, &self->window, self->client);
332     g_hash_table_insert(window_map, &self->backback, self->client);
333     g_hash_table_insert(window_map, &self->backfront, self->client);
334     g_hash_table_insert(window_map, &self->innerleft, self->client);
335     g_hash_table_insert(window_map, &self->innertop, self->client);
336     g_hash_table_insert(window_map, &self->innerright, self->client);
337     g_hash_table_insert(window_map, &self->innerbottom, self->client);
338     g_hash_table_insert(window_map, &self->title, self->client);
339     g_hash_table_insert(window_map, &self->label, self->client);
340     g_hash_table_insert(window_map, &self->max, self->client);
341     g_hash_table_insert(window_map, &self->close, self->client);
342     g_hash_table_insert(window_map, &self->desk, self->client);
343     g_hash_table_insert(window_map, &self->shade, self->client);
344     g_hash_table_insert(window_map, &self->icon, self->client);
345     g_hash_table_insert(window_map, &self->iconify, self->client);
346     g_hash_table_insert(window_map, &self->handle, self->client);
347     g_hash_table_insert(window_map, &self->lgrip, self->client);
348     g_hash_table_insert(window_map, &self->rgrip, self->client);
349     g_hash_table_insert(window_map, &self->topresize, self->client);
350     g_hash_table_insert(window_map, &self->tltresize, self->client);
351     g_hash_table_insert(window_map, &self->tllresize, self->client);
352     g_hash_table_insert(window_map, &self->trtresize, self->client);
353     g_hash_table_insert(window_map, &self->trrresize, self->client);
354     g_hash_table_insert(window_map, &self->left, self->client);
355     g_hash_table_insert(window_map, &self->right, self->client);
356     g_hash_table_insert(window_map, &self->titleleft, self->client);
357     g_hash_table_insert(window_map, &self->titletop, self->client);
358     g_hash_table_insert(window_map, &self->titletopleft, self->client);
359     g_hash_table_insert(window_map, &self->titletopright, self->client);
360     g_hash_table_insert(window_map, &self->titleright, self->client);
361     g_hash_table_insert(window_map, &self->titlebottom, self->client);
362     g_hash_table_insert(window_map, &self->handleleft, self->client);
363     g_hash_table_insert(window_map, &self->handletop, self->client);
364     g_hash_table_insert(window_map, &self->handleright, self->client);
365     g_hash_table_insert(window_map, &self->handlebottom, self->client);
366     g_hash_table_insert(window_map, &self->lgripleft, self->client);
367     g_hash_table_insert(window_map, &self->lgriptop, self->client);
368     g_hash_table_insert(window_map, &self->lgripbottom, self->client);
369     g_hash_table_insert(window_map, &self->rgripright, self->client);
370     g_hash_table_insert(window_map, &self->rgriptop, self->client);
371     g_hash_table_insert(window_map, &self->rgripbottom, self->client);
372 }
373
374 void frame_ungrab(gpointer _self, GHashTable * window_map)
375 {
376     ObDefaultFrame * self = (ObDefaultFrame *) _self;
377     /* remove all the windows for the frame from the window_map */
378     g_hash_table_remove(window_map, &self->window);
379     g_hash_table_remove(window_map, &self->backback);
380     g_hash_table_remove(window_map, &self->backfront);
381     g_hash_table_remove(window_map, &self->innerleft);
382     g_hash_table_remove(window_map, &self->innertop);
383     g_hash_table_remove(window_map, &self->innerright);
384     g_hash_table_remove(window_map, &self->innerbottom);
385     g_hash_table_remove(window_map, &self->title);
386     g_hash_table_remove(window_map, &self->label);
387     g_hash_table_remove(window_map, &self->max);
388     g_hash_table_remove(window_map, &self->close);
389     g_hash_table_remove(window_map, &self->desk);
390     g_hash_table_remove(window_map, &self->shade);
391     g_hash_table_remove(window_map, &self->icon);
392     g_hash_table_remove(window_map, &self->iconify);
393     g_hash_table_remove(window_map, &self->handle);
394     g_hash_table_remove(window_map, &self->lgrip);
395     g_hash_table_remove(window_map, &self->rgrip);
396     g_hash_table_remove(window_map, &self->topresize);
397     g_hash_table_remove(window_map, &self->tltresize);
398     g_hash_table_remove(window_map, &self->tllresize);
399     g_hash_table_remove(window_map, &self->trtresize);
400     g_hash_table_remove(window_map, &self->trrresize);
401     g_hash_table_remove(window_map, &self->left);
402     g_hash_table_remove(window_map, &self->right);
403     g_hash_table_remove(window_map, &self->titleleft);
404     g_hash_table_remove(window_map, &self->titletop);
405     g_hash_table_remove(window_map, &self->titletopleft);
406     g_hash_table_remove(window_map, &self->titletopright);
407     g_hash_table_remove(window_map, &self->titleright);
408     g_hash_table_remove(window_map, &self->titlebottom);
409     g_hash_table_remove(window_map, &self->handleleft);
410     g_hash_table_remove(window_map, &self->handletop);
411     g_hash_table_remove(window_map, &self->handleright);
412     g_hash_table_remove(window_map, &self->handlebottom);
413     g_hash_table_remove(window_map, &self->lgripleft);
414     g_hash_table_remove(window_map, &self->lgriptop);
415     g_hash_table_remove(window_map, &self->lgripbottom);
416     g_hash_table_remove(window_map, &self->rgripright);
417     g_hash_table_remove(window_map, &self->rgriptop);
418     g_hash_table_remove(window_map, &self->rgripbottom);
419     
420
421 }
422
423 ObFrameContext frame_context(gpointer _self, Window win, gint x, gint y)
424 {
425     ObDefaultFrame * self = OBDEFAULTFRAME(_self);
426
427     /* when the user clicks in the corners of the titlebar and the client
428      is fully maximized, then treat it like they clicked in the
429      button that is there */
430     if (self->max_horz && self->max_vert && (win == self->title || win
431             == self->titletop || win == self->titleleft || win
432             == self->titletopleft || win == self->titleright || win
433             == self->titletopright)) {
434         /* get the mouse coords in reference to the whole frame */
435         gint fx = x;
436         gint fy = y;
437
438         /* these windows are down a border width from the top of the frame */
439         if (win == self->title || win == self->titleleft || win
440                 == self->titleright)
441             fy += self->bwidth;
442
443         /* title is a border width in from the edge */
444         if (win == self->title)
445             fx += self->bwidth;
446         /* titletop is a bit to the right */
447         else if (win == self->titletop)
448             fx += theme_config.grip_width + self->bwidth;
449         /* titletopright is way to the right edge */
450         else if (win == self->titletopright)
451             fx += self->area.width - (theme_config.grip_width + self->bwidth);
452         /* titleright is even more way to the right edge */
453         else if (win == self->titleright)
454             fx += self->area.width - self->bwidth;
455
456         /* figure out if we're over the area that should be considered a
457          button */
458         if (fy < self->bwidth + theme_config.paddingy + 1
459                 + theme_config.button_size) {
460             if (fx < (self->bwidth + theme_config.paddingx + 1
461                     + theme_config.button_size)) {
462                 if (self->leftmost != OB_FRAME_CONTEXT_NONE)
463                     return self->leftmost;
464             }
465             else if (fx >= (self->area.width - (self->bwidth
466                     + theme_config.paddingx + 1 + theme_config.button_size))) {
467                 if (self->rightmost != OB_FRAME_CONTEXT_NONE)
468                     return self->rightmost;
469             }
470         }
471
472         /* there is no resizing maximized windows so make them the titlebar
473          context */
474         return OB_FRAME_CONTEXT_TITLEBAR;
475     }
476     else if (self->max_vert
477             && (win == self->titletop || win == self->topresize))
478         /* can't resize vertically when max vert */
479         return OB_FRAME_CONTEXT_TITLEBAR;
480     else if (self->shaded && (win == self->titletop || win == self->topresize))
481         /* can't resize vertically when shaded */
482         return OB_FRAME_CONTEXT_TITLEBAR;
483
484     if (win == self->window)
485         return OB_FRAME_CONTEXT_FRAME;
486     if (win == self->label)
487         return OB_FRAME_CONTEXT_TITLEBAR;
488     if (win == self->handle)
489         return OB_FRAME_CONTEXT_BOTTOM;
490     if (win == self->handletop)
491         return OB_FRAME_CONTEXT_BOTTOM;
492     if (win == self->handlebottom)
493         return OB_FRAME_CONTEXT_BOTTOM;
494     if (win == self->handleleft)
495         return OB_FRAME_CONTEXT_BLCORNER;
496     if (win == self->lgrip)
497         return OB_FRAME_CONTEXT_BLCORNER;
498     if (win == self->lgripleft)
499         return OB_FRAME_CONTEXT_BLCORNER;
500     if (win == self->lgriptop)
501         return OB_FRAME_CONTEXT_BLCORNER;
502     if (win == self->lgripbottom)
503         return OB_FRAME_CONTEXT_BLCORNER;
504     if (win == self->handleright)
505         return OB_FRAME_CONTEXT_BRCORNER;
506     if (win == self->rgrip)
507         return OB_FRAME_CONTEXT_BRCORNER;
508     if (win == self->rgripright)
509         return OB_FRAME_CONTEXT_BLCORNER;
510     if (win == self->rgriptop)
511         return OB_FRAME_CONTEXT_BLCORNER;
512     if (win == self->rgripbottom)
513         return OB_FRAME_CONTEXT_BLCORNER;
514     if (win == self->title)
515         return OB_FRAME_CONTEXT_TITLEBAR;
516     if (win == self->titlebottom)
517         return OB_FRAME_CONTEXT_TITLEBAR;
518     if (win == self->titleleft)
519         return OB_FRAME_CONTEXT_TLCORNER;
520     if (win == self->titletopleft)
521         return OB_FRAME_CONTEXT_TLCORNER;
522     if (win == self->titleright)
523         return OB_FRAME_CONTEXT_TRCORNER;
524     if (win == self->titletopright)
525         return OB_FRAME_CONTEXT_TRCORNER;
526     if (win == self->titletop)
527         return OB_FRAME_CONTEXT_TOP;
528     if (win == self->topresize)
529         return OB_FRAME_CONTEXT_TOP;
530     if (win == self->tltresize)
531         return OB_FRAME_CONTEXT_TLCORNER;
532     if (win == self->tllresize)
533         return OB_FRAME_CONTEXT_TLCORNER;
534     if (win == self->trtresize)
535         return OB_FRAME_CONTEXT_TRCORNER;
536     if (win == self->trrresize)
537         return OB_FRAME_CONTEXT_TRCORNER;
538     if (win == self->left)
539         return OB_FRAME_CONTEXT_LEFT;
540     if (win == self->right)
541         return OB_FRAME_CONTEXT_RIGHT;
542     if (win == self->innertop)
543         return OB_FRAME_CONTEXT_TITLEBAR;
544     if (win == self->innerleft)
545         return OB_FRAME_CONTEXT_LEFT;
546     if (win == self->innerbottom)
547         return OB_FRAME_CONTEXT_BOTTOM;
548     if (win == self->innerright)
549         return OB_FRAME_CONTEXT_RIGHT;
550     if (win == self->max)
551         return OB_FRAME_CONTEXT_MAXIMIZE;
552     if (win == self->iconify)
553         return OB_FRAME_CONTEXT_ICONIFY;
554     if (win == self->close)
555         return OB_FRAME_CONTEXT_CLOSE;
556     if (win == self->icon)
557         return OB_FRAME_CONTEXT_ICON;
558     if (win == self->desk)
559         return OB_FRAME_CONTEXT_ALLDESKTOPS;
560     if (win == self->shade)
561         return OB_FRAME_CONTEXT_SHADE;
562
563     return OB_FRAME_CONTEXT_NONE;
564 }
565
566 void frame_set_is_visible(gpointer self, gboolean b)
567 {
568     OBDEFAULTFRAME(self)->visible = b;
569 }
570
571 void frame_set_is_focus(gpointer self, gboolean b)
572 {
573     OBDEFAULTFRAME(self)->focused = b;
574 }
575
576 void frame_set_is_max_vert(gpointer self, gboolean b)
577 {
578     OBDEFAULTFRAME(self)->max_vert = b;
579 }
580
581 void frame_set_is_max_horz(gpointer self, gboolean b)
582 {
583     OBDEFAULTFRAME(self)->max_horz = b;
584 }
585
586 void frame_set_is_shaded(gpointer self, gboolean b)
587 {
588     OBDEFAULTFRAME(self)->shaded = b;
589 }
590
591 void frame_unfocus(gpointer self)
592 {
593     OBDEFAULTFRAME(self)->focused = FALSE;
594 }
595
596 void frame_set_decorations(gpointer self, ObFrameDecorations d)
597 {
598     OBDEFAULTFRAME(self)->decorations = d;
599 }
600
601 void frame_get_window_area(gpointer self, Rect * r)
602 {
603     /* *r = (OBDEFAULTFRAME(self)->area) ??? */ 
604     memcpy(r, &(OBDEFAULTFRAME(self)->area), sizeof(Rect));
605 }
606 void frame_set_client_area(gpointer self, Rect r)
607 {
608     OBDEFAULTFRAME(self)->client_area = r;
609 }
610
611 void frame_update_layout(gpointer _self, Rect area, gboolean is_resize, gboolean is_fake)
612 {
613     ObDefaultFrame * self = (ObDefaultFrame *) _self;
614     Strut oldsize;
615
616     oldsize = self->size;
617     self->client_area = area;
618     self->area = self->client_area;
619
620     /* do this before changing the frame's status like max_horz max_vert */
621     frame_adjust_cursors(self);
622
623     if (self->decorations & OB_FRAME_DECOR_BORDER
624             || (config_theme_keepborder)) {
625         self->bwidth = theme_config.fbwidth;
626     }
627     else {
628         self->bwidth = 0;
629     }
630
631     if (self->decorations & OB_FRAME_DECOR_BORDER) {
632         self->cbwidth_l = theme_config.cbwidthx;
633         self->cbwidth_r = theme_config.cbwidthx;
634         self->cbwidth_t = theme_config.cbwidthy;
635         self->cbwidth_b = theme_config.cbwidthy;
636     }
637     else {
638         self->cbwidth_l = 0;
639         self->cbwidth_t = 0;
640         self->cbwidth_r = 0;
641         self->cbwidth_b = 0;
642     }
643
644     if (self->max_horz) {
645         self->cbwidth_l = 0;
646         self->cbwidth_r = 0;
647         self->width = self->client_area.width;
648         if (self->max_vert)
649             self->cbwidth_b = 0;
650     }
651     else {
652         self->width = self->client_area.width + self->cbwidth_l
653                 + self->cbwidth_r;
654     }
655
656     /* some elements are sized based of the width, so don't let them have
657      negative values */
658     self->width = MAX(self->width, (theme_config.grip_width + self->bwidth) * 2
659             + 1);
660
661     STRUT_SET(self->size, self->cbwidth_l
662             + (!self->max_horz ? self->bwidth : 0), self->cbwidth_t
663             + self->bwidth, self->cbwidth_r + (!self->max_horz ? self->bwidth
664             : 0), self->cbwidth_b
665             + (!self->max_horz || !self->max_vert ? self->bwidth : 0));
666
667     if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
668         self->size.top += theme_config.title_height + self->bwidth;
669     if (self->decorations & OB_FRAME_DECOR_HANDLE && theme_config.handle_height
670             > 0) {
671         self->size.bottom += theme_config.handle_height + self->bwidth;
672     }
673
674     /* position/size and map/unmap all the windows */
675     if (!is_fake) {
676         gint innercornerheight = theme_config.grip_width - self->size.bottom;
677
678         if (self->cbwidth_l) {
679             XMoveResizeWindow(obp_display, self->innerleft, self->size.left
680                     - self->cbwidth_l, self->size.top, self->cbwidth_l,
681                     self->client_area.height);
682
683             XMapWindow(obp_display, self->innerleft);
684         }
685         else
686             XUnmapWindow(obp_display, self->innerleft);
687
688         if (self->cbwidth_l && innercornerheight > 0) {
689             XMoveResizeWindow(obp_display, self->innerbll, 0,
690                     self->client_area.height - (theme_config.grip_width
691                             - self->size.bottom), self->cbwidth_l,
692                     theme_config.grip_width - self->size.bottom);
693
694             XMapWindow(obp_display, self->innerbll);
695         }
696         else
697             XUnmapWindow(obp_display, self->innerbll);
698
699         if (self->cbwidth_r) {
700             XMoveResizeWindow(obp_display, self->innerright, self->size.left
701                     + self->client_area.width, self->size.top, self->cbwidth_r,
702                     self->client_area.height);
703
704             XMapWindow(obp_display, self->innerright);
705         }
706         else
707             XUnmapWindow(obp_display, self->innerright);
708
709         if (self->cbwidth_r && innercornerheight > 0) {
710             XMoveResizeWindow(obp_display, self->innerbrr, 0,
711                     self->client_area.height - (theme_config.grip_width
712                             - self->size.bottom), self->cbwidth_r,
713                     theme_config.grip_width - self->size.bottom);
714
715             XMapWindow(obp_display, self->innerbrr);
716         }
717         else
718             XUnmapWindow(obp_display, self->innerbrr);
719
720         if (self->cbwidth_t) {
721             XMoveResizeWindow(
722                     obp_display,
723                     self->innertop,
724                     self->size.left - self->cbwidth_l,
725                     self->size.top - self->cbwidth_t,
726                     self->client_area.width + self->cbwidth_l + self->cbwidth_r,
727                     self->cbwidth_t);
728
729             XMapWindow(obp_display, self->innertop);
730         }
731         else
732             XUnmapWindow(obp_display, self->innertop);
733
734         if (self->cbwidth_b) {
735             XMoveResizeWindow(obp_display, self->innerbottom, self->size.left
736                     - self->cbwidth_l, self->size.top
737                     + self->client_area.height, self->client_area.width
738                     + self->cbwidth_l + self->cbwidth_r, self->cbwidth_b);
739
740             XMoveResizeWindow(obp_display, self->innerblb, 0, 0,
741                     theme_config.grip_width + self->bwidth, self->cbwidth_b);
742             XMoveResizeWindow(obp_display, self->innerbrb,
743                     self->client_area.width + self->cbwidth_l + self->cbwidth_r
744                             - (theme_config.grip_width + self->bwidth), 0,
745                     theme_config.grip_width + self->bwidth, self->cbwidth_b);
746
747             XMapWindow(obp_display, self->innerbottom);
748             XMapWindow(obp_display, self->innerblb);
749             XMapWindow(obp_display, self->innerbrb);
750         }
751         else {
752             XUnmapWindow(obp_display, self->innerbottom);
753             XUnmapWindow(obp_display, self->innerblb);
754             XUnmapWindow(obp_display, self->innerbrb);
755         }
756
757         if (self->bwidth) {
758             gint titlesides;
759
760             /* height of titleleft and titleright */
761             titlesides = (!self->max_horz ? theme_config.grip_width : 0);
762
763             XMoveResizeWindow(obp_display, self->titletop,
764                     theme_config.grip_width + self->bwidth, 0,
765                     /* width + bwidth*2 - bwidth*2 - grips*2 */
766                     self->width - theme_config.grip_width * 2, self->bwidth);
767             XMoveResizeWindow(obp_display, self->titletopleft, 0, 0,
768                     theme_config.grip_width + self->bwidth, self->bwidth);
769             XMoveResizeWindow(obp_display, self->titletopright,
770                     self->client_area.width + self->size.left
771                             + self->size.right - theme_config.grip_width
772                             - self->bwidth, 0, theme_config.grip_width
773                             + self->bwidth, self->bwidth);
774
775             if (titlesides > 0) {
776                 XMoveResizeWindow(obp_display, self->titleleft, 0,
777                         self->bwidth, self->bwidth, titlesides);
778                 XMoveResizeWindow(obp_display, self->titleright,
779                         self->client_area.width + self->size.left
780                                 + self->size.right - self->bwidth,
781                         self->bwidth, self->bwidth, titlesides);
782
783                 XMapWindow(obp_display, self->titleleft);
784                 XMapWindow(obp_display, self->titleright);
785             }
786             else {
787                 XUnmapWindow(obp_display, self->titleleft);
788                 XUnmapWindow(obp_display, self->titleright);
789             }
790
791             XMapWindow(obp_display, self->titletop);
792             XMapWindow(obp_display, self->titletopleft);
793             XMapWindow(obp_display, self->titletopright);
794
795             if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
796                 XMoveResizeWindow(obp_display, self->titlebottom,
797                         (self->max_horz ? 0 : self->bwidth),
798                         theme_config.title_height + self->bwidth, self->width,
799                         self->bwidth);
800
801                 XMapWindow(obp_display, self->titlebottom);
802             }
803             else
804                 XUnmapWindow(obp_display, self->titlebottom);
805         }
806         else {
807             XUnmapWindow(obp_display, self->titlebottom);
808
809             XUnmapWindow(obp_display, self->titletop);
810             XUnmapWindow(obp_display, self->titletopleft);
811             XUnmapWindow(obp_display, self->titletopright);
812             XUnmapWindow(obp_display, self->titleleft);
813             XUnmapWindow(obp_display, self->titleright);
814         }
815
816         if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
817             XMoveResizeWindow(obp_display, self->title, (self->max_horz ? 0
818                     : self->bwidth), self->bwidth, self->width,
819                     theme_config.title_height);
820
821             XMapWindow(obp_display, self->title);
822
823             if (self->decorations & OB_FRAME_DECOR_GRIPS) {
824                 XMoveResizeWindow(obp_display, self->topresize,
825                         theme_config.grip_width, 0, self->width
826                                 - theme_config.grip_width *2,
827                         theme_config.paddingy + 1);
828
829                 XMoveWindow(obp_display, self->tltresize, 0, 0);
830                 XMoveWindow(obp_display, self->tllresize, 0, 0);
831                 XMoveWindow(obp_display, self->trtresize, self->width
832                         - theme_config.grip_width, 0);
833                 XMoveWindow(obp_display, self->trrresize, self->width
834                         - theme_config.paddingx - 1, 0);
835
836                 XMapWindow(obp_display, self->topresize);
837                 XMapWindow(obp_display, self->tltresize);
838                 XMapWindow(obp_display, self->tllresize);
839                 XMapWindow(obp_display, self->trtresize);
840                 XMapWindow(obp_display, self->trrresize);
841             }
842             else {
843                 XUnmapWindow(obp_display, self->topresize);
844                 XUnmapWindow(obp_display, self->tltresize);
845                 XUnmapWindow(obp_display, self->tllresize);
846                 XUnmapWindow(obp_display, self->trtresize);
847                 XUnmapWindow(obp_display, self->trrresize);
848             }
849         }
850         else
851             XUnmapWindow(obp_display, self->title);
852     }
853
854     if ((self->decorations & OB_FRAME_DECOR_TITLEBAR))
855         /* layout the title bar elements */
856         layout_title(self);
857
858     if (!is_fake) {
859         gint sidebwidth = self->max_horz ? 0 : self->bwidth;
860
861         if (self->bwidth && self->size.bottom) {
862             XMoveResizeWindow(obp_display, self->handlebottom,
863                     theme_config.grip_width + self->bwidth + sidebwidth,
864                     self->size.top + self->client_area.height
865                             + self->size.bottom - self->bwidth, self->width
866                             - (theme_config.grip_width + sidebwidth) * 2,
867                     self->bwidth);
868
869             if (sidebwidth) {
870                 XMoveResizeWindow(obp_display, self->lgripleft, 0,
871                         self->size.top + self->client_area.height
872                                 + self->size.bottom
873                                 - (!self->max_horz ? theme_config.grip_width
874                                         : self->size.bottom - self->cbwidth_b),
875                         self->bwidth,
876                         (!self->max_horz ? theme_config.grip_width
877                                 : self->size.bottom - self->cbwidth_b));
878                 XMoveResizeWindow(obp_display, self->rgripright,
879                         self->size.left + self->client_area.width
880                                 + self->size.right - self->bwidth,
881                         self->size.top + self->client_area.height
882                                 + self->size.bottom
883                                 - (!self->max_horz ? theme_config.grip_width
884                                         : self->size.bottom - self->cbwidth_b),
885                         self->bwidth,
886                         (!self->max_horz ? theme_config.grip_width
887                                 : self->size.bottom - self->cbwidth_b));
888
889                 XMapWindow(obp_display, self->lgripleft);
890                 XMapWindow(obp_display, self->rgripright);
891             }
892             else {
893                 XUnmapWindow(obp_display, self->lgripleft);
894                 XUnmapWindow(obp_display, self->rgripright);
895             }
896
897             XMoveResizeWindow(obp_display, self->lgripbottom, sidebwidth,
898                     self->size.top + self->client_area.height
899                             + self->size.bottom - self->bwidth,
900                     theme_config.grip_width + self->bwidth, self->bwidth);
901             XMoveResizeWindow(obp_display, self->rgripbottom, self->size.left
902                     + self->client_area.width + self->size.right - self->bwidth
903                     - sidebwidth - theme_config.grip_width, self->size.top
904                     + self->client_area.height + self->size.bottom
905                     - self->bwidth, theme_config.grip_width + self->bwidth,
906                     self->bwidth);
907
908             XMapWindow(obp_display, self->handlebottom);
909             XMapWindow(obp_display, self->lgripbottom);
910             XMapWindow(obp_display, self->rgripbottom);
911
912             if (self->decorations & OB_FRAME_DECOR_HANDLE
913                     && theme_config.handle_height > 0) {
914                 XMoveResizeWindow(obp_display, self->handletop,
915                         theme_config.grip_width + self->bwidth + sidebwidth, 
916                         FRAME_HANDLE_Y(self), self->width - (theme_config.grip_width
917                                 + sidebwidth) * 2, self->bwidth);
918                 XMapWindow(obp_display, self->handletop);
919
920                 if (self->decorations & OB_FRAME_DECOR_GRIPS) {
921                     XMoveResizeWindow(obp_display, self->handleleft,
922                             theme_config.grip_width, 0, self->bwidth,
923                             theme_config.handle_height);
924                     XMoveResizeWindow(obp_display, self->handleright,
925                             self->width - theme_config.grip_width
926                                     - self->bwidth, 0, self->bwidth,
927                             theme_config.handle_height);
928
929                     XMoveResizeWindow(obp_display, self->lgriptop, sidebwidth, 
930                     FRAME_HANDLE_Y(self), theme_config.grip_width + self->bwidth,
931                             self->bwidth);
932                     XMoveResizeWindow(obp_display, self->rgriptop,
933                             self->size.left + self->client_area.width
934                                     + self->size.right - self->bwidth
935                                     - sidebwidth - theme_config.grip_width, 
936                             FRAME_HANDLE_Y(self), theme_config.grip_width
937                                     + self->bwidth, self->bwidth);
938
939                     XMapWindow(obp_display, self->handleleft);
940                     XMapWindow(obp_display, self->handleright);
941                     XMapWindow(obp_display, self->lgriptop);
942                     XMapWindow(obp_display, self->rgriptop);
943                 }
944                 else {
945                     XUnmapWindow(obp_display, self->handleleft);
946                     XUnmapWindow(obp_display, self->handleright);
947                     XUnmapWindow(obp_display, self->lgriptop);
948                     XUnmapWindow(obp_display, self->rgriptop);
949                 }
950             }
951             else {
952                 XUnmapWindow(obp_display, self->handleleft);
953                 XUnmapWindow(obp_display, self->handleright);
954                 XUnmapWindow(obp_display, self->lgriptop);
955                 XUnmapWindow(obp_display, self->rgriptop);
956
957                 XUnmapWindow(obp_display, self->handletop);
958             }
959         }
960         else {
961             XUnmapWindow(obp_display, self->handleleft);
962             XUnmapWindow(obp_display, self->handleright);
963             XUnmapWindow(obp_display, self->lgriptop);
964             XUnmapWindow(obp_display, self->rgriptop);
965
966             XUnmapWindow(obp_display, self->handletop);
967
968             XUnmapWindow(obp_display, self->handlebottom);
969             XUnmapWindow(obp_display, self->lgripleft);
970             XUnmapWindow(obp_display, self->rgripright);
971             XUnmapWindow(obp_display, self->lgripbottom);
972             XUnmapWindow(obp_display, self->rgripbottom);
973         }
974
975         if (self->decorations & OB_FRAME_DECOR_HANDLE
976                 && theme_config.handle_height > 0) {
977             XMoveResizeWindow(obp_display, self->handle, sidebwidth, 
978             FRAME_HANDLE_Y(self) + self->bwidth, self->width,
979                     theme_config.handle_height);
980             XMapWindow(obp_display, self->handle);
981
982             if (self->decorations & OB_FRAME_DECOR_GRIPS) {
983                 XMoveResizeWindow(obp_display, self->lgrip, 0, 0,
984                         theme_config.grip_width, theme_config.handle_height);
985                 XMoveResizeWindow(obp_display, self->rgrip, self->width
986                         - theme_config.grip_width, 0, theme_config.grip_width,
987                         theme_config.handle_height);
988
989                 XMapWindow(obp_display, self->lgrip);
990                 XMapWindow(obp_display, self->rgrip);
991             }
992             else {
993                 XUnmapWindow(obp_display, self->lgrip);
994                 XUnmapWindow(obp_display, self->rgrip);
995             }
996         }
997         else {
998             XUnmapWindow(obp_display, self->lgrip);
999             XUnmapWindow(obp_display, self->rgrip);
1000
1001             XUnmapWindow(obp_display, self->handle);
1002         }
1003
1004         if (self->bwidth && !self->max_horz && (self->client_area.height
1005                 + self->size.top + self->size.bottom) > theme_config.grip_width
1006                 * 2) {
1007             XMoveResizeWindow(obp_display, self->left, 0, self->bwidth
1008                     + theme_config.grip_width, self->bwidth,
1009                     self->client_area.height + self->size.top
1010                             + self->size.bottom - theme_config.grip_width * 2);
1011
1012             XMapWindow(obp_display, self->left);
1013         }
1014         else
1015             XUnmapWindow(obp_display, self->left);
1016
1017         if (self->bwidth && !self->max_horz && (self->client_area.height
1018                 + self->size.top + self->size.bottom) > theme_config.grip_width
1019                 * 2) {
1020             XMoveResizeWindow(obp_display, self->right, self->client_area.width
1021                     + self->cbwidth_l + self->cbwidth_r + self->bwidth,
1022                     self->bwidth + theme_config.grip_width, self->bwidth,
1023                     self->client_area.height + self->size.top
1024                             + self->size.bottom - theme_config.grip_width * 2);
1025
1026             XMapWindow(obp_display, self->right);
1027         }
1028         else
1029             XUnmapWindow(obp_display, self->right);
1030
1031         XMoveResizeWindow(obp_display, self->backback, self->size.left,
1032                 self->size.top, self->client_area.width,
1033                 self->client_area.height);
1034     }
1035
1036     /* shading can change without being moved or resized */
1037     RECT_SET_SIZE(self->area, self->client_area.width + self->size.left
1038             + self->size.right, (self->shaded ? theme_config.title_height
1039             + self->bwidth * 2 : self->client_area.height + self->size.top
1040             + self->size.bottom));
1041
1042     if ((is_resize) && !is_fake) {
1043         /* find the new coordinates, done after setting the frame.size, for
1044          frame_client_gravity. */
1045         self->area.x = self->client_area.x;
1046         self->area.y = self->client_area.y;
1047         frame_client_gravity(OBDEFAULTFRAME(_self)->client, &self->area.x, &self->area.y);
1048     }
1049
1050     if (!is_fake) {
1051         /* move and resize the top level frame.
1052          shading can change without being moved or resized.
1053          but don't do this during an iconify animation. it will be
1054          reflected afterwards.
1055          */
1056         XMoveResizeWindow(obp_display, self->window, self->area.x,
1057                 self->area.y, self->area.width, self->area.height);
1058
1059         /* when the client has StaticGravity, it likes to move around.
1060          also this correctly positions the client when it maps.
1061          this also needs to be run when the frame's decorations sizes change!
1062          */
1063         if (!is_resize)
1064             XMoveResizeWindow(obp_display, self->client->w_client,
1065                     self->size.left, self->size.top, self->client_area.width,
1066                     self->client_area.height);
1067
1068         if (is_resize) {
1069             self->need_render = TRUE;
1070             frame_update_skin(self);
1071             frame_adjust_shape(self);
1072         }
1073
1074         if (!STRUT_EQUAL(self->size, oldsize)) {
1075             gulong vals[4];
1076             vals[0] = self->size.left;
1077             vals[1] = self->size.right;
1078             vals[2] = self->size.top;
1079             vals[3] = self->size.bottom;
1080             OBT_PROP_SETA32(self->client->w_client, NET_FRAME_EXTENTS,
1081                     CARDINAL, vals, 4);
1082             OBT_PROP_SETA32(self->client->w_client, KDE_NET_WM_FRAME_STRUT,
1083                     CARDINAL, vals, 4);
1084         }
1085
1086         /* if this occurs while we are focus cycling, the indicator needs to
1087          match the changes */
1088         if (plugin.focus_cycle_target == self->client)
1089             focus_cycle_draw_indicator(self->client);
1090     }
1091     if (is_resize && (self->decorations & OB_FRAME_DECOR_TITLEBAR))
1092         XResizeWindow(obp_display, self->label, self->label_width,
1093                 theme_config.label_height);
1094 }
1095
1096 void frame_set_hover_flag(gpointer self, ObFrameButton button)
1097 {
1098     if (OBDEFAULTFRAME(self)->hover_flag != button) {
1099         OBDEFAULTFRAME(self)->hover_flag = button;
1100         frame_update_skin(self);
1101     }
1102 }
1103
1104 void frame_set_press_flag(gpointer self, ObFrameButton button)
1105 {
1106     if (OBDEFAULTFRAME(self)->press_flag != button) {
1107         OBDEFAULTFRAME(self)->press_flag = button;
1108         frame_update_skin(self);
1109     }
1110 }
1111
1112 Window frame_get_window(gpointer self)
1113 {
1114     return OBDEFAULTFRAME(self)->window;
1115 }
1116
1117 void frame_get_size(gpointer self, Strut * s)
1118 {
1119     memcpy(s, &(OBDEFAULTFRAME(self)->size), sizeof(Strut));
1120 }
1121
1122 gint frame_get_decorations(gpointer self)
1123 {
1124     return OBDEFAULTFRAME(self)->decorations;
1125 }
1126
1127 void frame_update_title(gpointer self, const gchar * src)
1128 {
1129     g_free(OBDEFAULTFRAME(self)->stitle);
1130     OBDEFAULTFRAME(self)->stitle = g_strdup(src);
1131 }
1132
1133 gboolean frame_is_visible(gpointer self)
1134 {
1135     return OBDEFAULTFRAME(self)->visible;
1136 }
1137
1138 gboolean frame_is_max_horz(gpointer self)
1139 {
1140     return OBDEFAULTFRAME(self)->max_horz;
1141 }
1142
1143 gboolean frame_is_max_vert(gpointer self)
1144 {
1145     return OBDEFAULTFRAME(self)->max_vert;
1146 }
1147
1148 void frame_adjust_cursors(gpointer _self)
1149 {
1150     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1151     if ((self->functions & OB_CLIENT_FUNC_RESIZE) != (self->functions
1152             & OB_CLIENT_FUNC_RESIZE) || self->max_horz != self->max_horz
1153             || self->max_vert != self->max_vert || self->shaded != self->shaded) {
1154         gboolean r = (self->functions & OB_CLIENT_FUNC_RESIZE)
1155                 && !(self->max_horz && self->max_vert);
1156         gboolean topbot = !self->max_vert;
1157         gboolean sh = self->shaded;
1158         XSetWindowAttributes a;
1159
1160         /* these ones turn off when max vert, and some when shaded */
1161         a.cursor = ob_cursor(r && topbot && !sh ? OB_CURSOR_NORTH
1162                 : OB_CURSOR_NONE);
1163         XChangeWindowAttributes(obp_display, self->topresize, CWCursor, &a);
1164         XChangeWindowAttributes(obp_display, self->titletop, CWCursor, &a);
1165         a.cursor = ob_cursor(r && topbot ? OB_CURSOR_SOUTH : OB_CURSOR_NONE);
1166         XChangeWindowAttributes(obp_display, self->handle, CWCursor, &a);
1167         XChangeWindowAttributes(obp_display, self->handletop, CWCursor, &a);
1168         XChangeWindowAttributes(obp_display, self->handlebottom, CWCursor, &a);
1169         XChangeWindowAttributes(obp_display, self->innerbottom, CWCursor, &a);
1170
1171         /* these ones change when shaded */
1172         a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_WEST : OB_CURSOR_NORTHWEST)
1173                 : OB_CURSOR_NONE);
1174         XChangeWindowAttributes(obp_display, self->titleleft, CWCursor, &a);
1175         XChangeWindowAttributes(obp_display, self->tltresize, CWCursor, &a);
1176         XChangeWindowAttributes(obp_display, self->tllresize, CWCursor, &a);
1177         XChangeWindowAttributes(obp_display, self->titletopleft, CWCursor, &a);
1178         a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_EAST : OB_CURSOR_NORTHEAST)
1179                 : OB_CURSOR_NONE);
1180         XChangeWindowAttributes(obp_display, self->titleright, CWCursor, &a);
1181         XChangeWindowAttributes(obp_display, self->trtresize, CWCursor, &a);
1182         XChangeWindowAttributes(obp_display, self->trrresize, CWCursor, &a);
1183         XChangeWindowAttributes(obp_display, self->titletopright, CWCursor, &a);
1184
1185         /* these ones are pretty static */
1186         a.cursor = ob_cursor(r ? OB_CURSOR_WEST : OB_CURSOR_NONE);
1187         XChangeWindowAttributes(obp_display, self->left, CWCursor, &a);
1188         XChangeWindowAttributes(obp_display, self->innerleft, CWCursor, &a);
1189         a.cursor = ob_cursor(r ? OB_CURSOR_EAST : OB_CURSOR_NONE);
1190         XChangeWindowAttributes(obp_display, self->right, CWCursor, &a);
1191         XChangeWindowAttributes(obp_display, self->innerright, CWCursor, &a);
1192         a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHWEST : OB_CURSOR_NONE);
1193         XChangeWindowAttributes(obp_display, self->lgrip, CWCursor, &a);
1194         XChangeWindowAttributes(obp_display, self->handleleft, CWCursor, &a);
1195         XChangeWindowAttributes(obp_display, self->lgripleft, CWCursor, &a);
1196         XChangeWindowAttributes(obp_display, self->lgriptop, CWCursor, &a);
1197         XChangeWindowAttributes(obp_display, self->lgripbottom, CWCursor, &a);
1198         XChangeWindowAttributes(obp_display, self->innerbll, CWCursor, &a);
1199         XChangeWindowAttributes(obp_display, self->innerblb, CWCursor, &a);
1200         a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHEAST : OB_CURSOR_NONE);
1201         XChangeWindowAttributes(obp_display, self->rgrip, CWCursor, &a);
1202         XChangeWindowAttributes(obp_display, self->handleright, CWCursor, &a);
1203         XChangeWindowAttributes(obp_display, self->rgripright, CWCursor, &a);
1204         XChangeWindowAttributes(obp_display, self->rgriptop, CWCursor, &a);
1205         XChangeWindowAttributes(obp_display, self->rgripbottom, CWCursor, &a);
1206         XChangeWindowAttributes(obp_display, self->innerbrr, CWCursor, &a);
1207         XChangeWindowAttributes(obp_display, self->innerbrb, CWCursor, &a);
1208     }
1209 }
1210
1211 void frame_adjust_client_area(gpointer _self)
1212 {
1213     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1214     /* adjust the window which is there to prevent flashing on unmap */
1215     XMoveResizeWindow(obp_display, self->backfront, 0, 0,
1216             self->client_area.width, self->client_area.height);
1217 }
1218
1219 void frame_adjust_state(gpointer _self)
1220 {
1221     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1222     self->need_render = TRUE;
1223     frame_update_skin(self);
1224 }
1225
1226 void frame_adjust_focus(gpointer _self, gboolean hilite)
1227 {
1228     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1229     self->focused = hilite;
1230     self->need_render = TRUE;
1231     frame_update_skin(self);
1232     XFlush(obp_display);
1233 }
1234
1235 void frame_adjust_title(gpointer _self)
1236 {
1237     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1238     self->need_render = TRUE;
1239     frame_update_skin(self);
1240 }
1241
1242 void frame_adjust_icon(gpointer _self)
1243 {
1244     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1245     self->need_render = TRUE;
1246     frame_update_skin(self);
1247 }
1248
1249 /* is there anything present between us and the label? */
1250 static gboolean is_button_present(ObDefaultFrame *_self, const gchar *lc,
1251         gint dir)
1252 {
1253     ObDefaultFrame * self = (ObDefaultFrame *) _self;
1254     for (; *lc != '\0' && lc >= config_title_layout; lc += dir) {
1255         if (*lc == ' ')
1256             continue; /* it was invalid */
1257         if (*lc == 'N' && self->decorations & OB_FRAME_DECOR_ICON)
1258             return TRUE;
1259         if (*lc == 'D' && self->decorations & OB_FRAME_DECOR_ALLDESKTOPS)
1260             return TRUE;
1261         if (*lc == 'S' && self->decorations & OB_FRAME_DECOR_SHADE)
1262             return TRUE;
1263         if (*lc == 'I' && self->decorations & OB_FRAME_DECOR_ICONIFY)
1264             return TRUE;
1265         if (*lc == 'M' && self->decorations & OB_FRAME_DECOR_MAXIMIZE)
1266             return TRUE;
1267         if (*lc == 'C' && self->decorations & OB_FRAME_DECOR_CLOSE)
1268             return TRUE;
1269         if (*lc == 'L')
1270             return FALSE;
1271     }
1272     return FALSE;
1273 }
1274
1275 void layout_title(ObDefaultFrame * self)
1276 {
1277     gchar *lc;
1278     gint i;
1279
1280     const gint bwidth = theme_config.button_size + theme_config.paddingx + 1;
1281     /* position of the left most button */
1282     const gint left = theme_config.paddingx + 1;
1283     /* position of the right most button */
1284     const gint right = self->width;
1285
1286     /* turn them all off */
1287     self->icon_on = self->desk_on = self->shade_on = self->iconify_on
1288             = self->max_on = self->close_on = self->label_on = FALSE;
1289     self->label_width = self->width - (theme_config.paddingx + 1) * 2;
1290     self->leftmost = self->rightmost = OB_FRAME_CONTEXT_NONE;
1291
1292     /* figure out what's being show, find each element's position, and the
1293      width of the label
1294
1295      do the ones before the label, then after the label,
1296      i will be +1 the first time through when working to the left,
1297      and -1 the second time through when working to the right */
1298     for (i = 1; i >= -1; i-=2) {
1299         gint x;
1300         ObFrameContext *firstcon;
1301
1302         if (i > 0) {
1303             x = left;
1304             lc = config_title_layout;
1305             firstcon = &self->leftmost;
1306         }
1307         else {
1308             x = right;
1309             lc = config_title_layout
1310                     + strlen(config_title_layout)-1;
1311             firstcon = &self->rightmost;
1312         }
1313
1314         /* stop at the end of the string (or the label, which calls break) */
1315         for (; *lc != '\0' && lc >= config_title_layout; lc+=i) {
1316             if (*lc == 'L') {
1317                 if (i > 0) {
1318                     self->label_on = TRUE;
1319                     self->label_x = x;
1320                 }
1321                 break; /* break the for loop, do other side of label */
1322             }
1323             else if (*lc == 'N') {
1324                 if (firstcon)
1325                     *firstcon = OB_FRAME_CONTEXT_ICON;
1326                 if ((self->icon_on = is_button_present(self, lc, i))) {
1327                     /* icon is bigger than buttons */
1328                     self->label_width -= bwidth + 2;
1329                     if (i > 0)
1330                         self->icon_x = x;
1331                     x += i * (bwidth + 2);
1332                     if (i < 0)
1333                         self->icon_x = x;
1334                 }
1335             }
1336             else if (*lc == 'D') {
1337                 if (firstcon)
1338                     *firstcon = OB_FRAME_CONTEXT_ALLDESKTOPS;
1339                 if ((self->desk_on = is_button_present(self, lc, i))) {
1340                     self->label_width -= bwidth;
1341                     if (i > 0)
1342                         self->desk_x = x;
1343                     x += i * bwidth;
1344                     if (i < 0)
1345                         self->desk_x = x;
1346                 }
1347             }
1348             else if (*lc == 'S') {
1349                 if (firstcon)
1350                     *firstcon = OB_FRAME_CONTEXT_SHADE;
1351                 if ((self->shade_on = is_button_present(self, lc, i))) {
1352                     self->label_width -= bwidth;
1353                     if (i > 0)
1354                         self->shade_x = x;
1355                     x += i * bwidth;
1356                     if (i < 0)
1357                         self->shade_x = x;
1358                 }
1359             }
1360             else if (*lc == 'I') {
1361                 if (firstcon)
1362                     *firstcon = OB_FRAME_CONTEXT_ICONIFY;
1363                 if ((self->iconify_on = is_button_present(self, lc, i))) {
1364                     self->label_width -= bwidth;
1365                     if (i > 0)
1366                         self->iconify_x = x;
1367                     x += i * bwidth;
1368                     if (i < 0)
1369                         self->iconify_x = x;
1370                 }
1371             }
1372             else if (*lc == 'M') {
1373                 if (firstcon)
1374                     *firstcon = OB_FRAME_CONTEXT_MAXIMIZE;
1375                 if ((self->max_on = is_button_present(self, lc, i))) {
1376                     self->label_width -= bwidth;
1377                     if (i > 0)
1378                         self->max_x = x;
1379                     x += i * bwidth;
1380                     if (i < 0)
1381                         self->max_x = x;
1382                 }
1383             }
1384             else if (*lc == 'C') {
1385                 if (firstcon)
1386                     *firstcon = OB_FRAME_CONTEXT_CLOSE;
1387                 if ((self->close_on = is_button_present(self, lc, i))) {
1388                     self->label_width -= bwidth;
1389                     if (i > 0)
1390                         self->close_x = x;
1391                     x += i * bwidth;
1392                     if (i < 0)
1393                         self->close_x = x;
1394                 }
1395             }
1396             else
1397                 continue; /* don't set firstcon */
1398             firstcon = NULL;
1399         }
1400     }
1401
1402     /* position and map the elements */
1403     if (self->icon_on) {
1404         XMapWindow(obp_display, self->icon);
1405         XMoveWindow(obp_display, self->icon, self->icon_x,
1406                 theme_config.paddingy);
1407     }
1408     else
1409         XUnmapWindow(obp_display, self->icon);
1410
1411     if (self->desk_on) {
1412         XMapWindow(obp_display, self->desk);
1413         XMoveWindow(obp_display, self->desk, self->desk_x,
1414                 theme_config.paddingy + 1);
1415     }
1416     else
1417         XUnmapWindow(obp_display, self->desk);
1418
1419     if (self->shade_on) {
1420         XMapWindow(obp_display, self->shade);
1421         XMoveWindow(obp_display, self->shade, self->shade_x,
1422                 theme_config.paddingy + 1);
1423     }
1424     else
1425         XUnmapWindow(obp_display, self->shade);
1426
1427     if (self->iconify_on) {
1428         XMapWindow(obp_display, self->iconify);
1429         XMoveWindow(obp_display, self->iconify, self->iconify_x,
1430                 theme_config.paddingy + 1);
1431     }
1432     else
1433         XUnmapWindow(obp_display, self->iconify);
1434
1435     if (self->max_on) {
1436         XMapWindow(obp_display, self->max);
1437         XMoveWindow(obp_display, self->max, self->max_x, theme_config.paddingy
1438                 + 1);
1439     }
1440     else
1441         XUnmapWindow(obp_display, self->max);
1442
1443     if (self->close_on) {
1444         XMapWindow(obp_display, self->close);
1445         XMoveWindow(obp_display, self->close, self->close_x,
1446                 theme_config.paddingy + 1);
1447     }
1448     else
1449         XUnmapWindow(obp_display, self->close);
1450
1451     if (self->label_on) {
1452         self->label_width = MAX(1, self->label_width); /* no lower than 1 */
1453         XMapWindow(obp_display, self->label);
1454         XMoveWindow(obp_display, self->label, self->label_x,
1455                 theme_config.paddingy);
1456     }
1457     else
1458         XUnmapWindow(obp_display, self->label);
1459 }
1460
1461 void trigger_none(gpointer self)
1462 {
1463 }
1464 void trigger_iconify(gpointer self)
1465 {
1466 }
1467 void trigger_uniconnity(gpointer self)
1468 {
1469 }
1470 void trigger_iconify_toggle(gpointer self)
1471 {
1472 }
1473 void trigger_shade(gpointer self)
1474 {
1475 }
1476 void trigger_unshade(gpointer self)
1477 {
1478 }
1479 void trigger_shade_toggle(gpointer self)
1480 {
1481 }
1482 void trigger_max(gpointer self)
1483 {
1484 }
1485 void trigger_unmax(gpointer self)
1486 {
1487 }
1488 void trigger_max_troggle(gpointer self)
1489 {
1490 }
1491 void trigger_max_vert(gpointer self)
1492 {
1493     OBDEFAULTFRAME(self)->max_vert = TRUE;
1494 }
1495 void trigger_unmax_vert(gpointer self)
1496 {
1497     OBDEFAULTFRAME(self)->max_vert = FALSE;
1498 }
1499 void trigger_max_toggle(gpointer self)
1500 {
1501 }
1502 void trigger_max_horz(gpointer self)
1503 {
1504     OBDEFAULTFRAME(self)->max_horz = TRUE;
1505 }
1506 void trigger_unmax_horz(gpointer self)
1507 {
1508     OBDEFAULTFRAME(self)->max_horz = FALSE;
1509 }
1510 void trigger_max_horz_toggle(gpointer self)
1511 {
1512 }
1513 void trigger_plugin1(gpointer self)
1514 {
1515 }
1516 void trigger_plugin2(gpointer self)
1517 {
1518 }
1519 void trigger_plugin3(gpointer self)
1520 {
1521 }
1522 void trigger_plugin4(gpointer self)
1523 {
1524 }
1525 void trigger_plugin5(gpointer self)
1526 {
1527 }
1528 void trigger_plugin6(gpointer self)
1529 {
1530 }
1531 void trigger_plugin7(gpointer self)
1532 {
1533 }
1534 void trigger_plugin8(gpointer self)
1535 {
1536 }
1537 void trigger_plugin9(gpointer self)
1538 {
1539 }
1540
1541 void frame_trigger(gpointer self, ObFrameTrigger trigger_name)
1542 {
1543
1544     static void (*trigger_func[64])(gpointer) = { trigger_none,
1545             trigger_iconify, trigger_uniconnity, trigger_iconify_toggle,
1546                     trigger_shade, trigger_unshade, trigger_shade_toggle,
1547                     trigger_max, trigger_unmax, trigger_max_troggle,
1548                     trigger_max_vert, trigger_unmax_vert, trigger_max_toggle,
1549                     trigger_max_horz, trigger_unmax_horz,
1550                     trigger_max_horz_toggle, trigger_plugin1, trigger_plugin2,
1551                     trigger_plugin3, trigger_plugin4, trigger_plugin5,
1552                     trigger_plugin6, trigger_plugin7, trigger_plugin8,
1553                     trigger_plugin9, NULL, 
1554 };
1555
1556 void (*call_trigger_func)(gpointer) = trigger_func[trigger_name];
1557 if(!call_trigger_func)
1558 {
1559     call_trigger_func (self);
1560 }
1561 }
1562
1563 ObFrameEngine plugin = {
1564         0, /* gpointer handler */
1565         "libdefault.la", /* gchar * filename */
1566         "Default", /* gchar * name */
1567         init, //gint (*init) (Display * display, gint screen);
1568         0, /* */
1569         frame_new, //gpointer (*frame_new) (struct _ObClient *c);
1570         frame_free, //void (*frame_free) (gpointer self);
1571         frame_adjust_theme, //void (*frame_adjust_theme) (gpointer self);
1572         frame_adjust_shape, //void (*frame_adjust_shape) (gpointer self);
1573         frame_grab, //void (*frame_adjust_area) (gpointer self, gboolean moved, gboolean resized, gboolean fake);
1574         frame_ungrab, /* */
1575         frame_context, //void (*frame_adjust_state) (gpointer self);
1576         frame_set_is_visible, /* */
1577         frame_set_is_focus, /* */
1578         frame_set_is_max_vert, /* */
1579         frame_set_is_max_horz, /* */
1580         frame_set_is_shaded, /* */
1581         0, //frame_flash_start, /* */
1582         0, //frame_flash_stop, /* */
1583         frame_set_decorations, /* */
1584         frame_update_title, /* */
1585         /* This give the window area */
1586         frame_get_window_area, /* */
1587         frame_set_client_area, /* */
1588         /* Draw the frame */
1589         frame_update_layout, /* */
1590         frame_update_skin, /* */
1591         frame_set_hover_flag, /* */
1592         frame_set_press_flag, /* */
1593         frame_get_size, /* */
1594         frame_get_decorations, /* */
1595         frame_is_visible, /* */
1596         frame_is_max_horz, /* */
1597         frame_is_max_vert, /* */
1598         frame_trigger, /* */
1599         load_theme_config, /* */
1600         /* This fields are fill by openbox. */
1601         0, /*struct _ObClient *focus_cycle_target; */
1602         FALSE, /*gboolean moveresize_in_progress;*/
1603 };
1604
1605 ObFrameEngine * get_info()
1606 {
1607     return &plugin;
1608 }
1609
1610 gboolean flash_timeout(gpointer data)
1611 {
1612     return TRUE;
1613 }
1614