Remove binary from git
[notion/jeffpc.git] / mod_dock / dock.c
blobe589fa0171e4417c7d4fb7ae65db9a4984768cbb
1 /*
2 * Ion dock module
3 * Copyright (C) 2003 Tom Payne
4 * Copyright (C) 2003 Per Olofsson
5 * Copyright (C) 2004-2009 Tuomo Valkonen
7 * by Tom Payne <ion@tompayne.org>
8 * based on code by Per Olofsson <pelle@dsv.su.se>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * $Header: /home/twp/cvsroot/twp/ion/ion-devel-dock/dock.c,v 1.17 2003/12/21 11:59:48 twp Exp $
29 /*{{{ Includes */
31 #include <limits.h>
32 #include <string.h>
33 #include <X11/Xlib.h>
34 #include <X11/Xatom.h>
35 #include <X11/Xutil.h>
36 #include <X11/extensions/shape.h>
38 #include <libtu/objp.h>
39 #include <libtu/map.h>
40 #include <libtu/minmax.h>
41 #include <libextl/extl.h>
42 #include <libextl/readconfig.h>
43 #include <libmainloop/defer.h>
45 #include <ioncore/common.h>
46 #include <ioncore/clientwin.h>
47 #include <ioncore/eventh.h>
48 #include <ioncore/global.h>
49 #include <ioncore/manage.h>
50 #include <ioncore/names.h>
51 #include <ioncore/property.h>
52 #include <ioncore/resize.h>
53 #include <ioncore/window.h>
54 #include <ioncore/mplex.h>
55 #include <ioncore/saveload.h>
56 #include <ioncore/bindmaps.h>
57 #include <ioncore/regbind.h>
58 #include <ioncore/extlconv.h>
59 #include <ioncore/event.h>
60 #include <ioncore/resize.h>
61 #include <ioncore/sizehint.h>
62 #include <ioncore/basicpholder.h>
64 #include "exports.h"
66 /*}}}*/
69 /*{{{ Macros */
71 #ifdef __GNUC__
72 #define UNUSED __attribute__ ((unused))
73 #else
74 #define UNUSED
75 #endif
77 /*}}}*/
80 /*{{{ Variables */
82 #include "../version.h"
84 static const char *modname="dock";
85 const char mod_dock_ion_api_version[]=NOTION_API_VERSION;
87 static WBindmap *dock_bindmap=NULL;
89 /*}}}*/
92 /*{{{ Classes */
94 INTRSTRUCT(WDockParam);
95 INTRSTRUCT(WDockApp);
96 INTRCLASS(WDock);
98 DECLSTRUCT(WDockParam){
99 const char *key;
100 const char *desc;
101 const StringIntMap *map;
102 int dflt;
105 DECLSTRUCT(WDockApp){
106 WDockApp *next, *prev;
107 WRegion *reg;
108 int pos;
109 bool draw_border;
110 bool tile;
111 WRectangle geom;
112 WRectangle tile_geom;
113 WRectangle border_geom;
116 DECLCLASS(WDock){
117 WWindow win;
118 WDock *dock_next, *dock_prev;
119 int pos, grow;
120 bool is_auto;
121 GrBrush *brush;
122 WDockApp *dockapps;
124 int min_w, min_h;
125 int max_w, max_h;
127 bool arrange_called;
128 bool save;
131 static WDock *docks=NULL;
133 /*}}}*/
136 /*{{{ Parameter conversion */
138 static void dock_param_extl_table_get(const WDockParam *param,
139 ExtlTab conftab, int value)
141 const char *s;
143 s=stringintmap_key(param->map, value, NULL);
144 if(s){
145 extl_table_sets_s(conftab, param->key, s);
151 static bool dock_param_do_set(const WDockParam *param, char *s,
152 int *ret)
154 bool changed=FALSE;
155 int i=stringintmap_value(param->map, s, -1);
156 if(i<0){
157 warn_obj(modname, "Invalid %s \"%s\"", param->desc, s);
158 }else{
159 if(*ret!=i){
160 changed=TRUE;
162 *ret=i;
164 free(s);
166 return changed;
171 static bool dock_param_extl_table_set(const WDockParam *param, ExtlTab conftab,
172 int *ret)
174 char *s;
176 if(extl_table_gets_s(conftab, param->key, &s))
177 return dock_param_do_set(param, s, ret);
179 return FALSE;
184 static bool dock_param_brush_set(const WDockParam *param, GrBrush *brush,
185 int *ret)
187 char *s;
189 if(grbrush_get_extra(brush, param->key, 's', &s))
190 return dock_param_do_set(param, s, ret);
192 return FALSE;
196 /*}}}*/
199 /*{{{ Parameter descriptions */
201 static const WDockParam dock_param_name={
202 "name",
203 "name",
204 NULL,
209 #define DOCK_HPOS_MASK 0x000f
210 #define DOCK_HPOS_LEFT 0x0000
211 #define DOCK_HPOS_CENTER 0x0001
212 #define DOCK_HPOS_RIGHT 0x0002
213 #define DOCK_VPOS_MASK 0x00f0
214 #define DOCK_VPOS_TOP 0x0000
215 #define DOCK_VPOS_MIDDLE 0x0010
216 #define DOCK_VPOS_BOTTOM 0x0020
219 static StringIntMap dock_pos_map[]={
220 {"tl", DOCK_VPOS_TOP|DOCK_HPOS_LEFT},
221 {"tc", DOCK_VPOS_TOP|DOCK_HPOS_CENTER},
222 {"tr", DOCK_VPOS_TOP|DOCK_HPOS_RIGHT},
223 {"ml", DOCK_VPOS_MIDDLE|DOCK_HPOS_LEFT},
224 {"mc", DOCK_VPOS_MIDDLE|DOCK_HPOS_CENTER},
225 {"mr", DOCK_VPOS_MIDDLE|DOCK_HPOS_RIGHT},
226 {"bl", DOCK_VPOS_BOTTOM|DOCK_HPOS_LEFT},
227 {"bc", DOCK_VPOS_BOTTOM|DOCK_HPOS_CENTER},
228 {"br", DOCK_VPOS_BOTTOM|DOCK_HPOS_RIGHT},
229 END_STRINGINTMAP
232 static WDockParam dock_param_pos={
233 "pos",
234 "dock position",
235 dock_pos_map,
236 DOCK_HPOS_LEFT|DOCK_VPOS_BOTTOM
240 enum WDockGrow{
241 DOCK_GROW_UP,
242 DOCK_GROW_DOWN,
243 DOCK_GROW_LEFT,
244 DOCK_GROW_RIGHT
247 static StringIntMap dock_grow_map[]={
248 {"up", DOCK_GROW_UP},
249 {"down", DOCK_GROW_DOWN},
250 {"left", DOCK_GROW_LEFT},
251 {"right", DOCK_GROW_RIGHT},
252 END_STRINGINTMAP
255 WDockParam dock_param_grow={
256 "grow",
257 "growth direction",
258 dock_grow_map,
259 DOCK_GROW_RIGHT
263 static const WDockParam dock_param_is_auto={
264 "is_auto",
265 "is automatic",
266 NULL,
267 TRUE
271 enum WDockOutlineStyle{
272 DOCK_OUTLINE_STYLE_NONE,
273 DOCK_OUTLINE_STYLE_ALL,
274 DOCK_OUTLINE_STYLE_EACH
277 static StringIntMap dock_outline_style_map[]={
278 {"none", DOCK_OUTLINE_STYLE_NONE},
279 {"all", DOCK_OUTLINE_STYLE_ALL},
280 {"each", DOCK_OUTLINE_STYLE_EACH},
281 END_STRINGINTMAP
284 WDockParam dock_param_outline_style={
285 "outline_style",
286 "outline style",
287 dock_outline_style_map,
288 DOCK_OUTLINE_STYLE_ALL
292 static const WDockParam dock_param_tile_width={
293 "width",
294 "tile width",
295 NULL,
299 static const WDockParam dock_param_tile_height={
300 "height",
301 "tile height",
302 NULL,
307 /*}}}*/
310 /*{{{ Misc. */
312 #define CLIENTWIN_WINPROP_POSITION "dockposition"
313 #define CLIENTWIN_WINPROP_BORDER "dockborder"
315 static WDockApp *dock_find_dockapp(WDock *dock, WRegion *reg)
317 WDockApp *dockapp;
319 for(dockapp=dock->dockapps; dockapp!=NULL; dockapp=dockapp->next){
320 if(dockapp->reg==reg){
321 return dockapp;
325 return NULL;
330 static void dock_get_outline_style(WDock *dock, int *ret)
333 *ret=dock_param_outline_style.dflt;
334 if(dock->brush!=NULL)
335 dock_param_brush_set(&dock_param_outline_style, dock->brush, ret);
339 /*}}}*/
342 /*{{{ Size calculation */
345 static void dock_get_tile_size(WDock *dock, WRectangle *ret)
347 ExtlTab tile_size_table;
349 ret->x=0;
350 ret->y=0;
351 ret->w=dock_param_tile_width.dflt;
352 ret->h=dock_param_tile_height.dflt;
353 if(dock->brush==NULL)
354 return;
355 if(grbrush_get_extra(dock->brush, "tile_size", 't', &tile_size_table)){
356 extl_table_gets_i(tile_size_table, dock_param_tile_width.key, &ret->w);
357 extl_table_gets_i(tile_size_table, dock_param_tile_height.key, &ret->h);
358 extl_unref_table(tile_size_table);
364 static void dock_get_pos_grow(WDock *dock, int *pos, int *grow)
366 WMPlex *mplex=OBJ_CAST(REGION_PARENT(dock), WMPlex);
367 WRegion *mplex_stdisp;
368 WMPlexSTDispInfo din;
370 if(mplex!=NULL){
371 mplex_get_stdisp(mplex, &mplex_stdisp, &din);
372 if(mplex_stdisp==(WRegion*)dock){
373 /* Ok, we're assigned as a status display for mplex, so
374 * get parameters from there.
376 *pos=((din.pos==MPLEX_STDISP_TL || din.pos==MPLEX_STDISP_BL)
377 ? DOCK_HPOS_LEFT
378 : DOCK_HPOS_RIGHT)
379 | ((din.pos==MPLEX_STDISP_TL || din.pos==MPLEX_STDISP_TR)
380 ? DOCK_VPOS_TOP
381 : DOCK_VPOS_BOTTOM);
382 *grow=dock->grow;
383 return;
387 *grow=dock->grow;
388 *pos=dock->pos;
393 static void dock_reshape(WDock *dock)
395 int outline_style;
397 if(!ioncore_g.shape_extension)
398 return;
400 dock_get_outline_style(dock, &outline_style);
402 switch(outline_style){
403 case DOCK_OUTLINE_STYLE_NONE:
404 case DOCK_OUTLINE_STYLE_EACH:
406 WDockApp *dockapp;
408 /* Start with an empty set */
409 XShapeCombineRectangles(ioncore_g.dpy, ((WWindow*)dock)->win,
410 ShapeBounding, 0, 0, NULL, 0, ShapeSet, 0);
412 /* Union with dockapp shapes */
413 for(dockapp=dock->dockapps; dockapp!=NULL; dockapp=dockapp->next){
414 WClientWin *cwin=OBJ_CAST(dockapp->reg, WClientWin);
415 if(outline_style==DOCK_OUTLINE_STYLE_EACH
416 && dockapp->draw_border){
417 /* Union with border shape */
418 XRectangle tile_rect;
420 tile_rect.x=dockapp->border_geom.x;
421 tile_rect.y=dockapp->border_geom.y;
422 tile_rect.width=dockapp->border_geom.w;
423 tile_rect.height=dockapp->border_geom.h;
424 XShapeCombineRectangles(ioncore_g.dpy, ((WWindow*)dock)->win,
425 ShapeBounding, 0, 0, &tile_rect, 1,
426 ShapeUnion, 0);
427 }else if(cwin!=NULL){
428 /* Union with dockapp shape */
429 int count;
430 int ordering;
432 XRectangle *rects=XShapeGetRectangles(ioncore_g.dpy, cwin->win,
433 ShapeBounding, &count,
434 &ordering);
435 if(rects!=NULL){
436 WRectangle dockapp_geom=REGION_GEOM(cwin);
437 XShapeCombineRectangles(ioncore_g.dpy, ((WWindow*)dock)->win,
438 ShapeBounding,
439 dockapp_geom.x, dockapp_geom.y,
440 rects, count, ShapeUnion, ordering);
441 XFree(rects);
446 break;
448 case DOCK_OUTLINE_STYLE_ALL:
450 WRectangle geom;
451 XRectangle rect;
453 geom=REGION_GEOM(dock);
454 rect.x=0;
455 rect.y=0;
456 rect.width=geom.w;
457 rect.height=geom.h;
458 XShapeCombineRectangles(ioncore_g.dpy, ((WWindow*)dock)->win,
459 ShapeBounding, 0, 0, &rect, 1, ShapeSet, 0);
461 break;
467 static void dock_arrange_dockapps(WDock *dock, const WRectangle *bd_dockg,
468 const WDockApp *replace_this,
469 WDockApp *with_this)
471 GrBorderWidths dock_bdw, dockapp_bdw;
472 WDockApp dummy_copy, *dockapp;
473 int pos, grow, cur_coord=0;
474 WRectangle dock_geom;
476 dock->arrange_called=TRUE;
478 dock_get_pos_grow(dock, &pos, &grow);
480 /* Determine dock and dockapp border widths */
481 memset(&dock_bdw, 0, sizeof(GrBorderWidths));
482 memset(&dockapp_bdw, 0, sizeof(GrBorderWidths));
484 if(dock->brush){
485 int outline_style;
487 dock_get_outline_style(dock, &outline_style);
488 switch(outline_style){
489 case DOCK_OUTLINE_STYLE_NONE:
490 break;
491 case DOCK_OUTLINE_STYLE_ALL:
492 grbrush_get_border_widths(dock->brush, &dock_bdw);
493 dockapp_bdw.spacing=dock_bdw.spacing;
494 break;
495 case DOCK_OUTLINE_STYLE_EACH:
496 grbrush_get_border_widths(dock->brush, &dockapp_bdw);
497 break;
501 dock_geom.w=bd_dockg->w-dock_bdw.left-dock_bdw.right;
502 dock_geom.h=bd_dockg->h-dock_bdw.top-dock_bdw.bottom;
504 /* Calculate initial co-ordinate for layout algorithm */
505 switch(grow){
506 case DOCK_GROW_UP:
507 cur_coord=dock_bdw.top+dock_geom.h;
508 break;
509 case DOCK_GROW_DOWN:
510 cur_coord=dock_bdw.top;
511 break;
512 case DOCK_GROW_LEFT:
513 cur_coord=dock_bdw.left+dock_geom.w;
514 break;
515 case DOCK_GROW_RIGHT:
516 cur_coord=dock_bdw.left;
517 break;
520 /* Arrange dockapps */
521 for(dockapp=dock->dockapps; dockapp!=NULL; dockapp=dockapp->next){
522 WDockApp *da=dockapp;
524 if(replace_this!=NULL){
525 if(replace_this==dockapp){
526 da=with_this;
527 }else{
528 dummy_copy=*dockapp;
529 da=&dummy_copy;
533 /* Calculate first co-ordinate */
534 switch(grow){
535 case DOCK_GROW_UP:
536 case DOCK_GROW_DOWN:
537 switch(pos&DOCK_HPOS_MASK){
538 case DOCK_HPOS_LEFT:
539 da->border_geom.x=0;
540 break;
541 case DOCK_HPOS_CENTER:
542 da->border_geom.x=(dock_geom.w-da->border_geom.w)/2;
543 break;
544 case DOCK_HPOS_RIGHT:
545 da->border_geom.x=dock_geom.w-da->border_geom.w;
546 break;
548 da->border_geom.x+=dock_bdw.left;
549 break;
550 case DOCK_GROW_LEFT:
551 case DOCK_GROW_RIGHT:
552 switch(pos&DOCK_VPOS_MASK){
553 case DOCK_VPOS_TOP:
554 da->border_geom.y=0;
555 break;
556 case DOCK_VPOS_MIDDLE:
557 da->border_geom.y=(dock_geom.h-da->border_geom.h)/2;
558 break;
559 case DOCK_VPOS_BOTTOM:
560 da->border_geom.y=dock_geom.h-da->border_geom.h;
561 break;
563 da->border_geom.y+=dock_bdw.top;
564 break;
567 /* Calculate second co-ordinate */
568 switch(grow){
569 case DOCK_GROW_UP:
570 cur_coord-=da->border_geom.h;
571 da->border_geom.y=cur_coord;
572 cur_coord-=dockapp_bdw.spacing;
573 break;
574 case DOCK_GROW_DOWN:
575 da->border_geom.y=cur_coord;
576 cur_coord+=da->border_geom.h+dockapp_bdw.spacing;
577 break;
578 case DOCK_GROW_LEFT:
579 cur_coord-=da->border_geom.w;
580 da->border_geom.x=cur_coord;
581 cur_coord-=dockapp_bdw.spacing;
582 break;
583 case DOCK_GROW_RIGHT:
584 da->border_geom.x=cur_coord;
585 cur_coord+=da->border_geom.w+dockapp_bdw.spacing;
586 break;
589 /* Calculate tile geom */
590 da->tile_geom.x=da->border_geom.x+dockapp_bdw.left;
591 da->tile_geom.y=da->border_geom.y+dockapp_bdw.top;
593 /* Calculate dockapp geom */
594 if(da->tile){
595 da->geom.x=da->tile_geom.x+(da->tile_geom.w-da->geom.w)/2;
596 da->geom.y=da->tile_geom.y+(da->tile_geom.h-da->geom.h)/2;
597 }else{
598 da->geom.x=da->tile_geom.x;
599 da->geom.y=da->tile_geom.y;
602 if(replace_this==NULL)
603 region_fit(da->reg, &(da->geom), REGION_FIT_BOUNDS);
608 static void dock_set_minmax(WDock *dock, int grow, const WRectangle *g)
610 dock->min_w=g->w;
611 dock->min_h=g->h;
612 if(grow==DOCK_GROW_UP || grow==DOCK_GROW_DOWN){
613 dock->max_w=g->w;
614 dock->max_h=INT_MAX;
615 }else{
616 dock->max_w=INT_MAX;
617 dock->max_h=g->h;
622 static void dockapp_calc_preferred_size(WDock *dock, int grow,
623 const WRectangle *tile_size,
624 WDockApp *da)
626 int w=da->geom.w, h=da->geom.h;
628 if(grow==DOCK_GROW_UP || grow==DOCK_GROW_DOWN){
629 da->geom.w=minof(w, tile_size->w);
630 da->geom.h=h;
631 }else{
632 da->geom.w=w;
633 da->geom.h=minof(h, tile_size->h);
636 region_size_hints_correct(da->reg, &(da->geom.w), &(da->geom.h), TRUE);
641 static void dock_managed_rqgeom_(WDock *dock, WRegion *reg, int flags,
642 const WRectangle *geom, WRectangle *geomret,
643 bool just_update_minmax)
645 WDockApp *dockapp=NULL, *thisdockapp=NULL, thisdockapp_copy;
646 WRectangle parent_geom, dock_geom, border_dock_geom;
647 GrBorderWidths dock_bdw, dockapp_bdw;
648 int n_dockapps=0, max_w=1, max_h=1, total_w=0, total_h=0;
649 int pos, grow;
650 WRectangle tile_size;
651 WWindow *par=REGION_PARENT(dock);
653 /* dock_resize calls with NULL parameters. */
654 assert(reg!=NULL || (geomret==NULL && !(flags&REGION_RQGEOM_TRYONLY)));
656 dock_get_pos_grow(dock, &pos, &grow);
658 /* Determine parent and tile geoms */
659 parent_geom.x=0;
660 parent_geom.y=0;
661 if(par!=NULL){
662 parent_geom.w=REGION_GEOM(par).w;
663 parent_geom.h=REGION_GEOM(par).h;
664 }else{
665 /* Should not happen in normal operation. */
666 parent_geom.w=1;
667 parent_geom.h=1;
670 dock_get_tile_size(dock, &tile_size);
672 /* Determine dock and dockapp border widths */
673 memset(&dock_bdw, 0, sizeof(GrBorderWidths));
674 memset(&dockapp_bdw, 0, sizeof(GrBorderWidths));
676 if(dock->brush){
677 int outline_style;
679 dock_get_outline_style(dock, &outline_style);
680 switch(outline_style){
681 case DOCK_OUTLINE_STYLE_NONE:
682 break;
683 case DOCK_OUTLINE_STYLE_ALL:
684 grbrush_get_border_widths(dock->brush, &dock_bdw);
685 dockapp_bdw.spacing=dock_bdw.spacing;
686 break;
687 case DOCK_OUTLINE_STYLE_EACH:
688 grbrush_get_border_widths(dock->brush, &dockapp_bdw);
689 break;
693 /* Calculate widths and heights */
694 for(dockapp=dock->dockapps; dockapp!=NULL; dockapp=dockapp->next){
695 WDockApp *da=dockapp;
696 bool update=!(flags&REGION_RQGEOM_TRYONLY);
697 if(dockapp->reg==reg){
698 thisdockapp=dockapp;
699 if(flags&REGION_RQGEOM_TRYONLY){
700 thisdockapp_copy=*dockapp;
701 thisdockapp_copy.geom=*geom;
702 da=&thisdockapp_copy;
703 update=TRUE;
705 da->geom=*geom;
708 if(update){
709 /* Calculcate preferred size */
710 dockapp_calc_preferred_size(dock, grow, &tile_size, da);
712 /* Determine whether dockapp should be placed on a tile */
713 da->tile=da->geom.w<=tile_size.w && da->geom.h<=tile_size.h;
715 /* Calculate width and height */
716 if(da->tile){
717 da->tile_geom.w=tile_size.w;
718 da->tile_geom.h=tile_size.h;
719 }else{
720 da->tile_geom.w=da->geom.w;
721 da->tile_geom.h=da->geom.h;
724 /* Calculate border width and height */
725 da->border_geom.w=dockapp_bdw.left+da->tile_geom.w+dockapp_bdw.right;
726 da->border_geom.h=dockapp_bdw.top+da->tile_geom.h+dockapp_bdw.right;
729 /* Calculate maximum and accumulated widths and heights */
730 if(da->border_geom.w>max_w)
731 max_w=da->border_geom.w;
732 total_w+=da->border_geom.w+(n_dockapps ? dockapp_bdw.spacing : 0);
734 if(da->border_geom.h>max_h)
735 max_h=da->border_geom.h;
736 total_h+=da->border_geom.h+(n_dockapps ? dockapp_bdw.spacing : 0);
738 /* Count dockapps */
739 ++n_dockapps;
742 if(thisdockapp==NULL && reg!=NULL){
743 warn("Requesting dockapp not found.");
744 if(geomret)
745 *geomret=REGION_GEOM(reg);
746 return;
749 /* Calculate width and height of dock */
750 if(n_dockapps){
751 switch(grow){
752 case DOCK_GROW_LEFT:
753 case DOCK_GROW_RIGHT:
754 dock_geom.w=total_w;
755 dock_geom.h=max_h;
756 break;
757 case DOCK_GROW_UP:
758 case DOCK_GROW_DOWN:
759 default:
760 dock_geom.w=max_w;
761 dock_geom.h=total_h;
762 break;
764 }else{
765 dock_geom.w=tile_size.w;
766 dock_geom.h=tile_size.h;
769 border_dock_geom.x=REGION_GEOM(dock).x;
770 border_dock_geom.y=REGION_GEOM(dock).y;
771 border_dock_geom.w=dock_bdw.left+dock_geom.w+dock_bdw.right;
772 border_dock_geom.h=dock_bdw.top+dock_geom.h+dock_bdw.bottom;
774 /* Fit dock to new geom if required */
775 if(!(flags&REGION_RQGEOM_TRYONLY)){
776 WRQGeomParams rq=RQGEOMPARAMS_INIT;
778 dock_set_minmax(dock, grow, &border_dock_geom);
780 if(just_update_minmax)
781 return;
783 rq.flags=REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y;
784 rq.geom=border_dock_geom;
786 dock->arrange_called=FALSE;
788 region_rqgeom((WRegion*)dock, &rq, NULL);
790 if(!dock->arrange_called)
791 dock_arrange_dockapps(dock, &REGION_GEOM(dock), NULL, NULL);
793 if(thisdockapp!=NULL && geomret!=NULL)
794 *geomret=thisdockapp->geom;
795 }else{
796 if(thisdockapp!=NULL && geomret!=NULL){
797 dock_arrange_dockapps(dock, &REGION_GEOM(dock),
798 thisdockapp, &thisdockapp_copy);
799 *geomret=thisdockapp_copy.geom;
804 static void dock_managed_rqgeom(WDock *dock, WRegion *reg,
805 const WRQGeomParams *rq,
806 WRectangle *geomret)
808 dock_managed_rqgeom_(dock, reg, rq->flags, &rq->geom, geomret, FALSE);
812 void dock_size_hints(WDock *dock, WSizeHints *hints)
814 hints->min_set=TRUE;
815 hints->min_width=dock->min_w;
816 hints->min_height=dock->min_h;
818 hints->max_set=TRUE;
819 hints->max_width=dock->max_w;
820 hints->max_height=dock->max_h;
824 static bool dock_fitrep(WDock *dock, WWindow *parent, const WFitParams *fp)
826 if(!window_fitrep(&(dock->win), parent, fp))
827 return FALSE;
829 dock_arrange_dockapps(dock, &(fp->g), NULL, NULL);
831 if(ioncore_g.shape_extension)
832 dock_reshape(dock);
834 return TRUE;
838 static int dock_orientation(WDock *dock)
840 return ((dock->grow==DOCK_GROW_LEFT || dock->grow==DOCK_GROW_RIGHT)
841 ? REGION_ORIENTATION_HORIZONTAL
842 : REGION_ORIENTATION_VERTICAL);
846 /*}}}*/
849 /*{{{ Drawing */
852 static void dock_draw(WDock *dock, bool complete)
854 int outline_style;
855 WRectangle g;
857 if(dock->brush==NULL)
858 return;
860 g.x=0;
861 g.y=0;
862 g.w=REGION_GEOM(dock).w;
863 g.h=REGION_GEOM(dock).h;
865 grbrush_begin(dock->brush, &g, (complete ? 0 : GRBRUSH_NO_CLEAR_OK));
867 dock_get_outline_style(dock, &outline_style);
868 switch(outline_style){
869 case DOCK_OUTLINE_STYLE_NONE:
870 break;
871 case DOCK_OUTLINE_STYLE_ALL:
873 WRectangle geom=REGION_GEOM(dock);
874 geom.x=geom.y=0;
875 grbrush_draw_border(dock->brush, &geom);
877 break;
878 case DOCK_OUTLINE_STYLE_EACH:
880 WDockApp *dockapp;
881 for(dockapp=dock->dockapps; dockapp!=NULL;
882 dockapp=dockapp->next){
883 grbrush_draw_border(dock->brush, &dockapp->tile_geom);
886 break;
889 grbrush_end(dock->brush);
893 /*EXTL_DOC
894 * Resizes and refreshes \var{dock}.
896 EXTL_EXPORT_MEMBER
897 void dock_resize(WDock *dock)
899 dock_managed_rqgeom_(dock, NULL, 0, NULL, NULL, FALSE);
900 dock_draw(dock, TRUE);
904 static void dock_brush_release(WDock *dock)
907 if(dock->brush){
908 grbrush_release(dock->brush);
909 dock->brush=NULL;
915 static void dock_brush_get(WDock *dock)
918 dock_brush_release(dock);
919 dock->brush=gr_get_brush(((WWindow*)dock)->win,
920 region_rootwin_of((WRegion*)dock),
921 "stdisp-dock");
925 static void dock_updategr(WDock *dock)
927 dock_brush_get(dock);
928 dock_resize(dock);
931 /*}}}*/
934 /*{{{ Set/get */
937 static void mplexpos(int pos, int *mpos)
939 int hp=pos&DOCK_HPOS_MASK, vp=pos&DOCK_VPOS_MASK;
940 int p;
942 p=(vp!=DOCK_VPOS_MIDDLE
943 ? (vp==DOCK_VPOS_TOP
944 ? (hp!=DOCK_HPOS_CENTER
945 ? (hp==DOCK_HPOS_RIGHT
946 ? MPLEX_STDISP_TR
947 : MPLEX_STDISP_TL)
948 : -1)
949 : (hp!=DOCK_HPOS_CENTER
950 ? (hp==DOCK_HPOS_RIGHT
951 ? MPLEX_STDISP_BR
952 : MPLEX_STDISP_BL)
953 : -1))
954 : -1);
956 if(p==-1)
957 warn("Invalid dock position while as stdisp.");
958 else
959 *mpos=p;
963 static void mplexszplcy(int pos, WSizePolicy *szplcy)
965 int hp=pos&DOCK_HPOS_MASK, vp=pos&DOCK_VPOS_MASK;
966 WSizePolicy p;
968 p=(vp!=DOCK_VPOS_MIDDLE
969 ? (vp==DOCK_VPOS_TOP
970 ? (hp!=DOCK_HPOS_CENTER
971 ? (hp==DOCK_HPOS_RIGHT
972 ? SIZEPOLICY_GRAVITY_NORTHEAST
973 : SIZEPOLICY_GRAVITY_NORTHWEST)
974 : SIZEPOLICY_GRAVITY_NORTH)
975 : (hp!=DOCK_HPOS_CENTER
976 ? (hp==DOCK_HPOS_RIGHT
977 ? SIZEPOLICY_GRAVITY_SOUTHEAST
978 : SIZEPOLICY_GRAVITY_SOUTHWEST)
979 : SIZEPOLICY_GRAVITY_SOUTH))
980 : (hp!=DOCK_HPOS_CENTER
981 ? (hp==DOCK_HPOS_RIGHT
982 ? SIZEPOLICY_GRAVITY_EAST
983 : SIZEPOLICY_GRAVITY_WEST)
984 : SIZEPOLICY_GRAVITY_CENTER));
986 *szplcy=p;
990 static void dock_do_set(WDock *dock, ExtlTab conftab, bool resize)
992 char *s;
993 bool b;
994 bool growset=FALSE;
995 bool posset=FALSE;
996 bool save=FALSE;
998 if(extl_table_gets_s(conftab, dock_param_name.key, &s)){
999 if(!region_set_name((WRegion*)dock, s)){
1000 warn_obj(modname, "Can't set name to \"%s\"", s);
1002 free(s);
1005 if(extl_table_gets_b(conftab, "save", &save))
1006 dock->save=save;
1008 if(dock_param_extl_table_set(&dock_param_pos, conftab, &dock->pos))
1009 posset=TRUE;
1011 if(dock_param_extl_table_set(&dock_param_grow, conftab, &dock->grow))
1012 growset=TRUE;
1014 if(extl_table_gets_b(conftab, dock_param_is_auto.key, &b))
1015 dock->is_auto=b;
1017 if(resize && (growset || posset)){
1018 WMPlex *par=OBJ_CAST(REGION_PARENT(dock), WMPlex);
1019 WRegion *stdisp=NULL;
1020 WMPlexSTDispInfo din;
1022 if(par!=NULL){
1023 mplex_get_stdisp(par, &stdisp, &din);
1024 din.fullsize=FALSE; /* not supported. */
1025 if(stdisp==(WRegion*)dock){
1026 if(posset)
1027 mplexpos(dock->pos, &din.pos);
1028 if(growset){
1029 /* Update min/max first */
1030 dock_managed_rqgeom_(dock, NULL, 0, NULL, NULL, TRUE);
1032 mplex_set_stdisp(par, (WRegion*)dock, &din);
1033 }else if((WRegion*)par==REGION_MANAGER(dock)){
1034 WSizePolicy szplcy;
1035 mplexszplcy(dock->pos, &szplcy);
1036 mplex_set_szplcy(par, (WRegion*)dock, szplcy);
1040 dock_resize(dock);
1045 /*EXTL_DOC
1046 * Configure \var{dock}. \var{conftab} is a table of key/value pairs:
1048 * \begin{tabularx}{\linewidth}{llX}
1049 * \tabhead{Key & Values & Description}
1050 * \var{name} & string & Name of dock \\
1051 * \var{pos} & string in $\{t,m,b\}\times\{t,c,b\}$ & Dock position.
1052 * Can only be used in floating mode. \\
1053 * \var{grow} & up/down/left/right &
1054 * Growth direction where new dockapps are added. Also
1055 * sets orientation for dock when working as WMPlex status
1056 * display (see \fnref{WMPlex.set_stdisp}). \\
1057 * \var{is_auto} & bool &
1058 * Should \var{dock} automatically manage new dockapps? \\
1059 * \end{tabularx}
1061 * Any parameters not explicitly set in \var{conftab} will be left unchanged.
1063 EXTL_EXPORT_MEMBER
1064 void dock_set(WDock *dock, ExtlTab conftab)
1066 dock_do_set(dock, conftab, TRUE);
1070 static void dock_do_get(WDock *dock, ExtlTab conftab)
1072 extl_table_sets_s(conftab, dock_param_name.key,
1073 region_name((WRegion*)dock));
1074 dock_param_extl_table_get(&dock_param_pos, conftab, dock->pos);
1075 dock_param_extl_table_get(&dock_param_grow, conftab, dock->grow);
1076 extl_table_sets_b(conftab, dock_param_is_auto.key, dock->is_auto);
1077 extl_table_sets_b(conftab, "save", dock->save);
1081 /*EXTL_DOC
1082 * Get \var{dock}'s configuration table. See \fnref{WDock.set} for a
1083 * description of the table.
1085 EXTL_SAFE
1086 EXTL_EXPORT_MEMBER
1087 ExtlTab dock_get(WDock *dock)
1089 ExtlTab conftab;
1091 conftab=extl_create_table();
1092 dock_do_get(dock, conftab);
1093 return conftab;
1097 /*}}}*/
1100 /*{{{ Init/deinit */
1103 static bool dock_init(WDock *dock, WWindow *parent, const WFitParams *fp)
1105 WFitParams fp2=*fp;
1107 dock->pos=dock_param_pos.dflt;
1108 dock->grow=dock_param_grow.dflt;
1109 dock->is_auto=dock_param_is_auto.dflt;
1110 dock->brush=NULL;
1111 dock->dockapps=NULL;
1112 dock->min_w=1;
1113 dock->min_h=1;
1114 dock->max_w=1;
1115 dock->max_h=1;
1116 dock->arrange_called=FALSE;
1117 dock->save=TRUE;
1120 if(!window_init((WWindow*)dock, parent, &fp2, "WDock"))
1121 return FALSE;
1123 region_add_bindmap((WRegion*)dock, dock_bindmap);
1125 window_select_input(&(dock->win), IONCORE_EVENTMASK_CWINMGR);
1127 dock_brush_get(dock);
1129 LINK_ITEM(docks, dock, dock_next, dock_prev);
1131 return TRUE;
1135 static WDock *create_dock(WWindow *parent, const WFitParams *fp)
1137 CREATEOBJ_IMPL(WDock, dock, (p, parent, fp));
1141 static void dock_deinit(WDock *dock)
1143 while(dock->dockapps!=NULL)
1144 destroy_obj((Obj*)dock->dockapps->reg);
1146 UNLINK_ITEM(docks, dock, dock_next, dock_prev);
1148 dock_brush_release(dock);
1150 window_deinit((WWindow*) dock);
1154 EXTL_EXPORT
1155 WDock *mod_dock_create(ExtlTab tab)
1157 char *mode=NULL;
1158 bool floating=FALSE;
1159 int screenid=0;
1160 WScreen *screen=NULL;
1161 WDock *dock=NULL;
1162 WRegion *stdisp=NULL;
1163 WMPlexSTDispInfo din;
1164 WFitParams fp;
1166 if(extl_table_gets_s(tab, "mode", &mode)){
1167 if(strcmp(mode, "floating")==0){
1168 floating=TRUE;
1169 }else if(strcmp(mode, "embedded")!=0){
1170 warn("Invalid dock mode.");
1171 free(mode);
1172 return NULL;
1174 free(mode);
1177 extl_table_gets_i(tab, "screen", &screenid);
1178 screen=ioncore_find_screen_id(screenid);
1179 if(screen==NULL){
1180 warn("Screen %d does not exist.", screenid);
1181 return NULL;
1184 for(dock=docks; dock; dock=dock->dock_next){
1185 if(region_screen_of((WRegion*)dock)==screen){
1186 warn("Screen %d already has a dock. Refusing to create another.",
1187 screenid);
1188 return NULL;
1192 if(!floating){
1193 mplex_get_stdisp((WMPlex*)screen, &stdisp, &din);
1194 if(stdisp!=NULL && !extl_table_is_bool_set(tab, "force")){
1195 warn("Screen %d already has an stdisp. Refusing to add embedded "
1196 "dock.", screenid);
1197 return NULL;
1201 /* Create the dock */
1202 fp.mode=REGION_FIT_BOUNDS|REGION_FIT_WHATEVER;
1203 fp.g.x=0;
1204 fp.g.y=0;
1205 fp.g.w=1;
1206 fp.g.h=1;
1208 dock=create_dock((WWindow*)screen, &fp);
1210 if(dock==NULL){
1211 warn("Failed to create dock.");
1212 return NULL;
1216 /* Get parameters */
1217 dock->save=FALSE;
1218 dock_do_set(dock, tab, FALSE);
1220 /* Calculate min/max size */
1221 dock_managed_rqgeom_(dock, NULL, 0, NULL, NULL, TRUE);
1223 /* Final setup */
1224 if(floating){
1225 const WRectangle *pg=&REGION_GEOM(screen);
1226 WMPlexAttachParams par=MPLEXATTACHPARAMS_INIT;
1227 WRegionAttachData data;
1229 par.flags=(MPLEX_ATTACH_UNNUMBERED
1230 |MPLEX_ATTACH_SIZEPOLICY
1231 |MPLEX_ATTACH_GEOM
1232 |MPLEX_ATTACH_PASSIVE);
1234 par.geom.w=dock->min_w;
1235 par.geom.h=dock->min_h;
1236 par.geom.x=0;
1237 par.geom.y=0;
1239 mplexszplcy(dock->pos, &par.szplcy);
1241 if(extl_table_is_bool_set(tab, "floating_hidden"))
1242 par.flags|=MPLEX_ATTACH_HIDDEN;
1244 data.type=REGION_ATTACH_REPARENT;
1245 data.u.reg=(WRegion*)dock;
1247 if(mplex_do_attach((WMPlex*)screen, &par, &data))
1248 return dock;
1249 }else{
1250 mplexpos(dock->pos, &din.pos);
1251 din.fullsize=FALSE; /* not supported */
1252 if(mplex_set_stdisp((WMPlex*)screen, (WRegion*)dock, &din))
1253 return dock;
1256 /* Failed to attach. */
1257 warn("Failed to attach dock to screen.");
1258 destroy_obj((Obj*)dock);
1259 return NULL;
1263 /*}}}*/
1266 /*{{{ Toggle */
1269 /*EXTL_DOC
1270 * Toggle floating docks on \var{mplex}.
1272 EXTL_EXPORT
1273 void mod_dock_set_floating_shown_on(WMPlex *mplex, const char *how)
1275 int setpar=libtu_setparam_invert(libtu_string_to_setparam(how));
1276 WDock *dock;
1278 for(dock=docks; dock; dock=dock->dock_next){
1279 if(REGION_MANAGER(dock)==(WRegion*)mplex)
1280 mplex_set_hidden(mplex, (WRegion*)dock, setpar);
1285 /*}}}*/
1288 /*{{{ Save/load */
1291 ExtlTab dock_get_configuration(WDock *dock)
1293 ExtlTab tab;
1295 if(dock->save==FALSE)
1296 return extl_table_none();
1298 tab=region_get_base_configuration((WRegion*)dock);
1299 dock_do_get(dock, tab);
1301 return tab;
1305 WRegion *dock_load(WWindow *par, const WFitParams *fp, ExtlTab tab)
1307 WDock *dock=create_dock(par, fp);
1308 if(dock!=NULL){
1309 dock_set(dock, tab);
1310 dock_fitrep(dock, NULL, fp);
1313 return (WRegion*)dock;
1317 /*}}}*/
1320 /*{{{ Client window management setup */
1323 static bool dock_do_attach_final(WDock *dock, WRegion *reg, void *unused)
1325 WDockApp *dockapp, *before_dockapp;
1326 WRectangle geom;
1327 WFitParams fp;
1328 bool draw_border=TRUE;
1329 int pos=INT_MAX;
1331 /* Create and initialise a new WDockApp struct */
1332 dockapp=ALLOC(WDockApp);
1334 if(dockapp==NULL)
1335 return FALSE;
1337 if(OBJ_IS(reg, WClientWin)){
1338 ExtlTab proptab=((WClientWin*)reg)->proptab;
1339 extl_table_gets_b(proptab, CLIENTWIN_WINPROP_BORDER, &draw_border);
1340 extl_table_gets_i(proptab, CLIENTWIN_WINPROP_POSITION, &pos);
1343 dockapp->reg=reg;
1344 dockapp->draw_border=draw_border;
1345 dockapp->pos=pos;
1346 dockapp->tile=FALSE;
1348 /* Insert the dockapp at the correct relative position */
1349 before_dockapp=dock->dockapps;
1350 for(before_dockapp=dock->dockapps;
1351 before_dockapp!=NULL && dockapp->pos>=before_dockapp->pos;
1352 before_dockapp=before_dockapp->next){
1355 if(before_dockapp!=NULL){
1356 LINK_ITEM_BEFORE(dock->dockapps, before_dockapp, dockapp, next, prev);
1357 }else{
1358 LINK_ITEM(dock->dockapps, dockapp, next, prev);
1361 region_set_manager(reg, (WRegion*)dock);
1363 geom=REGION_GEOM(reg);
1364 dock_managed_rqgeom_(dock, reg,
1365 REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y,
1366 &geom, NULL, FALSE);
1368 region_map(reg);
1370 return TRUE;
1375 static WRegion *dock_do_attach(WDock *dock, WRegionAttachData *data)
1377 WFitParams fp;
1378 dock_get_tile_size(dock, &(fp.g));
1379 fp.g.x=0;
1380 fp.g.y=0;
1381 fp.mode=REGION_FIT_WHATEVER|REGION_FIT_BOUNDS;
1383 return region_attach_helper((WRegion*)dock, (WWindow*)dock, &fp,
1384 (WRegionDoAttachFn*)dock_do_attach_final,
1385 NULL, data);
1389 /*EXTL_DOC
1390 * Attach \var{reg} to \var{dock}.
1392 EXTL_EXPORT_MEMBER
1393 bool dock_attach(WDock *dock, WRegion *reg)
1395 WRegionAttachData data;
1396 WFitParams fp;
1398 data.type=REGION_ATTACH_REPARENT;
1399 data.u.reg=reg;
1401 return (dock_do_attach(dock, &data)!=NULL);
1405 static bool dock_handle_drop(WDock *dock, int x, int y,
1406 WRegion *dropped)
1408 return dock_attach(dock, dropped);
1412 static WRegion *dock_ph_handler(WDock *dock, int flags, WRegionAttachData *data)
1414 return dock_do_attach(dock, data);
1418 static WPHolder *dock_managed_get_pholder(WDock *dock, WRegion *mgd)
1420 return (WPHolder*)create_basicpholder((WRegion*)dock,
1421 ((WBasicPHolderHandler*)
1422 dock_ph_handler));
1426 static WPHolder *dock_prepare_manage(WDock *dock, const WClientWin *cwin,
1427 const WManageParams *param UNUSED,
1428 int priority)
1430 if(!MANAGE_PRIORITY_OK(priority, MANAGE_PRIORITY_LOW))
1431 return NULL;
1433 return (WPHolder*)create_basicpholder((WRegion*)dock,
1434 ((WBasicPHolderHandler*)
1435 dock_ph_handler));
1439 static void dock_managed_remove(WDock *dock, WRegion *reg)
1442 WDockApp *dockapp=dock_find_dockapp(dock, reg);
1444 if(dockapp==NULL)
1445 return;
1447 UNLINK_ITEM(dock->dockapps, dockapp, next, prev);
1448 free(dockapp);
1450 region_unset_manager(reg, (WRegion*)dock);
1452 dock_resize(dock);
1456 static bool dock_clientwin_is_dockapp(WClientWin *cwin,
1457 const WManageParams *param)
1459 bool is_dockapp=FALSE;
1461 /* First, inspect the WManageParams.dockapp parameter */
1462 if(param->dockapp){
1463 is_dockapp=TRUE;
1466 /* Second, inspect the _NET_WM_WINDOW_TYPE property */
1467 if(!is_dockapp){
1468 static Atom atom__net_wm_window_type=None;
1469 static Atom atom__net_wm_window_type_dock=None;
1470 Atom actual_type=None;
1471 int actual_format;
1472 unsigned long nitems;
1473 unsigned long bytes_after;
1474 unsigned char *prop;
1476 if(atom__net_wm_window_type==None){
1477 atom__net_wm_window_type=XInternAtom(ioncore_g.dpy,
1478 "_NET_WM_WINDOW_TYPE",
1479 False);
1481 if(atom__net_wm_window_type_dock==None){
1482 atom__net_wm_window_type_dock=XInternAtom(ioncore_g.dpy,
1483 "_NET_WM_WINDOW_TYPE_DOCK",
1484 False);
1486 if(XGetWindowProperty(ioncore_g.dpy, cwin->win, atom__net_wm_window_type,
1487 0, sizeof(Atom), False, XA_ATOM, &actual_type,
1488 &actual_format, &nitems, &bytes_after, &prop)
1489 ==Success){
1490 if(actual_type==XA_ATOM && nitems>=1
1491 && *(Atom*)prop==atom__net_wm_window_type_dock){
1492 is_dockapp=TRUE;
1494 XFree(prop);
1498 /* Third, inspect the WM_CLASS property */
1499 if(!is_dockapp){
1500 char **p;
1501 int n;
1503 p=xwindow_get_text_property(cwin->win, XA_WM_CLASS, &n);
1504 if(p!=NULL){
1505 if(n>=2 && strcmp(p[1], "DockApp")==0){
1506 is_dockapp=TRUE;
1508 XFreeStringList(p);
1512 /* Fourth, inspect the _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR property */
1513 if(!is_dockapp){
1514 static Atom atom__kde_net_wm_system_tray_window_for=None;
1515 Atom actual_type=None;
1516 int actual_format;
1517 unsigned long nitems;
1518 unsigned long bytes_after;
1519 unsigned char *prop;
1521 if(atom__kde_net_wm_system_tray_window_for==None){
1522 atom__kde_net_wm_system_tray_window_for=XInternAtom(ioncore_g.dpy,
1523 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
1524 False);
1526 if(XGetWindowProperty(ioncore_g.dpy, cwin->win,
1527 atom__kde_net_wm_system_tray_window_for, 0,
1528 sizeof(Atom), False, AnyPropertyType,
1529 &actual_type, &actual_format, &nitems,
1530 &bytes_after, &prop)==Success){
1531 if(actual_type!=None){
1532 is_dockapp=TRUE;
1534 XFree(prop);
1538 return is_dockapp;
1543 static WDock *dock_find_suitable_dock(WClientWin *cwin,
1544 const WManageParams *param)
1546 WDock *dock;
1548 for(dock=docks; dock; dock=dock->dock_next){
1549 if(!dock->is_auto)
1550 continue;
1551 if(!region_same_rootwin((WRegion*)dock, (WRegion*)cwin))
1552 continue;
1553 break;
1556 return dock;
1560 static bool clientwin_do_manage_hook(WClientWin *cwin, const WManageParams *param)
1562 WDock *dock;
1564 if(!dock_clientwin_is_dockapp(cwin, param)){
1565 return FALSE;
1568 dock=dock_find_suitable_dock(cwin, param);
1569 if(!dock){
1570 return FALSE;
1573 return region_manage_clientwin((WRegion*)dock, cwin, param,
1574 MANAGE_PRIORITY_NONE);
1578 /*}}}*/
1581 /*{{{ Module init/deinit */
1584 bool mod_dock_init()
1587 if(!ioncore_register_regclass(&CLASSDESCR(WDock),
1588 (WRegionLoadCreateFn*)dock_load)){
1589 return FALSE;
1592 if(!mod_dock_register_exports()){
1593 ioncore_unregister_regclass(&CLASSDESCR(WDock));
1594 return FALSE;
1597 dock_bindmap=ioncore_alloc_bindmap("WDock", NULL);
1598 if(dock_bindmap==NULL){
1599 warn("Unable to allocate dock bindmap.");
1600 mod_dock_unregister_exports();
1601 ioncore_unregister_regclass(&CLASSDESCR(WDock));
1604 extl_read_config("cfg_dock", NULL, TRUE);
1606 hook_add(clientwin_do_manage_alt,
1607 (WHookDummy*)clientwin_do_manage_hook);
1609 return TRUE;
1614 void mod_dock_deinit()
1616 WDock *dock;
1618 ioncore_unregister_regclass(&CLASSDESCR(WDock));
1620 hook_remove(clientwin_do_manage_alt,
1621 (WHookDummy*)clientwin_do_manage_hook);
1623 dock=docks;
1624 while(dock!=NULL){
1625 WDock *next=dock->dock_next;
1626 destroy_obj((Obj*)dock);
1627 dock=next;
1630 mod_dock_unregister_exports();
1632 if(dock_bindmap!=NULL){
1633 ioncore_free_bindmap("WDock", dock_bindmap);
1634 dock_bindmap=NULL;
1639 /*}}}*/
1642 /*{{{ WDock class description and dynfun list */
1645 static DynFunTab dock_dynfuntab[]={
1646 {window_draw, dock_draw},
1647 {region_updategr, dock_updategr},
1648 {region_managed_rqgeom, dock_managed_rqgeom},
1649 {(DynFun*)region_prepare_manage, (DynFun*)dock_prepare_manage},
1650 {region_managed_remove, dock_managed_remove},
1651 {(DynFun*)region_get_configuration, (DynFun*)dock_get_configuration},
1652 {region_size_hints, dock_size_hints},
1653 {(DynFun*)region_fitrep, (DynFun*)dock_fitrep},
1654 {(DynFun*)region_orientation, (DynFun*)dock_orientation},
1655 {(DynFun*)region_handle_drop, (DynFun*)dock_handle_drop},
1657 {(DynFun*)region_managed_get_pholder,
1658 (DynFun*)dock_managed_get_pholder},
1659 END_DYNFUNTAB
1663 EXTL_EXPORT
1664 IMPLCLASS(WDock, WWindow, dock_deinit, dock_dynfuntab);
1667 /*}}}*/