]> git.decadent.org.uk Git - ion3.git/blob - ioncore/window.c
0b122008e70a7a98231065fa74f9b1ff5ee288d2
[ion3.git] / ioncore / window.c
1 /*
2  * ion/ioncore/window.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2007. 
5  *
6  * Ion is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  */
11
12 #include <libtu/objp.h>
13 #include <libtu/minmax.h>
14
15 #include "common.h"
16 #include "global.h"
17 #include "window.h"
18 #include "focus.h"
19 #include "rootwin.h"
20 #include "region.h"
21 #include "xwindow.h"
22 #include "region-iter.h"
23
24
25 /*{{{ Dynfuns */
26
27
28 void window_draw(WWindow *wwin, bool complete)
29 {
30     CALL_DYN(window_draw, wwin, (wwin, complete));
31 }
32
33
34 void window_insstr(WWindow *wwin, const char *buf, size_t n)
35 {
36     CALL_DYN(window_insstr, wwin, (wwin, buf, n));
37 }
38
39
40 int window_press(WWindow *wwin, XButtonEvent *ev, WRegion **reg_ret)
41 {
42     int area=0;
43     CALL_DYN_RET(area, int, window_press, wwin, (wwin, ev, reg_ret));
44     return area;
45 }
46
47
48 void window_release(WWindow *wwin)
49 {
50     CALL_DYN(window_release, wwin, (wwin));
51 }
52
53
54 /*}}}*/
55     
56
57 /*{{{ Init, create */
58
59
60 bool window_do_init(WWindow *wwin, WWindow *par, 
61                     const WFitParams *fp, Window win)
62 {
63     if(win==None){
64         assert(par!=NULL);
65         win=create_xwindow(region_rootwin_of((WRegion*)par),
66                            par->win, &(fp->g));
67         if(win==None)
68             return FALSE;
69     }
70
71     wwin->win=win;
72     wwin->xic=NULL;
73     wwin->event_mask=0;
74     wwin->stacking=NULL;
75     
76     region_init(&(wwin->region), par, fp);
77     
78     XSaveContext(ioncore_g.dpy, win, ioncore_g.win_context, 
79                  (XPointer)wwin);
80     
81     return TRUE;
82 }
83
84
85 bool window_init(WWindow *wwin, WWindow *par, const WFitParams *fp)
86 {
87     return window_do_init(wwin, par, fp, None);
88 }
89
90
91 void window_deinit(WWindow *wwin)
92 {
93     region_deinit((WRegion*)wwin);
94     
95     region_pointer_focus_hack(&wwin->region);
96     
97     if(wwin->xic!=NULL)
98         XDestroyIC(wwin->xic);
99         
100     if(wwin->win!=None){
101         XDeleteContext(ioncore_g.dpy, wwin->win, ioncore_g.win_context);
102         /* Probably should not try destroy if root window... */
103         XDestroyWindow(ioncore_g.dpy, wwin->win);
104     }
105     
106     /* There are no backlinks from WStacking to us, so it is not
107      * necessary to do any deinitialisation there.
108      */
109 }
110
111
112 /*}}}*/
113
114
115 /*{{{ Region dynfuns */
116
117
118 static void window_notify_subs_rootpos(WWindow *wwin, int x, int y)
119 {
120     WRegion *sub;
121     
122     FOR_ALL_CHILDREN(wwin, sub){
123         region_notify_rootpos(sub,
124                               x+REGION_GEOM(sub).x, 
125                               y+REGION_GEOM(sub).y);
126     }
127 }
128
129
130 void window_notify_subs_move(WWindow *wwin)
131 {
132     int x=0, y=0;
133     region_rootpos(&(wwin->region), &x, &y);
134     window_notify_subs_rootpos(wwin, x, y);
135 }
136
137
138 void window_do_fitrep(WWindow *wwin, WWindow *par, const WRectangle *geom)
139 {
140     bool move=(REGION_GEOM(wwin).x!=geom->x ||
141                REGION_GEOM(wwin).y!=geom->y);
142     int w=maxof(1, geom->w);
143     int h=maxof(1, geom->h);
144
145     if(par!=NULL){
146         region_unset_parent((WRegion*)wwin);
147         XReparentWindow(ioncore_g.dpy, wwin->win, par->win, geom->x, geom->y);
148         XResizeWindow(ioncore_g.dpy, wwin->win, w, h);
149         region_set_parent((WRegion*)wwin, par);
150     }else{
151         XMoveResizeWindow(ioncore_g.dpy, wwin->win, geom->x, geom->y, w, h);
152     }
153     
154     REGION_GEOM(wwin)=*geom;
155
156     if(move)
157         window_notify_subs_move(wwin);
158 }
159
160
161 bool window_fitrep(WWindow *wwin, WWindow *par, const WFitParams *fp)
162 {
163     if(par!=NULL && !region_same_rootwin((WRegion*)wwin, (WRegion*)par))
164         return FALSE;
165     window_do_fitrep(wwin, par, &(fp->g));
166     return TRUE;
167 }
168
169
170 void window_map(WWindow *wwin)
171 {
172     XMapWindow(ioncore_g.dpy, wwin->win);
173     REGION_MARK_MAPPED(wwin);
174 }
175
176
177 void window_unmap(WWindow *wwin)
178 {
179     region_pointer_focus_hack(&wwin->region);
180
181     XUnmapWindow(ioncore_g.dpy, wwin->win);
182     REGION_MARK_UNMAPPED(wwin);
183 }
184
185
186 void window_do_set_focus(WWindow *wwin, bool warp)
187 {
188     region_finalise_focusing((WRegion*)wwin, wwin->win, warp);
189 }
190
191
192 void window_restack(WWindow *wwin, Window other, int mode)
193 {
194     xwindow_restack(wwin->win, other, mode);
195 }
196
197
198 Window window_xwindow(const WWindow *wwin)
199 {
200     return wwin->win;
201 }
202
203
204 /*}}}*/
205
206
207 /*{{{ Misc. */
208
209
210 /*EXTL_DOC
211  * Return the X window id for \var{wwin}.
212  */
213 EXTL_SAFE
214 EXTL_EXPORT_MEMBER
215 double window_xid(WWindow *wwin)
216 {
217     return wwin->win;
218 }
219
220
221 void window_select_input(WWindow *wwin, long event_mask)
222 {
223     XSelectInput(ioncore_g.dpy, wwin->win, event_mask);
224     wwin->event_mask=event_mask;
225 }
226
227
228 /*}}}*/
229
230
231 /*{{{ Dynamic function table and class implementation */
232
233
234 static DynFunTab window_dynfuntab[]={
235     {region_map, window_map},
236     {region_unmap, window_unmap},
237     {region_do_set_focus, window_do_set_focus},
238     {(DynFun*)region_fitrep, (DynFun*)window_fitrep},
239     {(DynFun*)region_xwindow, (DynFun*)window_xwindow},
240     {region_notify_rootpos, window_notify_subs_rootpos},
241     {region_restack, window_restack},
242     END_DYNFUNTAB
243 };
244
245
246 EXTL_EXPORT
247 IMPLCLASS(WWindow, WRegion, window_deinit, window_dynfuntab);
248
249     
250 /*}}}*/
251