2 * ion/ioncore/frame-draw.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
11 #include <libtu/objp.h>
12 #include <libtu/minmax.h>
13 #include <libtu/map.h>
18 #include "frame-draw.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
38 GR_DEFATTR(unselected);
40 GR_DEFATTR(not_tagged);
42 GR_DEFATTR(not_dragged);
44 GR_DEFATTR(no_activity);
47 static void ensure_create_attrs()
51 GR_ALLOCATTR(inactive);
52 GR_ALLOCATTR(selected);
53 GR_ALLOCATTR(unselected);
55 GR_ALLOCATTR(not_tagged);
56 GR_ALLOCATTR(dragged);
57 GR_ALLOCATTR(not_dragged);
58 GR_ALLOCATTR(no_activity);
59 GR_ALLOCATTR(activity);
64 void frame_update_attr(WFrame *frame, int i, WRegion *reg)
67 bool selected, tagged, dragged, activity;
69 if(i>=frame->titles_n){
70 /* Might happen when deinitialising */
74 ensure_create_attrs();
76 spec=&frame->titles[i].attr;
78 selected=(reg==FRAME_CURRENT(frame));
79 tagged=(reg!=NULL && reg->flags®ION_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));
94 /*{{{ (WFrame) dynfun default implementations */
97 static uint get_spacing(const WFrame *frame)
101 if(frame->brush==NULL)
104 grbrush_get_border_widths(frame->brush, &bdw);
110 void frame_border_geom(const WFrame *frame, WRectangle *geom)
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)
128 frame_border_geom(frame, geom);
130 if(frame->brush!=NULL){
131 grbrush_get_border_widths(frame->brush, &bdw);
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)
145 if(BAR_INSIDE_BORDER(frame)){
146 off=0; /*get_spacing(frame);*/
147 frame_border_inner_geom(frame, geom);
152 geom->w=(frame->barmode==FRAME_BAR_SHAPED
154 : REGION_GEOM(frame).w);
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);
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){
190 }else if(!BAR_INSIDE_BORDER(frame)){
195 grbrush_get_border_widths(frame->brush, &bdw);
197 return frame->bar_h+bdw.top+bdw.bottom;
202 void frame_set_shape(WFrame *frame)
207 if(frame->brush!=NULL){
208 if(BAR_EXISTS(frame)){
209 frame_bar_geom(frame, gs+n);
212 frame_border_geom(frame, gs+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 #define CF_TAB_MAX_TEXT_X_OFF 10
230 static void frame_shaped_recalc_bar_size(WFrame *frame, bool complete)
232 int bar_w=0, textw=0, tmaxw=frame->tab_min_w, tmp=0;
241 if(frame->bar_brush==NULL)
244 m=FRAME_MCOUNT(frame);
247 grbrush_get_border_widths(frame->bar_brush, &bdw);
248 bdtotal=((m-1)*(bdw.tb_ileft+bdw.tb_iright+bdw.spacing)
249 +bdw.right+bdw.left);
251 FRAME_MX_FOR_ALL(sub, frame, itmp){
252 p=region_displayname(sub);
256 textw=grbrush_get_text_width(frame->bar_brush,
262 bar_w=frame->bar_max_width_q*REGION_GEOM(frame).w;
263 if(bar_w<frame->tab_min_w &&
264 REGION_GEOM(frame).w>frame->tab_min_w)
265 bar_w=frame->tab_min_w;
267 tmp=bar_w-bdtotal-m*tmaxw;
270 /* No label truncation needed, good. See how much can be padded. */
272 if(tmp>CF_TAB_MAX_TEXT_X_OFF)
273 tmp=CF_TAB_MAX_TEXT_X_OFF;
274 bar_w=(tmaxw+tmp*2)*m+bdtotal;
276 /* Some labels must be truncated */
279 bar_w=frame->tab_min_w;
280 if(bar_w>frame->bar_max_width_q*REGION_GEOM(frame).w)
281 bar_w=frame->bar_max_width_q*REGION_GEOM(frame).w;
284 if(complete || frame->bar_w!=bar_w){
286 frame_set_shape(frame);
291 static int init_title(WFrame *frame, int i)
295 if(frame->titles[i].text!=NULL){
296 free(frame->titles[i].text);
297 frame->titles[i].text=NULL;
300 textw=frame_nth_tab_iw((WFrame*)frame, i);
301 frame->titles[i].iw=textw;
306 void frame_recalc_bar(WFrame *frame, bool complete)
313 if(frame->bar_brush==NULL || frame->titles==NULL)
316 if(frame->barmode==FRAME_BAR_SHAPED)
317 frame_shaped_recalc_bar_size(frame, complete);
319 frame_clear_shape(frame);
323 if(FRAME_MCOUNT(frame)==0){
324 textw=init_title(frame, i);
326 title=grbrush_make_label(frame->bar_brush, TR("<empty frame>"),
328 frame->titles[i].text=title;
333 FRAME_MX_FOR_ALL(sub, frame, tmp){
334 textw=init_title(frame, i);
336 title=region_make_label(sub, textw, frame->bar_brush);
337 frame->titles[i].text=title;
344 void frame_draw_bar(const WFrame *frame, bool complete)
348 if(frame->bar_brush==NULL
349 || !BAR_EXISTS(frame)
350 || frame->titles==NULL){
354 frame_bar_geom(frame, &geom);
356 grbrush_begin(frame->bar_brush, &geom, GRBRUSH_AMEND);
358 grbrush_init_attr(frame->bar_brush, &frame->baseattr);
360 grbrush_draw_textboxes(frame->bar_brush, &geom, frame->titles_n,
361 frame->titles, complete);
363 grbrush_end(frame->bar_brush);
366 void frame_draw(const WFrame *frame, bool complete)
370 if(frame->brush==NULL)
373 frame_border_geom(frame, &geom);
375 grbrush_begin(frame->brush, &geom, (complete ? 0 : GRBRUSH_NO_CLEAR_OK));
377 grbrush_init_attr(frame->brush, &frame->baseattr);
379 grbrush_draw_border(frame->brush, &geom);
381 frame_draw_bar(frame, TRUE);
383 grbrush_end(frame->brush);
387 void frame_brushes_updated(WFrame *frame)
389 WFrameBarMode barmode;
393 if(frame->brush==NULL)
396 if(frame->mode==FRAME_MODE_FLOATING){
397 barmode=FRAME_BAR_SHAPED;
398 }else if(frame->mode==FRAME_MODE_TILED || frame->mode==FRAME_MODE_UNKNOWN ||
399 frame->mode==FRAME_MODE_TRANSIENT_ALT){
400 barmode=FRAME_BAR_INSIDE;
402 barmode=FRAME_BAR_NONE;
405 if(grbrush_get_extra(frame->brush, "bar", 's', &s)){
406 if(strcmp(s, "inside")==0)
407 barmode=FRAME_BAR_INSIDE;
408 else if(strcmp(s, "outside")==0)
409 barmode=FRAME_BAR_OUTSIDE;
410 else if(strcmp(s, "shaped")==0)
411 barmode=FRAME_BAR_SHAPED;
412 else if(strcmp(s, "none")==0)
413 barmode=FRAME_BAR_NONE;
417 frame->barmode=barmode;
419 if(barmode==FRAME_BAR_NONE || frame->bar_brush==NULL){
425 grbrush_get_border_widths(frame->bar_brush, &bdw);
426 grbrush_get_font_extents(frame->bar_brush, &fnte);
428 frame->bar_h=bdw.top+bdw.bottom+fnte.max_height;
431 /* shaped mode stuff */
432 frame->tab_min_w=100;
433 frame->bar_max_width_q=0.95;
435 if(grbrush_get_extra(frame->brush, "floatframe_tab_min_w",
436 'i', &(frame->tab_min_w))){
437 if(frame->tab_min_w<=0)
441 if(grbrush_get_extra(frame->brush, "floatframe_bar_max_w_q",
442 'd', &(frame->bar_max_width_q))){
443 if(frame->bar_max_width_q<=0.0 || frame->bar_max_width_q>1.0)
444 frame->bar_max_width_q=1.0;
455 void frame_updategr(WFrame *frame)
457 frame_release_brushes(frame);
459 frame_initialise_gr(frame);
461 /* Update children */
462 region_updategr_default((WRegion*)frame);
464 mplex_fit_managed(&frame->mplex);
465 frame_recalc_bar(frame, TRUE);
466 frame_set_background(frame, TRUE);
470 static StringIntMap frame_tab_styles[]={
471 {"tab-frame-unknown", FRAME_MODE_UNKNOWN},
472 {"tab-frame-unknown-alt", FRAME_MODE_UNKNOWN_ALT},
473 {"tab-frame-tiled", FRAME_MODE_TILED},
474 {"tab-frame-tiled-alt", FRAME_MODE_TILED_ALT},
475 {"tab-frame-floating", FRAME_MODE_FLOATING},
476 {"tab-frame-floating-alt", FRAME_MODE_FLOATING_ALT},
477 {"tab-frame-transient", FRAME_MODE_TRANSIENT},
478 {"tab-frame-transient-alt", FRAME_MODE_TRANSIENT_ALT},
483 const char *framemode_get_tab_style(WFrameMode mode)
485 return stringintmap_key(frame_tab_styles, mode, "tab-frame");
489 const char *framemode_get_style(WFrameMode mode)
491 const char *p=framemode_get_tab_style(mode);
497 void frame_initialise_gr(WFrame *frame)
499 Window win=frame->mplex.win.win;
500 WRootWin *rw=region_rootwin_of((WRegion*)frame);
501 const char *style=framemode_get_style(frame->mode);
502 const char *tab_style=framemode_get_tab_style(frame->mode);
504 frame->brush=gr_get_brush(win, rw, style);
506 if(frame->brush==NULL)
509 frame->bar_brush=grbrush_get_slave(frame->brush, rw, tab_style);
511 if(frame->bar_brush==NULL)
514 frame_brushes_updated(frame);
518 void frame_release_brushes(WFrame *frame)
520 if(frame->bar_brush!=NULL){
521 grbrush_release(frame->bar_brush);
522 frame->bar_brush=NULL;
525 if(frame->brush!=NULL){
526 grbrush_release(frame->brush);
532 bool frame_set_background(WFrame *frame, bool set_always)
534 GrTransparency mode=GR_TRANSPARENCY_DEFAULT;
536 if(FRAME_CURRENT(frame)!=NULL){
537 if(OBJ_IS(FRAME_CURRENT(frame), WClientWin)){
538 WClientWin *cwin=(WClientWin*)FRAME_CURRENT(frame);
539 mode=(cwin->flags&CLIENTWIN_PROP_TRANSPARENT
540 ? GR_TRANSPARENCY_YES : GR_TRANSPARENCY_NO);
541 }else if(!OBJ_IS(FRAME_CURRENT(frame), WGroup)){
542 mode=GR_TRANSPARENCY_NO;
546 if(mode!=frame->tr_mode || set_always){
548 if(frame->brush!=NULL){
549 grbrush_enable_transparency(frame->brush, mode);
550 window_draw((WWindow*)frame, TRUE);
559 void frame_setup_dragwin_style(WFrame *frame, GrStyleSpec *spec, int tab)
561 gr_stylespec_append(spec, &frame->baseattr);
562 gr_stylespec_append(spec, &frame->titles[tab].attr);
569 /*{{{ Activated/inactivated */
572 void frame_inactivated(WFrame *frame)
574 ensure_create_attrs();
576 gr_stylespec_set(&frame->baseattr, GR_ATTR(inactive));
577 gr_stylespec_unset(&frame->baseattr, GR_ATTR(active));
579 window_draw((WWindow*)frame, FALSE);
583 void frame_activated(WFrame *frame)
585 ensure_create_attrs();
587 gr_stylespec_set(&frame->baseattr, GR_ATTR(active));
588 gr_stylespec_unset(&frame->baseattr, GR_ATTR(inactive));
590 window_draw((WWindow*)frame, FALSE);