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