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