JWM Source Documentation
resize.c
Go to the documentation of this file.
1 
10 #include "jwm.h"
11 #include "resize.h"
12 #include "client.h"
13 #include "outline.h"
14 #include "cursor.h"
15 #include "misc.h"
16 #include "pager.h"
17 #include "status.h"
18 #include "key.h"
19 #include "event.h"
20 #include "settings.h"
21 
22 static char shouldStopResize;
23 
24 static void StopResize(ClientNode *np);
25 static void ResizeController(int wasDestroyed);
26 static void FixWidth(ClientNode *np);
27 static void FixHeight(ClientNode *np);
28 
30 void ResizeController(int wasDestroyed)
31 {
33  ClearOutline();
34  }
35  JXUngrabPointer(display, CurrentTime);
36  JXUngrabKeyboard(display, CurrentTime);
38  shouldStopResize = 1;
39 }
40 
43  int startx, int starty)
44 {
45 
46  XEvent event;
47  int oldx, oldy;
48  int oldw, oldh;
49  int gwidth, gheight;
50  int lastgwidth, lastgheight;
51  int delta;
52  int north, south, east, west;
53 
54  Assert(np);
55 
56  if(!(np->state.border & BORDER_RESIZE)) {
57  return;
58  }
59  if((np->state.status & STAT_FULLSCREEN) || np->state.maxFlags) {
60  return;
61  }
62  if(JUNLIKELY(!GrabMouseForResize(action))) {
63  return;
64  }
65 
67  shouldStopResize = 0;
68 
69  oldx = np->x;
70  oldy = np->y;
71  oldw = np->width;
72  oldh = np->height;
73 
74  gwidth = (np->width - np->baseWidth) / np->xinc;
75  gheight = (np->height - np->baseHeight) / np->yinc;
76 
77  GetBorderSize(&np->state, &north, &south, &east, &west);
78 
79  startx += np->x - west;
80  starty += np->y - north;
81 
83  UpdateResizeWindow(np, gwidth, gheight);
84 
85  if(!(GetMouseMask() & (Button1Mask | Button3Mask))) {
86  StopResize(np);
87  return;
88  }
89 
90  for(;;) {
91 
92  WaitForEvent(&event);
93 
94  if(shouldStopResize) {
95  np->controller = NULL;
96  return;
97  }
98 
99  switch(event.type) {
100  case ButtonRelease:
101  if( event.xbutton.button == Button1
102  || event.xbutton.button == Button3) {
103  StopResize(np);
104  return;
105  }
106  break;
107  case MotionNotify:
108 
109  SetMousePosition(event.xmotion.x_root, event.xmotion.y_root,
110  event.xmotion.window);
111  DiscardMotionEvents(&event, np->window);
112 
113  if(action & BA_RESIZE_N) {
114  delta = (event.xmotion.y - starty) / np->yinc;
115  delta *= np->yinc;
116  if(oldh - delta >= np->minHeight
117  && (oldh - delta <= np->maxHeight || delta > 0)) {
118  np->height = oldh - delta;
119  np->y = oldy + delta;
120  }
121  if(!(action & (BA_RESIZE_E | BA_RESIZE_W))) {
122  FixWidth(np);
123  }
124  }
125  if(action & BA_RESIZE_S) {
126  delta = (event.xmotion.y - starty) / np->yinc;
127  delta *= np->yinc;
128  np->height = oldh + delta;
129  np->height = Max(np->height, np->minHeight);
130  np->height = Min(np->height, np->maxHeight);
131  if(!(action & (BA_RESIZE_E | BA_RESIZE_W))) {
132  FixWidth(np);
133  }
134  }
135  if(action & BA_RESIZE_E) {
136  delta = (event.xmotion.x - startx) / np->xinc;
137  delta *= np->xinc;
138  np->width = oldw + delta;
139  np->width = Max(np->width, np->minWidth);
140  np->width = Min(np->width, np->maxWidth);
141  if(!(action & (BA_RESIZE_N | BA_RESIZE_S))) {
142  FixHeight(np);
143  }
144  }
145  if(action & BA_RESIZE_W) {
146  delta = (event.xmotion.x - startx) / np->xinc;
147  delta *= np->xinc;
148  if(oldw - delta >= np->minWidth
149  && (oldw - delta <= np->maxWidth || delta > 0)) {
150  np->width = oldw - delta;
151  np->x = oldx + delta;
152  }
153  if(!(action & (BA_RESIZE_N | BA_RESIZE_S))) {
154  FixHeight(np);
155  }
156  }
157 
158  if(np->sizeFlags & PAspect) {
159  if((action & (BA_RESIZE_N | BA_RESIZE_S)) &&
160  (action & (BA_RESIZE_E | BA_RESIZE_W))) {
161 
162  if(np->width * np->aspect.miny < np->height * np->aspect.minx) {
163  delta = np->width;
164  np->width = (np->height * np->aspect.minx) / np->aspect.miny;
165  if(action & BA_RESIZE_W) {
166  np->x -= np->width - delta;
167  }
168  }
169  if(np->width * np->aspect.maxy > np->height * np->aspect.maxx) {
170  delta = np->height;
171  np->height = (np->width * np->aspect.maxy) / np->aspect.maxx;
172  if(action & BA_RESIZE_N) {
173  np->y -= np->height - delta;
174  }
175  }
176  }
177  }
178 
179  lastgwidth = gwidth;
180  lastgheight = gheight;
181 
182  gwidth = (np->width - np->baseWidth) / np->xinc;
183  gheight = (np->height - np->baseHeight) / np->yinc;
184 
185  if(lastgheight != gheight || lastgwidth != gwidth) {
186 
187  UpdateResizeWindow(np, gwidth, gheight);
188 
190  ClearOutline();
191  if(np->state.status & STAT_SHADED) {
192  DrawOutline(np->x - west, np->y - north,
193  np->width + west + east, north + south);
194  } else {
195  DrawOutline(np->x - west, np->y - north,
196  np->width + west + east,
197  np->height + north + south);
198  }
199  } else {
200  ResetBorder(np);
201  SendConfigureEvent(np);
202  }
203 
205 
206  }
207 
208  break;
209  default:
210  break;
211  }
212  }
213 
214 }
215 
218 {
219 
220  XEvent event;
221  int gwidth, gheight;
222  int lastgwidth, lastgheight;
223  int north, south, east, west;
224  int deltax, deltay;
225  int ratio, minr, maxr;
226 
227  Assert(np);
228 
229  if(!(np->state.border & BORDER_RESIZE)) {
230  return;
231  }
232  if((np->state.status & STAT_FULLSCREEN) || np->state.maxFlags) {
233  return;
234  }
235 
236  if(JUNLIKELY(JXGrabKeyboard(display, np->parent, True, GrabModeAsync,
237  GrabModeAsync, CurrentTime) != GrabSuccess)) {
238  return;
239  }
241  JXUngrabKeyboard(display, CurrentTime);
242  return;
243  }
244 
246  shouldStopResize = 0;
247 
248  gwidth = (np->width - np->baseWidth) / np->xinc;
249  gheight = (np->height - np->baseHeight) / np->yinc;
250 
251  GetBorderSize(&np->state, &north, &south, &east, &west);
252 
253  CreateResizeWindow(np);
254  UpdateResizeWindow(np, gwidth, gheight);
255 
256  if(np->state.status & STAT_SHADED) {
257  MoveMouse(rootWindow, np->x + np->width, np->y);
258  } else {
259  MoveMouse(rootWindow, np->x + np->width, np->y + np->height);
260  }
261  DiscardMotionEvents(&event, np->window);
262 
263  for(;;) {
264 
265  WaitForEvent(&event);
266 
267  if(shouldStopResize) {
268  np->controller = NULL;
269  return;
270  }
271 
272  deltax = 0;
273  deltay = 0;
274 
275  if(event.type == KeyPress) {
276 
277  DiscardKeyEvents(&event, np->window);
278  switch(GetKey(&event.xkey) & 0xFF) {
279  case KEY_UP:
280  deltay = Min(-np->yinc, -10);
281  break;
282  case KEY_DOWN:
283  deltay = Max(np->yinc, 10);
284  break;
285  case KEY_RIGHT:
286  deltax = Max(np->xinc, 10);
287  break;
288  case KEY_LEFT:
289  deltax = Min(-np->xinc, -10);
290  break;
291  default:
292  StopResize(np);
293  return;
294  }
295 
296  } else if(event.type == MotionNotify) {
297 
298  SetMousePosition(event.xmotion.x_root, event.xmotion.y_root,
299  event.xmotion.window);
300  DiscardMotionEvents(&event, np->window);
301 
302  deltax = event.xmotion.x - (np->x + np->width);
303  if(np->state.status & STAT_SHADED) {
304  deltay = 0;
305  } else {
306  deltay = event.xmotion.y - (np->y + np->height);
307  }
308 
309  } else if(event.type == ButtonRelease) {
310 
311  StopResize(np);
312  return;
313 
314  }
315 
316  if(abs(deltax) < np->xinc && abs(deltay) < np->yinc) {
317  continue;
318  }
319 
320  deltay -= deltay % np->yinc;
321  np->height += deltay;
322  np->height = Max(np->height, np->minHeight);
323  np->height = Min(np->height, np->maxHeight);
324  deltax -= deltax % np->xinc;
325  np->width += deltax;
326  np->width = Max(np->width, np->minWidth);
327  np->width = Min(np->width, np->maxWidth);
328 
329  if(np->sizeFlags & PAspect) {
330 
331  ratio = (np->width << 16) / np->height;
332 
333  minr = (np->aspect.minx << 16) / np->aspect.miny;
334  if(ratio < minr) {
335  np->width = (np->height * minr) >> 16;
336  }
337 
338  maxr = (np->aspect.maxx << 16) / np->aspect.maxy;
339  if(ratio > maxr) {
340  np->height = (np->width << 16) / maxr;
341  }
342 
343  }
344 
345  lastgwidth = gwidth;
346  lastgheight = gheight;
347  gwidth = (np->width - np->baseWidth) / np->xinc;
348  gheight = (np->height - np->baseHeight) / np->yinc;
349 
350  if(lastgwidth != gwidth || lastgheight != gheight) {
351 
352  UpdateResizeWindow(np, gwidth, gheight);
353 
355  ClearOutline();
356  if(np->state.status & STAT_SHADED) {
357  DrawOutline(np->x - west, np->y - north,
358  np->width + west + east,
359  north + south);
360  } else {
361  DrawOutline(np->x - west, np->y - north,
362  np->width + west + east,
363  np->height + north + south);
364  }
365  } else {
366  ResetBorder(np);
367  SendConfigureEvent(np);
368  }
369 
371 
372  }
373 
374  }
375 
376 }
377 
380 {
381 
382  np->controller = NULL;
383 
384  /* Set the old width/height if maximized so the window
385  * is restored to the new size. */
386  if(np->state.maxFlags & MAX_VERT) {
387  np->oldWidth = np->width;
388  np->oldx = np->x;
389  }
390  if(np->state.maxFlags & MAX_HORIZ) {
391  np->oldHeight = np->height;
392  np->oldy = np->y;
393  }
394 
396  ClearOutline();
397  }
398 
399  JXUngrabPointer(display, CurrentTime);
400  JXUngrabKeyboard(display, CurrentTime);
401 
403 
404  ResetBorder(np);
405  SendConfigureEvent(np);
406 
407 }
408 
411 {
412 
413  Assert(np);
414 
415  if((np->sizeFlags & PAspect) && np->height > 0) {
416  if(np->width * np->aspect.miny < np->height * np->aspect.minx) {
417  np->width = (np->height * np->aspect.minx) / np->aspect.miny;
418  }
419  if(np->width * np->aspect.maxy > np->height * np->aspect.maxx) {
420  np->width = (np->height * np->aspect.maxx) / np->aspect.maxy;
421  }
422  }
423 
424 }
425 
428 {
429 
430  Assert(np);
431 
432  if((np->sizeFlags & PAspect) && np->height > 0) {
433  if(np->width * np->aspect.miny < np->height * np->aspect.minx) {
434  np->height = (np->width * np->aspect.miny) / np->aspect.minx;
435  }
436  if(np->width * np->aspect.maxy > np->height * np->aspect.maxx) {
437  np->height = (np->width * np->aspect.maxy) / np->aspect.maxx;
438  }
439  }
440 
441 }
442 

joewing.net / Projects / JWM