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