]> Dogcows Code - chaz/openbox/blob - openbox/moveresize.c
or a full second?
[chaz/openbox] / openbox / moveresize.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3 moveresize.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 See the COPYING file for a copy of the GNU General Public License.
18 */
19
20 #include "grab.h"
21 #include "framerender.h"
22 #include "screen.h"
23 #include "prop.h"
24 #include "client.h"
25 #include "frame.h"
26 #include "openbox.h"
27 #include "resist.h"
28 #include "mainloop.h"
29 #include "modkeys.h"
30 #include "popup.h"
31 #include "moveresize.h"
32 #include "config.h"
33 #include "event.h"
34 #include "debug.h"
35 #include "extensions.h"
36 #include "render/render.h"
37 #include "render/theme.h"
38
39 #include <X11/Xlib.h>
40 #include <glib.h>
41
42 /* how far windows move and resize with the keyboard arrows */
43 #define KEY_DIST 8
44
45 gboolean moveresize_in_progress = FALSE;
46 ObClient *moveresize_client = NULL;
47 #ifdef SYNC
48 XSyncAlarm moveresize_alarm = None;
49 #endif
50
51 static gboolean moving = FALSE; /* TRUE - moving, FALSE - resizing */
52
53 static gint start_x, start_y, start_cx, start_cy, start_cw, start_ch;
54 static gint cur_x, cur_y, cur_w, cur_h;
55 static guint button;
56 static guint32 corner;
57 static ObCorner lockcorner;
58 static ObDirection edge_warp_dir = -1;
59 static ObDirection key_resize_edge = -1;
60 #ifdef SYNC
61 static gboolean waiting_for_sync;
62 #endif
63
64 static ObPopup *popup = NULL;
65
66 static void do_edge_warp(gint x, gint y);
67 static void cancel_edge_warp();
68 #ifdef SYNC
69 static gboolean sync_timeout_func(gpointer data);
70 #endif
71
72 static void client_dest(ObClient *client, gpointer data)
73 {
74 if (moveresize_client == client)
75 moveresize_end(TRUE);
76 }
77
78 void moveresize_startup(gboolean reconfig)
79 {
80 popup = popup_new(FALSE);
81 popup_set_text_align(popup, RR_JUSTIFY_CENTER);
82
83 if (!reconfig)
84 client_add_destroy_notify(client_dest, NULL);
85 }
86
87 void moveresize_shutdown(gboolean reconfig)
88 {
89 if (!reconfig) {
90 if (moveresize_in_progress)
91 moveresize_end(FALSE);
92 client_remove_destroy_notify(client_dest);
93 }
94
95 popup_free(popup);
96 popup = NULL;
97 }
98
99 static void popup_coords(ObClient *c, const gchar *format, gint a, gint b)
100 {
101 gchar *text;
102
103 text = g_strdup_printf(format, a, b);
104 if (config_resize_popup_pos == 1) /* == "Top" */
105 popup_position(popup, SouthGravity,
106 c->frame->area.x
107 + c->frame->area.width/2,
108 c->frame->area.y - ob_rr_theme->fbwidth);
109 else /* == "Center" */
110 popup_position(popup, CenterGravity,
111 c->frame->area.x + c->frame->size.left +
112 c->area.width / 2,
113 c->frame->area.y + c->frame->size.top +
114 c->area.height / 2);
115 popup_show(popup, text);
116 g_free(text);
117 }
118
119 void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
120 {
121 ObCursor cur;
122 gboolean mv = (cnr == prop_atoms.net_wm_moveresize_move ||
123 cnr == prop_atoms.net_wm_moveresize_move_keyboard);
124
125 if (moveresize_in_progress || !c->frame->visible ||
126 !(mv ?
127 (c->functions & OB_CLIENT_FUNC_MOVE) :
128 (c->functions & OB_CLIENT_FUNC_RESIZE)))
129 return;
130
131 if (cnr == prop_atoms.net_wm_moveresize_size_topleft)
132 cur = OB_CURSOR_NORTHWEST;
133 else if (cnr == prop_atoms.net_wm_moveresize_size_top)
134 cur = OB_CURSOR_NORTH;
135 else if (cnr == prop_atoms.net_wm_moveresize_size_topright)
136 cur = OB_CURSOR_NORTHEAST;
137 else if (cnr == prop_atoms.net_wm_moveresize_size_right)
138 cur = OB_CURSOR_EAST;
139 else if (cnr == prop_atoms.net_wm_moveresize_size_bottomright)
140 cur = OB_CURSOR_SOUTHEAST;
141 else if (cnr == prop_atoms.net_wm_moveresize_size_bottom)
142 cur = OB_CURSOR_SOUTH;
143 else if (cnr == prop_atoms.net_wm_moveresize_size_bottomleft)
144 cur = OB_CURSOR_SOUTHWEST;
145 else if (cnr == prop_atoms.net_wm_moveresize_size_left)
146 cur = OB_CURSOR_WEST;
147 else if (cnr == prop_atoms.net_wm_moveresize_size_keyboard)
148 cur = OB_CURSOR_SOUTHEAST;
149 else if (cnr == prop_atoms.net_wm_moveresize_move)
150 cur = OB_CURSOR_MOVE;
151 else if (cnr == prop_atoms.net_wm_moveresize_move_keyboard)
152 cur = OB_CURSOR_MOVE;
153 else
154 g_assert_not_reached();
155
156 /* keep the pointer bounded to the screen for move/resize */
157 if (!grab_pointer(FALSE, TRUE, cur))
158 return;
159 if (!grab_keyboard()) {
160 ungrab_pointer();
161 return;
162 }
163
164 frame_end_iconify_animation(c->frame);
165
166 moving = mv;
167 moveresize_client = c;
168 start_cx = c->area.x;
169 start_cy = c->area.y;
170 /* these adjustments for the size_inc make resizing a terminal more
171 friendly. you essentially start the resize in the middle of the
172 increment instead of at 0, so you have to move half an increment
173 either way instead of a full increment one and 1 px the other. */
174 start_cw = c->area.width + c->size_inc.width / 2;
175 start_ch = c->area.height + c->size_inc.height / 2;
176 start_x = x;
177 start_y = y;
178 corner = cnr;
179 button = b;
180 key_resize_edge = -1;
181
182 /*
183 have to change start_cx and start_cy if going to do this..
184 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
185 corner == prop_atoms.net_wm_moveresize_size_keyboard)
186 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
187 c->area.width / 2, c->area.height / 2);
188 */
189
190 cur_x = start_cx;
191 cur_y = start_cy;
192 cur_w = start_cw;
193 cur_h = start_ch;
194
195 moveresize_in_progress = TRUE;
196
197 #ifdef SYNC
198 if (config_resize_redraw && !moving && extensions_shape &&
199 moveresize_client->sync_request && moveresize_client->sync_counter)
200 {
201 /* Initialize values for the resize syncing, and create an alarm for
202 the client's xsync counter */
203
204 XSyncValue val;
205 XSyncAlarmAttributes aa;
206
207 /* set the counter to an initial value */
208 XSyncIntToValue(&val, 0);
209 XSyncSetCounter(ob_display, moveresize_client->sync_counter, val);
210
211 /* this will be incremented when we tell the client what we're
212 looking for */
213 moveresize_client->sync_counter_value = 0;
214
215 /* the next sequence we're waiting for with the alarm */
216 XSyncIntToValue(&val, 1);
217
218 /* set an alarm on the counter */
219 aa.trigger.counter = moveresize_client->sync_counter;
220 aa.trigger.wait_value = val;
221 aa.trigger.value_type = XSyncAbsolute;
222 aa.trigger.test_type = XSyncPositiveTransition;
223 aa.events = True;
224 XSyncIntToValue(&aa.delta, 1);
225 moveresize_alarm = XSyncCreateAlarm(ob_display,
226 XSyncCACounter |
227 XSyncCAValue |
228 XSyncCAValueType |
229 XSyncCATestType |
230 XSyncCADelta |
231 XSyncCAEvents,
232 &aa);
233
234 waiting_for_sync = FALSE;
235 }
236 #endif
237 }
238
239 void moveresize_end(gboolean cancel)
240 {
241 ungrab_keyboard();
242 ungrab_pointer();
243
244 popup_hide(popup);
245
246 if (moving) {
247 client_move(moveresize_client,
248 (cancel ? start_cx : cur_x),
249 (cancel ? start_cy : cur_y));
250 } else {
251 #ifdef SYNC
252 /* turn off the alarm */
253 if (moveresize_alarm != None) {
254 XSyncDestroyAlarm(ob_display, moveresize_alarm);
255 moveresize_alarm = None;
256 }
257
258 ob_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
259 #endif
260
261 client_configure(moveresize_client,
262 (cancel ? start_cx : cur_x),
263 (cancel ? start_cy : cur_y),
264 (cancel ? start_cw : cur_w),
265 (cancel ? start_ch : cur_h),
266 TRUE, TRUE, FALSE);
267 }
268
269 /* dont edge warp after its ended */
270 cancel_edge_warp();
271
272 moveresize_in_progress = FALSE;
273 moveresize_client = NULL;
274 }
275
276 static void do_move(gboolean keyboard, gint keydist)
277 {
278 gint resist;
279
280 if (keyboard) resist = keydist - 1; /* resist for one key press */
281 else resist = config_resist_win;
282 resist_move_windows(moveresize_client, resist, &cur_x, &cur_y);
283 if (!keyboard) resist = config_resist_edge;
284 resist_move_monitors(moveresize_client, resist, &cur_x, &cur_y);
285
286 client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h,
287 TRUE, FALSE, FALSE);
288 if (config_resize_popup_show == 2) /* == "Always" */
289 popup_coords(moveresize_client, "%d x %d",
290 moveresize_client->frame->area.x,
291 moveresize_client->frame->area.y);
292 }
293
294
295 static void do_resize()
296 {
297 gint x, y, w, h, lw, lh;
298
299 /* see if it is actually going to resize */
300 x = 0;
301 y = 0;
302 w = cur_w;
303 h = cur_h;
304 client_try_configure(moveresize_client, &x, &y, &w, &h,
305 &lw, &lh, TRUE);
306 if (w == moveresize_client->area.width &&
307 h == moveresize_client->area.height)
308 {
309 return;
310 }
311
312 #ifdef SYNC
313 if (config_resize_redraw && extensions_sync &&
314 moveresize_client->sync_request && moveresize_client->sync_counter)
315 {
316 XEvent ce;
317 XSyncValue val;
318
319 /* are we already waiting for the sync counter to catch up? */
320 if (waiting_for_sync)
321 return;
322
323 /* increment the value we're waiting for */
324 ++moveresize_client->sync_counter_value;
325 XSyncIntToValue(&val, moveresize_client->sync_counter_value);
326
327 /* tell the client what we're waiting for */
328 ce.xclient.type = ClientMessage;
329 ce.xclient.message_type = prop_atoms.wm_protocols;
330 ce.xclient.display = ob_display;
331 ce.xclient.window = moveresize_client->window;
332 ce.xclient.format = 32;
333 ce.xclient.data.l[0] = prop_atoms.net_wm_sync_request;
334 ce.xclient.data.l[1] = event_curtime;
335 ce.xclient.data.l[2] = XSyncValueLow32(val);
336 ce.xclient.data.l[3] = XSyncValueHigh32(val);
337 ce.xclient.data.l[4] = 0l;
338 XSendEvent(ob_display, moveresize_client->window, FALSE,
339 NoEventMask, &ce);
340
341 waiting_for_sync = TRUE;
342
343 ob_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
344 ob_main_loop_timeout_add(ob_main_loop, G_USEC_PER_SEC,
345 sync_timeout_func,
346 NULL, NULL, NULL);
347 }
348 #endif
349
350 client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h,
351 TRUE, FALSE, FALSE);
352
353 /* this would be better with a fixed width font ... XXX can do it better
354 if there are 2 text boxes */
355 if (config_resize_popup_show == 2 || /* == "Always" */
356 (config_resize_popup_show == 1 && /* == "Nonpixel" */
357 moveresize_client->size_inc.width > 1 &&
358 moveresize_client->size_inc.height > 1))
359 popup_coords(moveresize_client, "%d x %d",
360 moveresize_client->logical_size.width,
361 moveresize_client->logical_size.height);
362 }
363
364 #ifdef SYNC
365 static gboolean sync_timeout_func(gpointer data)
366 {
367 waiting_for_sync = FALSE; /* we timed out waiting for our sync... */
368 do_resize(); /* ...so let any pending resizes through */
369
370 return FALSE; /* don't repeat */
371 }
372 #endif
373
374 static void calc_resize(gboolean keyboard, gint keydist, gint *dw, gint *dh,
375 ObCorner cor)
376 {
377 gint resist, ow, oh, nw, nh;
378
379 /* resist_size_* needs the frame size */
380 ow = cur_w +
381 moveresize_client->frame->size.left +
382 moveresize_client->frame->size.right;
383 oh = cur_h +
384 moveresize_client->frame->size.top +
385 moveresize_client->frame->size.bottom;
386 nw = ow + *dw;
387 nh = oh + *dh;
388
389 if (keyboard) resist = keydist - 1; /* resist for one key press */
390 else resist = config_resist_win;
391 resist_size_windows(moveresize_client, resist, &nw, &nh, cor);
392 if (!keyboard) resist = config_resist_edge;
393 resist_size_monitors(moveresize_client, resist, &nw, &nh, cor);
394
395 *dw = nw - ow;
396 *dh = nh - oh;
397 }
398
399 static gboolean edge_warp_delay_func(gpointer data)
400 {
401 guint d;
402
403 d = screen_find_desktop(screen_desktop, edge_warp_dir, TRUE, FALSE);
404 if (d != screen_desktop) screen_set_desktop(d, TRUE);
405
406 edge_warp_dir = -1;
407
408 return FALSE; /* don't repeat */
409 }
410
411 static void do_edge_warp(gint x, gint y)
412 {
413 guint i;
414 ObDirection dir;
415
416 if (!config_mouse_screenedgetime) return;
417
418 dir = -1;
419
420 for (i = 0; i < screen_num_monitors; ++i) {
421 Rect *a = screen_physical_area_monitor(i);
422 if (x == RECT_LEFT(*a)) dir = OB_DIRECTION_WEST;
423 if (x == RECT_RIGHT(*a)) dir = OB_DIRECTION_EAST;
424 if (y == RECT_TOP(*a)) dir = OB_DIRECTION_NORTH;
425 if (y == RECT_BOTTOM(*a)) dir = OB_DIRECTION_SOUTH;
426
427 /* try check for xinerama boundaries */
428 if ((x + 1 == RECT_LEFT(*a) || x - 1 == RECT_RIGHT(*a)) &&
429 (dir == OB_DIRECTION_WEST || dir == OB_DIRECTION_EAST))
430 {
431 dir = -1;
432 }
433 if ((y + 1 == RECT_TOP(*a) || y - 1 == RECT_BOTTOM(*a)) &&
434 (dir == OB_DIRECTION_NORTH || dir == OB_DIRECTION_SOUTH))
435 {
436 dir = -1;
437 }
438 g_free(a);
439 }
440
441 if (dir != edge_warp_dir) {
442 if (dir == (ObDirection)-1)
443 cancel_edge_warp();
444 else
445 ob_main_loop_timeout_add(ob_main_loop,
446 config_mouse_screenedgetime * 1000,
447 edge_warp_delay_func,
448 NULL, NULL, NULL);
449 edge_warp_dir = dir;
450 }
451 }
452
453 static void cancel_edge_warp()
454 {
455 ob_main_loop_timeout_remove(ob_main_loop, edge_warp_delay_func);
456 }
457
458 static void move_with_keys(gint keycode, gint state)
459 {
460 gint dx = 0, dy = 0, ox = cur_x, oy = cur_y;
461 gint opx, px, opy, py;
462 gint dist = 0;
463
464 /* shift means jump to edge */
465 if (state & modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT)) {
466 gint x, y;
467 ObDirection dir;
468
469 if (keycode == ob_keycode(OB_KEY_RIGHT))
470 dir = OB_DIRECTION_EAST;
471 else if (keycode == ob_keycode(OB_KEY_LEFT))
472 dir = OB_DIRECTION_WEST;
473 else if (keycode == ob_keycode(OB_KEY_DOWN))
474 dir = OB_DIRECTION_SOUTH;
475 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
476 dir = OB_DIRECTION_NORTH;
477
478 client_find_move_directional(moveresize_client, dir, &x, &y);
479 dx = x - moveresize_client->area.x;
480 dy = y - moveresize_client->area.y;
481 } else {
482 /* control means fine grained */
483 if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
484 dist = 1;
485 else
486 dist = KEY_DIST;
487
488 if (keycode == ob_keycode(OB_KEY_RIGHT))
489 dx = dist;
490 else if (keycode == ob_keycode(OB_KEY_LEFT))
491 dx = -dist;
492 else if (keycode == ob_keycode(OB_KEY_DOWN))
493 dy = dist;
494 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
495 dy = -dist;
496 }
497
498 screen_pointer_pos(&opx, &opy);
499 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
500 /* steal the motion events this causes */
501 XSync(ob_display, FALSE);
502 {
503 XEvent ce;
504 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
505 }
506 screen_pointer_pos(&px, &py);
507
508 cur_x += dx;
509 cur_y += dy;
510 do_move(TRUE, dist);
511
512 /* because the cursor moves even though the window does
513 not nessesarily (resistance), this adjusts where the curor
514 thinks it started so that it keeps up with where the window
515 actually is */
516 start_x += (px - opx) - (cur_x - ox);
517 start_y += (py - opy) - (cur_y - oy);
518 }
519
520 static void resize_with_keys(gint keycode, gint state)
521 {
522 gint dw = 0, dh = 0, pdx = 0, pdy = 0, opx, opy, px, py;
523 gint dist = 0;
524 ObDirection dir;
525 ObCorner cor;
526
527 /* pick the edge if it needs to move */
528 if (keycode == ob_keycode(OB_KEY_RIGHT)) {
529 dir = OB_DIRECTION_EAST;
530 if (key_resize_edge != OB_DIRECTION_WEST &&
531 key_resize_edge != OB_DIRECTION_EAST)
532 {
533 key_resize_edge = OB_DIRECTION_EAST;
534 return;
535 }
536 }
537 if (keycode == ob_keycode(OB_KEY_LEFT)) {
538 dir = OB_DIRECTION_WEST;
539 if (key_resize_edge != OB_DIRECTION_WEST &&
540 key_resize_edge != OB_DIRECTION_EAST)
541 {
542 key_resize_edge = OB_DIRECTION_WEST;
543 return;
544 }
545 }
546 if (keycode == ob_keycode(OB_KEY_UP)) {
547 dir = OB_DIRECTION_NORTH;
548 if (key_resize_edge != OB_DIRECTION_NORTH &&
549 key_resize_edge != OB_DIRECTION_SOUTH)
550 {
551 key_resize_edge = OB_DIRECTION_NORTH;
552 return;
553 }
554 }
555 if (keycode == ob_keycode(OB_KEY_DOWN)) {
556 dir = OB_DIRECTION_SOUTH;
557 if (key_resize_edge != OB_DIRECTION_NORTH &&
558 key_resize_edge != OB_DIRECTION_SOUTH)
559 {
560 key_resize_edge = OB_DIRECTION_SOUTH;
561 return;
562 }
563 }
564
565 /* shift means jump to edge */
566 if (state & modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT)) {
567 gint x, y, w, h;
568
569 if (keycode == ob_keycode(OB_KEY_RIGHT))
570 dir = OB_DIRECTION_EAST;
571 else if (keycode == ob_keycode(OB_KEY_LEFT))
572 dir = OB_DIRECTION_WEST;
573 else if (keycode == ob_keycode(OB_KEY_DOWN))
574 dir = OB_DIRECTION_SOUTH;
575 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
576 dir = OB_DIRECTION_NORTH;
577
578 client_find_resize_directional(moveresize_client, key_resize_edge,
579 key_resize_edge == dir,
580 &x, &y, &w, &h);
581 dw = w - moveresize_client->area.width;
582 dh = h - moveresize_client->area.height;
583 } else {
584 gint distw, disth;
585
586 /* control means fine grained */
587 if (moveresize_client->size_inc.width > 1)
588 distw = moveresize_client->size_inc.width;
589 else if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
590 distw = 1;
591 else
592 distw = KEY_DIST;
593 if (moveresize_client->size_inc.height > 1)
594 disth = moveresize_client->size_inc.height;
595 else if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
596 disth = 1;
597 else
598 disth = KEY_DIST;
599
600 if (key_resize_edge == OB_DIRECTION_WEST) {
601 if (dir == OB_DIRECTION_WEST)
602 dw = (dist = distw);
603 else
604 dw = -(dist = distw);
605 }
606 else if (key_resize_edge == OB_DIRECTION_EAST) {
607 if (dir == OB_DIRECTION_EAST)
608 dw = (dist = distw);
609 else
610 dw = -(dist = distw);
611 }
612 else if (key_resize_edge == OB_DIRECTION_NORTH) {
613 if (dir == OB_DIRECTION_NORTH)
614 dh = (dist = disth);
615 else
616 dh = -(dist = disth);
617 }
618 else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
619 if (dir == OB_DIRECTION_SOUTH)
620 dh = (dist = disth);
621 else
622 dh = -(dist = disth);
623 }
624 }
625
626 /* which corner is locked, for resistance */
627 if (key_resize_edge == OB_DIRECTION_WEST)
628 cor = OB_CORNER_TOPRIGHT;
629 else if (key_resize_edge == OB_DIRECTION_EAST)
630 cor = OB_CORNER_TOPLEFT;
631 else if (key_resize_edge == OB_DIRECTION_NORTH)
632 cor = OB_CORNER_BOTTOMLEFT;
633 else if (key_resize_edge == OB_DIRECTION_SOUTH)
634 cor = OB_CORNER_TOPLEFT;
635
636 calc_resize(TRUE, dist, &dw, &dh, cor);
637 if (key_resize_edge == OB_DIRECTION_WEST)
638 cur_x -= dw;
639 else if (key_resize_edge == OB_DIRECTION_NORTH)
640 cur_y -= dh;
641 cur_w += dw;
642 cur_h += dh;
643
644 /* how to move the pointer to keep up with the change */
645 if (key_resize_edge == OB_DIRECTION_WEST)
646 pdx = -dw;
647 else if (key_resize_edge == OB_DIRECTION_EAST)
648 pdx = dw;
649 else if (key_resize_edge == OB_DIRECTION_NORTH)
650 pdy = -dh;
651 else if (key_resize_edge == OB_DIRECTION_SOUTH)
652 pdy = dh;
653
654 screen_pointer_pos(&opx, &opy);
655 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, pdx, pdy);
656 /* steal the motion events this causes */
657 XSync(ob_display, FALSE);
658 {
659 XEvent ce;
660 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
661 }
662 screen_pointer_pos(&px, &py);
663
664 do_resize();
665
666 /* because the cursor moves even though the window does
667 not nessesarily (resistance), this adjusts where the cursor
668 thinks it started so that it keeps up with where the window
669 actually is */
670 start_x += (px - opx) - dw;
671 start_y += (py - opy) - dh;
672
673 }
674
675 gboolean moveresize_event(XEvent *e)
676 {
677 gboolean used = FALSE;
678
679 if (!moveresize_in_progress) return FALSE;
680
681 if (e->type == ButtonPress) {
682 if (!button) {
683 start_x = e->xbutton.x_root;
684 start_y = e->xbutton.y_root;
685 button = e->xbutton.button; /* this will end it now */
686 }
687 used = e->xbutton.button == button;
688 } else if (e->type == ButtonRelease) {
689 if (!button || e->xbutton.button == button) {
690 moveresize_end(FALSE);
691 used = TRUE;
692 }
693 } else if (e->type == MotionNotify) {
694 if (moving) {
695 cur_x = start_cx + e->xmotion.x_root - start_x;
696 cur_y = start_cy + e->xmotion.y_root - start_y;
697 do_move(FALSE, 0);
698 do_edge_warp(e->xmotion.x_root, e->xmotion.y_root);
699 } else {
700 gint dw, dh;
701
702 if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
703 dw = -(e->xmotion.x_root - start_x);
704 dh = -(e->xmotion.y_root - start_y);
705 lockcorner = OB_CORNER_BOTTOMRIGHT;
706 } else if (corner == prop_atoms.net_wm_moveresize_size_top) {
707 dw = 0;
708 dh = (e->xmotion.y_root - start_y);
709 lockcorner = OB_CORNER_BOTTOMRIGHT;
710 } else if (corner == prop_atoms.net_wm_moveresize_size_topright) {
711 dw = (e->xmotion.x_root - start_x);
712 dh = -(e->xmotion.y_root - start_y);
713 lockcorner = OB_CORNER_BOTTOMLEFT;
714 } else if (corner == prop_atoms.net_wm_moveresize_size_right) {
715 dw = (e->xmotion.x_root - start_x);
716 dh = 0;
717 lockcorner = OB_CORNER_BOTTOMLEFT;
718 } else if (corner ==
719 prop_atoms.net_wm_moveresize_size_bottomright) {
720 dw = (e->xmotion.x_root - start_x);
721 dh = (e->xmotion.y_root - start_y);
722 lockcorner = OB_CORNER_TOPLEFT;
723 } else if (corner == prop_atoms.net_wm_moveresize_size_bottom) {
724 dw = 0;
725 dh = (e->xmotion.y_root - start_y);
726 lockcorner = OB_CORNER_TOPLEFT;
727 } else if (corner ==
728 prop_atoms.net_wm_moveresize_size_bottomleft) {
729 dw = -(e->xmotion.x_root - start_x);
730 dh = (e->xmotion.y_root - start_y);
731 lockcorner = OB_CORNER_TOPRIGHT;
732 } else if (corner == prop_atoms.net_wm_moveresize_size_left) {
733 dw = -(e->xmotion.x_root - start_x);
734 dh = 0;
735 lockcorner = OB_CORNER_TOPRIGHT;
736 } else if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
737 dw = (e->xmotion.x_root - start_x);
738 dh = (e->xmotion.y_root - start_y);
739 lockcorner = OB_CORNER_TOPLEFT;
740 } else
741 g_assert_not_reached();
742
743 dw -= cur_w - start_cw;
744 dh -= cur_h - start_ch;
745
746 calc_resize(FALSE, 0, &dw, &dh, lockcorner);
747 cur_w += dw;
748 cur_h += dh;
749
750 if (corner == prop_atoms.net_wm_moveresize_size_topleft ||
751 corner == prop_atoms.net_wm_moveresize_size_left ||
752 corner == prop_atoms.net_wm_moveresize_size_bottomleft)
753 {
754 cur_x -= dw;
755 }
756 if (corner == prop_atoms.net_wm_moveresize_size_topleft ||
757 corner == prop_atoms.net_wm_moveresize_size_top ||
758 corner == prop_atoms.net_wm_moveresize_size_topright)
759 {
760 cur_y -= dh;
761 }
762
763 do_resize();
764 }
765 used = TRUE;
766 } else if (e->type == KeyPress) {
767 if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) {
768 moveresize_end(TRUE);
769 used = TRUE;
770 } else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN)) {
771 moveresize_end(FALSE);
772 used = TRUE;
773 } else if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT) ||
774 e->xkey.keycode == ob_keycode(OB_KEY_LEFT) ||
775 e->xkey.keycode == ob_keycode(OB_KEY_DOWN) ||
776 e->xkey.keycode == ob_keycode(OB_KEY_UP))
777 {
778 if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
779 resize_with_keys(e->xkey.keycode, e->xkey.state);
780 used = TRUE;
781 } else if (corner == prop_atoms.net_wm_moveresize_move_keyboard) {
782 move_with_keys(e->xkey.keycode, e->xkey.state);
783 used = TRUE;
784 }
785 }
786 }
787 #ifdef SYNC
788 else if (e->type == extensions_sync_event_basep + XSyncAlarmNotify)
789 {
790 waiting_for_sync = FALSE; /* we got our sync... */
791 do_resize(); /* ...so try resize if there is more change pending */
792 used = TRUE;
793 }
794 #endif
795 return used;
796 }
This page took 0.071057 seconds and 5 git commands to generate.