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"
14 #define TITLE_HEIGHT (s_winfont_height + s_bevel * 2)
15 #define LABEL_HEIGHT (s_winfont_height)
16 #define HANDLE_Y(f) (f->innersize.top + f->frame.client->area.height + \
18 #define BUTTON_SIZE (LABEL_HEIGHT - 2)
19 #define GRIP_WIDTH (BUTTON_SIZE * 2)
20 #define HANDLE_WIDTH(f) (f->width - (GRIP_WIDTH + f->bwidth) * 2)
22 #define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
23 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask)
25 /* style settings - geometry */
30 /* style settings - colors */
32 color_rgb
*s_cb_focused_color
;
33 color_rgb
*s_cb_unfocused_color
;
34 color_rgb
*s_title_focused_color
;
35 color_rgb
*s_title_unfocused_color
;
36 /* style settings - fonts */
39 int s_winfont_shadow_offset
;
42 /* global appearances */
43 Appearance
*a_focused_unpressed_max
;
44 Appearance
*a_focused_pressed_max
;
45 Appearance
*a_unfocused_unpressed_max
;
46 Appearance
*a_unfocused_pressed_max
;
47 Appearance
*a_focused_unpressed_close
;
48 Appearance
*a_focused_pressed_close
;
49 Appearance
*a_unfocused_unpressed_close
;
50 Appearance
*a_unfocused_pressed_close
;
51 Appearance
*a_focused_unpressed_desk
;
52 Appearance
*a_focused_pressed_desk
;
53 Appearance
*a_unfocused_unpressed_desk
;
54 Appearance
*a_unfocused_pressed_desk
;
55 Appearance
*a_focused_unpressed_iconify
;
56 Appearance
*a_focused_pressed_iconify
;
57 Appearance
*a_unfocused_unpressed_iconify
;
58 Appearance
*a_unfocused_pressed_iconify
;
59 Appearance
*a_focused_grip
;
60 Appearance
*a_unfocused_grip
;
61 Appearance
*a_focused_title
;
62 Appearance
*a_unfocused_title
;
63 Appearance
*a_focused_label
;
64 Appearance
*a_unfocused_label
;
65 Appearance
*a_icon
; /* always parentrelative, so no focused/unfocused */
66 Appearance
*a_focused_handle
;
67 Appearance
*a_unfocused_handle
;
69 typedef struct ObFrame
{
83 Appearance
*a_unfocused_title
;
84 Appearance
*a_focused_title
;
85 Appearance
*a_unfocused_label
;
86 Appearance
*a_focused_label
;
88 Appearance
*a_unfocused_handle
;
89 Appearance
*a_focused_handle
;
95 int width
; /* title and handle */
97 int icon_x
; /* x-position of the window icon button */
98 int label_x
; /* x-position of the window title */
99 int iconify_x
; /* x-position of the window iconify button */
100 int desk_x
; /* x-position of the window all-desktops button */
101 int max_x
; /* x-position of the window maximize button */
102 int close_x
; /* x-position of the window close button */
103 int bwidth
; /* border width */
104 int cbwidth
; /* client border width */
107 gboolean close_press
;
109 gboolean iconify_press
;
112 static void layout_title(ObFrame
*self
);
113 static void render(ObFrame
*self
);
114 static void render_label(ObFrame
*self
);
115 static void render_max(ObFrame
*self
);
116 static void render_icon(ObFrame
*self
);
117 static void render_iconify(ObFrame
*self
);
118 static void render_desk(ObFrame
*self
);
119 static void render_close(ObFrame
*self
);
123 g_quark_from_string("none");
124 g_quark_from_string("root");
125 g_quark_from_string("client");
126 g_quark_from_string("titlebar");
127 g_quark_from_string("handle");
128 g_quark_from_string("frame");
129 g_quark_from_string("blcorner");
130 g_quark_from_string("brcorner");
131 g_quark_from_string("maximize");
132 g_quark_from_string("alldesktops");
133 g_quark_from_string("iconify");
134 g_quark_from_string("icon");
135 g_quark_from_string("close");
137 s_b_color
= s_cb_unfocused_color
= s_cb_focused_color
=
138 s_title_unfocused_color
= s_title_focused_color
= NULL
;
141 a_focused_unpressed_max
= appearance_new(Surface_Planar
, 0);//1);
142 a_focused_pressed_max
= appearance_new(Surface_Planar
, 0);//1);
143 a_unfocused_unpressed_max
= appearance_new(Surface_Planar
, 0);//1);
144 a_unfocused_pressed_max
= appearance_new(Surface_Planar
, 0);//1);
145 a_focused_unpressed_close
= NULL
;
146 a_focused_pressed_close
= NULL
;
147 a_unfocused_unpressed_close
= NULL
;
148 a_unfocused_pressed_close
= NULL
;
149 a_focused_unpressed_desk
= NULL
;
150 a_focused_pressed_desk
= NULL
;
151 a_unfocused_unpressed_desk
= NULL
;
152 a_unfocused_pressed_desk
= NULL
;
153 a_focused_unpressed_iconify
= NULL
;
154 a_focused_pressed_iconify
= NULL
;
155 a_unfocused_unpressed_iconify
= NULL
;
156 a_unfocused_pressed_iconify
= NULL
;
157 a_focused_grip
= appearance_new(Surface_Planar
, 0);
158 a_unfocused_grip
= appearance_new(Surface_Planar
, 0);
159 a_focused_title
= appearance_new(Surface_Planar
, 0);
160 a_unfocused_title
= appearance_new(Surface_Planar
, 0);
161 a_focused_label
= appearance_new(Surface_Planar
, 1);
162 a_unfocused_label
= appearance_new(Surface_Planar
, 1);
163 a_icon
= appearance_new(Surface_Planar
, 0);//1);
164 a_focused_handle
= appearance_new(Surface_Planar
, 0);
165 a_unfocused_handle
= appearance_new(Surface_Planar
, 0);
172 if (s_b_color
!= NULL
) color_free(s_b_color
);
173 if (s_cb_unfocused_color
!= NULL
) color_free(s_cb_unfocused_color
);
174 if (s_cb_focused_color
!= NULL
) color_free(s_cb_focused_color
);
175 if (s_title_unfocused_color
!= NULL
) color_free(s_title_unfocused_color
);
176 if (s_title_focused_color
!= NULL
) color_free(s_title_focused_color
);
178 if (s_winfont
!= NULL
) font_close(s_winfont
);
180 appearance_free(a_focused_unpressed_max
);
181 appearance_free(a_focused_pressed_max
);
182 appearance_free(a_unfocused_unpressed_max
);
183 appearance_free(a_unfocused_pressed_max
);
184 if (a_focused_unpressed_close
!= NULL
)
185 appearance_free(a_focused_unpressed_close
);
186 if (a_focused_pressed_close
!= NULL
)
187 appearance_free(a_focused_pressed_close
);
188 if (a_unfocused_unpressed_close
!= NULL
)
189 appearance_free(a_unfocused_unpressed_close
);
190 if (a_unfocused_pressed_close
!= NULL
)
191 appearance_free(a_unfocused_pressed_close
);
192 if (a_focused_unpressed_desk
!= NULL
)
193 appearance_free(a_focused_unpressed_desk
);
194 if (a_focused_pressed_desk
!= NULL
)
195 appearance_free(a_focused_pressed_desk
);
196 if (a_unfocused_unpressed_desk
!= NULL
)
197 appearance_free(a_unfocused_unpressed_desk
);
198 if (a_unfocused_pressed_desk
!= NULL
)
199 appearance_free(a_unfocused_pressed_desk
);
200 if (a_focused_unpressed_iconify
!= NULL
)
201 appearance_free(a_focused_unpressed_iconify
);
202 if (a_focused_pressed_iconify
!= NULL
)
203 appearance_free(a_focused_pressed_iconify
);
204 if (a_unfocused_unpressed_iconify
!= NULL
)
205 appearance_free(a_unfocused_unpressed_iconify
);
206 if (a_unfocused_pressed_iconify
!= NULL
)
207 appearance_free(a_unfocused_pressed_iconify
);
208 appearance_free(a_focused_grip
);
209 appearance_free(a_unfocused_grip
);
210 appearance_free(a_focused_title
);
211 appearance_free(a_unfocused_title
);
212 appearance_free(a_focused_label
);
213 appearance_free(a_unfocused_label
);
214 appearance_free(a_icon
);
215 appearance_free(a_focused_handle
);
216 appearance_free(a_unfocused_handle
);
219 static Window
createWindow(Window parent
, unsigned long mask
,
220 XSetWindowAttributes
*attrib
)
222 /* XXX DONT USE THE DEFAULT SHIT */
223 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
224 DefaultDepth(ob_display
, ob_screen
), InputOutput
,
225 DefaultVisual(ob_display
, ob_screen
),
232 XSetWindowAttributes attrib
;
236 self
= g_new(ObFrame
, 1);
238 self
->frame
.visible
= FALSE
;
240 /* create all of the decor windows */
241 mask
= CWOverrideRedirect
| CWEventMask
;
242 attrib
.event_mask
= FRAME_EVENTMASK
;
243 attrib
.override_redirect
= TRUE
;
244 self
->frame
.window
= createWindow(ob_root
, mask
, &attrib
);
247 self
->frame
.plate
= createWindow(self
->frame
.window
, mask
, &attrib
);
250 attrib
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
|
251 ButtonMotionMask
| ExposureMask
);
252 self
->title
= createWindow(self
->frame
.window
, mask
, &attrib
);
253 self
->label
= createWindow(self
->title
, mask
, &attrib
);
254 self
->max
= createWindow(self
->title
, mask
, &attrib
);
255 self
->close
= createWindow(self
->title
, mask
, &attrib
);
256 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
257 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
258 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
259 self
->handle
= createWindow(self
->frame
.window
, mask
, &attrib
);
261 attrib
.cursor
= ob_cursors
.ll_angle
;
262 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
263 attrib
.cursor
= ob_cursors
.lr_angle
;
264 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
266 /* the other stuff is shown based on decor settings */
267 XMapWindow(ob_display
, self
->frame
.plate
);
268 XMapWindow(ob_display
, self
->lgrip
);
269 XMapWindow(ob_display
, self
->rgrip
);
270 XMapWindow(ob_display
, self
->label
);
272 /* set colors/appearance/sizes for stuff that doesn't change */
273 XSetWindowBorder(ob_display
, self
->frame
.window
, s_b_color
->pixel
);
274 XSetWindowBorder(ob_display
, self
->label
, s_b_color
->pixel
);
275 XSetWindowBorder(ob_display
, self
->rgrip
, s_b_color
->pixel
);
276 XSetWindowBorder(ob_display
, self
->lgrip
, s_b_color
->pixel
);
278 XResizeWindow(ob_display
, self
->max
, BUTTON_SIZE
, BUTTON_SIZE
);
279 XResizeWindow(ob_display
, self
->iconify
, BUTTON_SIZE
, BUTTON_SIZE
);
280 XResizeWindow(ob_display
, self
->icon
, BUTTON_SIZE
, BUTTON_SIZE
);
281 XResizeWindow(ob_display
, self
->close
, BUTTON_SIZE
, BUTTON_SIZE
);
282 XResizeWindow(ob_display
, self
->desk
, BUTTON_SIZE
, BUTTON_SIZE
);
283 XResizeWindow(ob_display
, self
->lgrip
, GRIP_WIDTH
, s_handle_height
);
284 XResizeWindow(ob_display
, self
->rgrip
, GRIP_WIDTH
, s_handle_height
);
286 /* set up the dynamic appearances */
287 self
->a_unfocused_title
= appearance_copy(a_unfocused_title
);
288 self
->a_focused_title
= appearance_copy(a_focused_title
);
289 self
->a_unfocused_label
= appearance_copy(a_unfocused_label
);
290 self
->a_focused_label
= appearance_copy(a_focused_label
);
291 self
->a_unfocused_handle
= appearance_copy(a_unfocused_handle
);
292 self
->a_focused_handle
= appearance_copy(a_focused_handle
);
293 self
->a_icon
= appearance_copy(a_icon
);
295 self
->max_press
= self
->close_press
= self
->desk_press
=
296 self
->iconify_press
= FALSE
;
301 static void frame_free(ObFrame
*self
)
303 appearance_free(self
->a_unfocused_title
);
304 appearance_free(self
->a_focused_title
);
305 appearance_free(self
->a_unfocused_label
);
306 appearance_free(self
->a_focused_label
);
307 appearance_free(self
->a_unfocused_handle
);
308 appearance_free(self
->a_focused_handle
);
309 appearance_free(self
->a_icon
);
311 XDestroyWindow(ob_display
, self
->frame
.window
);
316 void frame_show(ObFrame
*self
)
318 if (!self
->frame
.visible
) {
319 self
->frame
.visible
= TRUE
;
320 XMapWindow(ob_display
, self
->frame
.window
);
324 void frame_hide(ObFrame
*self
)
326 if (self
->frame
.visible
) {
327 self
->frame
.visible
= FALSE
;
328 self
->frame
.client
->ignore_unmaps
++;
329 XUnmapWindow(ob_display
, self
->frame
.window
);
333 void frame_adjust_shape(ObFrame
*self
)
339 if (!self
->frame
.client
->shaped
) {
340 /* clear the shape on the frame window */
341 XShapeCombineMask(ob_display
, self
->frame
.window
, ShapeBounding
,
342 self
->innersize
.left
,
346 /* make the frame's shape match the clients */
347 XShapeCombineShape(ob_display
, self
->frame
.window
, ShapeBounding
,
348 self
->innersize
.left
,
350 self
->frame
.client
->window
,
351 ShapeBounding
, ShapeSet
);
354 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
355 xrect
[0].x
= -s_bevel
;
356 xrect
[0].y
= -s_bevel
;
357 xrect
[0].width
= self
->width
+ self
->bwidth
* 2;
358 xrect
[0].height
= TITLE_HEIGHT
+
363 if (self
->frame
.client
->decorations
& Decor_Handle
) {
364 xrect
[1].x
= -s_bevel
;
365 xrect
[1].y
= HANDLE_Y(self
);
366 xrect
[1].width
= self
->width
+ self
->bwidth
* 2;
367 xrect
[1].height
= s_handle_height
+
372 XShapeCombineRectangles(ob_display
, self
->frame
.window
,
373 ShapeBounding
, 0, 0, xrect
, num
,
374 ShapeUnion
, Unsorted
);
379 void frame_adjust_size(ObFrame
*self
)
381 if (self
->frame
.client
->decorations
& Decor_Border
) {
382 self
->bwidth
= s_bwidth
;
383 self
->cbwidth
= s_cbwidth
;
385 self
->bwidth
= self
->cbwidth
= 0;
387 STRUT_SET(self
->innersize
, self
->cbwidth
, self
->cbwidth
,
388 self
->cbwidth
, self
->cbwidth
);
389 self
->width
= self
->frame
.client
->area
.width
+ self
->cbwidth
* 2;
390 g_assert(self
->width
> 0);
392 /* set border widths */
393 XSetWindowBorderWidth(ob_display
, self
->frame
.plate
, self
->cbwidth
);
394 XSetWindowBorderWidth(ob_display
, self
->frame
.window
, self
->bwidth
);
395 XSetWindowBorderWidth(ob_display
, self
->title
, self
->bwidth
);
396 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->bwidth
);
397 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->bwidth
);
398 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->bwidth
);
400 /* position/size and map/unmap all the windows */
402 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
403 XMoveResizeWindow(ob_display
, self
->title
,
404 -self
->bwidth
, -self
->bwidth
,
405 self
->width
, TITLE_HEIGHT
);
406 self
->innersize
.top
+= TITLE_HEIGHT
+ self
->bwidth
;
407 XMapWindow(ob_display
, self
->title
);
409 /* layout the title bar elements */
412 XUnmapWindow(ob_display
, self
->title
);
413 /* make all the titlebar stuff not render */
414 self
->frame
.client
->decorations
&= ~(Decor_Icon
| Decor_Iconify
|
415 Decor_Maximize
| Decor_Close
|
419 if (self
->frame
.client
->decorations
& Decor_Handle
) {
420 XMoveResizeWindow(ob_display
, self
->handle
,
421 -self
->bwidth
, HANDLE_Y(self
),
422 self
->width
, s_handle_height
);
423 XMoveWindow(ob_display
, self
->lgrip
,
424 -self
->bwidth
, -self
->bwidth
);
425 XMoveWindow(ob_display
, self
->rgrip
,
426 -self
->bwidth
+ self
->width
-
427 GRIP_WIDTH
, -self
->bwidth
);
428 self
->innersize
.bottom
+= s_handle_height
+
430 XMapWindow(ob_display
, self
->handle
);
432 XUnmapWindow(ob_display
, self
->handle
);
434 XResizeWindow(ob_display
, self
->frame
.window
, self
->width
,
435 (self
->frame
.client
->shaded
? TITLE_HEIGHT
:
436 self
->innersize
.top
+ self
->innersize
.bottom
+
437 self
->frame
.client
->area
.height
));
439 /* do this in two steps because clients whose gravity is set to
440 'Static' don't end up getting moved at all with an XMoveResizeWindow */
441 XMoveWindow(ob_display
, self
->frame
.plate
,
442 self
->innersize
.left
- self
->cbwidth
,
443 self
->innersize
.top
- self
->cbwidth
);
444 XResizeWindow(ob_display
, self
->frame
.plate
,
445 self
->frame
.client
->area
.width
,
446 self
->frame
.client
->area
.height
);
448 STRUT_SET(self
->frame
.size
,
449 self
->innersize
.left
+ self
->bwidth
,
450 self
->innersize
.top
+ self
->bwidth
,
451 self
->innersize
.right
+ self
->bwidth
,
452 self
->innersize
.bottom
+ self
->bwidth
);
454 RECT_SET_SIZE(self
->frame
.area
,
455 self
->frame
.client
->area
.width
+
456 self
->frame
.size
.left
+ self
->frame
.size
.right
,
457 self
->frame
.client
->area
.height
+
458 self
->frame
.size
.top
+ self
->frame
.size
.bottom
);
462 frame_adjust_shape(self
);
465 void frame_adjust_position(ObFrame
*self
)
467 self
->frame
.area
.x
= self
->frame
.client
->area
.x
;
468 self
->frame
.area
.y
= self
->frame
.client
->area
.y
;
469 frame_client_gravity((Frame
*)self
,
470 &self
->frame
.area
.x
, &self
->frame
.area
.y
);
471 XMoveWindow(ob_display
, self
->frame
.window
,
472 self
->frame
.area
.x
, self
->frame
.area
.y
);
475 void frame_adjust_state(ObFrame
*self
)
481 void frame_adjust_focus(ObFrame
*self
)
486 void frame_adjust_title(ObFrame
*self
)
491 void frame_adjust_icon(ObFrame
*self
)
496 void frame_grab_client(ObFrame
*self
, Client
*client
)
498 self
->frame
.client
= client
;
500 /* reparent the client to the frame */
501 XReparentWindow(ob_display
, client
->window
, self
->frame
.plate
, 0, 0);
503 When reparenting the client window, it is usually not mapped yet, since
504 this occurs from a MapRequest. However, in the case where Openbox is
505 starting up, the window is already mapped, so we'll see unmap events for
506 it. There are 2 unmap events generated that we see, one with the 'event'
507 member set the root window, and one set to the client, but both get
508 handled and need to be ignored.
510 if (ob_state
== State_Starting
)
511 client
->ignore_unmaps
+= 2;
513 /* select the event mask on the client's parent (to receive config/map
514 req's) the ButtonPress is to catch clicks on the client border */
515 XSelectInput(ob_display
, self
->frame
.plate
, PLATE_EVENTMASK
);
517 /* map the client so it maps when the frame does */
518 XMapWindow(ob_display
, client
->window
);
520 frame_adjust_size(self
);
521 frame_adjust_position(self
);
523 /* set all the windows for the frame in the client_map */
524 g_hash_table_insert(client_map
, (gpointer
)self
->frame
.window
, client
);
525 g_hash_table_insert(client_map
, (gpointer
)self
->frame
.plate
, client
);
526 g_hash_table_insert(client_map
, (gpointer
)self
->title
, client
);
527 g_hash_table_insert(client_map
, (gpointer
)self
->label
, client
);
528 g_hash_table_insert(client_map
, (gpointer
)self
->max
, client
);
529 g_hash_table_insert(client_map
, (gpointer
)self
->close
, client
);
530 g_hash_table_insert(client_map
, (gpointer
)self
->desk
, client
);
531 g_hash_table_insert(client_map
, (gpointer
)self
->icon
, client
);
532 g_hash_table_insert(client_map
, (gpointer
)self
->iconify
, client
);
533 g_hash_table_insert(client_map
, (gpointer
)self
->handle
, client
);
534 g_hash_table_insert(client_map
, (gpointer
)self
->lgrip
, client
);
535 g_hash_table_insert(client_map
, (gpointer
)self
->rgrip
, client
);
538 void frame_release_client(ObFrame
*self
, Client
*client
)
542 g_assert(self
->frame
.client
== client
);
544 /* check if the app has already reparented its window away */
545 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
546 ReparentNotify
, &ev
)) {
547 XPutBackEvent(ob_display
, &ev
);
548 /* re-map the window since the unmanaging process unmaps it */
549 XMapWindow(ob_display
, client
->window
);
551 /* according to the ICCCM - if the client doesn't reparent itself,
552 then we will reparent the window to root for them */
553 XReparentWindow(ob_display
, client
->window
, ob_root
,
558 /* remove all the windows for the frame from the client_map */
559 g_hash_table_remove(client_map
, (gpointer
)self
->frame
.window
);
560 g_hash_table_remove(client_map
, (gpointer
)self
->frame
.plate
);
561 g_hash_table_remove(client_map
, (gpointer
)self
->title
);
562 g_hash_table_remove(client_map
, (gpointer
)self
->label
);
563 g_hash_table_remove(client_map
, (gpointer
)self
->max
);
564 g_hash_table_remove(client_map
, (gpointer
)self
->close
);
565 g_hash_table_remove(client_map
, (gpointer
)self
->desk
);
566 g_hash_table_remove(client_map
, (gpointer
)self
->icon
);
567 g_hash_table_remove(client_map
, (gpointer
)self
->iconify
);
568 g_hash_table_remove(client_map
, (gpointer
)self
->handle
);
569 g_hash_table_remove(client_map
, (gpointer
)self
->lgrip
);
570 g_hash_table_remove(client_map
, (gpointer
)self
->rgrip
);
575 static void layout_title(ObFrame
*self
)
579 gboolean n
, d
, i
, l
, m
,c
;
580 n
= d
= i
= l
= m
= c
= FALSE
;
582 /* figure out whats being shown, and the width of the label */
583 self
->label_width
= self
->width
- s_bevel
* 2;
584 for (lc
= themerc_titlebar_layout
; *lc
!= '\0'; ++lc
) {
587 if (!(self
->frame
.client
->decorations
& Decor_Icon
)) break;
589 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
592 if (!(self
->frame
.client
->decorations
& Decor_AllDesktops
)) break;
594 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
597 if (!(self
->frame
.client
->decorations
& Decor_Iconify
)) break;
599 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
605 if (!(self
->frame
.client
->decorations
& Decor_Maximize
)) break;
607 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
610 if (!(self
->frame
.client
->decorations
& Decor_Close
)) break;
612 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
616 if (self
->label_width
< 1) self
->label_width
= 1;
618 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
622 self
->frame
.client
->decorations
&= ~Decor_Icon
;
623 XUnmapWindow(ob_display
, self
->icon
);
627 self
->frame
.client
->decorations
&= ~Decor_AllDesktops
;
628 XUnmapWindow(ob_display
, self
->desk
);
632 self
->frame
.client
->decorations
&= ~Decor_Iconify
;
633 XUnmapWindow(ob_display
, self
->iconify
);
637 XUnmapWindow(ob_display
, self
->label
);
641 self
->frame
.client
->decorations
&= ~Decor_Maximize
;
642 XUnmapWindow(ob_display
, self
->max
);
646 self
->frame
.client
->decorations
&= ~Decor_Close
;
647 XUnmapWindow(ob_display
, self
->close
);
652 for (lc
= themerc_titlebar_layout
; *lc
!= '\0'; ++lc
) {
657 XMapWindow(ob_display
, self
->icon
);
658 XMoveWindow(ob_display
, self
->icon
, x
, s_bevel
+ 1);
659 x
+= BUTTON_SIZE
+ s_bevel
;
664 XMapWindow(ob_display
, self
->desk
);
665 XMoveWindow(ob_display
, self
->desk
, x
, s_bevel
+ 1);
666 x
+= BUTTON_SIZE
+ s_bevel
;
671 XMapWindow(ob_display
, self
->iconify
);
672 XMoveWindow(ob_display
, self
->iconify
, x
, s_bevel
+ 1);
673 x
+= BUTTON_SIZE
+ s_bevel
;
678 XMapWindow(ob_display
, self
->label
);
679 XMoveWindow(ob_display
, self
->label
, x
, s_bevel
);
680 x
+= self
->label_width
+ s_bevel
;
685 XMapWindow(ob_display
, self
->max
);
686 XMoveWindow(ob_display
, self
->max
, x
, s_bevel
+ 1);
687 x
+= BUTTON_SIZE
+ s_bevel
;
692 XMapWindow(ob_display
, self
->close
);
693 XMoveWindow(ob_display
, self
->close
, x
, s_bevel
+ 1);
694 x
+= BUTTON_SIZE
+ s_bevel
;
700 static void render(ObFrame
*self
)
702 if (self
->frame
.client
->focused
) {
703 XSetWindowBorder(ob_display
, self
->frame
.plate
,
704 s_cb_focused_color
->pixel
);
706 XSetWindowBorder(ob_display
, self
->frame
.plate
,
707 s_cb_unfocused_color
->pixel
);
710 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
711 paint(self
->title
, (self
->frame
.client
->focused
?
712 self
->a_focused_title
:
713 self
->a_unfocused_title
),
714 self
->width
, TITLE_HEIGHT
);
718 render_iconify(self
);
723 if (self
->frame
.client
->decorations
& Decor_Handle
) {
724 paint(self
->handle
, (self
->frame
.client
->focused
?
725 self
->a_focused_handle
:
726 self
->a_unfocused_handle
),
727 HANDLE_WIDTH(self
), s_handle_height
);
728 paint(self
->lgrip
, (self
->frame
.client
->focused
?
731 GRIP_WIDTH
, s_handle_height
);
732 paint(self
->rgrip
, (self
->frame
.client
->focused
?
735 GRIP_WIDTH
, s_handle_height
);
739 static void render_label(ObFrame
*self
)
743 if (self
->label_x
< 0) return;
745 a
= (self
->frame
.client
->focused
?
746 self
->a_focused_label
: self
->a_focused_label
);
748 /* set the texture's text! */
749 a
->texture
[0].data
.text
.string
= self
->frame
.client
->title
;
751 paint(self
->label
, a
, self
->label_width
, LABEL_HEIGHT
);
754 static void render_icon(ObFrame
*self
)
756 if (self
->icon_x
< 0) return;
758 /* XXX set the texture's icon picture! */
759 paint(self
->icon
, self
->a_icon
, BUTTON_SIZE
, BUTTON_SIZE
);
762 static void render_max(ObFrame
*self
)
764 gboolean press
= self
->max_press
||
765 self
->frame
.client
->max_vert
|| self
->frame
.client
->max_horz
;
767 if (self
->max_x
< 0) return;
769 paint(self
->max
, (self
->frame
.client
->focused
?
771 a_focused_pressed_max
:
772 a_focused_unpressed_max
) :
774 a_unfocused_pressed_max
:
775 a_unfocused_unpressed_max
)),
776 BUTTON_SIZE
, BUTTON_SIZE
);
779 static void render_iconify(ObFrame
*self
)
781 if (self
->iconify_x
< 0) return;
783 paint(self
->iconify
, (self
->frame
.client
->focused
?
784 (self
->iconify_press
?
785 a_focused_pressed_iconify
:
786 a_focused_unpressed_iconify
) :
787 (self
->iconify_press
?
788 a_unfocused_pressed_iconify
:
789 a_unfocused_unpressed_iconify
)),
790 BUTTON_SIZE
, BUTTON_SIZE
);
793 static void render_desk(ObFrame
*self
)
795 gboolean press
= self
->desk_press
||
796 self
->frame
.client
->desktop
== DESKTOP_ALL
;
798 if (self
->desk_x
< 0) return;
800 paint(self
->desk
, (self
->frame
.client
->focused
?
802 a_focused_pressed_desk
:
803 a_focused_unpressed_desk
) :
805 a_unfocused_pressed_desk
:
806 a_unfocused_unpressed_desk
)),
807 BUTTON_SIZE
, BUTTON_SIZE
);
810 static void render_close(ObFrame
*self
)
812 if (self
->close_x
< 0) return;
814 paint(self
->close
, (self
->frame
.client
->focused
?
816 a_focused_pressed_close
:
817 a_focused_unpressed_close
) :
819 a_unfocused_pressed_close
:
820 a_unfocused_unpressed_close
)),
821 BUTTON_SIZE
, BUTTON_SIZE
);
824 GQuark
get_context(Client
*client
, Window win
)
828 if (win
== ob_root
) return g_quark_try_string("root");
829 if (client
== NULL
) return g_quark_try_string("none");
830 if (win
== client
->window
) return g_quark_try_string("client");
832 self
= (ObFrame
*) client
->frame
;
833 if (win
== self
->frame
.window
) return g_quark_try_string("frame");
834 if (win
== self
->frame
.plate
) return g_quark_try_string("client");
835 if (win
== self
->title
) return g_quark_try_string("titlebar");
836 if (win
== self
->label
) return g_quark_try_string("titlebar");
837 if (win
== self
->handle
) return g_quark_try_string("handle");
838 if (win
== self
->lgrip
) return g_quark_try_string("blcorner");
839 if (win
== self
->rgrip
) return g_quark_try_string("brcorner");
840 if (win
== self
->max
) return g_quark_try_string("maximize");
841 if (win
== self
->iconify
) return g_quark_try_string("iconify");
842 if (win
== self
->close
) return g_quark_try_string("close");
843 if (win
== self
->icon
) return g_quark_try_string("icon");
844 if (win
== self
->desk
) return g_quark_try_string("alldesktops");
846 return g_quark_try_string("none");