1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 frame_default_plugin.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
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.
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.
17 See the COPYING file for a copy of the GNU General Public License.
23 /* Needed for the _() function */
27 #include "openbox/screen.h"
29 /* Needed for the grab_server */
30 #include "openbox/grab.h"
32 #include <X11/extensions/shape.h>
37 OB_FLAG_CLOSE = 1 << 1,
38 OB_FLAG_DESK = 1 << 2,
39 OB_FLAG_SHADE = 1 << 3,
40 OB_FLAG_ICONIFY = 1 << 4
43 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
44 ButtonPressMask | ButtonReleaseMask | \
45 SubstructureRedirectMask | FocusChangeMask)
46 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
47 ButtonMotionMask | PointerMotionMask | \
48 EnterWindowMask | LeaveWindowMask)
50 #define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */
51 #define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */
53 #define FRAME_HANDLE_Y(f) (f->size.top + f->client_area.height + f->cbwidth_b)
55 Display * obp_display;
57 RrInstance *ob_rr_inst;
59 Window createWindow(Window parent, Visual *visual, gulong mask,
60 XSetWindowAttributes *attrib)
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);
68 Visual *check_32bit_client(ObClient *c)
70 XWindowAttributes wattrib;
73 /* we're already running at 32 bit depth, yay. we don't need to use their
75 if (RrDepth(ob_rr_inst) == 32)
78 ret = XGetWindowAttributes(obp_display, c->w_client, &wattrib);
79 g_assert(ret != BadDrawable);
80 g_assert(ret != BadWindow);
82 if (wattrib.depth == 32)
83 return wattrib.visual;
88 gint init(Display * display, gint screen)
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;
97 gpointer frame_new(struct _ObClient * client, Window w_client, Window w_frame)
99 XSetWindowAttributes attrib;
101 ObDefaultFrame *self;
104 self = g_new0(ObDefaultFrame, 1);
105 self->client = client;
107 visual = check_32bit_client(client);
109 /* create the non-visible decor windows */
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,
119 attrib.background_pixel = BlackPixel(obp_display, obp_screen);
120 attrib.border_pixel = BlackPixel(obp_display, obp_screen);
122 self->window = w_frame;
124 /* create the visible decor windows */
128 /* client has a 32-bit visual */
129 mask |= CWColormap | CWBackPixel | CWBorderPixel;
130 attrib.colormap = RrColormap(ob_rr_inst);
133 self->backback = createWindow(self->window, NULL, mask, &attrib);
134 self->backfront = createWindow(self->backback, NULL, mask, &attrib);
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);
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);
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);
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);
162 self->left = createWindow(self->window, NULL, mask, &attrib);
163 self->right = createWindow(self->window, NULL, mask, &attrib);
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);
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);
177 self->handleleft = createWindow(self->handle, NULL, mask, &attrib);
178 self->handleright = createWindow(self->handle, NULL, mask, &attrib);
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);
189 self->stitle = g_strdup("");
190 self->focused = FALSE;
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);
197 self->hover_flag = OB_BUTTON_NONE;
198 self->press_flag = OB_BUTTON_NONE;
200 set_theme_statics(self);
205 void set_theme_statics(gpointer _self)
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);
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);
241 void free_theme_statics(gpointer _self)
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);
253 void frame_free(gpointer self)
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);
260 g_free(OBDEFAULTFRAME(self)->stitle);
264 void frame_adjust_theme(gpointer self)
266 free_theme_statics(self);
267 set_theme_statics(self);
270 void frame_adjust_shape(gpointer _self)
273 ObDefaultFrame * self = (ObDefaultFrame *) _self;
277 if (!self->client->shaped)
279 /* clear the shape on the frame window */
280 XShapeCombineMask(obp_display, self->window, ShapeBounding,
287 /* make the frame's shape match the clients */
288 XShapeCombineShape(obp_display, self->window, ShapeBounding,
291 self->client->w_client,
292 ShapeBounding, ShapeSet);
295 if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
299 xrect[0].width = self->area.width;
300 xrect[0].height = self->size.top;
304 if (self->decorations & OB_FRAME_DECOR_HANDLE &&
305 theme_config.handle_height> 0)
308 xrect[1].y = FRAME_HANDLE_Y(self);
309 xrect[1].width = self->area.width;
310 xrect[1].height = theme_config.handle_height +
315 XShapeCombineRectangles(obp_display, self->window,
316 ShapeBounding, 0, 0, xrect, num,
317 ShapeUnion, Unsorted);
322 void frame_grab(gpointer _self, GHashTable * window_map)
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.
330 /* reparent the client to the frame */
331 XReparentWindow(obp_display, self->client->w_client, self->window, 0, 0);
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
339 if (ob_state() == OB_STATE_STARTING)
340 ++self->client->ignore_unmaps;
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);
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);
390 void frame_ungrab(gpointer _self, GHashTable * window_map)
392 ObDefaultFrame * self = (ObDefaultFrame *) _self;
394 gboolean reparent = TRUE;
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);
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
407 Reparent events that are generated by us are just discarded here.
408 They are of no consequence to us anyhow.
410 if (ev.xreparent.parent != self->window) {
412 XPutBackEvent(obp_display, &ev);
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);
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);
468 obt_main_loop_timeout_remove_data(plugin.ob_main_loop, flash_timeout, self,
472 ObFrameContext frame_context(gpointer _self, Window win, gint x, gint y)
474 ObDefaultFrame * self = OBDEFAULTFRAME(_self);
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 */
487 /* these windows are down a border width from the top of the frame */
488 if (win == self->title || win == self->titleleft || win
492 /* title is a border width in from the edge */
493 if (win == self->title)
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;
505 /* figure out if we're over the area that should be considered a
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;
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;
521 /* there is no resizing maximized windows so make them the titlebar
523 return OB_FRAME_CONTEXT_TITLEBAR;
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;
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;
612 return OB_FRAME_CONTEXT_NONE;
615 void frame_set_is_visible(gpointer self, gboolean b)
617 OBDEFAULTFRAME(self)->visible = b;
620 void frame_set_is_focus(gpointer self, gboolean b)
622 OBDEFAULTFRAME(self)->focused = b;
625 void frame_set_is_max_vert(gpointer self, gboolean b)
627 OBDEFAULTFRAME(self)->max_vert = b;
630 void frame_set_is_max_horz(gpointer self, gboolean b)
632 OBDEFAULTFRAME(self)->max_horz = b;
635 void frame_set_is_shaded(gpointer self, gboolean b)
637 OBDEFAULTFRAME(self)->shaded = b;
640 void frame_unfocus(gpointer self)
642 OBDEFAULTFRAME(self)->focused = FALSE;
645 void frame_flash_start(gpointer _self)
647 ObDefaultFrame * self = (ObDefaultFrame *) _self;
648 self->flash_on = self->focused;
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);
656 self->flashing = TRUE;
659 void frame_flash_stop(gpointer _self)
661 ObDefaultFrame * self = (ObDefaultFrame *) _self;
662 self->flashing = FALSE;
665 void frame_begin_iconify_animation(gpointer _self, gboolean iconifying)
667 ObDefaultFrame * self = (ObDefaultFrame *) _self;
669 gboolean new_anim = FALSE;
670 gboolean set_end = TRUE;
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))
678 /* get the current time */
679 g_get_current_time(&now);
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);
689 /* animation was already going in the same direction */
694 self->iconify_animation_going = iconifying ? 1 : -1;
696 /* set the ending time */
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);
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);
710 /* do the first step */
711 frame_animate_iconify(self);
713 /* show it during the animation even if it is not "visible" */
715 XMapWindow(obp_display, self->window);
719 void frame_end_iconify_animation(gpointer _self)
721 ObDefaultFrame * self = (ObDefaultFrame *) _self;
722 /* see if there is an animation going */
723 if (self->iconify_animation_going == 0)
727 XUnmapWindow(obp_display, self->window);
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);
737 /* we're not animating any more ! */
738 self->iconify_animation_going = 0;
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);
747 gboolean frame_iconify_animating(gpointer _self)
749 ObDefaultFrame * self = (ObDefaultFrame *) _self;
750 return self->iconify_animation_going != 0;
753 void frame_set_decorations(gpointer self, ObFrameDecorations d)
755 OBDEFAULTFRAME(self)->decorations = d;
758 Rect frame_get_window_area(gpointer self)
760 return OBDEFAULTFRAME(self)->area;
762 void frame_set_client_area(gpointer self, Rect r)
764 OBDEFAULTFRAME(self)->client_area = r;
767 void frame_update_layout(gpointer _self, gboolean is_resize, gboolean is_fake)
769 ObDefaultFrame * self = (ObDefaultFrame *) _self;
772 oldsize = self->size;
773 self->area = self->client_area;
775 /* do this before changing the frame's status like max_horz max_vert */
776 frame_adjust_cursors(self);
778 if (self->decorations & OB_FRAME_DECOR_BORDER
779 || (plugin.config_theme_keepborder)) {
780 self->bwidth = theme_config.fbwidth;
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;
799 if (self->max_horz) {
802 self->width = self->client_area.width;
807 self->width = self->client_area.width + self->cbwidth_l
811 /* some elements are sized based of the width, so don't let them have
813 self->width = MAX(self->width, (theme_config.grip_width + self->bwidth) * 2
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));
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
826 self->size.bottom += theme_config.handle_height + self->bwidth;
829 /* position/size and map/unmap all the windows */
831 gint innercornerheight = theme_config.grip_width - self->size.bottom;
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);
838 XMapWindow(obp_display, self->innerleft);
841 XUnmapWindow(obp_display, self->innerleft);
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);
849 XMapWindow(obp_display, self->innerbll);
852 XUnmapWindow(obp_display, self->innerbll);
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);
859 XMapWindow(obp_display, self->innerright);
862 XUnmapWindow(obp_display, self->innerright);
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);
870 XMapWindow(obp_display, self->innerbrr);
873 XUnmapWindow(obp_display, self->innerbrr);
875 if (self->cbwidth_t) {
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,
884 XMapWindow(obp_display, self->innertop);
887 XUnmapWindow(obp_display, self->innertop);
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);
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);
902 XMapWindow(obp_display, self->innerbottom);
903 XMapWindow(obp_display, self->innerblb);
904 XMapWindow(obp_display, self->innerbrb);
907 XUnmapWindow(obp_display, self->innerbottom);
908 XUnmapWindow(obp_display, self->innerblb);
909 XUnmapWindow(obp_display, self->innerbrb);
915 /* height of titleleft and titleright */
916 titlesides = (!self->max_horz ? theme_config.grip_width : 0);
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);
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);
938 XMapWindow(obp_display, self->titleleft);
939 XMapWindow(obp_display, self->titleright);
942 XUnmapWindow(obp_display, self->titleleft);
943 XUnmapWindow(obp_display, self->titleright);
946 XMapWindow(obp_display, self->titletop);
947 XMapWindow(obp_display, self->titletopleft);
948 XMapWindow(obp_display, self->titletopright);
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,
956 XMapWindow(obp_display, self->titlebottom);
959 XUnmapWindow(obp_display, self->titlebottom);
962 XUnmapWindow(obp_display, self->titlebottom);
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);
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);
976 XMapWindow(obp_display, self->title);
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);
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);
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);
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);
1006 XUnmapWindow(obp_display, self->title);
1009 if ((self->decorations & OB_FRAME_DECOR_TITLEBAR))
1010 /* layout the title bar elements */
1014 gint sidebwidth = self->max_horz ? 0 : self->bwidth;
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,
1025 XMoveResizeWindow(obp_display, self->lgripleft, 0,
1026 self->size.top + self->client_area.height
1028 - (!self->max_horz ? theme_config.grip_width
1029 : self->size.bottom - self->cbwidth_b),
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
1038 - (!self->max_horz ? theme_config.grip_width
1039 : self->size.bottom - self->cbwidth_b),
1041 (!self->max_horz ? theme_config.grip_width
1042 : self->size.bottom - self->cbwidth_b));
1044 XMapWindow(obp_display, self->lgripleft);
1045 XMapWindow(obp_display, self->rgripright);
1048 XUnmapWindow(obp_display, self->lgripleft);
1049 XUnmapWindow(obp_display, self->rgripright);
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,
1063 XMapWindow(obp_display, self->handlebottom);
1064 XMapWindow(obp_display, self->lgripbottom);
1065 XMapWindow(obp_display, self->rgripbottom);
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);
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);
1084 XMoveResizeWindow(obp_display, self->lgriptop, sidebwidth,
1085 FRAME_HANDLE_Y(self), theme_config.grip_width + 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);
1094 XMapWindow(obp_display, self->handleleft);
1095 XMapWindow(obp_display, self->handleright);
1096 XMapWindow(obp_display, self->lgriptop);
1097 XMapWindow(obp_display, self->rgriptop);
1100 XUnmapWindow(obp_display, self->handleleft);
1101 XUnmapWindow(obp_display, self->handleright);
1102 XUnmapWindow(obp_display, self->lgriptop);
1103 XUnmapWindow(obp_display, self->rgriptop);
1107 XUnmapWindow(obp_display, self->handleleft);
1108 XUnmapWindow(obp_display, self->handleright);
1109 XUnmapWindow(obp_display, self->lgriptop);
1110 XUnmapWindow(obp_display, self->rgriptop);
1112 XUnmapWindow(obp_display, self->handletop);
1116 XUnmapWindow(obp_display, self->handleleft);
1117 XUnmapWindow(obp_display, self->handleright);
1118 XUnmapWindow(obp_display, self->lgriptop);
1119 XUnmapWindow(obp_display, self->rgriptop);
1121 XUnmapWindow(obp_display, self->handletop);
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);
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);
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);
1144 XMapWindow(obp_display, self->lgrip);
1145 XMapWindow(obp_display, self->rgrip);
1148 XUnmapWindow(obp_display, self->lgrip);
1149 XUnmapWindow(obp_display, self->rgrip);
1153 XUnmapWindow(obp_display, self->lgrip);
1154 XUnmapWindow(obp_display, self->rgrip);
1156 XUnmapWindow(obp_display, self->handle);
1159 if (self->bwidth && !self->max_horz && (self->client_area.height
1160 + self->size.top + self->size.bottom) > theme_config.grip_width
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);
1167 XMapWindow(obp_display, self->left);
1170 XUnmapWindow(obp_display, self->left);
1172 if (self->bwidth && !self->max_horz && (self->client_area.height
1173 + self->size.top + self->size.bottom) > theme_config.grip_width
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);
1181 XMapWindow(obp_display, self->right);
1184 XUnmapWindow(obp_display, self->right);
1186 XMoveResizeWindow(obp_display, self->backback, self->size.left,
1187 self->size.top, self->client_area.width,
1188 self->client_area.height);
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));
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);
1206 if (!frame_iconify_animating(self))
1207 /* move and resize the top level frame.
1208 shading can change without being moved or resized.
1210 but don't do this during an iconify animation. it will be
1211 reflected afterwards.
1213 XMoveResizeWindow(obp_display, self->window, self->area.x,
1214 self->area.y, self->area.width, self->area.height);
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!
1221 XMoveResizeWindow(obp_display, self->client->w_client,
1222 self->size.left, self->size.top, self->client_area.width,
1223 self->client_area.height);
1226 self->need_render = TRUE;
1227 frame_update_skin(self);
1228 frame_adjust_shape(self);
1231 if (!STRUT_EQUAL(self->size, oldsize)) {
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,
1239 OBT_PROP_SETA32(self->client->w_client, KDE_NET_WM_FRAME_STRUT,
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);
1248 if (is_resize && (self->decorations & OB_FRAME_DECOR_TITLEBAR))
1249 XResizeWindow(obp_display, self->label, self->label_width,
1250 theme_config.label_height);
1253 void frame_set_hover_flag(gpointer self, ObFrameButton button)
1255 if (OBDEFAULTFRAME(self)->hover_flag != button) {
1256 OBDEFAULTFRAME(self)->hover_flag = button;
1257 frame_update_skin(self);
1261 void frame_set_press_flag(gpointer self, ObFrameButton button)
1263 if (OBDEFAULTFRAME(self)->press_flag != button) {
1264 OBDEFAULTFRAME(self)->press_flag = button;
1265 frame_update_skin(self);
1269 Window frame_get_window(gpointer self)
1271 return OBDEFAULTFRAME(self)->window;
1274 Strut frame_get_size(gpointer self)
1276 return OBDEFAULTFRAME(self)->size;
1279 gint frame_get_decorations(gpointer self)
1281 return OBDEFAULTFRAME(self)->decorations;
1284 void frame_update_title(gpointer self, const gchar * src)
1286 g_free(OBDEFAULTFRAME(self)->stitle);
1287 OBDEFAULTFRAME(self)->stitle = g_strdup(src);
1290 gboolean frame_is_visible(gpointer self)
1292 return OBDEFAULTFRAME(self)->visible;
1295 gboolean frame_is_max_horz(gpointer self)
1297 return OBDEFAULTFRAME(self)->max_horz;
1300 gboolean frame_is_max_vert(gpointer self)
1302 return OBDEFAULTFRAME(self)->max_vert;
1305 gulong frame_animate_iconify_time_left(gpointer _self, const GTimeVal *now)
1307 ObDefaultFrame * self = (ObDefaultFrame *) _self;
1309 sec = self->iconify_animation_end.tv_sec - now->tv_sec;
1310 usec = self->iconify_animation_end.tv_usec - now->tv_usec;
1312 usec += G_USEC_PER_SEC;
1315 /* no negative values */
1316 return MAX(sec * G_USEC_PER_SEC + usec, 0);
1319 gboolean frame_animate_iconify(gpointer p)
1321 ObDefaultFrame *self = p;
1323 gint iconx, icony, iconw;
1326 gboolean iconifying;
1328 if (self->client->icon_geometry.width == 0) {
1329 /* there is no icon geometry set so just go straight down */
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;
1338 iconx = self->client->icon_geometry.x;
1339 icony = self->client->icon_geometry.y;
1340 iconw = self->client->icon_geometry.width;
1343 iconifying = self->iconify_animation_going > 0;
1345 /* how far do we have left to go ? */
1346 g_get_current_time(&now);
1347 time = frame_animate_iconify_time_left(self, &now);
1349 if (time == 0 || iconifying) {
1350 /* start where the frame is supposed to be */
1353 w = self->area.width;
1354 h = self->area.height;
1357 /* start at the icon */
1361 h = self->size.top; /* just the titlebar */
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 */
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 */
1386 frame_end_iconify_animation(self);
1388 XMoveResizeWindow(obp_display, self->window, x, y, w, h);
1389 XFlush(obp_display);
1392 return time > 0; /* repeat until we're out of time */
1395 void frame_adjust_cursors(gpointer _self)
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;
1407 /* these ones turn off when max vert, and some when shaded */
1408 a.cursor = ob_cursor(r && topbot && !sh ? OB_CURSOR_NORTH
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);
1418 /* these ones change when shaded */
1419 a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_WEST : OB_CURSOR_NORTHWEST)
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)
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);
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);
1458 void frame_adjust_client_area(gpointer _self)
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);
1466 void frame_adjust_state(gpointer _self)
1468 ObDefaultFrame * self = (ObDefaultFrame *) _self;
1469 self->need_render = TRUE;
1470 frame_update_skin(self);
1473 void frame_adjust_focus(gpointer _self, gboolean hilite)
1475 ObDefaultFrame * self = (ObDefaultFrame *) _self;
1476 self->focused = hilite;
1477 self->need_render = TRUE;
1478 frame_update_skin(self);
1479 XFlush(obp_display);
1482 void frame_adjust_title(gpointer _self)
1484 ObDefaultFrame * self = (ObDefaultFrame *) _self;
1485 self->need_render = TRUE;
1486 frame_update_skin(self);
1489 void frame_adjust_icon(gpointer _self)
1491 ObDefaultFrame * self = (ObDefaultFrame *) _self;
1492 self->need_render = TRUE;
1493 frame_update_skin(self);
1496 /* is there anything present between us and the label? */
1497 static gboolean is_button_present(ObDefaultFrame *_self, const gchar *lc,
1500 ObDefaultFrame * self = (ObDefaultFrame *) _self;
1501 for (; *lc != '\0' && lc >= plugin.config_title_layout; lc += dir) {
1503 continue; /* it was invalid */
1504 if (*lc == 'N' && self->decorations & OB_FRAME_DECOR_ICON)
1506 if (*lc == 'D' && self->decorations & OB_FRAME_DECOR_ALLDESKTOPS)
1508 if (*lc == 'S' && self->decorations & OB_FRAME_DECOR_SHADE)
1510 if (*lc == 'I' && self->decorations & OB_FRAME_DECOR_ICONIFY)
1512 if (*lc == 'M' && self->decorations & OB_FRAME_DECOR_MAXIMIZE)
1514 if (*lc == 'C' && self->decorations & OB_FRAME_DECOR_CLOSE)
1522 void flash_done(gpointer data)
1524 ObDefaultFrame *self = data;
1526 if (self->focused != self->flash_on)
1527 frame_adjust_focus(self, self->focused);
1530 gboolean flash_timeout(gpointer data)
1532 ObDefaultFrame *self = data;
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;
1541 if (!self->flashing)
1542 return FALSE; /* we are done */
1544 self->flash_on = !self->flash_on;
1545 if (!self->focused) {
1546 frame_adjust_focus(self, self->flash_on);
1547 self->focused = FALSE;
1550 return TRUE; /* go again */
1553 void layout_title(ObDefaultFrame * self)
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;
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;
1570 /* figure out what's being show, find each element's position, and the
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) {
1578 ObFrameContext *firstcon;
1582 lc = plugin.config_title_layout;
1583 firstcon = &self->leftmost;
1587 lc = plugin.config_title_layout
1588 + strlen(plugin.config_title_layout)-1;
1589 firstcon = &self->rightmost;
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) {
1596 self->label_on = TRUE;
1599 break; /* break the for loop, do other side of label */
1601 else if (*lc == 'N') {
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;
1609 x += i * (bwidth + 2);
1614 else if (*lc == 'D') {
1616 *firstcon = OB_FRAME_CONTEXT_ALLDESKTOPS;
1617 if ((self->desk_on = is_button_present(self, lc, i))) {
1618 self->label_width -= bwidth;
1626 else if (*lc == 'S') {
1628 *firstcon = OB_FRAME_CONTEXT_SHADE;
1629 if ((self->shade_on = is_button_present(self, lc, i))) {
1630 self->label_width -= bwidth;
1638 else if (*lc == 'I') {
1640 *firstcon = OB_FRAME_CONTEXT_ICONIFY;
1641 if ((self->iconify_on = is_button_present(self, lc, i))) {
1642 self->label_width -= bwidth;
1644 self->iconify_x = x;
1647 self->iconify_x = x;
1650 else if (*lc == 'M') {
1652 *firstcon = OB_FRAME_CONTEXT_MAXIMIZE;
1653 if ((self->max_on = is_button_present(self, lc, i))) {
1654 self->label_width -= bwidth;
1662 else if (*lc == 'C') {
1664 *firstcon = OB_FRAME_CONTEXT_CLOSE;
1665 if ((self->close_on = is_button_present(self, lc, i))) {
1666 self->label_width -= bwidth;
1675 continue; /* don't set firstcon */
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);
1687 XUnmapWindow(obp_display, self->icon);
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);
1695 XUnmapWindow(obp_display, self->desk);
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);
1703 XUnmapWindow(obp_display, self->shade);
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);
1711 XUnmapWindow(obp_display, self->iconify);
1714 XMapWindow(obp_display, self->max);
1715 XMoveWindow(obp_display, self->max, self->max_x, theme_config.paddingy
1719 XUnmapWindow(obp_display, self->max);
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);
1727 XUnmapWindow(obp_display, self->close);
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);
1736 XUnmapWindow(obp_display, self->label);
1739 void trigger_none(gpointer self)
1742 void trigger_iconify(gpointer self)
1745 void trigger_uniconnity(gpointer self)
1748 void trigger_iconify_toggle(gpointer self)
1751 void trigger_shade(gpointer self)
1754 void trigger_unshade(gpointer self)
1757 void trigger_shade_toggle(gpointer self)
1760 void trigger_max(gpointer self)
1763 void trigger_unmax(gpointer self)
1766 void trigger_max_troggle(gpointer self)
1769 void trigger_max_vert(gpointer self)
1771 OBDEFAULTFRAME(self)->max_vert = TRUE;
1773 void trigger_unmax_vert(gpointer self)
1775 OBDEFAULTFRAME(self)->max_vert = FALSE;
1777 void trigger_max_toggle(gpointer self)
1780 void trigger_max_horz(gpointer self)
1782 OBDEFAULTFRAME(self)->max_horz = TRUE;
1784 void trigger_unmax_horz(gpointer self)
1786 OBDEFAULTFRAME(self)->max_horz = FALSE;
1788 void trigger_max_horz_toggle(gpointer self)
1791 void trigger_plugin1(gpointer self)
1794 void trigger_plugin2(gpointer self)
1797 void trigger_plugin3(gpointer self)
1800 void trigger_plugin4(gpointer self)
1803 void trigger_plugin5(gpointer self)
1806 void trigger_plugin6(gpointer self)
1809 void trigger_plugin7(gpointer self)
1812 void trigger_plugin8(gpointer self)
1815 void trigger_plugin9(gpointer self)
1819 void frame_trigger(gpointer self, ObFrameTrigger trigger_name)
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,
1834 void (*call_trigger_func)(gpointer) = trigger_func[trigger_name];
1835 if(!call_trigger_func)
1837 call_trigger_func (self);
1841 ObFramePlugin plugin = { 0, /* gpointer handler */
1842 "libdefault.la", /* gchar * filename */
1843 "Default", /* gchar * name */
1844 init, //gint (*init) (Display * display, gint screen);
1846 frame_new, //gpointer (*frame_new) (struct _ObClient *c);
1847 frame_free, //void (*frame_free) (gpointer self);
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, /* */
1859 frame_flash_start, /* */
1860 frame_flash_stop, /* */
1861 frame_begin_iconify_animation, /* */
1862 frame_end_iconify_animation, /* */
1863 frame_iconify_animating, /* */
1865 frame_set_decorations, /* */
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, /* */
1875 frame_set_hover_flag, /* */
1876 frame_set_press_flag, /* */
1878 frame_get_window,/* */
1880 frame_get_size, /* */
1881 frame_get_decorations, /* */
1883 frame_is_visible, /* */
1884 frame_is_max_horz, /* */
1885 frame_is_max_vert, /* */
1887 frame_trigger, /* */
1889 load_theme_config, /* */
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;
1902 ObFramePlugin * get_info()