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"
31 #include "moveresize.h"
35 #include "extensions.h"
36 #include "render/render.h"
37 #include "render/theme.h"
42 /* how far windows move and resize with the keyboard arrows */
45 gboolean moveresize_in_progress
= FALSE
;
46 ObClient
*moveresize_client
= NULL
;
48 XSyncAlarm moveresize_alarm
= None
;
51 static gboolean moving
= FALSE
; /* TRUE - moving, FALSE - resizing */
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
;
56 static guint32 corner
;
57 static ObDirection edge_warp_dir
= -1;
58 static gboolean edge_warp_odd
= FALSE
;
59 static ObDirection key_resize_edge
= -1;
61 static gboolean waiting_for_sync
;
64 static ObPopup
*popup
= NULL
;
66 static void do_edge_warp(gint x
, gint y
);
67 static void cancel_edge_warp();
69 static gboolean
sync_timeout_func(gpointer data
);
72 static void client_dest(ObClient
*client
, gpointer data
)
74 if (moveresize_client
== client
)
78 void moveresize_startup(gboolean reconfig
)
81 popup_set_text_align(popup
, RR_JUSTIFY_CENTER
);
84 client_add_destroy_notify(client_dest
, NULL
);
87 void moveresize_shutdown(gboolean reconfig
)
90 if (moveresize_in_progress
)
91 moveresize_end(FALSE
);
92 client_remove_destroy_notify(client_dest
);
99 static void popup_coords(ObClient
*c
, const gchar
*format
, gint a
, gint b
)
103 text
= g_strdup_printf(format
, a
, b
);
104 if (config_resize_popup_pos
== OB_RESIZE_POS_TOP
)
105 popup_position(popup
, SouthGravity
,
107 + c
->frame
->area
.width
/2,
108 c
->frame
->area
.y
- ob_rr_theme
->fbwidth
);
109 else if (config_resize_popup_pos
== OB_RESIZE_POS_CENTER
)
110 popup_position(popup
, CenterGravity
,
111 c
->frame
->area
.x
+ c
->frame
->size
.left
+
113 c
->frame
->area
.y
+ c
->frame
->size
.top
+
116 Rect
*area
= screen_physical_area_active();
119 x
= config_resize_popup_fixed
.x
.pos
;
120 if (config_resize_popup_fixed
.x
.center
)
121 x
= area
->x
+ area
->width
/2;
122 else if (config_resize_popup_fixed
.x
.opposite
)
123 x
= RECT_RIGHT(*area
) - x
;
127 y
= config_resize_popup_fixed
.y
.pos
;
128 if (config_resize_popup_fixed
.y
.center
)
129 y
= area
->y
+ area
->height
/2;
130 else if (config_resize_popup_fixed
.y
.opposite
)
131 y
= RECT_RIGHT(*area
) - y
;
135 if (config_resize_popup_fixed
.x
.center
) {
136 if (config_resize_popup_fixed
.y
.center
)
137 gravity
= CenterGravity
;
138 else if (config_resize_popup_fixed
.y
.opposite
)
139 gravity
= SouthGravity
;
141 gravity
= NorthGravity
;
143 else if (config_resize_popup_fixed
.x
.opposite
) {
144 if (config_resize_popup_fixed
.y
.center
)
145 gravity
= EastGravity
;
146 else if (config_resize_popup_fixed
.y
.opposite
)
147 gravity
= SouthEastGravity
;
149 gravity
= NorthEastGravity
;
152 if (config_resize_popup_fixed
.y
.center
)
153 gravity
= WestGravity
;
154 else if (config_resize_popup_fixed
.y
.opposite
)
155 gravity
= SouthWestGravity
;
157 gravity
= NorthWestGravity
;
160 popup_position(popup
, gravity
, x
, y
);
164 popup_show(popup
, text
);
168 void moveresize_start(ObClient
*c
, gint x
, gint y
, guint b
, guint32 cnr
)
171 gboolean mv
= (cnr
== prop_atoms
.net_wm_moveresize_move
||
172 cnr
== prop_atoms
.net_wm_moveresize_move_keyboard
);
176 if (moveresize_in_progress
|| !c
->frame
->visible
||
178 (c
->functions
& OB_CLIENT_FUNC_MOVE
) :
179 (c
->functions
& OB_CLIENT_FUNC_RESIZE
)))
182 if (cnr
== prop_atoms
.net_wm_moveresize_size_topleft
) {
183 cur
= OB_CURSOR_NORTHWEST
;
185 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_top
) {
186 cur
= OB_CURSOR_NORTH
;
188 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_topright
) {
189 cur
= OB_CURSOR_NORTHEAST
;
191 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_right
)
192 cur
= OB_CURSOR_EAST
;
193 else if (cnr
== prop_atoms
.net_wm_moveresize_size_bottomright
)
194 cur
= OB_CURSOR_SOUTHEAST
;
195 else if (cnr
== prop_atoms
.net_wm_moveresize_size_bottom
)
196 cur
= OB_CURSOR_SOUTH
;
197 else if (cnr
== prop_atoms
.net_wm_moveresize_size_bottomleft
) {
198 cur
= OB_CURSOR_SOUTHWEST
;
200 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_left
) {
201 cur
= OB_CURSOR_WEST
;
203 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_keyboard
)
204 cur
= OB_CURSOR_SOUTHEAST
;
205 else if (cnr
== prop_atoms
.net_wm_moveresize_move
)
206 cur
= OB_CURSOR_MOVE
;
207 else if (cnr
== prop_atoms
.net_wm_moveresize_move_keyboard
)
208 cur
= OB_CURSOR_MOVE
;
210 g_assert_not_reached();
212 /* keep the pointer bounded to the screen for move/resize */
213 if (!grab_pointer(FALSE
, TRUE
, cur
))
215 if (!grab_keyboard()) {
220 frame_end_iconify_animation(c
->frame
);
223 moveresize_client
= c
;
224 start_cx
= c
->area
.x
;
225 start_cy
= c
->area
.y
;
226 start_cw
= c
->area
.width
;
227 start_ch
= c
->area
.height
;
228 /* these adjustments for the size_inc make resizing a terminal more
229 friendly. you essentially start the resize in the middle of the
230 increment instead of at 0, so you have to move half an increment
231 either way instead of a full increment one and 1 px the other. */
232 start_x
= x
- (mv
? 0 : left
* c
->size_inc
.width
/ 2);
233 start_y
= y
- (mv
? 0 : up
* c
->size_inc
.height
/ 2);
236 key_resize_edge
= -1;
239 have to change start_cx and start_cy if going to do this..
240 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
241 corner == prop_atoms.net_wm_moveresize_size_keyboard)
242 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
243 c->area.width / 2, c->area.height / 2);
251 moveresize_in_progress
= TRUE
;
254 if (config_resize_redraw
&& !moving
&& extensions_sync
&&
255 moveresize_client
->sync_request
&& moveresize_client
->sync_counter
&&
256 !moveresize_client
->not_responding
)
258 /* Initialize values for the resize syncing, and create an alarm for
259 the client's xsync counter */
262 XSyncAlarmAttributes aa
;
264 /* set the counter to an initial value */
265 XSyncIntToValue(&val
, 0);
266 XSyncSetCounter(ob_display
, moveresize_client
->sync_counter
, val
);
268 /* this will be incremented when we tell the client what we're
270 moveresize_client
->sync_counter_value
= 0;
272 /* the next sequence we're waiting for with the alarm */
273 XSyncIntToValue(&val
, 1);
275 /* set an alarm on the counter */
276 aa
.trigger
.counter
= moveresize_client
->sync_counter
;
277 aa
.trigger
.wait_value
= val
;
278 aa
.trigger
.value_type
= XSyncAbsolute
;
279 aa
.trigger
.test_type
= XSyncPositiveTransition
;
281 XSyncIntToValue(&aa
.delta
, 1);
282 moveresize_alarm
= XSyncCreateAlarm(ob_display
,
291 waiting_for_sync
= FALSE
;
296 void moveresize_end(gboolean cancel
)
304 client_move(moveresize_client
,
305 (cancel
? start_cx
: cur_x
),
306 (cancel
? start_cy
: cur_y
));
309 /* turn off the alarm */
310 if (moveresize_alarm
!= None
) {
311 XSyncDestroyAlarm(ob_display
, moveresize_alarm
);
312 moveresize_alarm
= None
;
315 ob_main_loop_timeout_remove(ob_main_loop
, sync_timeout_func
);
318 client_configure(moveresize_client
,
319 (cancel
? start_cx
: cur_x
),
320 (cancel
? start_cy
: cur_y
),
321 (cancel
? start_cw
: cur_w
),
322 (cancel
? start_ch
: cur_h
),
326 /* dont edge warp after its ended */
329 moveresize_in_progress
= FALSE
;
330 moveresize_client
= NULL
;
333 static void do_move(gboolean keyboard
, gint keydist
)
337 if (keyboard
) resist
= keydist
- 1; /* resist for one key press */
338 else resist
= config_resist_win
;
339 resist_move_windows(moveresize_client
, resist
, &cur_x
, &cur_y
);
340 if (!keyboard
) resist
= config_resist_edge
;
341 resist_move_monitors(moveresize_client
, resist
, &cur_x
, &cur_y
);
343 client_configure(moveresize_client
, cur_x
, cur_y
, cur_w
, cur_h
,
345 if (config_resize_popup_show
== 2) /* == "Always" */
346 popup_coords(moveresize_client
, "%d x %d",
347 moveresize_client
->frame
->area
.x
,
348 moveresize_client
->frame
->area
.y
);
351 static void do_resize(void)
353 gint x
, y
, w
, h
, lw
, lh
;
355 /* see if it is actually going to resize */
360 client_try_configure(moveresize_client
, &x
, &y
, &w
, &h
,
362 if (w
== moveresize_client
->area
.width
&&
363 h
== moveresize_client
->area
.height
)
369 if (config_resize_redraw
&& extensions_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
= prop_atoms
.wm_protocols
;
387 ce
.xclient
.display
= ob_display
;
388 ce
.xclient
.window
= moveresize_client
->window
;
389 ce
.xclient
.format
= 32;
390 ce
.xclient
.data
.l
[0] = prop_atoms
.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(ob_display
, moveresize_client
->window
, FALSE
,
398 waiting_for_sync
= TRUE
;
400 ob_main_loop_timeout_remove(ob_main_loop
, sync_timeout_func
);
401 ob_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
,
410 /* this would be better with a fixed width font ... XXX can do it better
411 if there are 2 text boxes */
412 if (config_resize_popup_show
== 2 || /* == "Always" */
413 (config_resize_popup_show
== 1 && /* == "Nonpixel" */
414 moveresize_client
->size_inc
.width
> 1 &&
415 moveresize_client
->size_inc
.height
> 1))
416 popup_coords(moveresize_client
, "%d x %d",
417 moveresize_client
->logical_size
.width
,
418 moveresize_client
->logical_size
.height
);
422 static gboolean
sync_timeout_func(gpointer data
)
424 waiting_for_sync
= FALSE
; /* we timed out waiting for our sync... */
425 do_resize(); /* ...so let any pending resizes through */
427 return FALSE
; /* don't repeat */
431 static void calc_resize(gboolean keyboard
, gint keydist
, gint
*dw
, gint
*dh
,
434 gint resist
, x
= 0, y
= 0, lw
, lh
, ow
, oh
, nw
, nh
;
443 (moveresize_client
->max_ratio
|| moveresize_client
->min_ratio
))
446 case OB_DIRECTION_NORTH
:
447 case OB_DIRECTION_SOUTH
:
448 /* resize the width based on the height */
449 if (moveresize_client
->min_ratio
) {
450 if (nh
* moveresize_client
->min_ratio
> nw
)
451 nw
= (gint
)(nh
* moveresize_client
->min_ratio
);
453 if (moveresize_client
->max_ratio
) {
454 if (nh
* moveresize_client
->max_ratio
< nw
)
455 nw
= (gint
)(nh
* moveresize_client
->max_ratio
);
459 /* resize the height based on the width */
460 if (moveresize_client
->min_ratio
) {
461 if (nh
* moveresize_client
->min_ratio
> nw
)
462 nh
= (gint
)(nw
/ moveresize_client
->min_ratio
);
464 if (moveresize_client
->max_ratio
) {
465 if (nh
* moveresize_client
->max_ratio
< nw
)
466 nh
= (gint
)(nw
/ moveresize_client
->max_ratio
);
471 /* see its actual size (apply aspect ratios) */
472 client_try_configure(moveresize_client
, &x
, &y
, &nw
, &nh
, &lw
, &lh
,
478 /* resist_size_* needs the frame size */
479 nw
+= moveresize_client
->frame
->size
.left
+
480 moveresize_client
->frame
->size
.right
;
481 nh
+= moveresize_client
->frame
->size
.top
+
482 moveresize_client
->frame
->size
.bottom
;
484 if (keyboard
) resist
= keydist
- 1; /* resist for one key press */
485 else resist
= config_resist_win
;
486 resist_size_windows(moveresize_client
, resist
, &nw
, &nh
, dir
);
487 if (!keyboard
) resist
= config_resist_edge
;
488 resist_size_monitors(moveresize_client
, resist
, &nw
, &nh
, dir
);
490 nw
-= moveresize_client
->frame
->size
.left
+
491 moveresize_client
->frame
->size
.right
;
492 nh
-= moveresize_client
->frame
->size
.top
+
493 moveresize_client
->frame
->size
.bottom
;
498 /* take aspect ratios into account for resistance */
500 (moveresize_client
->max_ratio
|| moveresize_client
->min_ratio
))
502 if (*dh
!= trydh
) { /* got resisted */
503 /* resize the width based on the height */
504 if (moveresize_client
->min_ratio
) {
505 if (nh
* moveresize_client
->min_ratio
> nw
)
506 nw
= (gint
)(nh
* moveresize_client
->min_ratio
);
508 if (moveresize_client
->max_ratio
) {
509 if (nh
* moveresize_client
->max_ratio
< nw
)
510 nw
= (gint
)(nh
* moveresize_client
->max_ratio
);
513 if (*dw
!= trydw
) { /* got resisted */
514 /* resize the height based on the width */
515 if (moveresize_client
->min_ratio
) {
516 if (nh
* moveresize_client
->min_ratio
> nw
)
517 nh
= (gint
)(nw
/ moveresize_client
->min_ratio
);
519 if (moveresize_client
->max_ratio
) {
520 if (nh
* moveresize_client
->max_ratio
< nw
)
521 nh
= (gint
)(nw
/ moveresize_client
->max_ratio
);
526 /* make sure it's all valid */
527 client_try_configure(moveresize_client
, &x
, &y
, &nw
, &nh
, &lw
, &lh
, TRUE
);
533 static gboolean
edge_warp_delay_func(gpointer data
)
537 /* only fire every second time. so it's fast the first time, but slower
540 d
= screen_find_desktop(screen_desktop
, edge_warp_dir
, TRUE
, FALSE
);
541 if (d
!= screen_desktop
) screen_set_desktop(d
, TRUE
);
543 edge_warp_odd
= !edge_warp_odd
;
545 return TRUE
; /* do repeat ! */
548 static void do_edge_warp(gint x
, gint y
)
553 if (!config_mouse_screenedgetime
) return;
557 for (i
= 0; i
< screen_num_monitors
; ++i
) {
558 Rect
*a
= screen_physical_area_monitor(i
);
559 if (x
== RECT_LEFT(*a
)) dir
= OB_DIRECTION_WEST
;
560 if (x
== RECT_RIGHT(*a
)) dir
= OB_DIRECTION_EAST
;
561 if (y
== RECT_TOP(*a
)) dir
= OB_DIRECTION_NORTH
;
562 if (y
== RECT_BOTTOM(*a
)) dir
= OB_DIRECTION_SOUTH
;
564 /* try check for xinerama boundaries */
565 if ((x
+ 1 == RECT_LEFT(*a
) || x
- 1 == RECT_RIGHT(*a
)) &&
566 (dir
== OB_DIRECTION_WEST
|| dir
== OB_DIRECTION_EAST
))
570 if ((y
+ 1 == RECT_TOP(*a
) || y
- 1 == RECT_BOTTOM(*a
)) &&
571 (dir
== OB_DIRECTION_NORTH
|| dir
== OB_DIRECTION_SOUTH
))
578 if (dir
!= edge_warp_dir
) {
580 if (dir
!= (ObDirection
)-1) {
581 edge_warp_odd
= TRUE
; /* switch on the first timeout */
582 ob_main_loop_timeout_add(ob_main_loop
,
583 config_mouse_screenedgetime
* 1000,
584 edge_warp_delay_func
,
591 static void cancel_edge_warp(void)
593 ob_main_loop_timeout_remove(ob_main_loop
, edge_warp_delay_func
);
596 static void move_with_keys(gint keycode
, gint state
)
598 gint dx
= 0, dy
= 0, ox
= cur_x
, oy
= cur_y
;
599 gint opx
, px
, opy
, py
;
602 /* shift means jump to edge */
603 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
607 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
608 dir
= OB_DIRECTION_EAST
;
609 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
610 dir
= OB_DIRECTION_WEST
;
611 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
612 dir
= OB_DIRECTION_SOUTH
;
613 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
614 dir
= OB_DIRECTION_NORTH
;
616 client_find_move_directional(moveresize_client
, dir
, &x
, &y
);
617 dx
= x
- moveresize_client
->area
.x
;
618 dy
= y
- moveresize_client
->area
.y
;
620 /* control means fine grained */
621 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
))
626 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
628 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
630 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
632 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
636 screen_pointer_pos(&opx
, &opy
);
637 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, dx
, dy
);
638 /* steal the motion events this causes */
639 XSync(ob_display
, FALSE
);
642 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
644 screen_pointer_pos(&px
, &py
);
650 /* because the cursor moves even though the window does
651 not nessesarily (resistance), this adjusts where the curor
652 thinks it started so that it keeps up with where the window
654 start_x
+= (px
- opx
) - (cur_x
- ox
);
655 start_y
+= (py
- opy
) - (cur_y
- oy
);
658 static void resize_with_keys(gint keycode
, gint state
)
660 gint dw
= 0, dh
= 0, pdx
= 0, pdy
= 0, opx
, opy
, px
, py
;
661 gint dist
= 0, resist
= 0;
664 /* pick the edge if it needs to move */
665 if (keycode
== ob_keycode(OB_KEY_RIGHT
)) {
666 dir
= OB_DIRECTION_EAST
;
667 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
668 key_resize_edge
!= OB_DIRECTION_EAST
)
670 key_resize_edge
= OB_DIRECTION_EAST
;
674 if (keycode
== ob_keycode(OB_KEY_LEFT
)) {
675 dir
= OB_DIRECTION_WEST
;
676 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
677 key_resize_edge
!= OB_DIRECTION_EAST
)
679 key_resize_edge
= OB_DIRECTION_WEST
;
683 if (keycode
== ob_keycode(OB_KEY_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
;
692 if (keycode
== ob_keycode(OB_KEY_DOWN
)) {
693 dir
= OB_DIRECTION_SOUTH
;
694 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
695 key_resize_edge
!= OB_DIRECTION_SOUTH
)
697 key_resize_edge
= OB_DIRECTION_SOUTH
;
702 /* shift means jump to edge */
703 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
706 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
707 dir
= OB_DIRECTION_EAST
;
708 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
709 dir
= OB_DIRECTION_WEST
;
710 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
711 dir
= OB_DIRECTION_SOUTH
;
712 else /* if (keycode == ob_keycode(OB_KEY_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
;
728 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
736 if (moveresize_client
->size_inc
.height
> 1) {
737 disth
= moveresize_client
->size_inc
.height
;
740 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
749 if (key_resize_edge
== OB_DIRECTION_WEST
) {
750 if (dir
== OB_DIRECTION_WEST
)
753 dw
= -(dist
= distw
);
755 else if (key_resize_edge
== OB_DIRECTION_EAST
) {
756 if (dir
== OB_DIRECTION_EAST
)
759 dw
= -(dist
= distw
);
761 else if (key_resize_edge
== OB_DIRECTION_NORTH
) {
762 if (dir
== OB_DIRECTION_NORTH
)
765 dh
= -(dist
= disth
);
767 else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
768 if (dir
== OB_DIRECTION_SOUTH
)
771 dh
= -(dist
= disth
);
775 calc_resize(TRUE
, resist
, &dw
, &dh
, dir
);
776 if (key_resize_edge
== OB_DIRECTION_WEST
)
778 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
783 /* how to move the pointer to keep up with the change */
784 if (key_resize_edge
== OB_DIRECTION_WEST
)
786 else if (key_resize_edge
== OB_DIRECTION_EAST
)
788 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
790 else if (key_resize_edge
== OB_DIRECTION_SOUTH
)
793 screen_pointer_pos(&opx
, &opy
);
794 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, pdx
, pdy
);
795 /* steal the motion events this causes */
796 XSync(ob_display
, FALSE
);
799 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
801 screen_pointer_pos(&px
, &py
);
805 /* because the cursor moves even though the window does
806 not nessesarily (resistance), this adjusts where the cursor
807 thinks it started so that it keeps up with where the window
809 start_x
+= (px
- opx
) - dw
;
810 start_y
+= (py
- opy
) - dh
;
814 gboolean
moveresize_event(XEvent
*e
)
816 gboolean used
= FALSE
;
818 if (!moveresize_in_progress
) return FALSE
;
820 if (e
->type
== ButtonPress
) {
822 start_x
= e
->xbutton
.x_root
;
823 start_y
= e
->xbutton
.y_root
;
824 button
= e
->xbutton
.button
; /* this will end it now */
826 used
= e
->xbutton
.button
== button
;
827 } else if (e
->type
== ButtonRelease
) {
828 if (!button
|| e
->xbutton
.button
== button
) {
829 moveresize_end(FALSE
);
832 } else if (e
->type
== MotionNotify
) {
834 cur_x
= start_cx
+ e
->xmotion
.x_root
- start_x
;
835 cur_y
= start_cy
+ e
->xmotion
.y_root
- start_y
;
837 do_edge_warp(e
->xmotion
.x_root
, e
->xmotion
.y_root
);
842 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
) {
843 dw
= -(e
->xmotion
.x_root
- start_x
);
844 dh
= -(e
->xmotion
.y_root
- start_y
);
845 dir
= OB_DIRECTION_NORTHWEST
;
846 } else if (corner
== prop_atoms
.net_wm_moveresize_size_top
) {
848 dh
= -(e
->xmotion
.y_root
- start_y
);
849 dir
= OB_DIRECTION_NORTH
;
850 } else if (corner
== prop_atoms
.net_wm_moveresize_size_topright
) {
851 dw
= (e
->xmotion
.x_root
- start_x
);
852 dh
= -(e
->xmotion
.y_root
- start_y
);
853 dir
= OB_DIRECTION_NORTHEAST
;
854 } else if (corner
== prop_atoms
.net_wm_moveresize_size_right
) {
855 dw
= (e
->xmotion
.x_root
- start_x
);
857 dir
= OB_DIRECTION_EAST
;
859 prop_atoms
.net_wm_moveresize_size_bottomright
) {
860 dw
= (e
->xmotion
.x_root
- start_x
);
861 dh
= (e
->xmotion
.y_root
- start_y
);
862 dir
= OB_DIRECTION_SOUTHEAST
;
863 } else if (corner
== prop_atoms
.net_wm_moveresize_size_bottom
) {
865 dh
= (e
->xmotion
.y_root
- start_y
);
866 dir
= OB_DIRECTION_SOUTH
;
868 prop_atoms
.net_wm_moveresize_size_bottomleft
) {
869 dw
= -(e
->xmotion
.x_root
- start_x
);
870 dh
= (e
->xmotion
.y_root
- start_y
);
871 dir
= OB_DIRECTION_SOUTHWEST
;
872 } else if (corner
== prop_atoms
.net_wm_moveresize_size_left
) {
873 dw
= -(e
->xmotion
.x_root
- start_x
);
875 dir
= OB_DIRECTION_WEST
;
876 } else if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
877 dw
= (e
->xmotion
.x_root
- start_x
);
878 dh
= (e
->xmotion
.y_root
- start_y
);
879 dir
= OB_DIRECTION_SOUTHEAST
;
881 g_assert_not_reached();
883 dw
-= cur_w
- start_cw
;
884 dh
-= cur_h
- start_ch
;
886 calc_resize(FALSE
, 0, &dw
, &dh
, dir
);
890 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
||
891 corner
== prop_atoms
.net_wm_moveresize_size_left
||
892 corner
== prop_atoms
.net_wm_moveresize_size_bottomleft
)
896 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
||
897 corner
== prop_atoms
.net_wm_moveresize_size_top
||
898 corner
== prop_atoms
.net_wm_moveresize_size_topright
)
906 } else if (e
->type
== KeyPress
) {
907 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_ESCAPE
)) {
908 moveresize_end(TRUE
);
910 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RETURN
)) {
911 moveresize_end(FALSE
);
913 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RIGHT
) ||
914 e
->xkey
.keycode
== ob_keycode(OB_KEY_LEFT
) ||
915 e
->xkey
.keycode
== ob_keycode(OB_KEY_DOWN
) ||
916 e
->xkey
.keycode
== ob_keycode(OB_KEY_UP
))
918 if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
919 resize_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
921 } else if (corner
== prop_atoms
.net_wm_moveresize_move_keyboard
) {
922 move_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
928 else if (e
->type
== extensions_sync_event_basep
+ XSyncAlarmNotify
)
930 waiting_for_sync
= FALSE
; /* we got our sync... */
931 do_resize(); /* ...so try resize if there is more change pending */