]> Dogcows Code - chaz/openbox/blob - openbox/moveresize.c
1d4b322cf6a80506cc9c343ffa4cc553e4485551
[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 start_cw = c->area.width;
171 start_ch = c->area.height;
172 /* these adjustments for the size_inc make resizing a terminal more
173 friendly. you essentially start the resize in the middle of the
174 increment instead of at 0, so you have to move half an increment
175 either way instead of a full increment one and 1 px the other. */
176 start_x = x - (mv ? 0 : c->size_inc.width / 2);
177 start_y = y - (mv ? 0 : c->size_inc.height / 2);
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_sync &&
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 * 2,
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, x, y, lw, lh, ow, oh, nw, nh;
378
379 ow = cur_w;
380 oh = cur_h;
381 /* resist_size_* needs the frame size */
382 nw = ow + *dw +
383 moveresize_client->frame->size.left +
384 moveresize_client->frame->size.right;
385 nh = oh + *dh +
386 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, cor);
392 if (!keyboard) resist = config_resist_edge;
393 resist_size_monitors(moveresize_client, resist, &nw, &nh, cor);
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 /* see its actual size */
401 x = 0;
402 y = 0;
403 client_try_configure(moveresize_client, &x, &y, &nw, &nh, &lw, &lh, TRUE);
404
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;
535 ObDirection dir;
536 ObCorner cor;
537
538 /* pick the edge if it needs to move */
539 if (keycode == ob_keycode(OB_KEY_RIGHT)) {
540 dir = OB_DIRECTION_EAST;
541 if (key_resize_edge != OB_DIRECTION_WEST &&
542 key_resize_edge != OB_DIRECTION_EAST)
543 {
544 key_resize_edge = OB_DIRECTION_EAST;
545 return;
546 }
547 }
548 if (keycode == ob_keycode(OB_KEY_LEFT)) {
549 dir = OB_DIRECTION_WEST;
550 if (key_resize_edge != OB_DIRECTION_WEST &&
551 key_resize_edge != OB_DIRECTION_EAST)
552 {
553 key_resize_edge = OB_DIRECTION_WEST;
554 return;
555 }
556 }
557 if (keycode == ob_keycode(OB_KEY_UP)) {
558 dir = OB_DIRECTION_NORTH;
559 if (key_resize_edge != OB_DIRECTION_NORTH &&
560 key_resize_edge != OB_DIRECTION_SOUTH)
561 {
562 key_resize_edge = OB_DIRECTION_NORTH;
563 return;
564 }
565 }
566 if (keycode == ob_keycode(OB_KEY_DOWN)) {
567 dir = OB_DIRECTION_SOUTH;
568 if (key_resize_edge != OB_DIRECTION_NORTH &&
569 key_resize_edge != OB_DIRECTION_SOUTH)
570 {
571 key_resize_edge = OB_DIRECTION_SOUTH;
572 return;
573 }
574 }
575
576 /* shift means jump to edge */
577 if (state & modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT)) {
578 gint x, y, w, h;
579
580 if (keycode == ob_keycode(OB_KEY_RIGHT))
581 dir = OB_DIRECTION_EAST;
582 else if (keycode == ob_keycode(OB_KEY_LEFT))
583 dir = OB_DIRECTION_WEST;
584 else if (keycode == ob_keycode(OB_KEY_DOWN))
585 dir = OB_DIRECTION_SOUTH;
586 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
587 dir = OB_DIRECTION_NORTH;
588
589 client_find_resize_directional(moveresize_client, key_resize_edge,
590 key_resize_edge == dir,
591 &x, &y, &w, &h);
592 dw = w - moveresize_client->area.width;
593 dh = h - moveresize_client->area.height;
594 } else {
595 gint distw, disth;
596
597 /* control means fine grained */
598 if (moveresize_client->size_inc.width > 1)
599 distw = moveresize_client->size_inc.width;
600 else if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
601 distw = 1;
602 else
603 distw = KEY_DIST;
604 if (moveresize_client->size_inc.height > 1)
605 disth = moveresize_client->size_inc.height;
606 else if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
607 disth = 1;
608 else
609 disth = KEY_DIST;
610
611 if (key_resize_edge == OB_DIRECTION_WEST) {
612 if (dir == OB_DIRECTION_WEST)
613 dw = (dist = distw);
614 else
615 dw = -(dist = distw);
616 }
617 else if (key_resize_edge == OB_DIRECTION_EAST) {
618 if (dir == OB_DIRECTION_EAST)
619 dw = (dist = distw);
620 else
621 dw = -(dist = distw);
622 }
623 else if (key_resize_edge == OB_DIRECTION_NORTH) {
624 if (dir == OB_DIRECTION_NORTH)
625 dh = (dist = disth);
626 else
627 dh = -(dist = disth);
628 }
629 else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
630 if (dir == OB_DIRECTION_SOUTH)
631 dh = (dist = disth);
632 else
633 dh = -(dist = disth);
634 }
635 }
636
637 /* which corner is locked, for resistance */
638 if (key_resize_edge == OB_DIRECTION_WEST)
639 cor = OB_CORNER_TOPRIGHT;
640 else if (key_resize_edge == OB_DIRECTION_EAST)
641 cor = OB_CORNER_TOPLEFT;
642 else if (key_resize_edge == OB_DIRECTION_NORTH)
643 cor = OB_CORNER_BOTTOMLEFT;
644 else if (key_resize_edge == OB_DIRECTION_SOUTH)
645 cor = OB_CORNER_TOPLEFT;
646
647 calc_resize(TRUE, dist, &dw, &dh, cor);
648 if (key_resize_edge == OB_DIRECTION_WEST)
649 cur_x -= dw;
650 else if (key_resize_edge == OB_DIRECTION_NORTH)
651 cur_y -= dh;
652 cur_w += dw;
653 cur_h += dh;
654
655 /* how to move the pointer to keep up with the change */
656 if (key_resize_edge == OB_DIRECTION_WEST)
657 pdx = -dw;
658 else if (key_resize_edge == OB_DIRECTION_EAST)
659 pdx = dw;
660 else if (key_resize_edge == OB_DIRECTION_NORTH)
661 pdy = -dh;
662 else if (key_resize_edge == OB_DIRECTION_SOUTH)
663 pdy = dh;
664
665 screen_pointer_pos(&opx, &opy);
666 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, pdx, pdy);
667 /* steal the motion events this causes */
668 XSync(ob_display, FALSE);
669 {
670 XEvent ce;
671 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
672 }
673 screen_pointer_pos(&px, &py);
674
675 do_resize();
676
677 /* because the cursor moves even though the window does
678 not nessesarily (resistance), this adjusts where the cursor
679 thinks it started so that it keeps up with where the window
680 actually is */
681 start_x += (px - opx) - dw;
682 start_y += (py - opy) - dh;
683
684 }
685
686 gboolean moveresize_event(XEvent *e)
687 {
688 gboolean used = FALSE;
689
690 if (!moveresize_in_progress) return FALSE;
691
692 if (e->type == ButtonPress) {
693 if (!button) {
694 start_x = e->xbutton.x_root;
695 start_y = e->xbutton.y_root;
696 button = e->xbutton.button; /* this will end it now */
697 }
698 used = e->xbutton.button == button;
699 } else if (e->type == ButtonRelease) {
700 if (!button || e->xbutton.button == button) {
701 moveresize_end(FALSE);
702 used = TRUE;
703 }
704 } else if (e->type == MotionNotify) {
705 if (moving) {
706 cur_x = start_cx + e->xmotion.x_root - start_x;
707 cur_y = start_cy + e->xmotion.y_root - start_y;
708 do_move(FALSE, 0);
709 do_edge_warp(e->xmotion.x_root, e->xmotion.y_root);
710 } else {
711 gint dw, dh;
712
713 if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
714 dw = -(e->xmotion.x_root - start_x);
715 dh = -(e->xmotion.y_root - start_y);
716 lockcorner = OB_CORNER_BOTTOMRIGHT;
717 } else if (corner == prop_atoms.net_wm_moveresize_size_top) {
718 dw = 0;
719 dh = -(e->xmotion.y_root - start_y);
720 lockcorner = OB_CORNER_BOTTOMRIGHT;
721 } else if (corner == prop_atoms.net_wm_moveresize_size_topright) {
722 dw = (e->xmotion.x_root - start_x);
723 dh = -(e->xmotion.y_root - start_y);
724 lockcorner = OB_CORNER_BOTTOMLEFT;
725 } else if (corner == prop_atoms.net_wm_moveresize_size_right) {
726 dw = (e->xmotion.x_root - start_x);
727 dh = 0;
728 lockcorner = OB_CORNER_BOTTOMLEFT;
729 } else if (corner ==
730 prop_atoms.net_wm_moveresize_size_bottomright) {
731 dw = (e->xmotion.x_root - start_x);
732 dh = (e->xmotion.y_root - start_y);
733 lockcorner = OB_CORNER_TOPLEFT;
734 } else if (corner == prop_atoms.net_wm_moveresize_size_bottom) {
735 dw = 0;
736 dh = (e->xmotion.y_root - start_y);
737 lockcorner = OB_CORNER_TOPLEFT;
738 } else if (corner ==
739 prop_atoms.net_wm_moveresize_size_bottomleft) {
740 dw = -(e->xmotion.x_root - start_x);
741 dh = (e->xmotion.y_root - start_y);
742 lockcorner = OB_CORNER_TOPRIGHT;
743 } else if (corner == prop_atoms.net_wm_moveresize_size_left) {
744 dw = -(e->xmotion.x_root - start_x);
745 dh = 0;
746 lockcorner = OB_CORNER_TOPRIGHT;
747 } else if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
748 dw = (e->xmotion.x_root - start_x);
749 dh = (e->xmotion.y_root - start_y);
750 lockcorner = OB_CORNER_TOPLEFT;
751 } else
752 g_assert_not_reached();
753
754 dw -= cur_w - start_cw;
755 dh -= cur_h - start_ch;
756
757 calc_resize(FALSE, 0, &dw, &dh, lockcorner);
758 cur_w += dw;
759 cur_h += dh;
760
761 if (corner == prop_atoms.net_wm_moveresize_size_topleft ||
762 corner == prop_atoms.net_wm_moveresize_size_left ||
763 corner == prop_atoms.net_wm_moveresize_size_bottomleft)
764 {
765 cur_x -= dw;
766 }
767 if (corner == prop_atoms.net_wm_moveresize_size_topleft ||
768 corner == prop_atoms.net_wm_moveresize_size_top ||
769 corner == prop_atoms.net_wm_moveresize_size_topright)
770 {
771 cur_y -= dh;
772 }
773
774 do_resize();
775 }
776 used = TRUE;
777 } else if (e->type == KeyPress) {
778 if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) {
779 moveresize_end(TRUE);
780 used = TRUE;
781 } else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN)) {
782 moveresize_end(FALSE);
783 used = TRUE;
784 } else if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT) ||
785 e->xkey.keycode == ob_keycode(OB_KEY_LEFT) ||
786 e->xkey.keycode == ob_keycode(OB_KEY_DOWN) ||
787 e->xkey.keycode == ob_keycode(OB_KEY_UP))
788 {
789 if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
790 resize_with_keys(e->xkey.keycode, e->xkey.state);
791 used = TRUE;
792 } else if (corner == prop_atoms.net_wm_moveresize_move_keyboard) {
793 move_with_keys(e->xkey.keycode, e->xkey.state);
794 used = TRUE;
795 }
796 }
797 }
798 #ifdef SYNC
799 else if (e->type == extensions_sync_event_basep + XSyncAlarmNotify)
800 {
801 waiting_for_sync = FALSE; /* we got our sync... */
802 do_resize(); /* ...so try resize if there is more change pending */
803 used = TRUE;
804 }
805 #endif
806 return used;
807 }
This page took 0.065491 seconds and 3 git commands to generate.