]> Dogcows Code - chaz/openbox/blob - openbox/moveresize.c
remove a debug print
[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 gint trydw, trydh;
378
379 ow = cur_w;
380 oh = cur_h;
381 nw = ow + *dw;
382 nh = oh + *dh;
383
384 if (moveresize_client->max_ratio || moveresize_client->min_ratio) {
385 switch (dir) {
386 case OB_DIRECTION_NORTH:
387 case OB_DIRECTION_SOUTH:
388 /* resize the width based on the height */
389 if (moveresize_client->min_ratio) {
390 if (nh * moveresize_client->min_ratio > nw)
391 nw = (gint)(nh * moveresize_client->min_ratio);
392 }
393 if (moveresize_client->max_ratio) {
394 if (nh * moveresize_client->max_ratio < nw)
395 nw = (gint)(nh * moveresize_client->max_ratio);
396 }
397 break;
398 default:
399 /* resize the height based on the width */
400 if (moveresize_client->min_ratio) {
401 if (nh * moveresize_client->min_ratio > nw)
402 nh = (gint)(nw / moveresize_client->min_ratio);
403 }
404 if (moveresize_client->max_ratio) {
405 if (nh * moveresize_client->max_ratio < nw)
406 nh = (gint)(nw / moveresize_client->max_ratio);
407 }
408 break;
409 }
410 }
411
412 /* see its actual size (apply aspect ratios) */
413 client_try_configure(moveresize_client, &x, &y, &nw, &nh, &lw, &lh, TRUE);
414 trydw = nw - ow;
415 trydh = nh - oh;
416
417 /* resist_size_* needs the frame size */
418 nw += moveresize_client->frame->size.left +
419 moveresize_client->frame->size.right;
420 nh += moveresize_client->frame->size.top +
421 moveresize_client->frame->size.bottom;
422
423 if (keyboard) resist = keydist - 1; /* resist for one key press */
424 else resist = config_resist_win;
425 resist_size_windows(moveresize_client, resist, &nw, &nh, dir);
426 if (!keyboard) resist = config_resist_edge;
427 resist_size_monitors(moveresize_client, resist, &nw, &nh, dir);
428
429 nw -= moveresize_client->frame->size.left +
430 moveresize_client->frame->size.right;
431 nh -= moveresize_client->frame->size.top +
432 moveresize_client->frame->size.bottom;
433
434 *dw = nw - ow;
435 *dh = nh - oh;
436
437 /* take aspect ratios into account for resistance */
438 if (*dh != trydh) { /* got resisted */
439 /* resize the width based on the height */
440 if (moveresize_client->min_ratio) {
441 if (nh * moveresize_client->min_ratio > nw)
442 nw = (gint)(nh * moveresize_client->min_ratio);
443 }
444 if (moveresize_client->max_ratio) {
445 if (nh * moveresize_client->max_ratio < nw)
446 nw = (gint)(nh * moveresize_client->max_ratio);
447 }
448 }
449 if (*dw != trydw) { /* got resisted */
450 /* resize the height based on the width */
451 if (moveresize_client->min_ratio) {
452 if (nh * moveresize_client->min_ratio > nw)
453 nh = (gint)(nw / moveresize_client->min_ratio);
454 }
455 if (moveresize_client->max_ratio) {
456 if (nh * moveresize_client->max_ratio < nw)
457 nh = (gint)(nw / moveresize_client->max_ratio);
458 }
459 }
460
461 /* make sure it's all valid */
462 client_try_configure(moveresize_client, &x, &y, &nw, &nh, &lw, &lh, TRUE);
463
464 *dw = nw - ow;
465 *dh = nh - oh;
466 }
467
468 static gboolean edge_warp_delay_func(gpointer data)
469 {
470 guint d;
471
472 d = screen_find_desktop(screen_desktop, edge_warp_dir, TRUE, FALSE);
473 if (d != screen_desktop) screen_set_desktop(d, TRUE);
474
475 edge_warp_dir = -1;
476
477 return FALSE; /* don't repeat */
478 }
479
480 static void do_edge_warp(gint x, gint y)
481 {
482 guint i;
483 ObDirection dir;
484
485 if (!config_mouse_screenedgetime) return;
486
487 dir = -1;
488
489 for (i = 0; i < screen_num_monitors; ++i) {
490 Rect *a = screen_physical_area_monitor(i);
491 if (x == RECT_LEFT(*a)) dir = OB_DIRECTION_WEST;
492 if (x == RECT_RIGHT(*a)) dir = OB_DIRECTION_EAST;
493 if (y == RECT_TOP(*a)) dir = OB_DIRECTION_NORTH;
494 if (y == RECT_BOTTOM(*a)) dir = OB_DIRECTION_SOUTH;
495
496 /* try check for xinerama boundaries */
497 if ((x + 1 == RECT_LEFT(*a) || x - 1 == RECT_RIGHT(*a)) &&
498 (dir == OB_DIRECTION_WEST || dir == OB_DIRECTION_EAST))
499 {
500 dir = -1;
501 }
502 if ((y + 1 == RECT_TOP(*a) || y - 1 == RECT_BOTTOM(*a)) &&
503 (dir == OB_DIRECTION_NORTH || dir == OB_DIRECTION_SOUTH))
504 {
505 dir = -1;
506 }
507 g_free(a);
508 }
509
510 if (dir != edge_warp_dir) {
511 if (dir == (ObDirection)-1)
512 cancel_edge_warp();
513 else
514 ob_main_loop_timeout_add(ob_main_loop,
515 config_mouse_screenedgetime * 1000,
516 edge_warp_delay_func,
517 NULL, NULL, NULL);
518 edge_warp_dir = dir;
519 }
520 }
521
522 static void cancel_edge_warp()
523 {
524 ob_main_loop_timeout_remove(ob_main_loop, edge_warp_delay_func);
525 }
526
527 static void move_with_keys(gint keycode, gint state)
528 {
529 gint dx = 0, dy = 0, ox = cur_x, oy = cur_y;
530 gint opx, px, opy, py;
531 gint dist = 0;
532
533 /* shift means jump to edge */
534 if (state & modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT)) {
535 gint x, y;
536 ObDirection dir;
537
538 if (keycode == ob_keycode(OB_KEY_RIGHT))
539 dir = OB_DIRECTION_EAST;
540 else if (keycode == ob_keycode(OB_KEY_LEFT))
541 dir = OB_DIRECTION_WEST;
542 else if (keycode == ob_keycode(OB_KEY_DOWN))
543 dir = OB_DIRECTION_SOUTH;
544 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
545 dir = OB_DIRECTION_NORTH;
546
547 client_find_move_directional(moveresize_client, dir, &x, &y);
548 dx = x - moveresize_client->area.x;
549 dy = y - moveresize_client->area.y;
550 } else {
551 /* control means fine grained */
552 if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL))
553 dist = 1;
554 else
555 dist = KEY_DIST;
556
557 if (keycode == ob_keycode(OB_KEY_RIGHT))
558 dx = dist;
559 else if (keycode == ob_keycode(OB_KEY_LEFT))
560 dx = -dist;
561 else if (keycode == ob_keycode(OB_KEY_DOWN))
562 dy = dist;
563 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
564 dy = -dist;
565 }
566
567 screen_pointer_pos(&opx, &opy);
568 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
569 /* steal the motion events this causes */
570 XSync(ob_display, FALSE);
571 {
572 XEvent ce;
573 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
574 }
575 screen_pointer_pos(&px, &py);
576
577 cur_x += dx;
578 cur_y += dy;
579 do_move(TRUE, dist);
580
581 /* because the cursor moves even though the window does
582 not nessesarily (resistance), this adjusts where the curor
583 thinks it started so that it keeps up with where the window
584 actually is */
585 start_x += (px - opx) - (cur_x - ox);
586 start_y += (py - opy) - (cur_y - oy);
587 }
588
589 static void resize_with_keys(gint keycode, gint state)
590 {
591 gint dw = 0, dh = 0, pdx = 0, pdy = 0, opx, opy, px, py;
592 gint dist = 0, resist = 0;
593 ObDirection dir;
594
595 /* pick the edge if it needs to move */
596 if (keycode == ob_keycode(OB_KEY_RIGHT)) {
597 dir = OB_DIRECTION_EAST;
598 if (key_resize_edge != OB_DIRECTION_WEST &&
599 key_resize_edge != OB_DIRECTION_EAST)
600 {
601 key_resize_edge = OB_DIRECTION_EAST;
602 return;
603 }
604 }
605 if (keycode == ob_keycode(OB_KEY_LEFT)) {
606 dir = OB_DIRECTION_WEST;
607 if (key_resize_edge != OB_DIRECTION_WEST &&
608 key_resize_edge != OB_DIRECTION_EAST)
609 {
610 key_resize_edge = OB_DIRECTION_WEST;
611 return;
612 }
613 }
614 if (keycode == ob_keycode(OB_KEY_UP)) {
615 dir = OB_DIRECTION_NORTH;
616 if (key_resize_edge != OB_DIRECTION_NORTH &&
617 key_resize_edge != OB_DIRECTION_SOUTH)
618 {
619 key_resize_edge = OB_DIRECTION_NORTH;
620 return;
621 }
622 }
623 if (keycode == ob_keycode(OB_KEY_DOWN)) {
624 dir = OB_DIRECTION_SOUTH;
625 if (key_resize_edge != OB_DIRECTION_NORTH &&
626 key_resize_edge != OB_DIRECTION_SOUTH)
627 {
628 key_resize_edge = OB_DIRECTION_SOUTH;
629 return;
630 }
631 }
632
633 /* shift means jump to edge */
634 if (state & modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT)) {
635 gint x, y, w, h;
636
637 if (keycode == ob_keycode(OB_KEY_RIGHT))
638 dir = OB_DIRECTION_EAST;
639 else if (keycode == ob_keycode(OB_KEY_LEFT))
640 dir = OB_DIRECTION_WEST;
641 else if (keycode == ob_keycode(OB_KEY_DOWN))
642 dir = OB_DIRECTION_SOUTH;
643 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
644 dir = OB_DIRECTION_NORTH;
645
646 client_find_resize_directional(moveresize_client, key_resize_edge,
647 key_resize_edge == dir,
648 &x, &y, &w, &h);
649 dw = w - moveresize_client->area.width;
650 dh = h - moveresize_client->area.height;
651 } else {
652 gint distw, disth;
653
654 /* control means fine grained */
655 if (moveresize_client->size_inc.width > 1) {
656 distw = moveresize_client->size_inc.width;
657 resist = 1;
658 }
659 else if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL)) {
660 distw = 1;
661 resist = 1;
662 }
663 else {
664 distw = KEY_DIST;
665 resist = KEY_DIST;
666 }
667 if (moveresize_client->size_inc.height > 1) {
668 disth = moveresize_client->size_inc.height;
669 resist = 1;
670 }
671 else if (state & modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL)) {
672 disth = 1;
673 resist = 1;
674 }
675 else {
676 disth = KEY_DIST;
677 resist = KEY_DIST;
678 }
679
680 if (key_resize_edge == OB_DIRECTION_WEST) {
681 if (dir == OB_DIRECTION_WEST)
682 dw = (dist = distw);
683 else
684 dw = -(dist = distw);
685 }
686 else if (key_resize_edge == OB_DIRECTION_EAST) {
687 if (dir == OB_DIRECTION_EAST)
688 dw = (dist = distw);
689 else
690 dw = -(dist = distw);
691 }
692 else if (key_resize_edge == OB_DIRECTION_NORTH) {
693 if (dir == OB_DIRECTION_NORTH)
694 dh = (dist = disth);
695 else
696 dh = -(dist = disth);
697 }
698 else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
699 if (dir == OB_DIRECTION_SOUTH)
700 dh = (dist = disth);
701 else
702 dh = -(dist = disth);
703 }
704 }
705
706 calc_resize(TRUE, resist, &dw, &dh, dir);
707 if (key_resize_edge == OB_DIRECTION_WEST)
708 cur_x -= dw;
709 else if (key_resize_edge == OB_DIRECTION_NORTH)
710 cur_y -= dh;
711 cur_w += dw;
712 cur_h += dh;
713
714 /* how to move the pointer to keep up with the change */
715 if (key_resize_edge == OB_DIRECTION_WEST)
716 pdx = -dw;
717 else if (key_resize_edge == OB_DIRECTION_EAST)
718 pdx = dw;
719 else if (key_resize_edge == OB_DIRECTION_NORTH)
720 pdy = -dh;
721 else if (key_resize_edge == OB_DIRECTION_SOUTH)
722 pdy = dh;
723
724 screen_pointer_pos(&opx, &opy);
725 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, pdx, pdy);
726 /* steal the motion events this causes */
727 XSync(ob_display, FALSE);
728 {
729 XEvent ce;
730 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
731 }
732 screen_pointer_pos(&px, &py);
733
734 do_resize();
735
736 /* because the cursor moves even though the window does
737 not nessesarily (resistance), this adjusts where the cursor
738 thinks it started so that it keeps up with where the window
739 actually is */
740 start_x += (px - opx) - dw;
741 start_y += (py - opy) - dh;
742
743 }
744
745 gboolean moveresize_event(XEvent *e)
746 {
747 gboolean used = FALSE;
748
749 if (!moveresize_in_progress) return FALSE;
750
751 if (e->type == ButtonPress) {
752 if (!button) {
753 start_x = e->xbutton.x_root;
754 start_y = e->xbutton.y_root;
755 button = e->xbutton.button; /* this will end it now */
756 }
757 used = e->xbutton.button == button;
758 } else if (e->type == ButtonRelease) {
759 if (!button || e->xbutton.button == button) {
760 moveresize_end(FALSE);
761 used = TRUE;
762 }
763 } else if (e->type == MotionNotify) {
764 if (moving) {
765 cur_x = start_cx + e->xmotion.x_root - start_x;
766 cur_y = start_cy + e->xmotion.y_root - start_y;
767 do_move(FALSE, 0);
768 do_edge_warp(e->xmotion.x_root, e->xmotion.y_root);
769 } else {
770 gint dw, dh;
771 ObDirection dir;
772
773 if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
774 dw = -(e->xmotion.x_root - start_x);
775 dh = -(e->xmotion.y_root - start_y);
776 dir = OB_DIRECTION_NORTHWEST;
777 } else if (corner == prop_atoms.net_wm_moveresize_size_top) {
778 dw = 0;
779 dh = -(e->xmotion.y_root - start_y);
780 dir = OB_DIRECTION_NORTH;
781 } else if (corner == prop_atoms.net_wm_moveresize_size_topright) {
782 dw = (e->xmotion.x_root - start_x);
783 dh = -(e->xmotion.y_root - start_y);
784 dir = OB_DIRECTION_NORTHEAST;
785 } else if (corner == prop_atoms.net_wm_moveresize_size_right) {
786 dw = (e->xmotion.x_root - start_x);
787 dh = 0;
788 dir = OB_DIRECTION_EAST;
789 } else if (corner ==
790 prop_atoms.net_wm_moveresize_size_bottomright) {
791 dw = (e->xmotion.x_root - start_x);
792 dh = (e->xmotion.y_root - start_y);
793 dir = OB_DIRECTION_SOUTHEAST;
794 } else if (corner == prop_atoms.net_wm_moveresize_size_bottom) {
795 dw = 0;
796 dh = (e->xmotion.y_root - start_y);
797 dir = OB_DIRECTION_SOUTH;
798 } else if (corner ==
799 prop_atoms.net_wm_moveresize_size_bottomleft) {
800 dw = -(e->xmotion.x_root - start_x);
801 dh = (e->xmotion.y_root - start_y);
802 dir = OB_DIRECTION_SOUTHWEST;
803 } else if (corner == prop_atoms.net_wm_moveresize_size_left) {
804 dw = -(e->xmotion.x_root - start_x);
805 dh = 0;
806 dir = OB_DIRECTION_WEST;
807 } else if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
808 dw = (e->xmotion.x_root - start_x);
809 dh = (e->xmotion.y_root - start_y);
810 dir = OB_DIRECTION_SOUTHEAST;
811 } else
812 g_assert_not_reached();
813
814 dw -= cur_w - start_cw;
815 dh -= cur_h - start_ch;
816
817 calc_resize(FALSE, 0, &dw, &dh, dir);
818 cur_w += dw;
819 cur_h += dh;
820
821 if (corner == prop_atoms.net_wm_moveresize_size_topleft ||
822 corner == prop_atoms.net_wm_moveresize_size_left ||
823 corner == prop_atoms.net_wm_moveresize_size_bottomleft)
824 {
825 cur_x -= dw;
826 }
827 if (corner == prop_atoms.net_wm_moveresize_size_topleft ||
828 corner == prop_atoms.net_wm_moveresize_size_top ||
829 corner == prop_atoms.net_wm_moveresize_size_topright)
830 {
831 cur_y -= dh;
832 }
833
834 do_resize();
835 }
836 used = TRUE;
837 } else if (e->type == KeyPress) {
838 if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) {
839 moveresize_end(TRUE);
840 used = TRUE;
841 } else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN)) {
842 moveresize_end(FALSE);
843 used = TRUE;
844 } else if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT) ||
845 e->xkey.keycode == ob_keycode(OB_KEY_LEFT) ||
846 e->xkey.keycode == ob_keycode(OB_KEY_DOWN) ||
847 e->xkey.keycode == ob_keycode(OB_KEY_UP))
848 {
849 if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
850 resize_with_keys(e->xkey.keycode, e->xkey.state);
851 used = TRUE;
852 } else if (corner == prop_atoms.net_wm_moveresize_move_keyboard) {
853 move_with_keys(e->xkey.keycode, e->xkey.state);
854 used = TRUE;
855 }
856 }
857 }
858 #ifdef SYNC
859 else if (e->type == extensions_sync_event_basep + XSyncAlarmNotify)
860 {
861 waiting_for_sync = FALSE; /* we got our sync... */
862 do_resize(); /* ...so try resize if there is more change pending */
863 used = TRUE;
864 }
865 #endif
866 return used;
867 }
This page took 0.07532 seconds and 5 git commands to generate.