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"
13 #define TITLE_HEIGHT (s_font_height + s_bevel * 2)
14 #define LABEL_HEIGHT (s_font_height)
15 #define HANDLE_Y(f) (f->innersize.top + f->frame.client->area.height + \
17 #define BUTTON_SIZE (LABEL_HEIGHT - 2)
18 #define GRIP_WIDTH (BUTTON_SIZE * 2)
19 #define HANDLE_WIDTH(f) (f->width - (GRIP_WIDTH + f->bwidth) * 2)
21 #define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
22 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask)
24 /* style settings - geometry */
30 /* style settings - colors */
32 color_rgb
*s_cb_focused_color
;
33 color_rgb
*s_cb_unfocused_color
;
35 /* global appearances */
36 Appearance
*a_focused_unpressed_max
;
37 Appearance
*a_focused_pressed_max
;
38 Appearance
*a_unfocused_unpressed_max
;
39 Appearance
*a_unfocused_pressed_max
;
40 Appearance
*a_focused_unpressed_close
;
41 Appearance
*a_focused_pressed_close
;
42 Appearance
*a_unfocused_unpressed_close
;
43 Appearance
*a_unfocused_pressed_close
;
44 Appearance
*a_focused_unpressed_desk
;
45 Appearance
*a_focused_pressed_desk
;
46 Appearance
*a_unfocused_unpressed_desk
;
47 Appearance
*a_unfocused_pressed_desk
;
48 Appearance
*a_focused_unpressed_iconify
;
49 Appearance
*a_focused_pressed_iconify
;
50 Appearance
*a_unfocused_unpressed_iconify
;
51 Appearance
*a_unfocused_pressed_iconify
;
52 Appearance
*a_focused_grip
;
53 Appearance
*a_unfocused_grip
;
54 Appearance
*a_focused_title
;
55 Appearance
*a_unfocused_title
;
56 Appearance
*a_focused_label
;
57 Appearance
*a_unfocused_label
;
58 Appearance
*a_icon
; /* always parentrelative, so no focused/unfocused */
59 Appearance
*a_focused_handle
;
60 Appearance
*a_unfocused_handle
;
62 typedef struct ObFrame
{
76 Appearance
*a_unfocused_title
;
77 Appearance
*a_focused_title
;
78 Appearance
*a_unfocused_label
;
79 Appearance
*a_focused_label
;
81 Appearance
*a_unfocused_handle
;
82 Appearance
*a_focused_handle
;
88 int width
; /* title and handle */
90 int icon_x
; /* x-position of the window icon button */
91 int label_x
; /* x-position of the window title */
92 int iconify_x
; /* x-position of the window iconify button */
93 int desk_x
; /* x-position of the window all-desktops button */
94 int max_x
; /* x-position of the window maximize button */
95 int close_x
; /* x-position of the window close button */
96 int bwidth
; /* border width */
97 int cbwidth
; /* client border width */
100 gboolean close_press
;
102 gboolean iconify_press
;
105 static void layout_title(ObFrame
*self
);
106 static void render(ObFrame
*self
);
107 static void render_label(ObFrame
*self
);
108 static void render_max(ObFrame
*self
);
109 static void render_icon(ObFrame
*self
);
110 static void render_iconify(ObFrame
*self
);
111 static void render_desk(ObFrame
*self
);
112 static void render_close(ObFrame
*self
);
116 g_quark_from_string("none");
117 g_quark_from_string("root");
118 g_quark_from_string("client");
119 g_quark_from_string("titlebar");
120 g_quark_from_string("handle");
121 g_quark_from_string("frame");
122 g_quark_from_string("blcorner");
123 g_quark_from_string("brcorner");
124 g_quark_from_string("maximize");
125 g_quark_from_string("alldesktops");
126 g_quark_from_string("iconify");
127 g_quark_from_string("icon");
128 g_quark_from_string("close");
130 s_b_color
= s_cb_unfocused_color
= s_cb_focused_color
= NULL
;
132 a_focused_unpressed_max
= appearance_new(Surface_Planar
, 0);//1);
133 a_focused_pressed_max
= appearance_new(Surface_Planar
, 0);//1);
134 a_unfocused_unpressed_max
= appearance_new(Surface_Planar
, 0);//1);
135 a_unfocused_pressed_max
= appearance_new(Surface_Planar
, 0);//1);
136 a_focused_unpressed_close
= NULL
;
137 a_focused_pressed_close
= NULL
;
138 a_unfocused_unpressed_close
= NULL
;
139 a_unfocused_pressed_close
= NULL
;
140 a_focused_unpressed_desk
= NULL
;
141 a_focused_pressed_desk
= NULL
;
142 a_unfocused_unpressed_desk
= NULL
;
143 a_unfocused_pressed_desk
= NULL
;
144 a_focused_unpressed_iconify
= NULL
;
145 a_focused_pressed_iconify
= NULL
;
146 a_unfocused_unpressed_iconify
= NULL
;
147 a_unfocused_pressed_iconify
= NULL
;
148 a_focused_grip
= appearance_new(Surface_Planar
, 0);
149 a_unfocused_grip
= appearance_new(Surface_Planar
, 0);
150 a_focused_title
= appearance_new(Surface_Planar
, 0);
151 a_unfocused_title
= appearance_new(Surface_Planar
, 0);
152 a_focused_label
= appearance_new(Surface_Planar
, 0);//1);
153 a_unfocused_label
= appearance_new(Surface_Planar
, 0);//1);
154 a_icon
= appearance_new(Surface_Planar
, 0);//1);
155 a_focused_handle
= appearance_new(Surface_Planar
, 0);
156 a_unfocused_handle
= appearance_new(Surface_Planar
, 0);
163 if (s_b_color
!= NULL
) color_free(s_b_color
);
164 if (s_cb_unfocused_color
!= NULL
) color_free(s_cb_unfocused_color
);
165 if (s_cb_focused_color
!= NULL
) color_free(s_cb_focused_color
);
167 appearance_free(a_focused_unpressed_max
);
168 appearance_free(a_focused_pressed_max
);
169 appearance_free(a_unfocused_unpressed_max
);
170 appearance_free(a_unfocused_pressed_max
);
171 if (a_focused_unpressed_close
!= NULL
)
172 appearance_free(a_focused_unpressed_close
);
173 if (a_focused_pressed_close
!= NULL
)
174 appearance_free(a_focused_pressed_close
);
175 if (a_unfocused_unpressed_close
!= NULL
)
176 appearance_free(a_unfocused_unpressed_close
);
177 if (a_unfocused_pressed_close
!= NULL
)
178 appearance_free(a_unfocused_pressed_close
);
179 if (a_focused_unpressed_desk
!= NULL
)
180 appearance_free(a_focused_unpressed_desk
);
181 if (a_focused_pressed_desk
!= NULL
)
182 appearance_free(a_focused_pressed_desk
);
183 if (a_unfocused_unpressed_desk
!= NULL
)
184 appearance_free(a_unfocused_unpressed_desk
);
185 if (a_unfocused_pressed_desk
!= NULL
)
186 appearance_free(a_unfocused_pressed_desk
);
187 if (a_focused_unpressed_iconify
!= NULL
)
188 appearance_free(a_focused_unpressed_iconify
);
189 if (a_focused_pressed_iconify
!= NULL
)
190 appearance_free(a_focused_pressed_iconify
);
191 if (a_unfocused_unpressed_iconify
!= NULL
)
192 appearance_free(a_unfocused_unpressed_iconify
);
193 if (a_unfocused_pressed_iconify
!= NULL
)
194 appearance_free(a_unfocused_pressed_iconify
);
195 appearance_free(a_focused_grip
);
196 appearance_free(a_unfocused_grip
);
197 appearance_free(a_focused_title
);
198 appearance_free(a_unfocused_title
);
199 appearance_free(a_focused_label
);
200 appearance_free(a_unfocused_label
);
201 appearance_free(a_icon
);
202 appearance_free(a_focused_handle
);
203 appearance_free(a_unfocused_handle
);
206 static Window
createWindow(Window parent
, unsigned long mask
,
207 XSetWindowAttributes
*attrib
)
209 /* XXX DONT USE THE DEFAULT SHIT */
210 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
211 DefaultDepth(ob_display
, ob_screen
), InputOutput
,
212 DefaultVisual(ob_display
, ob_screen
),
219 XSetWindowAttributes attrib
;
223 self
= g_new(ObFrame
, 1);
225 self
->frame
.visible
= FALSE
;
227 /* create all of the decor windows */
228 mask
= CWOverrideRedirect
| CWEventMask
;
229 attrib
.event_mask
= FRAME_EVENTMASK
;
230 attrib
.override_redirect
= TRUE
;
231 self
->frame
.window
= createWindow(ob_root
, mask
, &attrib
);
234 self
->frame
.plate
= createWindow(self
->frame
.window
, mask
, &attrib
);
237 attrib
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
|
238 ButtonMotionMask
| ExposureMask
);
239 self
->title
= createWindow(self
->frame
.window
, mask
, &attrib
);
240 self
->label
= createWindow(self
->title
, mask
, &attrib
);
241 self
->max
= createWindow(self
->title
, mask
, &attrib
);
242 self
->close
= createWindow(self
->title
, mask
, &attrib
);
243 self
->desk
= createWindow(self
->title
, mask
, &attrib
);
244 self
->icon
= createWindow(self
->title
, mask
, &attrib
);
245 self
->iconify
= createWindow(self
->title
, mask
, &attrib
);
246 self
->handle
= createWindow(self
->frame
.window
, mask
, &attrib
);
248 attrib
.cursor
= ob_cursors
.ll_angle
;
249 self
->lgrip
= createWindow(self
->handle
, mask
, &attrib
);
250 attrib
.cursor
= ob_cursors
.lr_angle
;
251 self
->rgrip
= createWindow(self
->handle
, mask
, &attrib
);
253 /* the other stuff is shown based on decor settings */
254 XMapWindow(ob_display
, self
->frame
.plate
);
255 XMapWindow(ob_display
, self
->lgrip
);
256 XMapWindow(ob_display
, self
->rgrip
);
257 XMapWindow(ob_display
, self
->label
);
259 /* set colors/appearance/sizes for stuff that doesn't change */
260 XSetWindowBorder(ob_display
, self
->frame
.window
, s_b_color
->pixel
);
261 XSetWindowBorder(ob_display
, self
->label
, s_b_color
->pixel
);
262 XSetWindowBorder(ob_display
, self
->rgrip
, s_b_color
->pixel
);
263 XSetWindowBorder(ob_display
, self
->lgrip
, s_b_color
->pixel
);
265 XResizeWindow(ob_display
, self
->max
, BUTTON_SIZE
, BUTTON_SIZE
);
266 XResizeWindow(ob_display
, self
->iconify
, BUTTON_SIZE
, BUTTON_SIZE
);
267 XResizeWindow(ob_display
, self
->icon
, BUTTON_SIZE
, BUTTON_SIZE
);
268 XResizeWindow(ob_display
, self
->close
, BUTTON_SIZE
, BUTTON_SIZE
);
269 XResizeWindow(ob_display
, self
->desk
, BUTTON_SIZE
, BUTTON_SIZE
);
270 XResizeWindow(ob_display
, self
->lgrip
, GRIP_WIDTH
, s_handle_height
);
271 XResizeWindow(ob_display
, self
->rgrip
, GRIP_WIDTH
, s_handle_height
);
273 /* set up the dynamic appearances */
274 self
->a_unfocused_title
= appearance_copy(a_unfocused_title
);
275 self
->a_focused_title
= appearance_copy(a_focused_title
);
276 self
->a_unfocused_label
= appearance_copy(a_unfocused_label
);
277 self
->a_focused_label
= appearance_copy(a_focused_label
);
278 self
->a_unfocused_handle
= appearance_copy(a_unfocused_handle
);
279 self
->a_focused_handle
= appearance_copy(a_focused_handle
);
280 self
->a_icon
= appearance_copy(a_icon
);
282 self
->max_press
= self
->close_press
= self
->desk_press
=
283 self
->iconify_press
= FALSE
;
288 static void frame_free(ObFrame
*self
)
290 appearance_free(self
->a_unfocused_title
);
291 appearance_free(self
->a_focused_title
);
292 appearance_free(self
->a_unfocused_label
);
293 appearance_free(self
->a_focused_label
);
294 appearance_free(self
->a_unfocused_handle
);
295 appearance_free(self
->a_focused_handle
);
296 appearance_free(self
->a_icon
);
298 XDestroyWindow(ob_display
, self
->frame
.window
);
303 void frame_show(ObFrame
*self
)
305 if (!self
->frame
.visible
) {
306 self
->frame
.visible
= TRUE
;
307 XMapWindow(ob_display
, self
->frame
.window
);
311 void frame_hide(ObFrame
*self
)
313 if (self
->frame
.visible
) {
314 self
->frame
.visible
= FALSE
;
315 self
->frame
.client
->ignore_unmaps
++;
316 XUnmapWindow(ob_display
, self
->frame
.window
);
320 void frame_adjust_shape(ObFrame
*self
)
326 if (!self
->frame
.client
->shaped
) {
327 /* clear the shape on the frame window */
328 XShapeCombineMask(ob_display
, self
->frame
.window
, ShapeBounding
,
329 self
->innersize
.left
,
333 /* make the frame's shape match the clients */
334 XShapeCombineShape(ob_display
, self
->frame
.window
, ShapeBounding
,
335 self
->innersize
.left
,
337 self
->frame
.client
->window
,
338 ShapeBounding
, ShapeSet
);
341 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
342 xrect
[0].x
= -s_bevel
;
343 xrect
[0].y
= -s_bevel
;
344 xrect
[0].width
= self
->width
+ self
->bwidth
* 2;
345 xrect
[0].height
= TITLE_HEIGHT
+
350 if (self
->frame
.client
->decorations
& Decor_Handle
) {
351 xrect
[1].x
= -s_bevel
;
352 xrect
[1].y
= HANDLE_Y(self
);
353 xrect
[1].width
= self
->width
+ self
->bwidth
* 2;
354 xrect
[1].height
= s_handle_height
+
359 XShapeCombineRectangles(ob_display
, self
->frame
.window
,
360 ShapeBounding
, 0, 0, xrect
, num
,
361 ShapeUnion
, Unsorted
);
366 void frame_adjust_size(ObFrame
*self
)
368 if (self
->frame
.client
->decorations
& Decor_Border
) {
369 self
->bwidth
= s_bwidth
;
370 self
->cbwidth
= s_cbwidth
;
372 self
->bwidth
= self
->cbwidth
= 0;
374 STRUT_SET(self
->innersize
, self
->cbwidth
, self
->cbwidth
,
375 self
->cbwidth
, self
->cbwidth
);
376 self
->width
= self
->frame
.client
->area
.width
+ self
->cbwidth
* 2;
377 g_assert(self
->width
> 0);
379 /* set border widths */
380 XSetWindowBorderWidth(ob_display
, self
->frame
.plate
, self
->cbwidth
);
381 XSetWindowBorderWidth(ob_display
, self
->frame
.window
, self
->bwidth
);
382 XSetWindowBorderWidth(ob_display
, self
->title
, self
->bwidth
);
383 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->bwidth
);
384 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->bwidth
);
385 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->bwidth
);
387 /* position/size and map/unmap all the windows */
389 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
390 XMoveResizeWindow(ob_display
, self
->title
,
391 -self
->bwidth
, -self
->bwidth
,
392 self
->width
, TITLE_HEIGHT
);
393 self
->innersize
.top
+= TITLE_HEIGHT
+ self
->bwidth
;
394 XMapWindow(ob_display
, self
->title
);
396 /* layout the title bar elements */
399 XUnmapWindow(ob_display
, self
->title
);
400 /* make all the titlebar stuff not render */
401 self
->frame
.client
->decorations
&= ~(Decor_Icon
| Decor_Iconify
|
402 Decor_Maximize
| Decor_Close
|
406 if (self
->frame
.client
->decorations
& Decor_Handle
) {
407 XMoveResizeWindow(ob_display
, self
->handle
,
408 -self
->bwidth
, HANDLE_Y(self
),
409 self
->width
, s_handle_height
);
410 XMoveWindow(ob_display
, self
->lgrip
,
411 -self
->bwidth
, -self
->bwidth
);
412 XMoveWindow(ob_display
, self
->rgrip
,
413 -self
->bwidth
+ self
->width
-
414 GRIP_WIDTH
, -self
->bwidth
);
415 self
->innersize
.bottom
+= s_handle_height
+
417 XMapWindow(ob_display
, self
->handle
);
419 XUnmapWindow(ob_display
, self
->handle
);
421 XResizeWindow(ob_display
, self
->frame
.window
, self
->width
,
422 (self
->frame
.client
->shaded
? TITLE_HEIGHT
:
423 self
->innersize
.top
+ self
->innersize
.bottom
+
424 self
->frame
.client
->area
.height
));
426 /* do this in two steps because clients whose gravity is set to
427 'Static' don't end up getting moved at all with an XMoveResizeWindow */
428 XMoveWindow(ob_display
, self
->frame
.plate
,
429 self
->innersize
.left
- self
->cbwidth
,
430 self
->innersize
.top
- self
->cbwidth
);
431 XResizeWindow(ob_display
, self
->frame
.plate
,
432 self
->frame
.client
->area
.width
,
433 self
->frame
.client
->area
.height
);
435 STRUT_SET(self
->frame
.size
,
436 self
->innersize
.left
+ self
->bwidth
,
437 self
->innersize
.top
+ self
->bwidth
,
438 self
->innersize
.right
+ self
->bwidth
,
439 self
->innersize
.bottom
+ self
->bwidth
);
441 RECT_SET_SIZE(self
->frame
.area
,
442 self
->frame
.client
->area
.width
+
443 self
->frame
.size
.left
+ self
->frame
.size
.right
,
444 self
->frame
.client
->area
.height
+
445 self
->frame
.size
.top
+ self
->frame
.size
.bottom
);
449 frame_adjust_shape(self
);
452 void frame_adjust_position(ObFrame
*self
)
454 self
->frame
.area
.x
= self
->frame
.client
->area
.x
;
455 self
->frame
.area
.y
= self
->frame
.client
->area
.y
;
456 frame_client_gravity((Frame
*)self
,
457 &self
->frame
.area
.x
, &self
->frame
.area
.y
);
458 XMoveWindow(ob_display
, self
->frame
.window
,
459 self
->frame
.area
.x
, self
->frame
.area
.y
);
462 void frame_adjust_state(ObFrame
*self
)
468 void frame_adjust_focus(ObFrame
*self
)
473 void frame_adjust_title(ObFrame
*self
)
478 void frame_adjust_icon(ObFrame
*self
)
483 void frame_grab_client(ObFrame
*self
, Client
*client
)
485 self
->frame
.client
= client
;
487 /* reparent the client to the frame */
488 XReparentWindow(ob_display
, client
->window
, self
->frame
.plate
, 0, 0);
490 When reparenting the client window, it is usually not mapped yet, since
491 this occurs from a MapRequest. However, in the case where Openbox is
492 starting up, the window is already mapped, so we'll see unmap events for
493 it. There are 2 unmap events generated that we see, one with the 'event'
494 member set the root window, and one set to the client, but both get
495 handled and need to be ignored.
497 if (ob_state
== State_Starting
)
498 client
->ignore_unmaps
+= 2;
500 /* select the event mask on the client's parent (to receive config/map
501 req's) the ButtonPress is to catch clicks on the client border */
502 XSelectInput(ob_display
, self
->frame
.plate
, PLATE_EVENTMASK
);
504 /* map the client so it maps when the frame does */
505 XMapWindow(ob_display
, client
->window
);
507 frame_adjust_size(self
);
508 frame_adjust_position(self
);
510 /* set all the windows for the frame in the client_map */
511 g_hash_table_insert(client_map
, (gpointer
)self
->frame
.window
, client
);
512 g_hash_table_insert(client_map
, (gpointer
)self
->frame
.plate
, client
);
513 g_hash_table_insert(client_map
, (gpointer
)self
->title
, client
);
514 g_hash_table_insert(client_map
, (gpointer
)self
->label
, client
);
515 g_hash_table_insert(client_map
, (gpointer
)self
->max
, client
);
516 g_hash_table_insert(client_map
, (gpointer
)self
->close
, client
);
517 g_hash_table_insert(client_map
, (gpointer
)self
->desk
, client
);
518 g_hash_table_insert(client_map
, (gpointer
)self
->icon
, client
);
519 g_hash_table_insert(client_map
, (gpointer
)self
->iconify
, client
);
520 g_hash_table_insert(client_map
, (gpointer
)self
->handle
, client
);
521 g_hash_table_insert(client_map
, (gpointer
)self
->lgrip
, client
);
522 g_hash_table_insert(client_map
, (gpointer
)self
->rgrip
, client
);
525 void frame_release_client(ObFrame
*self
, Client
*client
)
529 g_assert(self
->frame
.client
== client
);
531 /* check if the app has already reparented its window away */
532 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
533 ReparentNotify
, &ev
)) {
534 XPutBackEvent(ob_display
, &ev
);
535 /* re-map the window since the unmanaging process unmaps it */
536 XMapWindow(ob_display
, client
->window
);
538 /* according to the ICCCM - if the client doesn't reparent itself,
539 then we will reparent the window to root for them */
540 XReparentWindow(ob_display
, client
->window
, ob_root
,
545 /* remove all the windows for the frame from the client_map */
546 g_hash_table_remove(client_map
, (gpointer
)self
->frame
.window
);
547 g_hash_table_remove(client_map
, (gpointer
)self
->frame
.plate
);
548 g_hash_table_remove(client_map
, (gpointer
)self
->title
);
549 g_hash_table_remove(client_map
, (gpointer
)self
->label
);
550 g_hash_table_remove(client_map
, (gpointer
)self
->max
);
551 g_hash_table_remove(client_map
, (gpointer
)self
->close
);
552 g_hash_table_remove(client_map
, (gpointer
)self
->desk
);
553 g_hash_table_remove(client_map
, (gpointer
)self
->icon
);
554 g_hash_table_remove(client_map
, (gpointer
)self
->iconify
);
555 g_hash_table_remove(client_map
, (gpointer
)self
->handle
);
556 g_hash_table_remove(client_map
, (gpointer
)self
->lgrip
);
557 g_hash_table_remove(client_map
, (gpointer
)self
->rgrip
);
562 static void layout_title(ObFrame
*self
)
566 gboolean n
, d
, i
, l
, m
,c
;
567 n
= d
= i
= l
= m
= c
= FALSE
;
569 /* figure out whats being shown, and the width of the label */
570 self
->label_width
= self
->width
- s_bevel
* 2;
571 for (lc
= themerc_titlebar_layout
; *lc
!= '\0'; ++lc
) {
574 if (!(self
->frame
.client
->decorations
& Decor_Icon
)) break;
576 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
579 if (!(self
->frame
.client
->decorations
& Decor_AllDesktops
)) break;
581 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
584 if (!(self
->frame
.client
->decorations
& Decor_Iconify
)) break;
586 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
592 if (!(self
->frame
.client
->decorations
& Decor_Maximize
)) break;
594 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
597 if (!(self
->frame
.client
->decorations
& Decor_Close
)) break;
599 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
603 if (self
->label_width
< 1) self
->label_width
= 1;
605 XResizeWindow(ob_display
, self
->label
, self
->label_width
, s_font_height
);
608 self
->frame
.client
->decorations
&= ~Decor_Icon
;
609 XUnmapWindow(ob_display
, self
->icon
);
613 self
->frame
.client
->decorations
&= ~Decor_AllDesktops
;
614 XUnmapWindow(ob_display
, self
->desk
);
618 self
->frame
.client
->decorations
&= ~Decor_Iconify
;
619 XUnmapWindow(ob_display
, self
->iconify
);
623 XUnmapWindow(ob_display
, self
->label
);
627 self
->frame
.client
->decorations
&= ~Decor_Maximize
;
628 XUnmapWindow(ob_display
, self
->max
);
632 self
->frame
.client
->decorations
&= ~Decor_Close
;
633 XUnmapWindow(ob_display
, self
->close
);
638 for (lc
= themerc_titlebar_layout
; *lc
!= '\0'; ++lc
) {
643 XMapWindow(ob_display
, self
->icon
);
644 XMoveWindow(ob_display
, self
->icon
, x
, s_bevel
+ 1);
645 x
+= BUTTON_SIZE
+ s_bevel
;
650 XMapWindow(ob_display
, self
->desk
);
651 XMoveWindow(ob_display
, self
->desk
, x
, s_bevel
+ 1);
652 x
+= BUTTON_SIZE
+ s_bevel
;
657 XMapWindow(ob_display
, self
->iconify
);
658 XMoveWindow(ob_display
, self
->iconify
, x
, s_bevel
+ 1);
659 x
+= BUTTON_SIZE
+ s_bevel
;
664 XMapWindow(ob_display
, self
->label
);
665 XMoveWindow(ob_display
, self
->label
, x
, s_bevel
);
666 x
+= self
->label_width
+ s_bevel
;
671 XMapWindow(ob_display
, self
->max
);
672 XMoveWindow(ob_display
, self
->max
, x
, s_bevel
+ 1);
673 x
+= BUTTON_SIZE
+ s_bevel
;
678 XMapWindow(ob_display
, self
->close
);
679 XMoveWindow(ob_display
, self
->close
, x
, s_bevel
+ 1);
680 x
+= BUTTON_SIZE
+ s_bevel
;
686 static void render(ObFrame
*self
)
688 if (self
->frame
.client
->focused
) {
689 XSetWindowBorder(ob_display
, self
->frame
.plate
,
690 s_cb_focused_color
->pixel
);
692 XSetWindowBorder(ob_display
, self
->frame
.plate
,
693 s_cb_unfocused_color
->pixel
);
696 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
697 paint(self
->title
, (self
->frame
.client
->focused
?
698 self
->a_focused_title
:
699 self
->a_unfocused_title
),
700 self
->width
, TITLE_HEIGHT
);
704 render_iconify(self
);
709 if (self
->frame
.client
->decorations
& Decor_Handle
) {
710 paint(self
->handle
, (self
->frame
.client
->focused
?
711 self
->a_focused_handle
:
712 self
->a_unfocused_handle
),
713 HANDLE_WIDTH(self
), s_handle_height
);
714 paint(self
->lgrip
, (self
->frame
.client
->focused
?
717 GRIP_WIDTH
, s_handle_height
);
718 paint(self
->rgrip
, (self
->frame
.client
->focused
?
721 GRIP_WIDTH
, s_handle_height
);
725 static void render_label(ObFrame
*self
)
727 if (self
->label_x
< 0) return;
729 /* XXX set the texture's text! */
730 paint(self
->label
, (self
->frame
.client
->focused
?
731 self
->a_focused_label
:
732 self
->a_unfocused_label
),
733 self
->label_width
, LABEL_HEIGHT
);
736 static void render_icon(ObFrame
*self
)
738 if (self
->icon_x
< 0) return;
740 /* XXX set the texture's icon picture! */
741 paint(self
->icon
, self
->a_icon
, BUTTON_SIZE
, BUTTON_SIZE
);
744 static void render_max(ObFrame
*self
)
746 gboolean press
= self
->max_press
||
747 self
->frame
.client
->max_vert
|| self
->frame
.client
->max_horz
;
749 if (self
->max_x
< 0) return;
751 paint(self
->max
, (self
->frame
.client
->focused
?
753 a_focused_pressed_max
:
754 a_focused_unpressed_max
) :
756 a_unfocused_pressed_max
:
757 a_unfocused_unpressed_max
)),
758 BUTTON_SIZE
, BUTTON_SIZE
);
761 static void render_iconify(ObFrame
*self
)
763 if (self
->iconify_x
< 0) return;
765 paint(self
->iconify
, (self
->frame
.client
->focused
?
766 (self
->iconify_press
?
767 a_focused_pressed_iconify
:
768 a_focused_unpressed_iconify
) :
769 (self
->iconify_press
?
770 a_unfocused_pressed_iconify
:
771 a_unfocused_unpressed_iconify
)),
772 BUTTON_SIZE
, BUTTON_SIZE
);
775 static void render_desk(ObFrame
*self
)
777 gboolean press
= self
->desk_press
||
778 self
->frame
.client
->desktop
== DESKTOP_ALL
;
780 if (self
->desk_x
< 0) return;
782 paint(self
->desk
, (self
->frame
.client
->focused
?
784 a_focused_pressed_desk
:
785 a_focused_unpressed_desk
) :
787 a_unfocused_pressed_desk
:
788 a_unfocused_unpressed_desk
)),
789 BUTTON_SIZE
, BUTTON_SIZE
);
792 static void render_close(ObFrame
*self
)
794 if (self
->close_x
< 0) return;
796 paint(self
->close
, (self
->frame
.client
->focused
?
798 a_focused_pressed_close
:
799 a_focused_unpressed_close
) :
801 a_unfocused_pressed_close
:
802 a_unfocused_unpressed_close
)),
803 BUTTON_SIZE
, BUTTON_SIZE
);
806 GQuark
get_context(Client
*client
, Window win
)
810 if (win
== ob_root
) return g_quark_try_string("root");
811 if (client
== NULL
) return g_quark_try_string("none");
812 if (win
== client
->window
) return g_quark_try_string("client");
814 self
= (ObFrame
*) client
->frame
;
815 if (win
== self
->frame
.window
) return g_quark_try_string("frame");
816 if (win
== self
->frame
.plate
) return g_quark_try_string("client");
817 if (win
== self
->title
) return g_quark_try_string("titlebar");
818 if (win
== self
->label
) return g_quark_try_string("titlebar");
819 if (win
== self
->handle
) return g_quark_try_string("handle");
820 if (win
== self
->lgrip
) return g_quark_try_string("blcorner");
821 if (win
== self
->rgrip
) return g_quark_try_string("brcorner");
822 if (win
== self
->max
) return g_quark_try_string("maximize");
823 if (win
== self
->iconify
) return g_quark_try_string("iconify");
824 if (win
== self
->close
) return g_quark_try_string("close");
825 if (win
== self
->icon
) return g_quark_try_string("icon");
826 if (win
== self
->desk
) return g_quark_try_string("alldesktops");
828 return g_quark_try_string("none");