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.
21 #include "framerender.h"
28 #include "moveresize.h"
32 #include "obrender/render.h"
33 #include "obrender/theme.h"
34 #include "obt/display.h"
36 #include "obt/keyboard.h"
41 /* how far windows move and resize with the keyboard arrows */
44 gboolean moveresize_in_progress = FALSE;
45 ObClient *moveresize_client = NULL;
47 XSyncAlarm moveresize_alarm = None;
50 static gboolean moving = FALSE; /* TRUE - moving, FALSE - resizing */
52 static gint start_x, start_y, start_cx, start_cy, start_cw, start_ch;
53 static gint cur_x, cur_y, cur_w, cur_h;
55 static guint32 corner;
56 static ObDirection edge_warp_dir = -1;
57 static gboolean edge_warp_odd = FALSE;
58 static ObDirection key_resize_edge = -1;
60 static gboolean waiting_for_sync;
63 static ObPopup *popup = NULL;
65 static void do_move(gboolean keyboard, gint keydist);
66 static void do_resize(void);
67 static void do_edge_warp(gint x, gint y);
68 static void cancel_edge_warp();
70 static gboolean sync_timeout_func(gpointer data);
73 static void client_dest(ObClient *client, gpointer data)
75 if (moveresize_client == client)
79 void moveresize_startup(gboolean reconfig)
82 popup_set_text_align(popup, RR_JUSTIFY_CENTER);
85 client_add_destroy_notify(client_dest, NULL);
88 void moveresize_shutdown(gboolean reconfig)
91 if (moveresize_in_progress)
92 moveresize_end(FALSE);
93 client_remove_destroy_notify(client_dest);
100 static void popup_coords(ObClient *c, const gchar *format, gint a, gint b)
104 text = g_strdup_printf(format, a, b);
105 if (config_resize_popup_pos == OB_RESIZE_POS_TOP)
106 popup_position(popup, SouthGravity,
108 + c->frame->area.width/2,
109 c->frame->area.y - ob_rr_theme->fbwidth);
110 else if (config_resize_popup_pos == OB_RESIZE_POS_CENTER)
111 popup_position(popup, CenterGravity,
112 c->frame->area.x + c->frame->area.width / 2,
113 c->frame->area.y + c->frame->area.height / 2);
115 Rect const *area = screen_physical_area_active();
118 x = config_resize_popup_fixed.x.pos;
119 if (config_resize_popup_fixed.x.center)
120 x = area->x + area->width/2;
121 else if (config_resize_popup_fixed.x.opposite)
122 x = RECT_RIGHT(*area) - x;
126 y = config_resize_popup_fixed.y.pos;
127 if (config_resize_popup_fixed.y.center)
128 y = area->y + area->height/2;
129 else if (config_resize_popup_fixed.y.opposite)
130 y = RECT_RIGHT(*area) - y;
134 if (config_resize_popup_fixed.x.center) {
135 if (config_resize_popup_fixed.y.center)
136 gravity = CenterGravity;
137 else if (config_resize_popup_fixed.y.opposite)
138 gravity = SouthGravity;
140 gravity = NorthGravity;
142 else if (config_resize_popup_fixed.x.opposite) {
143 if (config_resize_popup_fixed.y.center)
144 gravity = EastGravity;
145 else if (config_resize_popup_fixed.y.opposite)
146 gravity = SouthEastGravity;
148 gravity = NorthEastGravity;
151 if (config_resize_popup_fixed.y.center)
152 gravity = WestGravity;
153 else if (config_resize_popup_fixed.y.opposite)
154 gravity = SouthWestGravity;
156 gravity = NorthWestGravity;
159 popup_position(popup, gravity, x, y);
161 popup_show(popup, text);
165 void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr)
168 gboolean mv = (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE) ||
169 cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD));
173 if (moveresize_in_progress || !c->frame->visible ||
175 (c->functions & OB_CLIENT_FUNC_MOVE) :
176 (c->functions & OB_CLIENT_FUNC_RESIZE)))
179 if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT)) {
180 cur = OB_CURSOR_NORTHWEST;
183 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP)) {
184 cur = OB_CURSOR_NORTH;
187 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT)) {
188 cur = OB_CURSOR_NORTHEAST;
191 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT))
192 cur = OB_CURSOR_EAST;
193 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT))
194 cur = OB_CURSOR_SOUTHEAST;
195 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM))
196 cur = OB_CURSOR_SOUTH;
197 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT)) {
198 cur = OB_CURSOR_SOUTHWEST;
201 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT)) {
202 cur = OB_CURSOR_WEST;
205 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD))
206 cur = OB_CURSOR_SOUTHEAST;
207 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE))
208 cur = OB_CURSOR_MOVE;
209 else if (cnr == OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD))
210 cur = OB_CURSOR_MOVE;
212 g_assert_not_reached();
214 /* keep the pointer bounded to the screen for move/resize */
215 if (!grab_pointer(FALSE, TRUE, cur))
217 if (!grab_keyboard()) {
222 frame_end_iconify_animation(c->frame);
225 moveresize_client = c;
226 start_cx = c->area.x;
227 start_cy = c->area.y;
228 start_cw = c->area.width;
229 start_ch = c->area.height;
230 /* these adjustments for the size_inc make resizing a terminal more
231 friendly. you essentially start the resize in the middle of the
232 increment instead of at 0, so you have to move half an increment
233 either way instead of a full increment one and 1 px the other. */
234 start_x = x - (mv ? 0 : left * c->size_inc.width / 2);
235 start_y = y - (mv ? 0 : up * c->size_inc.height / 2);
238 key_resize_edge = -1;
241 have to change start_cx and start_cy if going to do this..
242 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
243 corner == prop_atoms.net_wm_moveresize_size_keyboard)
244 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
245 c->area.width / 2, c->area.height / 2);
253 moveresize_in_progress = TRUE;
256 if (config_resize_redraw && !moving && obt_display_extension_sync &&
257 moveresize_client->sync_request && moveresize_client->sync_counter &&
258 !moveresize_client->not_responding)
260 /* Initialize values for the resize syncing, and create an alarm for
261 the client's xsync counter */
264 XSyncAlarmAttributes aa;
266 /* set the counter to an initial value */
267 XSyncIntToValue(&val, 0);
268 XSyncSetCounter(obt_display, moveresize_client->sync_counter, val);
270 /* this will be incremented when we tell the client what we're
272 moveresize_client->sync_counter_value = 0;
274 /* the next sequence we're waiting for with the alarm */
275 XSyncIntToValue(&val, 1);
277 /* set an alarm on the counter */
278 aa.trigger.counter = moveresize_client->sync_counter;
279 aa.trigger.wait_value = val;
280 aa.trigger.value_type = XSyncAbsolute;
281 aa.trigger.test_type = XSyncPositiveTransition;
283 XSyncIntToValue(&aa.delta, 1);
284 moveresize_alarm = XSyncCreateAlarm(obt_display,
293 waiting_for_sync = FALSE;
298 void moveresize_end(gboolean cancel)
307 /* turn off the alarm */
308 if (moveresize_alarm != None) {
309 XSyncDestroyAlarm(obt_display, moveresize_alarm);
310 moveresize_alarm = None;
313 obt_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
317 /* don't use client_move() here, use the same width/height as
318 we've been using during the move, otherwise we get different results
319 when moving maximized windows between monitors of different sizes !
321 client_configure(moveresize_client,
322 (cancel ? start_cx : cur_x),
323 (cancel ? start_cy : cur_y),
324 (cancel ? start_cw : cur_w),
325 (cancel ? start_ch : cur_h),
328 /* dont edge warp after its ended */
331 moveresize_in_progress = FALSE;
332 moveresize_client = NULL;
335 static void do_move(gboolean keyboard, gint keydist)
339 if (keyboard) resist = keydist - 1; /* resist for one key press */
340 else resist = config_resist_win;
341 resist_move_windows(moveresize_client, resist, &cur_x, &cur_y);
342 if (!keyboard) resist = config_resist_edge;
343 resist_move_monitors(moveresize_client, resist, &cur_x, &cur_y);
345 client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h,
347 if (config_resize_popup_show == 2) /* == "Always" */
348 popup_coords(moveresize_client, "%d x %d",
349 moveresize_client->frame->area.x,
350 moveresize_client->frame->area.y);
353 static void do_resize(void)
355 gint x, y, w, h, lw, lh;
357 /* see if it is actually going to resize */
362 client_try_configure(moveresize_client, &x, &y, &w, &h,
364 if (!(w == moveresize_client->area.width &&
365 h == moveresize_client->area.height))
369 if (config_resize_redraw && obt_display_extension_sync &&
370 moveresize_client->sync_request && moveresize_client->sync_counter &&
371 !moveresize_client->not_responding)
376 /* are we already waiting for the sync counter to catch up? */
377 if (waiting_for_sync)
380 /* increment the value we're waiting for */
381 ++moveresize_client->sync_counter_value;
382 XSyncIntToValue(&val, moveresize_client->sync_counter_value);
384 /* tell the client what we're waiting for */
385 ce.xclient.type = ClientMessage;
386 ce.xclient.message_type = OBT_PROP_ATOM(WM_PROTOCOLS);
387 ce.xclient.display = obt_display;
388 ce.xclient.window = moveresize_client->window;
389 ce.xclient.format = 32;
390 ce.xclient.data.l[0] = OBT_PROP_ATOM(NET_WM_SYNC_REQUEST);
391 ce.xclient.data.l[1] = event_curtime;
392 ce.xclient.data.l[2] = XSyncValueLow32(val);
393 ce.xclient.data.l[3] = XSyncValueHigh32(val);
394 ce.xclient.data.l[4] = 0l;
395 XSendEvent(obt_display, moveresize_client->window, FALSE,
398 waiting_for_sync = TRUE;
400 obt_main_loop_timeout_remove(ob_main_loop, sync_timeout_func);
401 obt_main_loop_timeout_add(ob_main_loop, G_USEC_PER_SEC * 2,
407 client_configure(moveresize_client, cur_x, cur_y, cur_w, cur_h,
411 /* this would be better with a fixed width font ... XXX can do it better
412 if there are 2 text boxes */
413 if (config_resize_popup_show == 2 || /* == "Always" */
414 (config_resize_popup_show == 1 && /* == "Nonpixel" */
415 moveresize_client->size_inc.width > 1 &&
416 moveresize_client->size_inc.height > 1))
417 popup_coords(moveresize_client, "%d x %d", lw, lh);
421 static gboolean sync_timeout_func(gpointer data)
423 waiting_for_sync = FALSE; /* we timed out waiting for our sync... */
424 do_resize(); /* ...so let any pending resizes through */
426 return FALSE; /* don't repeat */
430 static void calc_resize(gboolean keyboard, gint keydist, gint *dw, gint *dh,
433 gint resist, x = 0, y = 0, lw, lh, ow, oh, nw, nh;
442 (moveresize_client->max_ratio || moveresize_client->min_ratio))
445 case OB_DIRECTION_NORTH:
446 case OB_DIRECTION_SOUTH:
447 /* resize the width based on the height */
448 if (moveresize_client->min_ratio) {
449 if (nh * moveresize_client->min_ratio > nw)
450 nw = (gint)(nh * moveresize_client->min_ratio);
452 if (moveresize_client->max_ratio) {
453 if (nh * moveresize_client->max_ratio < nw)
454 nw = (gint)(nh * moveresize_client->max_ratio);
458 /* resize the height based on the width */
459 if (moveresize_client->min_ratio) {
460 if (nh * moveresize_client->min_ratio > nw)
461 nh = (gint)(nw / moveresize_client->min_ratio);
463 if (moveresize_client->max_ratio) {
464 if (nh * moveresize_client->max_ratio < nw)
465 nh = (gint)(nw / moveresize_client->max_ratio);
470 /* see its actual size (apply aspect ratios) */
471 client_try_configure(moveresize_client, &x, &y, &nw, &nh, &lw, &lh,
477 /* resist_size_* needs the frame size */
478 nw += moveresize_client->frame->size.left +
479 moveresize_client->frame->size.right;
480 nh += moveresize_client->frame->size.top +
481 moveresize_client->frame->size.bottom;
483 if (keyboard) resist = keydist - 1; /* resist for one key press */
484 else resist = config_resist_win;
485 resist_size_windows(moveresize_client, resist, &nw, &nh, dir);
486 if (!keyboard) resist = config_resist_edge;
487 resist_size_monitors(moveresize_client, resist, &nw, &nh, dir);
489 nw -= moveresize_client->frame->size.left +
490 moveresize_client->frame->size.right;
491 nh -= moveresize_client->frame->size.top +
492 moveresize_client->frame->size.bottom;
497 /* take aspect ratios into account for resistance */
499 (moveresize_client->max_ratio || moveresize_client->min_ratio))
501 if (*dh != trydh) { /* got resisted */
502 /* resize the width based on the height */
503 if (moveresize_client->min_ratio) {
504 if (nh * moveresize_client->min_ratio > nw)
505 nw = (gint)(nh * moveresize_client->min_ratio);
507 if (moveresize_client->max_ratio) {
508 if (nh * moveresize_client->max_ratio < nw)
509 nw = (gint)(nh * moveresize_client->max_ratio);
512 if (*dw != trydw) { /* got resisted */
513 /* resize the height based on the width */
514 if (moveresize_client->min_ratio) {
515 if (nh * moveresize_client->min_ratio > nw)
516 nh = (gint)(nw / moveresize_client->min_ratio);
518 if (moveresize_client->max_ratio) {
519 if (nh * moveresize_client->max_ratio < nw)
520 nh = (gint)(nw / moveresize_client->max_ratio);
525 /* make sure it's all valid */
526 client_try_configure(moveresize_client, &x, &y, &nw, &nh, &lw, &lh, TRUE);
532 static gboolean edge_warp_delay_func(gpointer data)
536 /* only fire every second time. so it's fast the first time, but slower
539 d = screen_find_desktop(screen_desktop, edge_warp_dir, TRUE, FALSE);
540 if (d != screen_desktop) screen_set_desktop(d, TRUE);
542 edge_warp_odd = !edge_warp_odd;
544 return TRUE; /* do repeat ! */
547 static void do_edge_warp(gint x, gint y)
552 if (!config_mouse_screenedgetime) return;
556 for (i = 0; i < screen_num_monitors; ++i) {
557 Rect const *a = screen_physical_area_monitor(i);
558 if (x == RECT_LEFT(*a)) dir = OB_DIRECTION_WEST;
559 if (x == RECT_RIGHT(*a)) dir = OB_DIRECTION_EAST;
560 if (y == RECT_TOP(*a)) dir = OB_DIRECTION_NORTH;
561 if (y == RECT_BOTTOM(*a)) dir = OB_DIRECTION_SOUTH;
563 /* try check for xinerama boundaries */
564 if ((x + 1 == RECT_LEFT(*a) || x - 1 == RECT_RIGHT(*a)) &&
565 (dir == OB_DIRECTION_WEST || dir == OB_DIRECTION_EAST))
569 if ((y + 1 == RECT_TOP(*a) || y - 1 == RECT_BOTTOM(*a)) &&
570 (dir == OB_DIRECTION_NORTH || dir == OB_DIRECTION_SOUTH))
576 if (dir != edge_warp_dir) {
578 if (dir != (ObDirection)-1) {
579 edge_warp_odd = TRUE; /* switch on the first timeout */
580 obt_main_loop_timeout_add(ob_main_loop,
581 config_mouse_screenedgetime * 1000,
582 edge_warp_delay_func,
589 static void cancel_edge_warp(void)
591 obt_main_loop_timeout_remove(ob_main_loop, edge_warp_delay_func);
594 static void move_with_keys(KeySym sym, guint state)
596 gint dx = 0, dy = 0, ox = cur_x, oy = cur_y;
597 gint opx, px, opy, py;
600 /* shift means jump to edge */
601 if (state & obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT))
607 dir = OB_DIRECTION_EAST;
608 else if (sym == XK_Left)
609 dir = OB_DIRECTION_WEST;
610 else if (sym == XK_Down)
611 dir = OB_DIRECTION_SOUTH;
612 else /* sym == XK_Up */
613 dir = OB_DIRECTION_NORTH;
615 client_find_move_directional(moveresize_client, dir, &x, &y);
616 dx = x - moveresize_client->area.x;
617 dy = y - moveresize_client->area.y;
619 /* control means fine grained */
621 obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_CONTROL))
630 else if (sym == XK_Left)
632 else if (sym == XK_Down)
634 else /* if (sym == XK_Up) */
638 screen_pointer_pos(&opx, &opy);
639 XWarpPointer(obt_display, None, None, 0, 0, 0, 0, dx, dy);
640 /* steal the motion events this causes */
641 XSync(obt_display, FALSE);
644 while (XCheckTypedEvent(obt_display, MotionNotify, &ce));
646 screen_pointer_pos(&px, &py);
652 /* because the cursor moves even though the window does
653 not nessesarily (resistance), this adjusts where the curor
654 thinks it started so that it keeps up with where the window
656 start_x += (px - opx) - (cur_x - ox);
657 start_y += (py - opy) - (cur_y - oy);
660 static void resize_with_keys(KeySym sym, guint state)
662 gint dw = 0, dh = 0, pdx = 0, pdy = 0, opx, opy, px, py;
666 /* pick the edge if it needs to move */
667 if (sym == XK_Right) {
668 dir = OB_DIRECTION_EAST;
669 if (key_resize_edge != OB_DIRECTION_WEST &&
670 key_resize_edge != OB_DIRECTION_EAST)
672 key_resize_edge = OB_DIRECTION_EAST;
675 } else if (sym == XK_Left) {
676 dir = OB_DIRECTION_WEST;
677 if (key_resize_edge != OB_DIRECTION_WEST &&
678 key_resize_edge != OB_DIRECTION_EAST)
680 key_resize_edge = OB_DIRECTION_WEST;
683 } else if (sym == XK_Up) {
684 dir = OB_DIRECTION_NORTH;
685 if (key_resize_edge != OB_DIRECTION_NORTH &&
686 key_resize_edge != OB_DIRECTION_SOUTH)
688 key_resize_edge = OB_DIRECTION_NORTH;
691 } else /* if (sym == XK_Down) */ {
692 dir = OB_DIRECTION_SOUTH;
693 if (key_resize_edge != OB_DIRECTION_NORTH &&
694 key_resize_edge != OB_DIRECTION_SOUTH)
696 key_resize_edge = OB_DIRECTION_SOUTH;
701 /* shift means jump to edge */
702 if (state & obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_SHIFT))
707 dir = OB_DIRECTION_EAST;
708 else if (sym == XK_Left)
709 dir = OB_DIRECTION_WEST;
710 else if (sym == XK_Down)
711 dir = OB_DIRECTION_SOUTH;
712 else /* if (sym == XK_Up)) */
713 dir = OB_DIRECTION_NORTH;
715 client_find_resize_directional(moveresize_client, key_resize_edge,
716 key_resize_edge == dir,
718 dw = w - moveresize_client->area.width;
719 dh = h - moveresize_client->area.height;
723 /* control means fine grained */
724 if (moveresize_client->size_inc.width > 1) {
725 distw = moveresize_client->size_inc.width;
729 obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_CONTROL))
738 if (moveresize_client->size_inc.height > 1) {
739 disth = moveresize_client->size_inc.height;
743 obt_keyboard_modkey_to_modmask(OBT_KEYBOARD_MODKEY_CONTROL))
753 if (key_resize_edge == OB_DIRECTION_WEST) {
754 if (dir == OB_DIRECTION_WEST)
759 else if (key_resize_edge == OB_DIRECTION_EAST) {
760 if (dir == OB_DIRECTION_EAST)
765 else if (key_resize_edge == OB_DIRECTION_NORTH) {
766 if (dir == OB_DIRECTION_NORTH)
771 else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
772 if (dir == OB_DIRECTION_SOUTH)
779 calc_resize(TRUE, resist, &dw, &dh, dir);
780 if (key_resize_edge == OB_DIRECTION_WEST)
782 else if (key_resize_edge == OB_DIRECTION_NORTH)
787 /* how to move the pointer to keep up with the change */
788 if (key_resize_edge == OB_DIRECTION_WEST)
790 else if (key_resize_edge == OB_DIRECTION_EAST)
792 else if (key_resize_edge == OB_DIRECTION_NORTH)
794 else if (key_resize_edge == OB_DIRECTION_SOUTH)
797 screen_pointer_pos(&opx, &opy);
798 XWarpPointer(obt_display, None, None, 0, 0, 0, 0, pdx, pdy);
799 /* steal the motion events this causes */
800 XSync(obt_display, FALSE);
803 while (XCheckTypedEvent(obt_display, MotionNotify, &ce));
805 screen_pointer_pos(&px, &py);
809 /* because the cursor moves even though the window does
810 not nessesarily (resistance), this adjusts where the cursor
811 thinks it started so that it keeps up with where the window
813 start_x += (px - opx) - dw;
814 start_y += (py - opy) - dh;
818 gboolean moveresize_event(XEvent *e)
820 gboolean used = FALSE;
822 if (!moveresize_in_progress) return FALSE;
824 if (e->type == ButtonPress) {
826 start_x = e->xbutton.x_root;
827 start_y = e->xbutton.y_root;
828 button = e->xbutton.button; /* this will end it now */
830 used = e->xbutton.button == button;
831 } else if (e->type == ButtonRelease) {
832 if (!button || e->xbutton.button == button) {
833 moveresize_end(FALSE);
836 } else if (e->type == MotionNotify) {
838 cur_x = start_cx + e->xmotion.x_root - start_x;
839 cur_y = start_cy + e->xmotion.y_root - start_y;
841 do_edge_warp(e->xmotion.x_root, e->xmotion.y_root);
846 if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT)) {
847 dw = -(e->xmotion.x_root - start_x);
848 dh = -(e->xmotion.y_root - start_y);
849 dir = OB_DIRECTION_NORTHWEST;
850 } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP)) {
852 dh = -(e->xmotion.y_root - start_y);
853 dir = OB_DIRECTION_NORTH;
855 OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT)) {
856 dw = (e->xmotion.x_root - start_x);
857 dh = -(e->xmotion.y_root - start_y);
858 dir = OB_DIRECTION_NORTHEAST;
859 } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT)) {
860 dw = (e->xmotion.x_root - start_x);
862 dir = OB_DIRECTION_EAST;
864 OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT)) {
865 dw = (e->xmotion.x_root - start_x);
866 dh = (e->xmotion.y_root - start_y);
867 dir = OB_DIRECTION_SOUTHEAST;
868 } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM))
871 dh = (e->xmotion.y_root - start_y);
872 dir = OB_DIRECTION_SOUTH;
874 OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT)) {
875 dw = -(e->xmotion.x_root - start_x);
876 dh = (e->xmotion.y_root - start_y);
877 dir = OB_DIRECTION_SOUTHWEST;
878 } else if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT)) {
879 dw = -(e->xmotion.x_root - start_x);
881 dir = OB_DIRECTION_WEST;
883 OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD)) {
884 dw = (e->xmotion.x_root - start_x);
885 dh = (e->xmotion.y_root - start_y);
886 dir = OB_DIRECTION_SOUTHEAST;
888 g_assert_not_reached();
890 dw -= cur_w - start_cw;
891 dh -= cur_h - start_ch;
893 calc_resize(FALSE, 0, &dw, &dh, dir);
897 if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT) ||
898 corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT) ||
899 corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT))
903 if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT) ||
904 corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP) ||
905 corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT))
913 } else if (e->type == KeyPress) {
914 KeySym sym = obt_keyboard_keypress_to_keysym(e);
916 if (sym == XK_Escape) {
917 moveresize_end(TRUE);
919 } else if (sym == XK_Return) {
920 moveresize_end(FALSE);
922 } else if (sym == XK_Right || sym == XK_Left ||
923 sym == XK_Up || sym == XK_Down)
925 if (corner == OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD)) {
926 resize_with_keys(sym, e->xkey.state);
929 OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD))
931 move_with_keys(sym, e->xkey.state);
937 else if (e->type == obt_display_extension_sync_basep + XSyncAlarmNotify)
939 waiting_for_sync = FALSE; /* we got our sync... */
940 do_resize(); /* ...so try resize if there is more change pending */