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