1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 moveresize.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
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.
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.
17 See the COPYING file for a copy of the GNU General Public License.
23 #include "engine_interface.h"
27 #include "moveresize.h"
31 #include "render/render.h"
32 #include "render/theme.h"
33 #include "obt/display.h"
35 #include "obt/keyboard.h"
40 /* how far windows move and resize with the keyboard arrows */
43 //gboolean moveresize_in_progress = FALSE;
44 ObClient *moveresize_client = NULL;
46 XSyncAlarm moveresize_alarm = None;
49 static gboolean moving = FALSE; /* TRUE - moving, FALSE - resizing */
51 static gint start_x, start_y, start_cx, start_cy, start_cw, start_ch;
52 static gint cur_x, cur_y, cur_w, cur_h;
54 static guint32 corner;
55 static ObDirection edge_warp_dir = -1;
56 static gboolean edge_warp_odd = FALSE;
57 static ObDirection key_resize_edge = -1;
59 static gboolean waiting_for_sync;
62 static ObPopup *popup = NULL;
64 static void do_edge_warp(gint x, gint y);
65 static void cancel_edge_warp();
67 static gboolean sync_timeout_func(gpointer data);
70 static void client_dest(ObClient *client, gpointer data)
72 if (moveresize_client == client)
76 void moveresize_startup(gboolean reconfig)
79 popup_set_text_align(popup, RR_JUSTIFY_CENTER);
82 client_add_destroy_notify(client_dest, NULL);
85 void moveresize_shutdown(gboolean reconfig)
88 if (frame_engine->moveresize_in_progress)
89 moveresize_end(FALSE);
90 client_remove_destroy_notify(client_dest);
97 static void popup_coords(ObClient *c, const gchar *format, gint a, gint b)
102 frame_engine->frame_get_size(c->frame, &size);
104 frame_engine->frame_get_window_area(c->frame, &area);
105 text = g_strdup_printf(format, a, b);
106 if (config_resize_popup_pos == OB_RESIZE_POS_TOP)
107 popup_position(popup, SouthGravity,
110 area.y - ob_rr_theme->fbwidth);
111 else if (config_resize_popup_pos == OB_RESIZE_POS_CENTER)
112 popup_position(popup, CenterGravity,
118 Rect *area = screen_physical_area_active();
121 x = config_resize_popup_fixed.x.pos;
122 if (config_resize_popup_fixed.x.center)
123 x = area->x + area->width/2;
124 else if (config_resize_popup_fixed.x.opposite)
125 x = RECT_RIGHT(*area) - x;
129 y = config_resize_popup_fixed.y.pos;
130 if (config_resize_popup_fixed.y.center)
131 y = area->y + area->height/2;
132 else if (config_resize_popup_fixed.y.opposite)
133 y = RECT_RIGHT(*area) - y;
137 if (config_resize_popup_fixed.x.center) {
138 if (config_resize_popup_fixed.y.center)
139 gravity = CenterGravity;
140 else if (config_resize_popup_fixed.y.opposite)
141 gravity = SouthGravity;
143 gravity = NorthGravity;
145 else if (config_resize_popup_fixed.x.opposite) {
146 if (config_resize_popup_fixed.y.center)
147 gravity = EastGravity;
148 else if (config_resize_popup_fixed.y.opposite)
149 gravity = SouthEastGravity;
151 gravity = NorthEastGravity;
154 if (config_resize_popup_fixed.y.center)
155 gravity = WestGravity;
156 else if (config_resize_popup_fixed.y.opposite)
157 gravity = SouthWestGravity;
159 gravity = NorthWestGravity;
162 popup_position(popup, gravity, x, y);
166 popup_show(popup, text);
170 void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
173 gboolean mv = (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE) ||
174 cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD));
178 if (frame_engine->moveresize_in_progress || !frame_engine->frame_is_visible(c->frame) ||
180 (c->functions & OB_CLIENT_FUNC_MOVE) :
181 (c->functions & OB_CLIENT_FUNC_RESIZE)))
184 if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT)) {
185 cur = OB_CURSOR_NORTHWEST;
188 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP)) {
189 cur = OB_CURSOR_NORTH;
192 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT)) {
193 cur = OB_CURSOR_NORTHEAST;
196 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT))
197 cur = OB_CURSOR_EAST;
198 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT))
199 cur = OB_CURSOR_SOUTHEAST;
200 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM))
201 cur = OB_CURSOR_SOUTH;
202 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT)) {
203 cur = OB_CURSOR_SOUTHWEST;
206 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT)) {
207 cur = OB_CURSOR_WEST;
210 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD))
211 cur = OB_CURSOR_SOUTHEAST;
212 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE))
213 cur = OB_CURSOR_MOVE;
214 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD))
215 cur = OB_CURSOR_MOVE;
217 g_assert_not_reached();
219 /* keep the pointer bounded to the screen for move/resize */
220 if (!grab_pointer(FALSE, TRUE, cur))
222 if (!grab_keyboard()) {
228 moveresize_client = c;
229 start_cx = c->area.x;
230 start_cy = c->area.y;
231 start_cw = c->area.width;
232 start_ch = c->area.height;
233 /* these adjustments for the size_inc make resizing a terminal more
234 friendly. you essentially start the resize in the middle of the
235 increment instead of at 0, so you have to move half an increment
236 either way instead of a full increment one and 1 px the other. */
237 start_x = x - (mv ? 0 : left * c->size_inc.width / 2);
238 start_y = y - (mv ? 0 : up * c->size_inc.height / 2);
241 key_resize_edge = -1;
244 have to change start_cx and start_cy if going to do this..
245 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
246 corner == prop_atoms.net_wm_moveresize_size_keyboard)
247 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
248 c->area.width / 2, c->area.height / 2);
256 frame_engine->moveresize_in_progress = TRUE;
259 if (config_resize_redraw && !moving && obt_display_extension_sync &&
260 moveresize_client->sync_request && moveresize_client->sync_counter &&
261 !moveresize_client->not_responding)
263 /* Initialize values for the resize syncing, and create an alarm for
264 the client's xsync counter */
267 XSyncAlarmAttributes aa;
269 /* set the counter to an initial value */
270 XSyncIntToValue(&val, 0);
271 XSyncSetCounter(obt_display, moveresize_client->sync_counter, val);
273 /* this will be incremented when we tell the client what we're
275 moveresize_client->sync_counter_value = 0;
277 /* the next sequence we're waiting for with the alarm */
278 XSyncIntToValue(&val, 1);
280 /* set an alarm on the counter */
281 aa.trigger.counter = moveresize_client->sync_counter;
282 aa.trigger.wait_value = val;
283 aa.trigger.value_type = XSyncAbsolute;
284 aa.trigger.test_type = XSyncPositiveTransition;
286 XSyncIntToValue(&aa.delta, 1);
287 moveresize_alarm = XSyncCreateAlarm(obt_display,
296 waiting_for_sync = FALSE;
301 void moveresize_end(gboolean cancel)
309 client_move(moveresize_client,
310 (cancel ? start_cx : cur_x),
311 (cancel ? start_cy : cur_y));
314 /* turn off the alarm */
315 if (moveresize_alarm != None) {
316 XSyncDestroyAlarm(obt_display, moveresize_alarm);
317 moveresize_alarm = None;
320 obt_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
323 client_configure(moveresize_client,
324 (cancel ? start_cx : cur_x),
325 (cancel ? start_cy : cur_y),
326 (cancel ? start_cw : cur_w),
327 (cancel ? start_ch : cur_h),
331 /* dont edge warp after its ended */
334 frame_engine->moveresize_in_progress = FALSE;
335 moveresize_client = NULL;
338 static void do_move(gboolean keyboard, gint keydist)
342 if (keyboard) resist = keydist - 1; /* resist for one key press */
343 else resist = config_resist_win;
344 resist_move_windows(moveresize_client, resist, &cur_x, &cur_y);
345 if (!keyboard) resist = config_resist_edge;
346 resist_move_monitors(moveresize_client, resist, &cur_x, &cur_y);
348 client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h,
350 if (config_resize_popup_show == 2) /* == "Always" */
353 frame_engine->frame_get_window_area(moveresize_client->frame, &area);
354 popup_coords(moveresize_client, "%d x %d",
361 static void do_resize(void)
363 gint x, y, w, h, lw, lh;
365 /* see if it is actually going to resize */
370 client_try_configure(moveresize_client, &x, &y, &w, &h,
372 if (w == moveresize_client->area.width &&
373 h == moveresize_client->area.height)
379 if (config_resize_redraw && obt_display_extension_sync &&
380 moveresize_client->sync_request && moveresize_client->sync_counter &&
381 !moveresize_client->not_responding)
386 /* are we already waiting for the sync counter to catch up? */
387 if (waiting_for_sync)
390 /* increment the value we're waiting for */
391 ++moveresize_client->sync_counter_value;
392 XSyncIntToValue(&val, moveresize_client->sync_counter_value);
394 /* tell the client what we're waiting for */
395 ce.xclient.type = ClientMessage;
396 ce.xclient.message_type = OBT_PROP_ATOM(WM_PROTOCOLS);
397 ce.xclient.display = obt_display;
398 ce.xclient.window = moveresize_client->w_client;
399 ce.xclient.format = 32;
400 ce.xclient.data.l[0] = OBT_PROP_ATOM(NET_WM_SYNC_REQUEST);
401 ce.xclient.data.l[1] = event_curtime;
402 ce.xclient.data.l[2] = XSyncValueLow32(val);
403 ce.xclient.data.l[3] = XSyncValueHigh32(val);
404 ce.xclient.data.l[4] = 0l;
405 XSendEvent(obt_display, moveresize_client->w_client, FALSE,
408 waiting_for_sync = TRUE;
410 obt_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
411 obt_main_loop_timeout_add(ob_main_loop, G_USEC_PER_SEC * 2,
417 client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h,
420 /* this would be better with a fixed width font ... XXX can do it better
421 if there are 2 text boxes */
422 if (config_resize_popup_show == 2 || /* == "Always" */
423 (config_resize_popup_show == 1 && /* == "Nonpixel" */
424 moveresize_client->size_inc.width > 1 &&
425 moveresize_client->size_inc.height > 1))
426 popup_coords(moveresize_client, "%d x %d",
427 moveresize_client->logical_size.width,
428 moveresize_client->logical_size.height);
432 static gboolean sync_timeout_func(gpointer data)
434 waiting_for_sync = FALSE; /* we timed out waiting for our sync... */
435 do_resize(); /* ...so let any pending resizes through */
437 return FALSE; /* don't repeat */
441 static void calc_resize(gboolean keyboard, gint keydist, gint *dw, gint *dh,
444 gint resist, x = 0, y = 0, lw, lh, ow, oh, nw, nh;
453 (moveresize_client->max_ratio || moveresize_client->min_ratio))
456 case OB_DIRECTION_NORTH:
457 case OB_DIRECTION_SOUTH:
458 /* resize the width based on the height */
459 if (moveresize_client->min_ratio) {
460 if (nh * moveresize_client->min_ratio > nw)
461 nw = (gint)(nh * moveresize_client->min_ratio);
463 if (moveresize_client->max_ratio) {
464 if (nh * moveresize_client->max_ratio < nw)
465 nw = (gint)(nh * moveresize_client->max_ratio);
469 /* resize the height based on the width */
470 if (moveresize_client->min_ratio) {
471 if (nh * moveresize_client->min_ratio > nw)
472 nh = (gint)(nw / moveresize_client->min_ratio);
474 if (moveresize_client->max_ratio) {
475 if (nh * moveresize_client->max_ratio < nw)
476 nh = (gint)(nw / moveresize_client->max_ratio);
481 /* see its actual size (apply aspect ratios) */
482 client_try_configure(moveresize_client, &x, &y, &nw, &nh, &lw, &lh,
490 frame_engine->frame_get_size(moveresize_client->frame, &size);
491 /* resist_size_* needs the frame size */
497 if (keyboard) resist = keydist - 1; /* resist for one key press */
498 else resist = config_resist_win;
499 resist_size_windows(moveresize_client, resist, &nw, &nh, dir);
500 if (!keyboard) resist = config_resist_edge;
501 resist_size_monitors(moveresize_client, resist, &nw, &nh, dir);
511 /* take aspect ratios into account for resistance */
513 (moveresize_client->max_ratio || moveresize_client->min_ratio))
515 if (*dh != trydh) { /* got resisted */
516 /* resize the width based on the height */
517 if (moveresize_client->min_ratio) {
518 if (nh * moveresize_client->min_ratio > nw)
519 nw = (gint)(nh * moveresize_client->min_ratio);
521 if (moveresize_client->max_ratio) {
522 if (nh * moveresize_client->max_ratio < nw)
523 nw = (gint)(nh * moveresize_client->max_ratio);
526 if (*dw != trydw) { /* got resisted */
527 /* resize the height based on the width */
528 if (moveresize_client->min_ratio) {
529 if (nh * moveresize_client->min_ratio > nw)
530 nh = (gint)(nw / moveresize_client->min_ratio);
532 if (moveresize_client->max_ratio) {
533 if (nh * moveresize_client->max_ratio < nw)
534 nh = (gint)(nw / moveresize_client->max_ratio);
539 /* make sure it's all valid */
540 client_try_configure(moveresize_client, &x, &y, &nw, &nh, &lw, &lh, TRUE);
546 static gboolean edge_warp_delay_func(gpointer data)
550 /* only fire every second time. so it's fast the first time, but slower
553 d = screen_find_desktop(screen_desktop, edge_warp_dir, TRUE, FALSE);
554 if (d != screen_desktop) screen_set_desktop(d, TRUE);
556 edge_warp_odd = !edge_warp_odd;
558 return TRUE; /* do repeat ! */
561 static void do_edge_warp(gint x, gint y)
566 if (!config_mouse_screenedgetime) return;
570 for (i = 0; i < screen_num_monitors; ++i) {
571 Rect *a = screen_physical_area_monitor(i);
572 if (x == RECT_LEFT(*a)) dir = OB_DIRECTION_WEST;
573 if (x == RECT_RIGHT(*a)) dir = OB_DIRECTION_EAST;
574 if (y == RECT_TOP(*a)) dir = OB_DIRECTION_NORTH;
575 if (y == RECT_BOTTOM(*a)) dir = OB_DIRECTION_SOUTH;
577 /* try check for xinerama boundaries */
578 if ((x + 1 == RECT_LEFT(*a) || x - 1 == RECT_RIGHT(*a)) &&
579 (dir == OB_DIRECTION_WEST || dir == OB_DIRECTION_EAST))
583 if ((y + 1 == RECT_TOP(*a) || y - 1 == RECT_BOTTOM(*a)) &&
584 (dir == OB_DIRECTION_NORTH || dir == OB_DIRECTION_SOUTH))
591 if (dir != edge_warp_dir) {
593 if (dir != (ObDirection)-1) {
594 edge_warp_odd = TRUE; /* switch on the first timeout */
595 obt_main_loop_timeout_add(ob_main_loop,
596 config_mouse_screenedgetime * 1000,
597 edge_warp_delay_func,
604 static void cancel_edge_warp(void)
606 obt_main_loop_timeout_remove(ob_main_loop, edge_warp_delay_func);
609 static void move_with_keys(gint keycode, gint state)
611 gint dx = 0, dy = 0, ox = cur_x, oy = cur_y;
612 gint opx, px, opy, py;
615 /* shift means jump to edge */
616 if (state & obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT)) {
620 if (keycode == ob_keycode(OB_KEY_RIGHT))
621 dir = OB_DIRECTION_EAST;
622 else if (keycode == ob_keycode(OB_KEY_LEFT))
623 dir = OB_DIRECTION_WEST;
624 else if (keycode == ob_keycode(OB_KEY_DOWN))
625 dir = OB_DIRECTION_SOUTH;
626 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
627 dir = OB_DIRECTION_NORTH;
629 client_find_move_directional(moveresize_client, dir, &x, &y);
630 dx = x - moveresize_client->area.x;
631 dy = y - moveresize_client->area.y;
633 /* control means fine grained */
635 obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_CONTROL))
642 if (keycode == ob_keycode(OB_KEY_RIGHT))
644 else if (keycode == ob_keycode(OB_KEY_LEFT))
646 else if (keycode == ob_keycode(OB_KEY_DOWN))
648 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
652 screen_pointer_pos(&opx, &opy);
653 XWarpPointer(obt_display, None, None, 0, 0, 0, 0, dx, dy);
654 /* steal the motion events this causes */
655 XSync(obt_display, FALSE);
658 while (XCheckTypedEvent(obt_display, MotionNotify, &ce));
660 screen_pointer_pos(&px, &py);
666 /* because the cursor moves even though the window does
667 not nessesarily (resistance), this adjusts where the curor
668 thinks it started so that it keeps up with where the window
670 start_x += (px - opx) - (cur_x - ox);
671 start_y += (py - opy) - (cur_y - oy);
674 static void resize_with_keys(gint keycode, gint state)
676 gint dw = 0, dh = 0, pdx = 0, pdy = 0, opx, opy, px, py;
677 gint dist = 0, resist = 0;
680 /* pick the edge if it needs to move */
681 if (keycode == ob_keycode(OB_KEY_RIGHT)) {
682 dir = OB_DIRECTION_EAST;
683 if (key_resize_edge != OB_DIRECTION_WEST &&
684 key_resize_edge != OB_DIRECTION_EAST)
686 key_resize_edge = OB_DIRECTION_EAST;
690 if (keycode == ob_keycode(OB_KEY_LEFT)) {
691 dir = OB_DIRECTION_WEST;
692 if (key_resize_edge != OB_DIRECTION_WEST &&
693 key_resize_edge != OB_DIRECTION_EAST)
695 key_resize_edge = OB_DIRECTION_WEST;
699 if (keycode == ob_keycode(OB_KEY_UP)) {
700 dir = OB_DIRECTION_NORTH;
701 if (key_resize_edge != OB_DIRECTION_NORTH &&
702 key_resize_edge != OB_DIRECTION_SOUTH)
704 key_resize_edge = OB_DIRECTION_NORTH;
708 if (keycode == ob_keycode(OB_KEY_DOWN)) {
709 dir = OB_DIRECTION_SOUTH;
710 if (key_resize_edge != OB_DIRECTION_NORTH &&
711 key_resize_edge != OB_DIRECTION_SOUTH)
713 key_resize_edge = OB_DIRECTION_SOUTH;
718 /* shift means jump to edge */
719 if (state & obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT)) {
722 if (keycode == ob_keycode(OB_KEY_RIGHT))
723 dir = OB_DIRECTION_EAST;
724 else if (keycode == ob_keycode(OB_KEY_LEFT))
725 dir = OB_DIRECTION_WEST;
726 else if (keycode == ob_keycode(OB_KEY_DOWN))
727 dir = OB_DIRECTION_SOUTH;
728 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
729 dir = OB_DIRECTION_NORTH;
731 client_find_resize_directional(moveresize_client, key_resize_edge,
732 key_resize_edge == dir,
734 dw = w - moveresize_client->area.width;
735 dh = h - moveresize_client->area.height;
739 /* control means fine grained */
740 if (moveresize_client->size_inc.width > 1) {
741 distw = moveresize_client->size_inc.width;
745 obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_CONTROL))
754 if (moveresize_client->size_inc.height > 1) {
755 disth = moveresize_client->size_inc.height;
759 obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_CONTROL))
769 if (key_resize_edge == OB_DIRECTION_WEST) {
770 if (dir == OB_DIRECTION_WEST)
773 dw = -(dist = distw);
775 else if (key_resize_edge == OB_DIRECTION_EAST) {
776 if (dir == OB_DIRECTION_EAST)
779 dw = -(dist = distw);
781 else if (key_resize_edge == OB_DIRECTION_NORTH) {
782 if (dir == OB_DIRECTION_NORTH)
785 dh = -(dist = disth);
787 else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
788 if (dir == OB_DIRECTION_SOUTH)
791 dh = -(dist = disth);
795 calc_resize(TRUE, resist, &dw, &dh, dir);
796 if (key_resize_edge == OB_DIRECTION_WEST)
798 else if (key_resize_edge == OB_DIRECTION_NORTH)
803 /* how to move the pointer to keep up with the change */
804 if (key_resize_edge == OB_DIRECTION_WEST)
806 else if (key_resize_edge == OB_DIRECTION_EAST)
808 else if (key_resize_edge == OB_DIRECTION_NORTH)
810 else if (key_resize_edge == OB_DIRECTION_SOUTH)
813 screen_pointer_pos(&opx, &opy);
814 XWarpPointer(obt_display, None, None, 0, 0, 0, 0, pdx, pdy);
815 /* steal the motion events this causes */
816 XSync(obt_display, FALSE);
819 while (XCheckTypedEvent(obt_display, MotionNotify, &ce));
821 screen_pointer_pos(&px, &py);
825 /* because the cursor moves even though the window does
826 not nessesarily (resistance), this adjusts where the cursor
827 thinks it started so that it keeps up with where the window
829 start_x += (px - opx) - dw;
830 start_y += (py - opy) - dh;
834 gboolean moveresize_event(XEvent *e)
836 gboolean used = FALSE;
838 if (!frame_engine->moveresize_in_progress) return FALSE;
840 if (e->type == ButtonPress) {
842 start_x = e->xbutton.x_root;
843 start_y = e->xbutton.y_root;
844 button = e->xbutton.button; /* this will end it now */
846 used = e->xbutton.button == button;
847 } else if (e->type == ButtonRelease) {
848 if (!button || e->xbutton.button == button) {
849 moveresize_end(FALSE);
852 } else if (e->type == MotionNotify) {
854 cur_x = start_cx + e->xmotion.x_root - start_x;
855 cur_y = start_cy + e->xmotion.y_root - start_y;
857 do_edge_warp(e->xmotion.x_root, e->xmotion.y_root);
862 if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT)) {
863 dw = -(e->xmotion.x_root - start_x);
864 dh = -(e->xmotion.y_root - start_y);
865 dir = OB_DIRECTION_NORTHWEST;
866 } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP)) {
868 dh = -(e->xmotion.y_root - start_y);
869 dir = OB_DIRECTION_NORTH;
871 OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT)) {
872 dw = (e->xmotion.x_root - start_x);
873 dh = -(e->xmotion.y_root - start_y);
874 dir = OB_DIRECTION_NORTHEAST;
875 } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT)) {
876 dw = (e->xmotion.x_root - start_x);
878 dir = OB_DIRECTION_EAST;
880 OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT)) {
881 dw = (e->xmotion.x_root - start_x);
882 dh = (e->xmotion.y_root - start_y);
883 dir = OB_DIRECTION_SOUTHEAST;
884 } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM))
887 dh = (e->xmotion.y_root - start_y);
888 dir = OB_DIRECTION_SOUTH;
890 OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT)) {
891 dw = -(e->xmotion.x_root - start_x);
892 dh = (e->xmotion.y_root - start_y);
893 dir = OB_DIRECTION_SOUTHWEST;
894 } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT)) {
895 dw = -(e->xmotion.x_root - start_x);
897 dir = OB_DIRECTION_WEST;
899 OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD)) {
900 dw = (e->xmotion.x_root - start_x);
901 dh = (e->xmotion.y_root - start_y);
902 dir = OB_DIRECTION_SOUTHEAST;
904 g_assert_not_reached();
906 dw -= cur_w - start_cw;
907 dh -= cur_h - start_ch;
909 calc_resize(FALSE, 0, &dw, &dh, dir);
913 if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT) ||
914 corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT) ||
915 corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT))
919 if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT) ||
920 corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP) ||
921 corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT))
929 } else if (e->type == KeyPress) {
930 if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE)) {
931 moveresize_end(TRUE);
933 } else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN)) {
934 moveresize_end(FALSE);
936 } else if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT) ||
937 e->xkey.keycode == ob_keycode(OB_KEY_LEFT) ||
938 e->xkey.keycode == ob_keycode(OB_KEY_DOWN) ||
939 e->xkey.keycode == ob_keycode(OB_KEY_UP))
941 if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD)) {
942 resize_with_keys(e->xkey.keycode, e->xkey.state);
945 OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD))
947 move_with_keys(e->xkey.keycode, e->xkey.state);
953 else if (e->type == obt_display_extension_sync_basep + XSyncAlarmNotify)
955 waiting_for_sync = FALSE; /* we got our sync... */
956 do_resize(); /* ...so try resize if there is more change pending */