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