ion->notion
[notion/jeffpc.git] / ioncore / frame-draw.c
blob7ee249166f522d3e6cc326dfef2075c0a2ef32ec
1 /*
2 * ion/ioncore/frame-draw.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <string.h>
11 #include <libtu/objp.h>
12 #include <libtu/minmax.h>
13 #include <libtu/map.h>
15 #include "common.h"
16 #include "frame.h"
17 #include "framep.h"
18 #include "frame-draw.h"
19 #include "strings.h"
20 #include "activity.h"
21 #include "names.h"
22 #include "gr.h"
23 #include "gr-util.h"
26 #define BAR_INSIDE_BORDER(FRAME) \
27 ((FRAME)->barmode==FRAME_BAR_INSIDE || (FRAME)->barmode==FRAME_BAR_NONE)
28 #define BAR_EXISTS(FRAME) ((FRAME)->barmode!=FRAME_BAR_NONE)
29 #define BAR_H(FRAME) (FRAME)->bar_h
32 /*{{{ Attributes */
35 GR_DEFATTR(active);
36 GR_DEFATTR(inactive);
37 GR_DEFATTR(selected);
38 GR_DEFATTR(unselected);
39 GR_DEFATTR(tagged);
40 GR_DEFATTR(not_tagged);
41 GR_DEFATTR(dragged);
42 GR_DEFATTR(not_dragged);
43 GR_DEFATTR(activity);
44 GR_DEFATTR(no_activity);
47 static void ensure_create_attrs()
49 GR_ALLOCATTR_BEGIN;
50 GR_ALLOCATTR(active);
51 GR_ALLOCATTR(inactive);
52 GR_ALLOCATTR(selected);
53 GR_ALLOCATTR(unselected);
54 GR_ALLOCATTR(tagged);
55 GR_ALLOCATTR(not_tagged);
56 GR_ALLOCATTR(dragged);
57 GR_ALLOCATTR(not_dragged);
58 GR_ALLOCATTR(no_activity);
59 GR_ALLOCATTR(activity);
60 GR_ALLOCATTR_END;
64 void frame_update_attr(WFrame *frame, int i, WRegion *reg)
66 GrStyleSpec *spec;
67 bool selected, tagged, dragged, activity;
69 if(i>=frame->titles_n){
70 /* Might happen when deinitialising */
71 return;
74 ensure_create_attrs();
76 spec=&frame->titles[i].attr;
78 selected=(reg==FRAME_CURRENT(frame));
79 tagged=(reg!=NULL && reg->flags&REGION_TAGGED);
80 dragged=(i==frame->tab_dragged_idx);
81 activity=(reg!=NULL && region_is_activity_r(reg));
83 gr_stylespec_unalloc(spec);
84 gr_stylespec_set(spec, selected ? GR_ATTR(selected) : GR_ATTR(unselected));
85 gr_stylespec_set(spec, tagged ? GR_ATTR(tagged) : GR_ATTR(not_tagged));
86 gr_stylespec_set(spec, dragged ? GR_ATTR(dragged) : GR_ATTR(not_dragged));
87 gr_stylespec_set(spec, activity ? GR_ATTR(activity) : GR_ATTR(no_activity));
91 /*}}}*/
94 /*{{{ (WFrame) dynfun default implementations */
97 static uint get_spacing(const WFrame *frame)
99 GrBorderWidths bdw;
101 if(frame->brush==NULL)
102 return 0;
104 grbrush_get_border_widths(frame->brush, &bdw);
106 return bdw.spacing;
110 void frame_border_geom(const WFrame *frame, WRectangle *geom)
112 geom->x=0;
113 geom->y=0;
114 geom->w=REGION_GEOM(frame).w;
115 geom->h=REGION_GEOM(frame).h;
117 if(!BAR_INSIDE_BORDER(frame) && frame->brush!=NULL){
118 geom->y+=frame->bar_h;
119 geom->h=maxof(0, geom->h-frame->bar_h);
124 void frame_border_inner_geom(const WFrame *frame, WRectangle *geom)
126 GrBorderWidths bdw;
128 frame_border_geom(frame, geom);
130 if(frame->brush!=NULL){
131 grbrush_get_border_widths(frame->brush, &bdw);
133 geom->x+=bdw.left;
134 geom->y+=bdw.top;
135 geom->w=maxof(0, geom->w-(bdw.left+bdw.right));
136 geom->h=maxof(0, geom->h-(bdw.top+bdw.bottom));
141 void frame_bar_geom(const WFrame *frame, WRectangle *geom)
143 uint off;
145 if(BAR_INSIDE_BORDER(frame)){
146 off=0; /*get_spacing(frame);*/
147 frame_border_inner_geom(frame, geom);
148 }else{
149 off=0;
150 geom->x=0;
151 geom->y=0;
152 geom->w=(frame->barmode==FRAME_BAR_SHAPED
153 ? frame->bar_w
154 : REGION_GEOM(frame).w);
156 geom->x+=off;
157 geom->y+=off;
158 geom->w=maxof(0, geom->w-2*off);
159 geom->h=BAR_H(frame);
163 void frame_managed_geom(const WFrame *frame, WRectangle *geom)
165 uint spacing=get_spacing(frame);
167 frame_border_inner_geom(frame, geom);
170 geom->x+=spacing;
171 geom->y+=spacing;
172 geom->w-=2*spacing;
173 geom->h-=2*spacing;
176 if(BAR_INSIDE_BORDER(frame) && BAR_EXISTS(frame)){
177 geom->y+=frame->bar_h+spacing;
178 geom->h-=frame->bar_h+spacing;
181 geom->w=maxof(geom->w, 0);
182 geom->h=maxof(geom->h, 0);
186 int frame_shaded_height(const WFrame *frame)
188 if(frame->barmode==FRAME_BAR_NONE){
189 return 0;
190 }else if(!BAR_INSIDE_BORDER(frame)){
191 return frame->bar_h;
192 }else {
193 GrBorderWidths bdw;
195 grbrush_get_border_widths(frame->brush, &bdw);
197 return frame->bar_h+bdw.top+bdw.bottom;
202 void frame_set_shape(WFrame *frame)
204 WRectangle gs[2];
205 int n=0;
207 if(frame->brush!=NULL){
208 if(BAR_EXISTS(frame)){
209 frame_bar_geom(frame, gs+n);
210 n++;
212 frame_border_geom(frame, gs+n);
213 n++;
215 grbrush_set_window_shape(frame->brush, TRUE, n, gs);
220 void frame_clear_shape(WFrame *frame)
222 if(frame->brush!=NULL)
223 grbrush_set_window_shape(frame->brush, TRUE, 0, NULL);
227 static void free_title(WFrame *frame, int i)
229 if(frame->titles[i].text!=NULL){
230 free(frame->titles[i].text);
231 frame->titles[i].text=NULL;
236 void frame_recalc_bar(WFrame *frame, bool complete)
238 int textw, i;
239 WLListIterTmp tmp;
240 WRegion *sub;
241 char *title;
242 bool set_shape;
244 if(frame->bar_brush==NULL || frame->titles==NULL)
245 return;
247 set_shape=frame->tabs_params.alg(frame,complete);
249 if(set_shape) {
250 if(frame->barmode==FRAME_BAR_SHAPED)
251 frame_set_shape(frame);
252 else
253 frame_clear_shape(frame);
256 i=0;
258 if(FRAME_MCOUNT(frame)==0){
259 free_title(frame, i);
260 textw=frame->titles[i].iw;
261 if(textw>0){
262 title=grbrush_make_label(frame->bar_brush, TR("<empty frame>"),
263 textw);
264 frame->titles[i].text=title;
266 return;
269 FRAME_MX_FOR_ALL(sub, frame, tmp){
270 free_title(frame, i);
271 textw=frame->titles[i].iw;
272 if(textw>0){
273 title=region_make_label(sub, textw, frame->bar_brush);
274 frame->titles[i].text=title;
276 i++;
281 void frame_draw_bar(const WFrame *frame, bool complete)
283 WRectangle geom;
285 if(frame->bar_brush==NULL
286 || !BAR_EXISTS(frame)
287 || frame->titles==NULL){
288 return;
291 frame_bar_geom(frame, &geom);
293 grbrush_begin(frame->bar_brush, &geom, GRBRUSH_AMEND);
295 grbrush_init_attr(frame->bar_brush, &frame->baseattr);
297 grbrush_draw_textboxes(frame->bar_brush, &geom, frame->titles_n,
298 frame->titles, complete);
300 grbrush_end(frame->bar_brush);
303 void frame_draw(const WFrame *frame, bool complete)
305 WRectangle geom;
307 if(frame->brush==NULL)
308 return;
310 frame_border_geom(frame, &geom);
312 grbrush_begin(frame->brush, &geom, (complete ? 0 : GRBRUSH_NO_CLEAR_OK));
314 grbrush_init_attr(frame->brush, &frame->baseattr);
316 grbrush_draw_border(frame->brush, &geom);
318 frame_draw_bar(frame, TRUE);
320 grbrush_end(frame->brush);
324 void frame_brushes_updated(WFrame *frame)
326 WFrameBarMode barmode;
327 ExtlTab tab;
328 char *s;
330 if(frame->brush==NULL)
331 return;
333 if(frame->mode==FRAME_MODE_FLOATING){
334 barmode=FRAME_BAR_SHAPED;
335 }else if(frame->mode==FRAME_MODE_TILED || frame->mode==FRAME_MODE_UNKNOWN ||
336 frame->mode==FRAME_MODE_TRANSIENT_ALT){
337 barmode=FRAME_BAR_INSIDE;
338 }else{
339 barmode=FRAME_BAR_NONE;
342 if(grbrush_get_extra(frame->brush, "bar", 's', &s)){
343 if(strcmp(s, "inside")==0)
344 barmode=FRAME_BAR_INSIDE;
345 else if(strcmp(s, "outside")==0)
346 barmode=FRAME_BAR_OUTSIDE;
347 else if(strcmp(s, "shaped")==0)
348 barmode=FRAME_BAR_SHAPED;
349 else if(strcmp(s, "none")==0)
350 barmode=FRAME_BAR_NONE;
351 free(s);
354 frame->barmode=barmode;
356 if(barmode==FRAME_BAR_NONE || frame->bar_brush==NULL){
357 frame->bar_h=0;
358 }else{
359 GrBorderWidths bdw;
360 GrFontExtents fnte;
362 grbrush_get_border_widths(frame->bar_brush, &bdw);
363 grbrush_get_font_extents(frame->bar_brush, &fnte);
365 frame->bar_h=bdw.top+bdw.bottom+fnte.max_height;
368 /* tabs and bar width calculation stuff */
369 frame_tabs_calc_brushes_updated(frame);
373 /*}}}*/
376 /*{{{ Misc. */
379 void frame_updategr(WFrame *frame)
381 frame_release_brushes(frame);
383 frame_initialise_gr(frame);
385 /* Update children */
386 region_updategr_default((WRegion*)frame);
388 mplex_fit_managed(&frame->mplex);
389 frame_recalc_bar(frame, TRUE);
390 frame_set_background(frame, TRUE);
394 static StringIntMap frame_tab_styles[]={
395 {"tab-frame-unknown", FRAME_MODE_UNKNOWN},
396 {"tab-frame-unknown-alt", FRAME_MODE_UNKNOWN_ALT},
397 {"tab-frame-tiled", FRAME_MODE_TILED},
398 {"tab-frame-tiled-alt", FRAME_MODE_TILED_ALT},
399 {"tab-frame-floating", FRAME_MODE_FLOATING},
400 {"tab-frame-floating-alt", FRAME_MODE_FLOATING_ALT},
401 {"tab-frame-transient", FRAME_MODE_TRANSIENT},
402 {"tab-frame-transient-alt", FRAME_MODE_TRANSIENT_ALT},
403 END_STRINGINTMAP
407 const char *framemode_get_tab_style(WFrameMode mode)
409 return stringintmap_key(frame_tab_styles, mode, "tab-frame");
413 const char *framemode_get_style(WFrameMode mode)
415 const char *p=framemode_get_tab_style(mode);
416 assert(p!=NULL);
417 return (p+4);
421 void frame_initialise_gr(WFrame *frame)
423 Window win=frame->mplex.win.win;
424 WRootWin *rw=region_rootwin_of((WRegion*)frame);
425 const char *style=framemode_get_style(frame->mode);
426 const char *tab_style=framemode_get_tab_style(frame->mode);
428 frame->brush=gr_get_brush(win, rw, style);
430 if(frame->brush==NULL)
431 return;
433 frame->bar_brush=grbrush_get_slave(frame->brush, rw, tab_style);
435 if(frame->bar_brush==NULL)
436 return;
438 frame_brushes_updated(frame);
442 void frame_release_brushes(WFrame *frame)
444 if(frame->bar_brush!=NULL){
445 grbrush_release(frame->bar_brush);
446 frame->bar_brush=NULL;
449 if(frame->brush!=NULL){
450 grbrush_release(frame->brush);
451 frame->brush=NULL;
456 bool frame_set_background(WFrame *frame, bool set_always)
458 GrTransparency mode=GR_TRANSPARENCY_DEFAULT;
460 if(FRAME_CURRENT(frame)!=NULL){
461 if(OBJ_IS(FRAME_CURRENT(frame), WClientWin)){
462 WClientWin *cwin=(WClientWin*)FRAME_CURRENT(frame);
463 mode=(cwin->flags&CLIENTWIN_PROP_TRANSPARENT
464 ? GR_TRANSPARENCY_YES : GR_TRANSPARENCY_NO);
465 }else if(!OBJ_IS(FRAME_CURRENT(frame), WGroup)){
466 mode=GR_TRANSPARENCY_NO;
470 if(mode!=frame->tr_mode || set_always){
471 frame->tr_mode=mode;
472 if(frame->brush!=NULL){
473 grbrush_enable_transparency(frame->brush, mode);
474 window_draw((WWindow*)frame, TRUE);
476 return TRUE;
479 return FALSE;
483 void frame_setup_dragwin_style(WFrame *frame, GrStyleSpec *spec, int tab)
485 gr_stylespec_append(spec, &frame->baseattr);
486 gr_stylespec_append(spec, &frame->titles[tab].attr);
490 /*}}}*/
493 /*{{{ Activated/inactivated */
496 void frame_inactivated(WFrame *frame)
498 ensure_create_attrs();
500 gr_stylespec_set(&frame->baseattr, GR_ATTR(inactive));
501 gr_stylespec_unset(&frame->baseattr, GR_ATTR(active));
503 window_draw((WWindow*)frame, FALSE);
507 void frame_activated(WFrame *frame)
509 ensure_create_attrs();
511 gr_stylespec_set(&frame->baseattr, GR_ATTR(active));
512 gr_stylespec_unset(&frame->baseattr, GR_ATTR(inactive));
514 window_draw((WWindow*)frame, FALSE);
518 /*}}}*/