2 #include "../../kernel/openbox.h"
3 #include "../../kernel/screen.h"
4 #include "../../kernel/extensions.h"
5 #include "../../kernel/themerc.h"
6 #include "../../kernel/frame.h"
7 #include "../../render/render.h"
8 #include "../../render/color.h"
9 #include "../../render/font.h"
10 #include "../../render/mask.h"
15 #define TITLE_HEIGHT (s_winfont_height + s_bevel * 2)
16 #define LABEL_HEIGHT (s_winfont_height)
17 #define HANDLE_Y(f) (f->innersize.top + f->frame.client->area.height + \
19 #define BUTTON_SIZE (LABEL_HEIGHT - 2)
20 #define GRIP_WIDTH (BUTTON_SIZE * 2)
21 #define HANDLE_WIDTH(f) (f->width - (GRIP_WIDTH + f->bwidth) * 2)
23 #define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
24 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask)
26 /* style settings - geometry */
31 /* style settings - colors */
33 color_rgb
*s_cb_focused_color
;
34 color_rgb
*s_cb_unfocused_color
;
35 color_rgb
*s_title_focused_color
;
36 color_rgb
*s_title_unfocused_color
;
37 color_rgb
*s_titlebut_focused_color
;
38 color_rgb
*s_titlebut_unfocused_color
;
39 /* style settings - fonts */
42 int s_winfont_shadow_offset
;
44 /* style settings - masks */
45 pixmap_mask
*s_max_mask
;
46 pixmap_mask
*s_icon_mask
;
47 pixmap_mask
*s_desk_mask
;
48 pixmap_mask
*s_close_mask
;
50 /* global appearances */
51 Appearance
*a_focused_unpressed_max
;
52 Appearance
*a_focused_pressed_max
;
53 Appearance
*a_unfocused_unpressed_max
;
54 Appearance
*a_unfocused_pressed_max
;
55 Appearance
*a_focused_unpressed_close
;
56 Appearance
*a_focused_pressed_close
;
57 Appearance
*a_unfocused_unpressed_close
;
58 Appearance
*a_unfocused_pressed_close
;
59 Appearance
*a_focused_unpressed_desk
;
60 Appearance
*a_focused_pressed_desk
;
61 Appearance
*a_unfocused_unpressed_desk
;
62 Appearance
*a_unfocused_pressed_desk
;
63 Appearance
*a_focused_unpressed_iconify
;
64 Appearance
*a_focused_pressed_iconify
;
65 Appearance
*a_unfocused_unpressed_iconify
;
66 Appearance
*a_unfocused_pressed_iconify
;
67 Appearance
*a_focused_grip
;
68 Appearance
*a_unfocused_grip
;
69 Appearance
*a_focused_title
;
70 Appearance
*a_unfocused_title
;
71 Appearance
*a_focused_label
;
72 Appearance
*a_unfocused_label
;
73 Appearance
*a_icon
; /* always parentrelative, so no focused/unfocused */
74 Appearance
*a_focused_handle
;
75 Appearance
*a_unfocused_handle
;
77 typedef struct ObFrame
{
91 Appearance
*a_unfocused_title
;
92 Appearance
*a_focused_title
;
93 Appearance
*a_unfocused_label
;
94 Appearance
*a_focused_label
;
96 Appearance
*a_unfocused_handle
;
97 Appearance
*a_focused_handle
;
103 int width
; /* title and handle */
105 int icon_x
; /* x-position of the window icon button */
106 int label_x
; /* x-position of the window title */
107 int iconify_x
; /* x-position of the window iconify button */
108 int desk_x
; /* x-position of the window all-desktops button */
109 int max_x
; /* x-position of the window maximize button */
110 int close_x
; /* x-position of the window close button */
111 int bwidth
; /* border width */
112 int cbwidth
; /* client border width */
115 gboolean close_press
;
117 gboolean iconify_press
;
120 static void layout_title(ObFrame
*self
);
121 static void render(ObFrame
*self
);
122 static void render_label(ObFrame
*self
);
123 static void render_max(ObFrame
*self
);
124 static void render_icon(ObFrame
*self
);
125 static void render_iconify(ObFrame
*self
);
126 static void render_desk(ObFrame
*self
);
127 static void render_close(ObFrame
*self
);
131 g_quark_from_string("none");
132 g_quark_from_string("root");
133 g_quark_from_string("client");
134 g_quark_from_string("titlebar");
135 g_quark_from_string("handle");
136 g_quark_from_string("frame");
137 g_quark_from_string("blcorner");
138 g_quark_from_string("brcorner");
139 g_quark_from_string("maximize");
140 g_quark_from_string("alldesktops");
141 g_quark_from_string("iconify");
142 g_quark_from_string("icon");
143 g_quark_from_string("close");
145 s_b_color
= s_cb_unfocused_color
= s_cb_focused_color
=
146 s_title_unfocused_color
= s_title_focused_color
=
147 s_titlebut_unfocused_color
= s_titlebut_focused_color
= NULL
;
149 s_max_mask
= s_icon_mask
= s_desk_mask
= s_close_mask
= NULL
;
151 a_focused_unpressed_max
= appearance_new(Surface_Planar
, 1);
152 a_focused_pressed_max
= appearance_new(Surface_Planar
, 1);
153 a_unfocused_unpressed_max
= appearance_new(Surface_Planar
, 1);
154 a_unfocused_pressed_max
= appearance_new(Surface_Planar
, 1);
155 a_focused_unpressed_close
= NULL
;
156 a_focused_pressed_close
= NULL
;
157 a_unfocused_unpressed_close
= NULL
;
158 a_unfocused_pressed_close
= NULL
;
159 a_focused_unpressed_desk
= NULL
;
160 a_focused_pressed_desk
= NULL
;
161 a_unfocused_unpressed_desk
= NULL
;
162 a_unfocused_pressed_desk
= NULL
;
163 a_focused_unpressed_iconify
= NULL
;
164 a_focused_pressed_iconify
= NULL
;
165 a_unfocused_unpressed_iconify
= NULL
;
166 a_unfocused_pressed_iconify
= NULL
;
167 a_focused_grip
= appearance_new(Surface_Planar
, 0);
168 a_unfocused_grip
= appearance_new(Surface_Planar
, 0);
169 a_focused_title
= appearance_new(Surface_Planar
, 0);
170 a_unfocused_title
= appearance_new(Surface_Planar
, 0);
171 a_focused_label
= appearance_new(Surface_Planar
, 1);
172 a_unfocused_label
= appearance_new(Surface_Planar
, 1);
173 a_icon
= appearance_new(Surface_Planar
, 0);//1);
174 a_focused_handle
= appearance_new(Surface_Planar
, 0);
175 a_unfocused_handle
= appearance_new(Surface_Planar
, 0);
182 if (s_b_color
!= NULL
) color_free(s_b_color
);
183 if (s_cb_unfocused_color
!= NULL
) color_free(s_cb_unfocused_color
);
184 if (s_cb_focused_color
!= NULL
) color_free(s_cb_focused_color
);
185 if (s_title_unfocused_color
!= NULL
) color_free(s_title_unfocused_color
);
186 if (s_title_focused_color
!= NULL
) color_free(s_title_focused_color
);
187 if (s_titlebut_unfocused_color
!= NULL
)
188 color_free(s_titlebut_unfocused_color
);
189 if (s_titlebut_focused_color
!= NULL
)
190 color_free(s_titlebut_focused_color
);
192 if (s_max_mask
!= NULL
) pixmap_mask_free(s_max_mask
);
193 if (s_desk_mask
!= NULL
) pixmap_mask_free(s_desk_mask
);
194 if (s_icon_mask
!= NULL
) pixmap_mask_free(s_icon_mask
);
195 if (s_close_mask
!= NULL
) pixmap_mask_free(s_close_mask
);
197 if (s_winfont
!= NULL
) font_close(s_winfont
);
199 appearance_free(a_focused_unpressed_max
);
200 appearance_free(a_focused_pressed_max
);
201 appearance_free(a_unfocused_unpressed_max
);
202 appearance_free(a_unfocused_pressed_max
);
203 if (a_focused_unpressed_close
!= NULL
)
204 appearance_free(a_focused_unpressed_close
);
205 if (a_focused_pressed_close
!= NULL
)
206 appearance_free(a_focused_pressed_close
);
207 if (a_unfocused_unpressed_close
!= NULL
)
208 appearance_free(a_unfocused_unpressed_close
);
209 if (a_unfocused_pressed_close
!= NULL
)
210 appearance_free(a_unfocused_pressed_close
);
211 if (a_focused_unpressed_desk
!= NULL
)
212 appearance_free(a_focused_unpressed_desk
);
213 if (a_focused_pressed_desk
!= NULL
)
214 appearance_free(a_focused_pressed_desk
);
215 if (a_unfocused_unpressed_desk
!= NULL
)
216 appearance_free(a_unfocused_unpressed_desk
);
217 if (a_unfocused_pressed_desk
!= NULL
)
218 appearance_free(a_unfocused_pressed_desk
);
219 if (a_focused_unpressed_iconify
!= NULL
)
220 appearance_free(a_focused_unpressed_iconify
);
221 if (a_focused_pressed_iconify
!= NULL
)
222 appearance_free(a_focused_pressed_iconify
);
223 if (a_unfocused_unpressed_iconify
!= NULL
)
224 appearance_free(a_unfocused_unpressed_iconify
);
225 if (a_unfocused_pressed_iconify
!= NULL
)
226 appearance_free(a_unfocused_pressed_iconify
);
227 appearance_free(a_focused_grip
);
228 appearance_free(a_unfocused_grip
);
229 appearance_free(a_focused_title
);
230 appearance_free(a_unfocused_title
);
231 appearance_free(a_focused_label
);
232 appearance_free(a_unfocused_label
);
233 appearance_free(a_icon
);
234 appearance_free(a_focused_handle
);
235 appearance_free(a_unfocused_handle
);
238 static Window
createWindow(Window parent
, unsigned long mask
,
239 XSetWindowAttributes
*attrib
)
241 /* XXX DONT USE THE DEFAULT SHIT */
242 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
243 DefaultDepth(ob_display
, ob_screen
), InputOutput
,
244 DefaultVisual(ob_display
, ob_screen
),
251 XSetWindowAttributes attrib
;
255 self
= g_new(ObFrame
, 1);
257 self
->frame
.visible
= FALSE
;
259 /* create all of the decor windows */
260 mask
= CWOverrideRedirect
| CWEventMask
;
261 attrib
.event_mask
= FRAME_EVENTMASK
;
262 attrib
.override_redirect
= TRUE
;
263 self
->frame
.window
= createWindow(ob_root
, mask
, &attrib
);
266 self
->frame
.plate
= createWindow(self
->frame
.window
, mask
, &attrib
);
269 attrib
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
|
270 ButtonMotionMask
| ExposureMask
);
271 self
->title
= createWindow(self
->frame
.window
, mask
, &attrib
);
272 self
->label
= createWindow(self
->title
, mask
, &attrib
);
273 self
->max
= createWindow(self
->title
, mask
, &attrib
);
274 self
->close
= createWindow(self
->title
, mask
, &attrib
);
275 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
276 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
277 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
278 self
->handle
= createWindow(self
->frame
.window
, mask
, &attrib
);
280 attrib
.cursor
= ob_cursors
.ll_angle
;
281 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
282 attrib
.cursor
= ob_cursors
.lr_angle
;
283 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
285 /* the other stuff is shown based on decor settings */
286 XMapWindow(ob_display
, self
->frame
.plate
);
287 XMapWindow(ob_display
, self
->lgrip
);
288 XMapWindow(ob_display
, self
->rgrip
);
289 XMapWindow(ob_display
, self
->label
);
291 /* set colors/appearance/sizes for stuff that doesn't change */
292 XSetWindowBorder(ob_display
, self
->frame
.window
, s_b_color
->pixel
);
293 XSetWindowBorder(ob_display
, self
->label
, s_b_color
->pixel
);
294 XSetWindowBorder(ob_display
, self
->rgrip
, s_b_color
->pixel
);
295 XSetWindowBorder(ob_display
, self
->lgrip
, s_b_color
->pixel
);
297 XResizeWindow(ob_display
, self
->max
, BUTTON_SIZE
, BUTTON_SIZE
);
298 XResizeWindow(ob_display
, self
->iconify
, BUTTON_SIZE
, BUTTON_SIZE
);
299 XResizeWindow(ob_display
, self
->icon
, BUTTON_SIZE
, BUTTON_SIZE
);
300 XResizeWindow(ob_display
, self
->close
, BUTTON_SIZE
, BUTTON_SIZE
);
301 XResizeWindow(ob_display
, self
->desk
, BUTTON_SIZE
, BUTTON_SIZE
);
302 XResizeWindow(ob_display
, self
->lgrip
, GRIP_WIDTH
, s_handle_height
);
303 XResizeWindow(ob_display
, self
->rgrip
, GRIP_WIDTH
, s_handle_height
);
305 /* set up the dynamic appearances */
306 self
->a_unfocused_title
= appearance_copy(a_unfocused_title
);
307 self
->a_focused_title
= appearance_copy(a_focused_title
);
308 self
->a_unfocused_label
= appearance_copy(a_unfocused_label
);
309 self
->a_focused_label
= appearance_copy(a_focused_label
);
310 self
->a_unfocused_handle
= appearance_copy(a_unfocused_handle
);
311 self
->a_focused_handle
= appearance_copy(a_focused_handle
);
312 self
->a_icon
= appearance_copy(a_icon
);
314 self
->max_press
= self
->close_press
= self
->desk_press
=
315 self
->iconify_press
= FALSE
;
320 static void frame_free(ObFrame
*self
)
322 appearance_free(self
->a_unfocused_title
);
323 appearance_free(self
->a_focused_title
);
324 appearance_free(self
->a_unfocused_label
);
325 appearance_free(self
->a_focused_label
);
326 appearance_free(self
->a_unfocused_handle
);
327 appearance_free(self
->a_focused_handle
);
328 appearance_free(self
->a_icon
);
330 XDestroyWindow(ob_display
, self
->frame
.window
);
335 void frame_show(ObFrame
*self
)
337 if (!self
->frame
.visible
) {
338 self
->frame
.visible
= TRUE
;
339 XMapWindow(ob_display
, self
->frame
.window
);
343 void frame_hide(ObFrame
*self
)
345 if (self
->frame
.visible
) {
346 self
->frame
.visible
= FALSE
;
347 self
->frame
.client
->ignore_unmaps
++;
348 XUnmapWindow(ob_display
, self
->frame
.window
);
352 void frame_adjust_shape(ObFrame
*self
)
358 if (!self
->frame
.client
->shaped
) {
359 /* clear the shape on the frame window */
360 XShapeCombineMask(ob_display
, self
->frame
.window
, ShapeBounding
,
361 self
->innersize
.left
,
365 /* make the frame's shape match the clients */
366 XShapeCombineShape(ob_display
, self
->frame
.window
, ShapeBounding
,
367 self
->innersize
.left
,
369 self
->frame
.client
->window
,
370 ShapeBounding
, ShapeSet
);
373 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
374 xrect
[0].x
= -s_bevel
;
375 xrect
[0].y
= -s_bevel
;
376 xrect
[0].width
= self
->width
+ self
->bwidth
* 2;
377 xrect
[0].height
= TITLE_HEIGHT
+
382 if (self
->frame
.client
->decorations
& Decor_Handle
) {
383 xrect
[1].x
= -s_bevel
;
384 xrect
[1].y
= HANDLE_Y(self
);
385 xrect
[1].width
= self
->width
+ self
->bwidth
* 2;
386 xrect
[1].height
= s_handle_height
+
391 XShapeCombineRectangles(ob_display
, self
->frame
.window
,
392 ShapeBounding
, 0, 0, xrect
, num
,
393 ShapeUnion
, Unsorted
);
398 void frame_adjust_size(ObFrame
*self
)
400 if (self
->frame
.client
->decorations
& Decor_Border
) {
401 self
->bwidth
= s_bwidth
;
402 self
->cbwidth
= s_cbwidth
;
404 self
->bwidth
= self
->cbwidth
= 0;
406 STRUT_SET(self
->innersize
, self
->cbwidth
, self
->cbwidth
,
407 self
->cbwidth
, self
->cbwidth
);
408 self
->width
= self
->frame
.client
->area
.width
+ self
->cbwidth
* 2;
409 g_assert(self
->width
> 0);
411 /* set border widths */
412 XSetWindowBorderWidth(ob_display
, self
->frame
.plate
, self
->cbwidth
);
413 XSetWindowBorderWidth(ob_display
, self
->frame
.window
, self
->bwidth
);
414 XSetWindowBorderWidth(ob_display
, self
->title
, self
->bwidth
);
415 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->bwidth
);
416 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->bwidth
);
417 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->bwidth
);
419 /* position/size and map/unmap all the windows */
421 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
422 XMoveResizeWindow(ob_display
, self
->title
,
423 -self
->bwidth
, -self
->bwidth
,
424 self
->width
, TITLE_HEIGHT
);
425 self
->innersize
.top
+= TITLE_HEIGHT
+ self
->bwidth
;
426 XMapWindow(ob_display
, self
->title
);
428 /* layout the title bar elements */
431 XUnmapWindow(ob_display
, self
->title
);
432 /* make all the titlebar stuff not render */
433 self
->frame
.client
->decorations
&= ~(Decor_Icon
| Decor_Iconify
|
434 Decor_Maximize
| Decor_Close
|
438 if (self
->frame
.client
->decorations
& Decor_Handle
) {
439 XMoveResizeWindow(ob_display
, self
->handle
,
440 -self
->bwidth
, HANDLE_Y(self
),
441 self
->width
, s_handle_height
);
442 XMoveWindow(ob_display
, self
->lgrip
,
443 -self
->bwidth
, -self
->bwidth
);
444 XMoveWindow(ob_display
, self
->rgrip
,
445 -self
->bwidth
+ self
->width
-
446 GRIP_WIDTH
, -self
->bwidth
);
447 self
->innersize
.bottom
+= s_handle_height
+
449 XMapWindow(ob_display
, self
->handle
);
451 XUnmapWindow(ob_display
, self
->handle
);
453 XResizeWindow(ob_display
, self
->frame
.window
, self
->width
,
454 (self
->frame
.client
->shaded
? TITLE_HEIGHT
:
455 self
->innersize
.top
+ self
->innersize
.bottom
+
456 self
->frame
.client
->area
.height
));
458 /* do this in two steps because clients whose gravity is set to
459 'Static' don't end up getting moved at all with an XMoveResizeWindow */
460 XMoveWindow(ob_display
, self
->frame
.plate
,
461 self
->innersize
.left
- self
->cbwidth
,
462 self
->innersize
.top
- self
->cbwidth
);
463 XResizeWindow(ob_display
, self
->frame
.plate
,
464 self
->frame
.client
->area
.width
,
465 self
->frame
.client
->area
.height
);
467 STRUT_SET(self
->frame
.size
,
468 self
->innersize
.left
+ self
->bwidth
,
469 self
->innersize
.top
+ self
->bwidth
,
470 self
->innersize
.right
+ self
->bwidth
,
471 self
->innersize
.bottom
+ self
->bwidth
);
473 RECT_SET_SIZE(self
->frame
.area
,
474 self
->frame
.client
->area
.width
+
475 self
->frame
.size
.left
+ self
->frame
.size
.right
,
476 self
->frame
.client
->area
.height
+
477 self
->frame
.size
.top
+ self
->frame
.size
.bottom
);
481 frame_adjust_shape(self
);
484 void frame_adjust_position(ObFrame
*self
)
486 self
->frame
.area
.x
= self
->frame
.client
->area
.x
;
487 self
->frame
.area
.y
= self
->frame
.client
->area
.y
;
488 frame_client_gravity((Frame
*)self
,
489 &self
->frame
.area
.x
, &self
->frame
.area
.y
);
490 XMoveWindow(ob_display
, self
->frame
.window
,
491 self
->frame
.area
.x
, self
->frame
.area
.y
);
494 void frame_adjust_state(ObFrame
*self
)
500 void frame_adjust_focus(ObFrame
*self
)
505 void frame_adjust_title(ObFrame
*self
)
510 void frame_adjust_icon(ObFrame
*self
)
515 void frame_grab_client(ObFrame
*self
, Client
*client
)
517 self
->frame
.client
= client
;
519 /* reparent the client to the frame */
520 XReparentWindow(ob_display
, client
->window
, self
->frame
.plate
, 0, 0);
522 When reparenting the client window, it is usually not mapped yet, since
523 this occurs from a MapRequest. However, in the case where Openbox is
524 starting up, the window is already mapped, so we'll see unmap events for
525 it. There are 2 unmap events generated that we see, one with the 'event'
526 member set the root window, and one set to the client, but both get
527 handled and need to be ignored.
529 if (ob_state
== State_Starting
)
530 client
->ignore_unmaps
+= 2;
532 /* select the event mask on the client's parent (to receive config/map
533 req's) the ButtonPress is to catch clicks on the client border */
534 XSelectInput(ob_display
, self
->frame
.plate
, PLATE_EVENTMASK
);
536 /* map the client so it maps when the frame does */
537 XMapWindow(ob_display
, client
->window
);
539 frame_adjust_size(self
);
540 frame_adjust_position(self
);
542 /* set all the windows for the frame in the client_map */
543 g_hash_table_insert(client_map
, (gpointer
)self
->frame
.window
, client
);
544 g_hash_table_insert(client_map
, (gpointer
)self
->frame
.plate
, client
);
545 g_hash_table_insert(client_map
, (gpointer
)self
->title
, client
);
546 g_hash_table_insert(client_map
, (gpointer
)self
->label
, client
);
547 g_hash_table_insert(client_map
, (gpointer
)self
->max
, client
);
548 g_hash_table_insert(client_map
, (gpointer
)self
->close
, client
);
549 g_hash_table_insert(client_map
, (gpointer
)self
->desk
, client
);
550 g_hash_table_insert(client_map
, (gpointer
)self
->icon
, client
);
551 g_hash_table_insert(client_map
, (gpointer
)self
->iconify
, client
);
552 g_hash_table_insert(client_map
, (gpointer
)self
->handle
, client
);
553 g_hash_table_insert(client_map
, (gpointer
)self
->lgrip
, client
);
554 g_hash_table_insert(client_map
, (gpointer
)self
->rgrip
, client
);
557 void frame_release_client(ObFrame
*self
, Client
*client
)
561 g_assert(self
->frame
.client
== client
);
563 /* check if the app has already reparented its window away */
564 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
565 ReparentNotify
, &ev
)) {
566 XPutBackEvent(ob_display
, &ev
);
567 /* re-map the window since the unmanaging process unmaps it */
568 XMapWindow(ob_display
, client
->window
);
570 /* according to the ICCCM - if the client doesn't reparent itself,
571 then we will reparent the window to root for them */
572 XReparentWindow(ob_display
, client
->window
, ob_root
,
577 /* remove all the windows for the frame from the client_map */
578 g_hash_table_remove(client_map
, (gpointer
)self
->frame
.window
);
579 g_hash_table_remove(client_map
, (gpointer
)self
->frame
.plate
);
580 g_hash_table_remove(client_map
, (gpointer
)self
->title
);
581 g_hash_table_remove(client_map
, (gpointer
)self
->label
);
582 g_hash_table_remove(client_map
, (gpointer
)self
->max
);
583 g_hash_table_remove(client_map
, (gpointer
)self
->close
);
584 g_hash_table_remove(client_map
, (gpointer
)self
->desk
);
585 g_hash_table_remove(client_map
, (gpointer
)self
->icon
);
586 g_hash_table_remove(client_map
, (gpointer
)self
->iconify
);
587 g_hash_table_remove(client_map
, (gpointer
)self
->handle
);
588 g_hash_table_remove(client_map
, (gpointer
)self
->lgrip
);
589 g_hash_table_remove(client_map
, (gpointer
)self
->rgrip
);
594 static void layout_title(ObFrame
*self
)
598 gboolean n
, d
, i
, l
, m
,c
;
600 n
= d
= i
= l
= m
= c
= FALSE
;
602 /* figure out whats being shown, and the width of the label */
603 self
->label_width
= self
->width
- (s_bevel
+ 1) * 2;
604 for (lc
= themerc_titlebar_layout
; *lc
!= '\0'; ++lc
) {
607 if (!(self
->frame
.client
->decorations
& Decor_Icon
)) break;
609 self
->label_width
-= BUTTON_SIZE
+ s_bevel
+ 1;
612 if (!(self
->frame
.client
->decorations
& Decor_AllDesktops
)) break;
614 self
->label_width
-= BUTTON_SIZE
+ s_bevel
+ 1;
617 if (!(self
->frame
.client
->decorations
& Decor_Iconify
)) break;
619 self
->label_width
-= BUTTON_SIZE
+ s_bevel
+ 1;
625 if (!(self
->frame
.client
->decorations
& Decor_Maximize
)) break;
627 self
->label_width
-= BUTTON_SIZE
+ s_bevel
+ 1;
630 if (!(self
->frame
.client
->decorations
& Decor_Close
)) break;
632 self
->label_width
-= BUTTON_SIZE
+ s_bevel
+ 1;
636 if (self
->label_width
< 1) self
->label_width
= 1;
638 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
642 self
->frame
.client
->decorations
&= ~Decor_Icon
;
643 XUnmapWindow(ob_display
, self
->icon
);
647 self
->frame
.client
->decorations
&= ~Decor_AllDesktops
;
648 XUnmapWindow(ob_display
, self
->desk
);
652 self
->frame
.client
->decorations
&= ~Decor_Iconify
;
653 XUnmapWindow(ob_display
, self
->iconify
);
657 XUnmapWindow(ob_display
, self
->label
);
661 self
->frame
.client
->decorations
&= ~Decor_Maximize
;
662 XUnmapWindow(ob_display
, self
->max
);
666 self
->frame
.client
->decorations
&= ~Decor_Close
;
667 XUnmapWindow(ob_display
, self
->close
);
672 for (lc
= themerc_titlebar_layout
; *lc
!= '\0'; ++lc
) {
677 XMapWindow(ob_display
, self
->icon
);
678 XMoveWindow(ob_display
, self
->icon
, x
, s_bevel
+ 1);
679 x
+= BUTTON_SIZE
+ s_bevel
+ 1;
684 XMapWindow(ob_display
, self
->desk
);
685 XMoveWindow(ob_display
, self
->desk
, x
, s_bevel
+ 1);
686 x
+= BUTTON_SIZE
+ s_bevel
+ 1;
691 XMapWindow(ob_display
, self
->iconify
);
692 XMoveWindow(ob_display
, self
->iconify
, x
, s_bevel
+ 1);
693 x
+= BUTTON_SIZE
+ s_bevel
+ 1;
698 XMapWindow(ob_display
, self
->label
);
699 XMoveWindow(ob_display
, self
->label
, x
, s_bevel
);
700 x
+= self
->label_width
+ s_bevel
+ 1;
705 XMapWindow(ob_display
, self
->max
);
706 XMoveWindow(ob_display
, self
->max
, x
, s_bevel
+ 1);
707 x
+= BUTTON_SIZE
+ s_bevel
+ 1;
712 XMapWindow(ob_display
, self
->close
);
713 XMoveWindow(ob_display
, self
->close
, x
, s_bevel
+ 1);
714 x
+= BUTTON_SIZE
+ s_bevel
+ 1;
720 static void render(ObFrame
*self
)
722 if (self
->frame
.client
->focused
) {
723 XSetWindowBorder(ob_display
, self
->frame
.plate
,
724 s_cb_focused_color
->pixel
);
726 XSetWindowBorder(ob_display
, self
->frame
.plate
,
727 s_cb_unfocused_color
->pixel
);
730 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
731 paint(self
->title
, (self
->frame
.client
->focused
?
732 self
->a_focused_title
:
733 self
->a_unfocused_title
),
734 self
->width
, TITLE_HEIGHT
);
738 render_iconify(self
);
743 if (self
->frame
.client
->decorations
& Decor_Handle
) {
744 paint(self
->handle
, (self
->frame
.client
->focused
?
745 self
->a_focused_handle
:
746 self
->a_unfocused_handle
),
747 HANDLE_WIDTH(self
), s_handle_height
);
748 paint(self
->lgrip
, (self
->frame
.client
->focused
?
751 GRIP_WIDTH
, s_handle_height
);
752 paint(self
->rgrip
, (self
->frame
.client
->focused
?
755 GRIP_WIDTH
, s_handle_height
);
759 static void render_label(ObFrame
*self
)
763 if (self
->label_x
< 0) return;
765 a
= (self
->frame
.client
->focused
?
766 self
->a_focused_label
: self
->a_focused_label
);
768 /* set the texture's text! */
769 a
->texture
[0].data
.text
.string
= self
->frame
.client
->title
;
771 paint(self
->label
, a
, self
->label_width
, LABEL_HEIGHT
);
774 static void render_icon(ObFrame
*self
)
776 if (self
->icon_x
< 0) return;
778 /* XXX set the texture's icon picture! */
779 paint(self
->icon
, self
->a_icon
, BUTTON_SIZE
, BUTTON_SIZE
);
782 static void render_max(ObFrame
*self
)
784 gboolean press
= self
->max_press
||
785 self
->frame
.client
->max_vert
|| self
->frame
.client
->max_horz
;
787 if (self
->max_x
< 0) return;
789 paint(self
->max
, (self
->frame
.client
->focused
?
791 a_focused_pressed_max
:
792 a_focused_unpressed_max
) :
794 a_unfocused_pressed_max
:
795 a_unfocused_unpressed_max
)),
796 BUTTON_SIZE
, BUTTON_SIZE
);
799 static void render_iconify(ObFrame
*self
)
801 if (self
->iconify_x
< 0) return;
803 paint(self
->iconify
, (self
->frame
.client
->focused
?
804 (self
->iconify_press
?
805 a_focused_pressed_iconify
:
806 a_focused_unpressed_iconify
) :
807 (self
->iconify_press
?
808 a_unfocused_pressed_iconify
:
809 a_unfocused_unpressed_iconify
)),
810 BUTTON_SIZE
, BUTTON_SIZE
);
813 static void render_desk(ObFrame
*self
)
815 gboolean press
= self
->desk_press
||
816 self
->frame
.client
->desktop
== DESKTOP_ALL
;
818 if (self
->desk_x
< 0) return;
820 paint(self
->desk
, (self
->frame
.client
->focused
?
822 a_focused_pressed_desk
:
823 a_focused_unpressed_desk
) :
825 a_unfocused_pressed_desk
:
826 a_unfocused_unpressed_desk
)),
827 BUTTON_SIZE
, BUTTON_SIZE
);
830 static void render_close(ObFrame
*self
)
832 if (self
->close_x
< 0) return;
834 paint(self
->close
, (self
->frame
.client
->focused
?
836 a_focused_pressed_close
:
837 a_focused_unpressed_close
) :
839 a_unfocused_pressed_close
:
840 a_unfocused_unpressed_close
)),
841 BUTTON_SIZE
, BUTTON_SIZE
);
844 GQuark
get_context(Client
*client
, Window win
)
848 if (win
== ob_root
) return g_quark_try_string("root");
849 if (client
== NULL
) return g_quark_try_string("none");
850 if (win
== client
->window
) return g_quark_try_string("client");
852 self
= (ObFrame
*) client
->frame
;
853 if (win
== self
->frame
.window
) return g_quark_try_string("frame");
854 if (win
== self
->frame
.plate
) return g_quark_try_string("client");
855 if (win
== self
->title
) return g_quark_try_string("titlebar");
856 if (win
== self
->label
) return g_quark_try_string("titlebar");
857 if (win
== self
->handle
) return g_quark_try_string("handle");
858 if (win
== self
->lgrip
) return g_quark_try_string("blcorner");
859 if (win
== self
->rgrip
) return g_quark_try_string("brcorner");
860 if (win
== self
->max
) return g_quark_try_string("maximize");
861 if (win
== self
->iconify
) return g_quark_try_string("iconify");
862 if (win
== self
->close
) return g_quark_try_string("close");
863 if (win
== self
->icon
) return g_quark_try_string("icon");
864 if (win
== self
->desk
) return g_quark_try_string("alldesktops");
866 return g_quark_try_string("none");