Renamed package to ion1, and made it conflict with package 'ion'.
[ion1.git] / src / resize.c
blobe248e1e5063b1d4e3ba8b9c31a70f2b8747b510a
1 /*
2 * ion/resize.c
4 * Copyright (c) Tuomo Valkonen 1999-2001.
5 * See the included file LICENSE for details.
6 */
8 #include "common.h"
9 #include "global.h"
10 #include "split.h"
11 #include "resize.h"
12 #include "signal.h"
13 #include "event.h"
14 #include "cursor.h"
15 #include "sizehint.h"
16 #include "draw.h"
17 #include "grab.h"
20 #define XOR_RESIZE (!wglobal.opaque_resize)
22 static bool resize_handler(WThing *thing, XEvent *ev);
24 static bool resize_mode=FALSE;
25 static int tmpsize;
26 static WResizeTmp rtmp;
29 /*{{{ Resize timer */
32 static void tmr_end_resize(WTimer *unused)
34 WThing *holder;
35 if(!resize_mode){
36 return;
38 holder=grab_get_holder(resize_handler);
39 assert(holder && WTHING_IS(holder, WWindow));
41 end_resize((WWindow*)holder);
44 static WTimer resize_timer=INIT_TIMER(tmr_end_resize);
47 /*}}}*/
50 /*{{{ Rubberband and size display */
53 static void res_draw_rubberband(WScreen *scr, WRectangle geom)
55 if(rtmp.startnode!=NULL){
56 if(WOBJ_IS(rtmp.startnode, WWindow))
57 geom=((WWindow*)rtmp.startnode)->geom;
58 else
59 geom=((WWsSplit*)rtmp.startnode)->geom;
62 if(rtmp.dir==HORIZONTAL){
63 geom.x=rtmp.winpostmp;
64 geom.w=rtmp.winsizetmp;
65 }else{
66 geom.y=rtmp.winpostmp;
67 geom.h=rtmp.winsizetmp;
70 draw_rubberband(scr, geom, rtmp.dir==VERTICAL);
74 static void cwin_size(WScreen *scr, int *w, int *h, XSizeHints *sh)
76 correct_size(w, h, sh, FALSE);
78 if(sh->flags&PBaseSize){
79 *w-=sh->base_width;
80 *h-=sh->base_height;
83 if(sh->flags&PResizeInc){
84 *w/=sh->width_inc;
85 *h/=sh->height_inc;
86 }else{
87 *w/=scr->w_unit;
88 *h/=scr->h_unit;
93 static void res_draw_moveres(WScreen *scr, WWindow *wwin)
95 int w, h, x, y;
96 WClientWin *cwin;
98 if(rtmp.dir==HORIZONTAL){
99 x=rtmp.winpostmp;
100 w=rtmp.winsizetmp;
101 h=wwin->geom.h;
102 y=wwin->geom.y;
103 }else{
104 x=wwin->geom.x;
105 w=wwin->geom.w;
106 y=rtmp.winpostmp;
107 h=rtmp.winsizetmp;
110 if(WTHING_IS(wwin, WFrame)){
111 w+=FRAME_CLIENT_WOFF(scr);
112 h+=FRAME_CLIENT_HOFF(scr);
113 if(((WFrame*)wwin)->current_client!=NULL &&
114 (cwin=FIRST_THING(((WFrame*)wwin)->current_client,
115 WClientWin))!=NULL){
116 cwin_size(scr, &w, &h, &(cwin->size_hints));
117 }else{
118 w/=scr->w_unit;
119 h/=scr->h_unit;
123 set_moveres_size(scr, w, h);
127 /*}}}*/
130 /*{{{ Resize/common */
133 static int do_calc_resize(int s, int unit, int off)
135 s-=off;
136 s=(s/unit)*unit;
137 return s+off;
141 static int calc_resize(WScreen *scr, int s, int dir)
143 if(dir==VERTICAL)
144 return do_calc_resize(s, scr->h_unit, FRAME_CLIENT_HOFF(scr));
145 else
146 return do_calc_resize(s, scr->w_unit, FRAME_CLIENT_WOFF(scr));
150 void begin_resize(WWindow *wwin, int dir, int primn)
152 WScreen *scr=SCREEN_OF(wwin);
154 tmpsize=wwin_size(wwin, dir);
155 resize_mode=TRUE;
157 if(XOR_RESIZE)
158 XGrabServer(wglobal.dpy);
160 XMoveWindow(wglobal.dpy, scr->grdata.moveres_win,
161 wwin->geom.x+(wwin->geom.w-scr->grdata.moveres_geom.w)/2,
162 wwin->geom.y+(wwin->geom.h-scr->grdata.moveres_geom.h)/2);
163 XMapRaised(wglobal.dpy, scr->grdata.moveres_win);
165 calcresize_window(wwin, dir, primn, tmpsize, &rtmp);
167 res_draw_moveres(scr, wwin);
169 if(XOR_RESIZE)
170 res_draw_rubberband(scr, wwin->geom);
174 void resize(WWindow *wwin, int delta, int primn, bool settmp)
176 WScreen *scr=SCREEN_OF(wwin);
177 int s, old;
178 int dir=rtmp.dir;
180 if(XOR_RESIZE)
181 res_draw_rubberband(scr, wwin->geom);
183 tmpsize+=delta;
184 s=calc_resize(SCREEN_OF(wwin), tmpsize, dir);
185 old=rtmp.winsizetmp;
187 calcresize_window(wwin, dir, primn, s, &rtmp);
189 if(settmp)
190 tmpsize=rtmp.winsizetmp;
192 res_draw_moveres(scr, wwin);
194 if(XOR_RESIZE)
195 res_draw_rubberband(scr, wwin->geom);
196 else
197 resize_tmp(&rtmp);
201 void end_resize(WWindow *wwin)
203 WScreen *scr=SCREEN_OF(wwin);
205 if(!resize_mode)
206 return;
208 resize_mode=FALSE;
210 reset_timer(&resize_timer);
212 if(XOR_RESIZE){
213 res_draw_rubberband(scr, wwin->geom);
214 resize_tmp(&rtmp);
215 XUngrabServer(wglobal.dpy);
217 XUnmapWindow(wglobal.dpy, scr->grdata.moveres_win);
221 void cancel_resize(WWindow *wwin)
223 WScreen *scr=SCREEN_OF(wwin);
225 if(!resize_mode)
226 return;
228 resize_mode=FALSE;
230 reset_timer(&resize_timer);
232 if(XOR_RESIZE){
233 res_draw_rubberband(scr, wwin->geom);
234 XUngrabServer(wglobal.dpy);
236 XUnmapWindow(wglobal.dpy, scr->grdata.moveres_win);
240 /*}}}*/
243 /*{{{ Keyboard resize */
245 static bool resize_handler(WThing *thing, XEvent *xev)
247 XKeyEvent *ev=&xev->xkey;
248 WScreen *scr;
249 WBinding *binding=NULL;
250 WBindmap **bindptr;
252 if(!resize_mode){
253 return TRUE;
256 if(ev->type==KeyRelease)
257 return FALSE;
259 assert(thing && WTHING_IS(thing, WWindow));
260 binding=lookup_binding(&wglobal.moveres_bindmap, ACT_KEYPRESS, ev->state, ev->keycode);
262 if(!binding)
263 return FALSE;
265 if(binding){
266 /* Get the screen now for waitrel grab - the thing might
267 * have been destroyed when call_binding returns.
269 scr=SCREEN_OF(thing);
270 call_binding(binding, thing);
273 return !resize_mode;
276 static void begin_keyresize(WWindow *wwin, int dir)
278 if(resize_mode)
279 return;
281 begin_resize(wwin, dir, ANY);
283 grab_establish((WThing*)wwin, resize_handler, FocusChangeMask);
284 change_grab_cursor(CURSOR_RESIZE);
288 static int get_unit(WWindow *wwin)
290 WScreen *scr=SCREEN_OF(wwin);
291 return (rtmp.dir==VERTICAL ? scr->h_unit : scr->w_unit);
295 void grow(WWindow *wwin)
297 if(!resize_mode)
298 resize_vert(wwin);
299 resize(wwin, get_unit(wwin), ANY, TRUE);
300 set_timer(&resize_timer, wglobal.resize_delay);
304 void shrink(WWindow *wwin)
306 if(!resize_mode)
307 resize_vert(wwin);
308 resize(wwin, -get_unit(wwin), ANY, TRUE);
309 set_timer(&resize_timer, wglobal.resize_delay);
313 void resize_vert(WWindow *wwin)
315 begin_keyresize(wwin, VERTICAL);
319 void resize_horiz(WWindow *wwin)
321 begin_keyresize(wwin, HORIZONTAL);
325 /*}}}*/
328 /*{{{ Maximize */
331 static void do_maximize(WWindow *wwin, int dir, int flag,
332 int *saved_size, int max_size)
334 WResizeTmp rtmp;
336 if(wwin->flags&flag){
337 calcresize_window(wwin, dir, ANY, *saved_size, &rtmp);
338 resize_tmp(&rtmp);
339 wwin->flags&=~flag;
340 }else{
341 *saved_size=wwin_size(wwin, dir);
342 calcresize_window(wwin, dir, ANY, max_size, &rtmp);
343 resize_tmp(&rtmp);
344 wwin->flags|=flag;
349 void maximize_vert(WWindow *wwin)
351 WScreen *scr=SCREEN_OF(wwin);
353 if(scr!=NULL){
354 do_maximize(wwin, VERTICAL, WWINDOW_HFORCED,
355 &(wwin->saved_h), scr->root.geom.h);
360 void maximize_horiz(WWindow *wwin)
362 WScreen *scr=SCREEN_OF(wwin);
364 if(scr!=NULL){
365 do_maximize(wwin, HORIZONTAL, WWINDOW_WFORCED,
366 &(wwin->saved_w), scr->root.geom.w);
371 /*}}}*/
374 /*{{{ Set size */
377 void set_height(WWindow *wwin, uint h)
379 WResizeTmp rtmp;
380 calcresize_window(wwin, VERTICAL, ANY, h, &rtmp);
381 resize_tmp(&rtmp);
385 void set_width(WWindow *wwin, uint w)
387 WResizeTmp rtmp;
388 calcresize_window(wwin, HORIZONTAL, ANY, w, &rtmp);
389 resize_tmp(&rtmp);
392 void set_heightq(WWindow *wwin, double q)
394 WScreen *scr=SCREEN_OF(wwin);
395 set_height(wwin, q*(double)scr->root.geom.h);
398 void set_widthq(WWindow *wwin, double q)
400 WScreen *scr=SCREEN_OF(wwin);
401 set_width(wwin, q*(double)scr->root.geom.w);
404 /*}}}*/