More cleanups of dead code
[notion.git] / mod_dock / dock.c
blob4370ceb939facd52b4a7fb9a23987d7ddcaf35cc
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 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;
652 /* dock_resize calls with NULL parameters. */
653 assert(reg!=NULL || (geomret==NULL && !(flags&REGION_RQGEOM_TRYONLY)));
655 dock_get_pos_grow(dock, &pos, &grow);
656 dock_get_tile_size(dock, &tile_size);
658 /* Determine dock and dockapp border widths */
659 memset(&dock_bdw, 0, sizeof(GrBorderWidths));
660 memset(&dockapp_bdw, 0, sizeof(GrBorderWidths));
662 if(dock->brush){
663 int outline_style;
665 dock_get_outline_style(dock, &outline_style);
666 switch(outline_style){
667 case DOCK_OUTLINE_STYLE_NONE:
668 break;
669 case DOCK_OUTLINE_STYLE_ALL:
670 grbrush_get_border_widths(dock->brush, &dock_bdw);
671 dockapp_bdw.spacing=dock_bdw.spacing;
672 break;
673 case DOCK_OUTLINE_STYLE_EACH:
674 grbrush_get_border_widths(dock->brush, &dockapp_bdw);
675 break;
679 /* Calculate widths and heights */
680 for(dockapp=dock->dockapps; dockapp!=NULL; dockapp=dockapp->next){
681 WDockApp *da=dockapp;
682 bool update=!(flags&REGION_RQGEOM_TRYONLY);
683 if(dockapp->reg==reg){
684 thisdockapp=dockapp;
685 if(flags&REGION_RQGEOM_TRYONLY){
686 thisdockapp_copy=*dockapp;
687 thisdockapp_copy.geom=*geom;
688 da=&thisdockapp_copy;
689 update=TRUE;
691 da->geom=*geom;
694 if(update){
695 /* Calculcate preferred size */
696 dockapp_calc_preferred_size(dock, grow, &tile_size, da);
698 /* Determine whether dockapp should be placed on a tile */
699 da->tile=da->geom.w<=tile_size.w && da->geom.h<=tile_size.h;
701 /* Calculate width and height */
702 if(da->tile){
703 da->tile_geom.w=tile_size.w;
704 da->tile_geom.h=tile_size.h;
705 }else{
706 da->tile_geom.w=da->geom.w;
707 da->tile_geom.h=da->geom.h;
710 /* Calculate border width and height */
711 da->border_geom.w=dockapp_bdw.left+da->tile_geom.w+dockapp_bdw.right;
712 da->border_geom.h=dockapp_bdw.top+da->tile_geom.h+dockapp_bdw.right;
715 /* Calculate maximum and accumulated widths and heights */
716 if(da->border_geom.w>max_w)
717 max_w=da->border_geom.w;
718 total_w+=da->border_geom.w+(n_dockapps ? dockapp_bdw.spacing : 0);
720 if(da->border_geom.h>max_h)
721 max_h=da->border_geom.h;
722 total_h+=da->border_geom.h+(n_dockapps ? dockapp_bdw.spacing : 0);
724 /* Count dockapps */
725 ++n_dockapps;
728 if(thisdockapp==NULL && reg!=NULL){
729 warn("Requesting dockapp not found.");
730 if(geomret)
731 *geomret=REGION_GEOM(reg);
732 return;
735 /* Calculate width and height of dock */
736 if(n_dockapps){
737 switch(grow){
738 case DOCK_GROW_LEFT:
739 case DOCK_GROW_RIGHT:
740 dock_geom.w=total_w;
741 dock_geom.h=max_h;
742 break;
743 case DOCK_GROW_UP:
744 case DOCK_GROW_DOWN:
745 default:
746 dock_geom.w=max_w;
747 dock_geom.h=total_h;
748 break;
750 }else{
751 dock_geom.w=tile_size.w;
752 dock_geom.h=tile_size.h;
755 border_dock_geom.x=REGION_GEOM(dock).x;
756 border_dock_geom.y=REGION_GEOM(dock).y;
757 border_dock_geom.w=dock_bdw.left+dock_geom.w+dock_bdw.right;
758 border_dock_geom.h=dock_bdw.top+dock_geom.h+dock_bdw.bottom;
760 /* Fit dock to new geom if required */
761 if(!(flags&REGION_RQGEOM_TRYONLY)){
762 WRQGeomParams rq=RQGEOMPARAMS_INIT;
764 dock_set_minmax(dock, grow, &border_dock_geom);
766 if(just_update_minmax)
767 return;
769 rq.flags=REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y;
770 rq.geom=border_dock_geom;
772 dock->arrange_called=FALSE;
774 region_rqgeom((WRegion*)dock, &rq, NULL);
776 if(!dock->arrange_called)
777 dock_arrange_dockapps(dock, &REGION_GEOM(dock), NULL, NULL);
779 if(thisdockapp!=NULL && geomret!=NULL)
780 *geomret=thisdockapp->geom;
781 }else{
782 if(thisdockapp!=NULL && geomret!=NULL){
783 dock_arrange_dockapps(dock, &REGION_GEOM(dock),
784 thisdockapp, &thisdockapp_copy);
785 *geomret=thisdockapp_copy.geom;
790 static void dock_managed_rqgeom(WDock *dock, WRegion *reg,
791 const WRQGeomParams *rq,
792 WRectangle *geomret)
794 dock_managed_rqgeom_(dock, reg, rq->flags, &rq->geom, geomret, FALSE);
798 void dock_size_hints(WDock *dock, WSizeHints *hints)
800 hints->min_set=TRUE;
801 hints->min_width=dock->min_w;
802 hints->min_height=dock->min_h;
804 hints->max_set=TRUE;
805 hints->max_width=dock->max_w;
806 hints->max_height=dock->max_h;
810 static bool dock_fitrep(WDock *dock, WWindow *parent, const WFitParams *fp)
812 if(!window_fitrep(&(dock->win), parent, fp))
813 return FALSE;
815 dock_arrange_dockapps(dock, &(fp->g), NULL, NULL);
817 if(ioncore_g.shape_extension)
818 dock_reshape(dock);
820 return TRUE;
824 static int dock_orientation(WDock *dock)
826 return ((dock->grow==DOCK_GROW_LEFT || dock->grow==DOCK_GROW_RIGHT)
827 ? REGION_ORIENTATION_HORIZONTAL
828 : REGION_ORIENTATION_VERTICAL);
832 /*}}}*/
835 /*{{{ Drawing */
838 static void dock_draw(WDock *dock, bool complete)
840 int outline_style;
841 WRectangle g;
843 if(dock->brush==NULL)
844 return;
846 g.x=0;
847 g.y=0;
848 g.w=REGION_GEOM(dock).w;
849 g.h=REGION_GEOM(dock).h;
851 grbrush_begin(dock->brush, &g, (complete ? 0 : GRBRUSH_NO_CLEAR_OK));
853 dock_get_outline_style(dock, &outline_style);
854 switch(outline_style){
855 case DOCK_OUTLINE_STYLE_NONE:
856 break;
857 case DOCK_OUTLINE_STYLE_ALL:
859 WRectangle geom=REGION_GEOM(dock);
860 geom.x=geom.y=0;
861 grbrush_draw_border(dock->brush, &geom);
863 break;
864 case DOCK_OUTLINE_STYLE_EACH:
866 WDockApp *dockapp;
867 for(dockapp=dock->dockapps; dockapp!=NULL;
868 dockapp=dockapp->next){
869 grbrush_draw_border(dock->brush, &dockapp->tile_geom);
872 break;
875 grbrush_end(dock->brush);
879 /*EXTL_DOC
880 * Resizes and refreshes \var{dock}.
882 EXTL_EXPORT_MEMBER
883 void dock_resize(WDock *dock)
885 dock_managed_rqgeom_(dock, NULL, 0, NULL, NULL, FALSE);
886 dock_draw(dock, TRUE);
890 static void dock_brush_release(WDock *dock)
893 if(dock->brush){
894 grbrush_release(dock->brush);
895 dock->brush=NULL;
901 static void dock_brush_get(WDock *dock)
904 dock_brush_release(dock);
905 dock->brush=gr_get_brush(((WWindow*)dock)->win,
906 region_rootwin_of((WRegion*)dock),
907 "stdisp-dock");
911 static void dock_updategr(WDock *dock)
913 dock_brush_get(dock);
914 dock_resize(dock);
917 /*}}}*/
920 /*{{{ Set/get */
923 static void mplexpos(int pos, int *mpos)
925 int hp=pos&DOCK_HPOS_MASK, vp=pos&DOCK_VPOS_MASK;
926 int p;
928 p=(vp!=DOCK_VPOS_MIDDLE
929 ? (vp==DOCK_VPOS_TOP
930 ? (hp!=DOCK_HPOS_CENTER
931 ? (hp==DOCK_HPOS_RIGHT
932 ? MPLEX_STDISP_TR
933 : MPLEX_STDISP_TL)
934 : -1)
935 : (hp!=DOCK_HPOS_CENTER
936 ? (hp==DOCK_HPOS_RIGHT
937 ? MPLEX_STDISP_BR
938 : MPLEX_STDISP_BL)
939 : -1))
940 : -1);
942 if(p==-1)
943 warn("Invalid dock position while as stdisp.");
944 else
945 *mpos=p;
949 static void mplexszplcy(int pos, WSizePolicy *szplcy)
951 int hp=pos&DOCK_HPOS_MASK, vp=pos&DOCK_VPOS_MASK;
952 WSizePolicy p;
954 p=(vp!=DOCK_VPOS_MIDDLE
955 ? (vp==DOCK_VPOS_TOP
956 ? (hp!=DOCK_HPOS_CENTER
957 ? (hp==DOCK_HPOS_RIGHT
958 ? SIZEPOLICY_GRAVITY_NORTHEAST
959 : SIZEPOLICY_GRAVITY_NORTHWEST)
960 : SIZEPOLICY_GRAVITY_NORTH)
961 : (hp!=DOCK_HPOS_CENTER
962 ? (hp==DOCK_HPOS_RIGHT
963 ? SIZEPOLICY_GRAVITY_SOUTHEAST
964 : SIZEPOLICY_GRAVITY_SOUTHWEST)
965 : SIZEPOLICY_GRAVITY_SOUTH))
966 : (hp!=DOCK_HPOS_CENTER
967 ? (hp==DOCK_HPOS_RIGHT
968 ? SIZEPOLICY_GRAVITY_EAST
969 : SIZEPOLICY_GRAVITY_WEST)
970 : SIZEPOLICY_GRAVITY_CENTER));
972 *szplcy=p;
976 static void dock_do_set(WDock *dock, ExtlTab conftab, bool resize)
978 char *s;
979 bool b;
980 bool growset=FALSE;
981 bool posset=FALSE;
982 bool save=FALSE;
984 if(extl_table_gets_s(conftab, dock_param_name.key, &s)){
985 if(!region_set_name((WRegion*)dock, s)){
986 warn_obj(modname, "Can't set name to \"%s\"", s);
988 free(s);
991 if(extl_table_gets_b(conftab, "save", &save))
992 dock->save=save;
994 if(dock_param_extl_table_set(&dock_param_pos, conftab, &dock->pos))
995 posset=TRUE;
997 if(dock_param_extl_table_set(&dock_param_grow, conftab, &dock->grow))
998 growset=TRUE;
1000 if(extl_table_gets_b(conftab, dock_param_is_auto.key, &b))
1001 dock->is_auto=b;
1003 if(resize && (growset || posset)){
1004 WMPlex *par=OBJ_CAST(REGION_PARENT(dock), WMPlex);
1005 WRegion *stdisp=NULL;
1006 WMPlexSTDispInfo din;
1008 if(par!=NULL){
1009 mplex_get_stdisp(par, &stdisp, &din);
1010 din.fullsize=FALSE; /* not supported. */
1011 if(stdisp==(WRegion*)dock){
1012 if(posset)
1013 mplexpos(dock->pos, &din.pos);
1014 if(growset){
1015 /* Update min/max first */
1016 dock_managed_rqgeom_(dock, NULL, 0, NULL, NULL, TRUE);
1018 mplex_set_stdisp(par, (WRegion*)dock, &din);
1019 }else if((WRegion*)par==REGION_MANAGER(dock)){
1020 WSizePolicy szplcy;
1021 mplexszplcy(dock->pos, &szplcy);
1022 mplex_set_szplcy(par, (WRegion*)dock, szplcy);
1026 dock_resize(dock);
1031 /*EXTL_DOC
1032 * Configure \var{dock}. \var{conftab} is a table of key/value pairs:
1034 * \begin{tabularx}{\linewidth}{llX}
1035 * \tabhead{Key & Values & Description}
1036 * \var{name} & string & Name of dock \\
1037 * \var{pos} & string in $\{t,m,b\}\times\{t,c,b\}$ & Dock position.
1038 * Can only be used in floating mode. \\
1039 * \var{grow} & up/down/left/right &
1040 * Growth direction where new dockapps are added. Also
1041 * sets orientation for dock when working as WMPlex status
1042 * display (see \fnref{WMPlex.set_stdisp}). \\
1043 * \var{is_auto} & bool &
1044 * Should \var{dock} automatically manage new dockapps? \\
1045 * \end{tabularx}
1047 * Any parameters not explicitly set in \var{conftab} will be left unchanged.
1049 EXTL_EXPORT_MEMBER
1050 void dock_set(WDock *dock, ExtlTab conftab)
1052 dock_do_set(dock, conftab, TRUE);
1056 static void dock_do_get(WDock *dock, ExtlTab conftab)
1058 extl_table_sets_s(conftab, dock_param_name.key,
1059 region_name((WRegion*)dock));
1060 dock_param_extl_table_get(&dock_param_pos, conftab, dock->pos);
1061 dock_param_extl_table_get(&dock_param_grow, conftab, dock->grow);
1062 extl_table_sets_b(conftab, dock_param_is_auto.key, dock->is_auto);
1063 extl_table_sets_b(conftab, "save", dock->save);
1067 /*EXTL_DOC
1068 * Get \var{dock}'s configuration table. See \fnref{WDock.set} for a
1069 * description of the table.
1071 EXTL_SAFE
1072 EXTL_EXPORT_MEMBER
1073 ExtlTab dock_get(WDock *dock)
1075 ExtlTab conftab;
1077 conftab=extl_create_table();
1078 dock_do_get(dock, conftab);
1079 return conftab;
1083 /*}}}*/
1086 /*{{{ Init/deinit */
1089 static bool dock_init(WDock *dock, WWindow *parent, const WFitParams *fp)
1091 WFitParams fp2=*fp;
1093 dock->pos=dock_param_pos.dflt;
1094 dock->grow=dock_param_grow.dflt;
1095 dock->is_auto=dock_param_is_auto.dflt;
1096 dock->brush=NULL;
1097 dock->dockapps=NULL;
1098 dock->min_w=1;
1099 dock->min_h=1;
1100 dock->max_w=1;
1101 dock->max_h=1;
1102 dock->arrange_called=FALSE;
1103 dock->save=TRUE;
1106 if(!window_init((WWindow*)dock, parent, &fp2, "WDock"))
1107 return FALSE;
1109 region_add_bindmap((WRegion*)dock, dock_bindmap);
1111 window_select_input(&(dock->win), IONCORE_EVENTMASK_CWINMGR);
1113 dock_brush_get(dock);
1115 LINK_ITEM(docks, dock, dock_next, dock_prev);
1117 return TRUE;
1121 static WDock *create_dock(WWindow *parent, const WFitParams *fp)
1123 CREATEOBJ_IMPL(WDock, dock, (p, parent, fp));
1127 static void dock_deinit(WDock *dock)
1129 while(dock->dockapps!=NULL)
1130 destroy_obj((Obj*)dock->dockapps->reg);
1132 UNLINK_ITEM(docks, dock, dock_next, dock_prev);
1134 dock_brush_release(dock);
1136 window_deinit((WWindow*) dock);
1140 EXTL_EXPORT
1141 WDock *mod_dock_create(ExtlTab tab)
1143 char *mode=NULL;
1144 bool floating=FALSE;
1145 int screenid=0;
1146 WScreen *screen=NULL;
1147 WDock *dock=NULL;
1148 WRegion *stdisp=NULL;
1149 WMPlexSTDispInfo din;
1150 WFitParams fp;
1152 if(extl_table_gets_s(tab, "mode", &mode)){
1153 if(strcmp(mode, "floating")==0){
1154 floating=TRUE;
1155 }else if(strcmp(mode, "embedded")!=0){
1156 warn("Invalid dock mode.");
1157 free(mode);
1158 return NULL;
1160 free(mode);
1163 extl_table_gets_i(tab, "screen", &screenid);
1164 screen=ioncore_find_screen_id(screenid);
1165 if(screen==NULL){
1166 warn("Screen %d does not exist.", screenid);
1167 return NULL;
1170 for(dock=docks; dock; dock=dock->dock_next){
1171 if(region_screen_of((WRegion*)dock)==screen){
1172 warn("Screen %d already has a dock. Refusing to create another.",
1173 screenid);
1174 return NULL;
1178 if(!floating){
1179 mplex_get_stdisp((WMPlex*)screen, &stdisp, &din);
1180 if(stdisp!=NULL && !extl_table_is_bool_set(tab, "force")){
1181 warn("Screen %d already has an stdisp. Refusing to add embedded "
1182 "dock.", screenid);
1183 return NULL;
1187 /* Create the dock */
1188 fp.mode=REGION_FIT_BOUNDS|REGION_FIT_WHATEVER;
1189 fp.g.x=0;
1190 fp.g.y=0;
1191 fp.g.w=1;
1192 fp.g.h=1;
1194 dock=create_dock((WWindow*)screen, &fp);
1196 if(dock==NULL){
1197 warn("Failed to create dock.");
1198 return NULL;
1202 /* Get parameters */
1203 dock->save=FALSE;
1204 dock_do_set(dock, tab, FALSE);
1206 /* Calculate min/max size */
1207 dock_managed_rqgeom_(dock, NULL, 0, NULL, NULL, TRUE);
1209 /* Final setup */
1210 if(floating){
1211 WMPlexAttachParams par=MPLEXATTACHPARAMS_INIT;
1212 WRegionAttachData data;
1214 par.flags=(MPLEX_ATTACH_UNNUMBERED
1215 |MPLEX_ATTACH_SIZEPOLICY
1216 |MPLEX_ATTACH_GEOM
1217 |MPLEX_ATTACH_PASSIVE);
1219 par.geom.w=dock->min_w;
1220 par.geom.h=dock->min_h;
1221 par.geom.x=0;
1222 par.geom.y=0;
1224 mplexszplcy(dock->pos, &par.szplcy);
1226 if(extl_table_is_bool_set(tab, "floating_hidden"))
1227 par.flags|=MPLEX_ATTACH_HIDDEN;
1229 data.type=REGION_ATTACH_REPARENT;
1230 data.u.reg=(WRegion*)dock;
1232 if(mplex_do_attach((WMPlex*)screen, &par, &data))
1233 return dock;
1234 }else{
1235 mplexpos(dock->pos, &din.pos);
1236 din.fullsize=FALSE; /* not supported */
1237 if(mplex_set_stdisp((WMPlex*)screen, (WRegion*)dock, &din))
1238 return dock;
1241 /* Failed to attach. */
1242 warn("Failed to attach dock to screen.");
1243 destroy_obj((Obj*)dock);
1244 return NULL;
1248 /*}}}*/
1251 /*{{{ Toggle */
1254 /*EXTL_DOC
1255 * Toggle floating docks on \var{mplex}.
1257 EXTL_EXPORT
1258 void mod_dock_set_floating_shown_on(WMPlex *mplex, const char *how)
1260 int setpar=libtu_setparam_invert(libtu_string_to_setparam(how));
1261 WDock *dock;
1263 for(dock=docks; dock; dock=dock->dock_next){
1264 if(REGION_MANAGER(dock)==(WRegion*)mplex)
1265 mplex_set_hidden(mplex, (WRegion*)dock, setpar);
1270 /*}}}*/
1273 /*{{{ Save/load */
1276 ExtlTab dock_get_configuration(WDock *dock)
1278 ExtlTab tab;
1280 if(dock->save==FALSE)
1281 return extl_table_none();
1283 tab=region_get_base_configuration((WRegion*)dock);
1284 dock_do_get(dock, tab);
1286 return tab;
1290 WRegion *dock_load(WWindow *par, const WFitParams *fp, ExtlTab tab)
1292 WDock *dock=create_dock(par, fp);
1293 if(dock!=NULL){
1294 dock_set(dock, tab);
1295 dock_fitrep(dock, NULL, fp);
1298 return (WRegion*)dock;
1302 /*}}}*/
1305 /*{{{ Client window management setup */
1308 static bool dock_do_attach_final(WDock *dock, WRegion *reg, void *unused)
1310 WDockApp *dockapp, *before_dockapp;
1311 WRectangle geom;
1312 bool draw_border=TRUE;
1313 int pos=INT_MAX;
1315 /* Create and initialise a new WDockApp struct */
1316 dockapp=ALLOC(WDockApp);
1318 if(dockapp==NULL)
1319 return FALSE;
1321 if(OBJ_IS(reg, WClientWin)){
1322 ExtlTab proptab=((WClientWin*)reg)->proptab;
1323 extl_table_gets_b(proptab, CLIENTWIN_WINPROP_BORDER, &draw_border);
1324 extl_table_gets_i(proptab, CLIENTWIN_WINPROP_POSITION, &pos);
1327 dockapp->reg=reg;
1328 dockapp->draw_border=draw_border;
1329 dockapp->pos=pos;
1330 dockapp->tile=FALSE;
1332 /* Insert the dockapp at the correct relative position */
1333 before_dockapp=dock->dockapps;
1334 for(before_dockapp=dock->dockapps;
1335 before_dockapp!=NULL && dockapp->pos>=before_dockapp->pos;
1336 before_dockapp=before_dockapp->next){
1339 if(before_dockapp!=NULL){
1340 LINK_ITEM_BEFORE(dock->dockapps, before_dockapp, dockapp, next, prev);
1341 }else{
1342 LINK_ITEM(dock->dockapps, dockapp, next, prev);
1345 region_set_manager(reg, (WRegion*)dock);
1347 geom=REGION_GEOM(reg);
1348 dock_managed_rqgeom_(dock, reg,
1349 REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y,
1350 &geom, NULL, FALSE);
1352 region_map(reg);
1354 return TRUE;
1359 static WRegion *dock_do_attach(WDock *dock, WRegionAttachData *data)
1361 WFitParams fp;
1362 dock_get_tile_size(dock, &(fp.g));
1363 fp.g.x=0;
1364 fp.g.y=0;
1365 fp.mode=REGION_FIT_WHATEVER|REGION_FIT_BOUNDS;
1367 return region_attach_helper((WRegion*)dock, (WWindow*)dock, &fp,
1368 (WRegionDoAttachFn*)dock_do_attach_final,
1369 NULL, data);
1373 /*EXTL_DOC
1374 * Attach \var{reg} to \var{dock}.
1376 EXTL_EXPORT_MEMBER
1377 bool dock_attach(WDock *dock, WRegion *reg)
1379 WRegionAttachData data;
1381 data.type=REGION_ATTACH_REPARENT;
1382 data.u.reg=reg;
1384 return (dock_do_attach(dock, &data)!=NULL);
1388 static bool dock_handle_drop(WDock *dock, int x, int y,
1389 WRegion *dropped)
1391 return dock_attach(dock, dropped);
1395 static WRegion *dock_ph_handler(WDock *dock, int flags, WRegionAttachData *data)
1397 return dock_do_attach(dock, data);
1401 static WPHolder *dock_managed_get_pholder(WDock *dock, WRegion *mgd)
1403 return (WPHolder*)create_basicpholder((WRegion*)dock,
1404 ((WBasicPHolderHandler*)
1405 dock_ph_handler));
1409 static WPHolder *dock_prepare_manage(WDock *dock, const WClientWin *cwin,
1410 const WManageParams *param UNUSED,
1411 int priority)
1413 if(!MANAGE_PRIORITY_OK(priority, MANAGE_PRIORITY_LOW))
1414 return NULL;
1416 return (WPHolder*)create_basicpholder((WRegion*)dock,
1417 ((WBasicPHolderHandler*)
1418 dock_ph_handler));
1422 static void dock_managed_remove(WDock *dock, WRegion *reg)
1425 WDockApp *dockapp=dock_find_dockapp(dock, reg);
1427 if(dockapp==NULL)
1428 return;
1430 UNLINK_ITEM(dock->dockapps, dockapp, next, prev);
1431 free(dockapp);
1433 region_unset_manager(reg, (WRegion*)dock);
1435 dock_resize(dock);
1439 static bool dock_clientwin_is_dockapp(WClientWin *cwin,
1440 const WManageParams *param)
1442 bool is_dockapp=FALSE;
1444 /* First, inspect the WManageParams.dockapp parameter */
1445 if(param->dockapp){
1446 is_dockapp=TRUE;
1449 /* Second, inspect the _NET_WM_WINDOW_TYPE property */
1450 if(!is_dockapp){
1451 static Atom atom__net_wm_window_type=None;
1452 static Atom atom__net_wm_window_type_dock=None;
1453 Atom actual_type=None;
1454 int actual_format;
1455 unsigned long nitems;
1456 unsigned long bytes_after;
1457 unsigned char *prop;
1459 if(atom__net_wm_window_type==None){
1460 atom__net_wm_window_type=XInternAtom(ioncore_g.dpy,
1461 "_NET_WM_WINDOW_TYPE",
1462 False);
1464 if(atom__net_wm_window_type_dock==None){
1465 atom__net_wm_window_type_dock=XInternAtom(ioncore_g.dpy,
1466 "_NET_WM_WINDOW_TYPE_DOCK",
1467 False);
1469 if(XGetWindowProperty(ioncore_g.dpy, cwin->win, atom__net_wm_window_type,
1470 0, sizeof(Atom), False, XA_ATOM, &actual_type,
1471 &actual_format, &nitems, &bytes_after, &prop)
1472 ==Success){
1473 if(actual_type==XA_ATOM && nitems>=1
1474 && *(Atom*)prop==atom__net_wm_window_type_dock){
1475 is_dockapp=TRUE;
1477 XFree(prop);
1481 /* Third, inspect the WM_CLASS property */
1482 if(!is_dockapp){
1483 char **p;
1484 int n;
1486 p=xwindow_get_text_property(cwin->win, XA_WM_CLASS, &n);
1487 if(p!=NULL){
1488 if(n>=2 && strcmp(p[1], "DockApp")==0){
1489 is_dockapp=TRUE;
1491 XFreeStringList(p);
1495 /* Fourth, inspect the _KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR property */
1496 if(!is_dockapp){
1497 static Atom atom__kde_net_wm_system_tray_window_for=None;
1498 Atom actual_type=None;
1499 int actual_format;
1500 unsigned long nitems;
1501 unsigned long bytes_after;
1502 unsigned char *prop;
1504 if(atom__kde_net_wm_system_tray_window_for==None){
1505 atom__kde_net_wm_system_tray_window_for=XInternAtom(ioncore_g.dpy,
1506 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
1507 False);
1509 if(XGetWindowProperty(ioncore_g.dpy, cwin->win,
1510 atom__kde_net_wm_system_tray_window_for, 0,
1511 sizeof(Atom), False, AnyPropertyType,
1512 &actual_type, &actual_format, &nitems,
1513 &bytes_after, &prop)==Success){
1514 if(actual_type!=None){
1515 is_dockapp=TRUE;
1517 XFree(prop);
1521 return is_dockapp;
1526 static WDock *dock_find_suitable_dock(WClientWin *cwin,
1527 const WManageParams *param)
1529 WDock *dock;
1531 for(dock=docks; dock; dock=dock->dock_next){
1532 if(!dock->is_auto)
1533 continue;
1534 if(!region_same_rootwin((WRegion*)dock, (WRegion*)cwin))
1535 continue;
1536 break;
1539 return dock;
1543 static bool clientwin_do_manage_hook(WClientWin *cwin, const WManageParams *param)
1545 WDock *dock;
1547 if(!dock_clientwin_is_dockapp(cwin, param)){
1548 return FALSE;
1551 dock=dock_find_suitable_dock(cwin, param);
1552 if(!dock){
1553 return FALSE;
1556 return region_manage_clientwin((WRegion*)dock, cwin, param,
1557 MANAGE_PRIORITY_NONE);
1561 /*}}}*/
1564 /*{{{ Module init/deinit */
1567 bool mod_dock_init()
1570 if(!ioncore_register_regclass(&CLASSDESCR(WDock),
1571 (WRegionLoadCreateFn*)dock_load)){
1572 return FALSE;
1575 if(!mod_dock_register_exports()){
1576 ioncore_unregister_regclass(&CLASSDESCR(WDock));
1577 return FALSE;
1580 dock_bindmap=ioncore_alloc_bindmap("WDock", NULL);
1581 if(dock_bindmap==NULL){
1582 warn("Unable to allocate dock bindmap.");
1583 mod_dock_unregister_exports();
1584 ioncore_unregister_regclass(&CLASSDESCR(WDock));
1587 extl_read_config("cfg_dock", NULL, TRUE);
1589 hook_add(clientwin_do_manage_alt,
1590 (WHookDummy*)clientwin_do_manage_hook);
1592 return TRUE;
1597 void mod_dock_deinit()
1599 WDock *dock;
1601 ioncore_unregister_regclass(&CLASSDESCR(WDock));
1603 hook_remove(clientwin_do_manage_alt,
1604 (WHookDummy*)clientwin_do_manage_hook);
1606 dock=docks;
1607 while(dock!=NULL){
1608 WDock *next=dock->dock_next;
1609 destroy_obj((Obj*)dock);
1610 dock=next;
1613 mod_dock_unregister_exports();
1615 if(dock_bindmap!=NULL){
1616 ioncore_free_bindmap("WDock", dock_bindmap);
1617 dock_bindmap=NULL;
1622 /*}}}*/
1625 /*{{{ WDock class description and dynfun list */
1628 static DynFunTab dock_dynfuntab[]={
1629 {window_draw, dock_draw},
1630 {region_updategr, dock_updategr},
1631 {region_managed_rqgeom, dock_managed_rqgeom},
1632 {(DynFun*)region_prepare_manage, (DynFun*)dock_prepare_manage},
1633 {region_managed_remove, dock_managed_remove},
1634 {(DynFun*)region_get_configuration, (DynFun*)dock_get_configuration},
1635 {region_size_hints, dock_size_hints},
1636 {(DynFun*)region_fitrep, (DynFun*)dock_fitrep},
1637 {(DynFun*)region_orientation, (DynFun*)dock_orientation},
1638 {(DynFun*)region_handle_drop, (DynFun*)dock_handle_drop},
1640 {(DynFun*)region_managed_get_pholder,
1641 (DynFun*)dock_managed_get_pholder},
1642 END_DYNFUNTAB
1646 EXTL_EXPORT
1647 IMPLCLASS(WDock, WWindow, dock_deinit, dock_dynfuntab);
1650 /*}}}*/