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
;
599 n
= d
= i
= l
= m
= c
= FALSE
;
601 /* figure out whats being shown, and the width of the label */
602 self
->label_width
= self
->width
- s_bevel
* 2;
603 for (lc
= themerc_titlebar_layout
; *lc
!= '\0'; ++lc
) {
606 if (!(self
->frame
.client
->decorations
& Decor_Icon
)) break;
608 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
611 if (!(self
->frame
.client
->decorations
& Decor_AllDesktops
)) break;
613 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
616 if (!(self
->frame
.client
->decorations
& Decor_Iconify
)) break;
618 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
624 if (!(self
->frame
.client
->decorations
& Decor_Maximize
)) break;
626 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
629 if (!(self
->frame
.client
->decorations
& Decor_Close
)) break;
631 self
->label_width
-= BUTTON_SIZE
+ s_bevel
;
635 if (self
->label_width
< 1) self
->label_width
= 1;
637 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
641 self
->frame
.client
->decorations
&= ~Decor_Icon
;
642 XUnmapWindow(ob_display
, self
->icon
);
646 self
->frame
.client
->decorations
&= ~Decor_AllDesktops
;
647 XUnmapWindow(ob_display
, self
->desk
);
651 self
->frame
.client
->decorations
&= ~Decor_Iconify
;
652 XUnmapWindow(ob_display
, self
->iconify
);
656 XUnmapWindow(ob_display
, self
->label
);
660 self
->frame
.client
->decorations
&= ~Decor_Maximize
;
661 XUnmapWindow(ob_display
, self
->max
);
665 self
->frame
.client
->decorations
&= ~Decor_Close
;
666 XUnmapWindow(ob_display
, self
->close
);
671 for (lc
= themerc_titlebar_layout
; *lc
!= '\0'; ++lc
) {
676 XMapWindow(ob_display
, self
->icon
);
677 XMoveWindow(ob_display
, self
->icon
, x
, s_bevel
+ 1);
678 x
+= BUTTON_SIZE
+ s_bevel
;
683 XMapWindow(ob_display
, self
->desk
);
684 XMoveWindow(ob_display
, self
->desk
, x
, s_bevel
+ 1);
685 x
+= BUTTON_SIZE
+ s_bevel
;
690 XMapWindow(ob_display
, self
->iconify
);
691 XMoveWindow(ob_display
, self
->iconify
, x
, s_bevel
+ 1);
692 x
+= BUTTON_SIZE
+ s_bevel
;
697 XMapWindow(ob_display
, self
->label
);
698 XMoveWindow(ob_display
, self
->label
, x
, s_bevel
);
699 x
+= self
->label_width
+ s_bevel
;
704 XMapWindow(ob_display
, self
->max
);
705 XMoveWindow(ob_display
, self
->max
, x
, s_bevel
+ 1);
706 x
+= BUTTON_SIZE
+ s_bevel
;
711 XMapWindow(ob_display
, self
->close
);
712 XMoveWindow(ob_display
, self
->close
, x
, s_bevel
+ 1);
713 x
+= BUTTON_SIZE
+ s_bevel
;
719 static void render(ObFrame
*self
)
721 if (self
->frame
.client
->focused
) {
722 XSetWindowBorder(ob_display
, self
->frame
.plate
,
723 s_cb_focused_color
->pixel
);
725 XSetWindowBorder(ob_display
, self
->frame
.plate
,
726 s_cb_unfocused_color
->pixel
);
729 if (self
->frame
.client
->decorations
& Decor_Titlebar
) {
730 paint(self
->title
, (self
->frame
.client
->focused
?
731 self
->a_focused_title
:
732 self
->a_unfocused_title
),
733 self
->width
, TITLE_HEIGHT
);
737 render_iconify(self
);
742 if (self
->frame
.client
->decorations
& Decor_Handle
) {
743 paint(self
->handle
, (self
->frame
.client
->focused
?
744 self
->a_focused_handle
:
745 self
->a_unfocused_handle
),
746 HANDLE_WIDTH(self
), s_handle_height
);
747 paint(self
->lgrip
, (self
->frame
.client
->focused
?
750 GRIP_WIDTH
, s_handle_height
);
751 paint(self
->rgrip
, (self
->frame
.client
->focused
?
754 GRIP_WIDTH
, s_handle_height
);
758 static void render_label(ObFrame
*self
)
762 if (self
->label_x
< 0) return;
764 a
= (self
->frame
.client
->focused
?
765 self
->a_focused_label
: self
->a_focused_label
);
767 /* set the texture's text! */
768 a
->texture
[0].data
.text
.string
= self
->frame
.client
->title
;
770 paint(self
->label
, a
, self
->label_width
, LABEL_HEIGHT
);
773 static void render_icon(ObFrame
*self
)
775 if (self
->icon_x
< 0) return;
777 /* XXX set the texture's icon picture! */
778 paint(self
->icon
, self
->a_icon
, BUTTON_SIZE
, BUTTON_SIZE
);
781 static void render_max(ObFrame
*self
)
783 gboolean press
= self
->max_press
||
784 self
->frame
.client
->max_vert
|| self
->frame
.client
->max_horz
;
786 if (self
->max_x
< 0) return;
788 paint(self
->max
, (self
->frame
.client
->focused
?
790 a_focused_pressed_max
:
791 a_focused_unpressed_max
) :
793 a_unfocused_pressed_max
:
794 a_unfocused_unpressed_max
)),
795 BUTTON_SIZE
, BUTTON_SIZE
);
798 static void render_iconify(ObFrame
*self
)
800 if (self
->iconify_x
< 0) return;
802 paint(self
->iconify
, (self
->frame
.client
->focused
?
803 (self
->iconify_press
?
804 a_focused_pressed_iconify
:
805 a_focused_unpressed_iconify
) :
806 (self
->iconify_press
?
807 a_unfocused_pressed_iconify
:
808 a_unfocused_unpressed_iconify
)),
809 BUTTON_SIZE
, BUTTON_SIZE
);
812 static void render_desk(ObFrame
*self
)
814 gboolean press
= self
->desk_press
||
815 self
->frame
.client
->desktop
== DESKTOP_ALL
;
817 if (self
->desk_x
< 0) return;
819 paint(self
->desk
, (self
->frame
.client
->focused
?
821 a_focused_pressed_desk
:
822 a_focused_unpressed_desk
) :
824 a_unfocused_pressed_desk
:
825 a_unfocused_unpressed_desk
)),
826 BUTTON_SIZE
, BUTTON_SIZE
);
829 static void render_close(ObFrame
*self
)
831 if (self
->close_x
< 0) return;
833 paint(self
->close
, (self
->frame
.client
->focused
?
835 a_focused_pressed_close
:
836 a_focused_unpressed_close
) :
838 a_unfocused_pressed_close
:
839 a_unfocused_unpressed_close
)),
840 BUTTON_SIZE
, BUTTON_SIZE
);
843 GQuark
get_context(Client
*client
, Window win
)
847 if (win
== ob_root
) return g_quark_try_string("root");
848 if (client
== NULL
) return g_quark_try_string("none");
849 if (win
== client
->window
) return g_quark_try_string("client");
851 self
= (ObFrame
*) client
->frame
;
852 if (win
== self
->frame
.window
) return g_quark_try_string("frame");
853 if (win
== self
->frame
.plate
) return g_quark_try_string("client");
854 if (win
== self
->title
) return g_quark_try_string("titlebar");
855 if (win
== self
->label
) return g_quark_try_string("titlebar");
856 if (win
== self
->handle
) return g_quark_try_string("handle");
857 if (win
== self
->lgrip
) return g_quark_try_string("blcorner");
858 if (win
== self
->rgrip
) return g_quark_try_string("brcorner");
859 if (win
== self
->max
) return g_quark_try_string("maximize");
860 if (win
== self
->iconify
) return g_quark_try_string("iconify");
861 if (win
== self
->close
) return g_quark_try_string("close");
862 if (win
== self
->icon
) return g_quark_try_string("icon");
863 if (win
== self
->desk
) return g_quark_try_string("alldesktops");
865 return g_quark_try_string("none");