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"
30 #include "moveresize.h"
34 #include "render/render.h"
35 #include "render/theme.h"
36 #include "obt/display.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_edge_warp(gint x
, gint y
);
66 static void cancel_edge_warp();
68 static gboolean
sync_timeout_func(gpointer data
);
71 static void client_dest(ObClient
*client
, gpointer data
)
73 if (moveresize_client
== client
)
77 void moveresize_startup(gboolean reconfig
)
80 popup_set_text_align(popup
, RR_JUSTIFY_CENTER
);
83 client_add_destroy_notify(client_dest
, NULL
);
86 void moveresize_shutdown(gboolean reconfig
)
89 if (moveresize_in_progress
)
90 moveresize_end(FALSE
);
91 client_remove_destroy_notify(client_dest
);
98 static void popup_coords(ObClient
*c
, const gchar
*format
, gint a
, gint b
)
102 text
= g_strdup_printf(format
, a
, b
);
103 if (config_resize_popup_pos
== OB_RESIZE_POS_TOP
)
104 popup_position(popup
, SouthGravity
,
106 + c
->frame
->area
.width
/2,
107 c
->frame
->area
.y
- ob_rr_theme
->fbwidth
);
108 else if (config_resize_popup_pos
== OB_RESIZE_POS_CENTER
)
109 popup_position(popup
, CenterGravity
,
110 c
->frame
->area
.x
+ c
->frame
->size
.left
+
112 c
->frame
->area
.y
+ c
->frame
->size
.top
+
115 Rect
*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
);
163 popup_show(popup
, text
);
167 void moveresize_start(ObClient
*c
, gint x
, gint y
, guint b
, guint32 cnr
)
170 gboolean mv
= (cnr
== prop_atoms
.net_wm_moveresize_move
||
171 cnr
== prop_atoms
.net_wm_moveresize_move_keyboard
);
175 if (moveresize_in_progress
|| !c
->frame
->visible
||
177 (c
->functions
& OB_CLIENT_FUNC_MOVE
) :
178 (c
->functions
& OB_CLIENT_FUNC_RESIZE
)))
181 if (cnr
== prop_atoms
.net_wm_moveresize_size_topleft
) {
182 cur
= OB_CURSOR_NORTHWEST
;
184 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_top
) {
185 cur
= OB_CURSOR_NORTH
;
187 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_topright
) {
188 cur
= OB_CURSOR_NORTHEAST
;
190 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_right
)
191 cur
= OB_CURSOR_EAST
;
192 else if (cnr
== prop_atoms
.net_wm_moveresize_size_bottomright
)
193 cur
= OB_CURSOR_SOUTHEAST
;
194 else if (cnr
== prop_atoms
.net_wm_moveresize_size_bottom
)
195 cur
= OB_CURSOR_SOUTH
;
196 else if (cnr
== prop_atoms
.net_wm_moveresize_size_bottomleft
) {
197 cur
= OB_CURSOR_SOUTHWEST
;
199 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_left
) {
200 cur
= OB_CURSOR_WEST
;
202 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_keyboard
)
203 cur
= OB_CURSOR_SOUTHEAST
;
204 else if (cnr
== prop_atoms
.net_wm_moveresize_move
)
205 cur
= OB_CURSOR_MOVE
;
206 else if (cnr
== prop_atoms
.net_wm_moveresize_move_keyboard
)
207 cur
= OB_CURSOR_MOVE
;
209 g_assert_not_reached();
211 /* keep the pointer bounded to the screen for move/resize */
212 if (!grab_pointer(FALSE
, TRUE
, cur
))
214 if (!grab_keyboard()) {
219 frame_end_iconify_animation(c
->frame
);
222 moveresize_client
= c
;
223 start_cx
= c
->area
.x
;
224 start_cy
= c
->area
.y
;
225 start_cw
= c
->area
.width
;
226 start_ch
= c
->area
.height
;
227 /* these adjustments for the size_inc make resizing a terminal more
228 friendly. you essentially start the resize in the middle of the
229 increment instead of at 0, so you have to move half an increment
230 either way instead of a full increment one and 1 px the other. */
231 start_x
= x
- (mv
? 0 : left
* c
->size_inc
.width
/ 2);
232 start_y
= y
- (mv
? 0 : up
* c
->size_inc
.height
/ 2);
235 key_resize_edge
= -1;
238 have to change start_cx and start_cy if going to do this..
239 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
240 corner == prop_atoms.net_wm_moveresize_size_keyboard)
241 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
242 c->area.width / 2, c->area.height / 2);
250 moveresize_in_progress
= TRUE
;
253 if (config_resize_redraw
&& !moving
&& obt_display_extension_sync
&&
254 moveresize_client
->sync_request
&& moveresize_client
->sync_counter
)
256 /* Initialize values for the resize syncing, and create an alarm for
257 the client's xsync counter */
260 XSyncAlarmAttributes aa
;
262 /* set the counter to an initial value */
263 XSyncIntToValue(&val
, 0);
264 XSyncSetCounter(obt_display
, moveresize_client
->sync_counter
, val
);
266 /* this will be incremented when we tell the client what we're
268 moveresize_client
->sync_counter_value
= 0;
270 /* the next sequence we're waiting for with the alarm */
271 XSyncIntToValue(&val
, 1);
273 /* set an alarm on the counter */
274 aa
.trigger
.counter
= moveresize_client
->sync_counter
;
275 aa
.trigger
.wait_value
= val
;
276 aa
.trigger
.value_type
= XSyncAbsolute
;
277 aa
.trigger
.test_type
= XSyncPositiveTransition
;
279 XSyncIntToValue(&aa
.delta
, 1);
280 moveresize_alarm
= XSyncCreateAlarm(obt_display
,
289 waiting_for_sync
= FALSE
;
294 void moveresize_end(gboolean cancel
)
302 client_move(moveresize_client
,
303 (cancel
? start_cx
: cur_x
),
304 (cancel
? start_cy
: cur_y
));
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
);
316 client_configure(moveresize_client
,
317 (cancel
? start_cx
: cur_x
),
318 (cancel
? start_cy
: cur_y
),
319 (cancel
? start_cw
: cur_w
),
320 (cancel
? start_ch
: cur_h
),
324 /* dont edge warp after its ended */
327 moveresize_in_progress
= FALSE
;
328 moveresize_client
= NULL
;
331 static void do_move(gboolean keyboard
, gint keydist
)
335 if (keyboard
) resist
= keydist
- 1; /* resist for one key press */
336 else resist
= config_resist_win
;
337 resist_move_windows(moveresize_client
, resist
, &cur_x
, &cur_y
);
338 if (!keyboard
) resist
= config_resist_edge
;
339 resist_move_monitors(moveresize_client
, resist
, &cur_x
, &cur_y
);
341 client_configure(moveresize_client
, cur_x
, cur_y
, cur_w
, cur_h
,
343 if (config_resize_popup_show
== 2) /* == "Always" */
344 popup_coords(moveresize_client
, "%d x %d",
345 moveresize_client
->frame
->area
.x
,
346 moveresize_client
->frame
->area
.y
);
350 static void do_resize(void)
352 gint x
, y
, w
, h
, lw
, lh
;
354 /* see if it is actually going to resize */
359 client_try_configure(moveresize_client
, &x
, &y
, &w
, &h
,
361 if (w
== moveresize_client
->area
.width
&&
362 h
== moveresize_client
->area
.height
)
368 if (config_resize_redraw
&& obt_display_extension_sync
&&
369 moveresize_client
->sync_request
&& moveresize_client
->sync_counter
)
374 /* are we already waiting for the sync counter to catch up? */
375 if (waiting_for_sync
)
378 /* increment the value we're waiting for */
379 ++moveresize_client
->sync_counter_value
;
380 XSyncIntToValue(&val
, moveresize_client
->sync_counter_value
);
382 /* tell the client what we're waiting for */
383 ce
.xclient
.type
= ClientMessage
;
384 ce
.xclient
.message_type
= prop_atoms
.wm_protocols
;
385 ce
.xclient
.display
= obt_display
;
386 ce
.xclient
.window
= moveresize_client
->window
;
387 ce
.xclient
.format
= 32;
388 ce
.xclient
.data
.l
[0] = prop_atoms
.net_wm_sync_request
;
389 ce
.xclient
.data
.l
[1] = event_curtime
;
390 ce
.xclient
.data
.l
[2] = XSyncValueLow32(val
);
391 ce
.xclient
.data
.l
[3] = XSyncValueHigh32(val
);
392 ce
.xclient
.data
.l
[4] = 0l;
393 XSendEvent(obt_display
, moveresize_client
->window
, FALSE
,
396 waiting_for_sync
= TRUE
;
398 obt_main_loop_timeout_remove(ob_main_loop
, sync_timeout_func
);
399 obt_main_loop_timeout_add(ob_main_loop
, G_USEC_PER_SEC
* 2,
405 client_configure(moveresize_client
, cur_x
, cur_y
, cur_w
, cur_h
,
408 /* this would be better with a fixed width font ... XXX can do it better
409 if there are 2 text boxes */
410 if (config_resize_popup_show
== 2 || /* == "Always" */
411 (config_resize_popup_show
== 1 && /* == "Nonpixel" */
412 moveresize_client
->size_inc
.width
> 1 &&
413 moveresize_client
->size_inc
.height
> 1))
414 popup_coords(moveresize_client
, "%d x %d",
415 moveresize_client
->logical_size
.width
,
416 moveresize_client
->logical_size
.height
);
420 static gboolean
sync_timeout_func(gpointer data
)
422 waiting_for_sync
= FALSE
; /* we timed out waiting for our sync... */
423 do_resize(); /* ...so let any pending resizes through */
425 return FALSE
; /* don't repeat */
429 static void calc_resize(gboolean keyboard
, gint keydist
, gint
*dw
, gint
*dh
,
432 gint resist
, x
= 0, y
= 0, lw
, lh
, ow
, oh
, nw
, nh
;
441 (moveresize_client
->max_ratio
|| moveresize_client
->min_ratio
))
444 case OB_DIRECTION_NORTH
:
445 case OB_DIRECTION_SOUTH
:
446 /* resize the width based on the height */
447 if (moveresize_client
->min_ratio
) {
448 if (nh
* moveresize_client
->min_ratio
> nw
)
449 nw
= (gint
)(nh
* moveresize_client
->min_ratio
);
451 if (moveresize_client
->max_ratio
) {
452 if (nh
* moveresize_client
->max_ratio
< nw
)
453 nw
= (gint
)(nh
* moveresize_client
->max_ratio
);
457 /* resize the height based on the width */
458 if (moveresize_client
->min_ratio
) {
459 if (nh
* moveresize_client
->min_ratio
> nw
)
460 nh
= (gint
)(nw
/ moveresize_client
->min_ratio
);
462 if (moveresize_client
->max_ratio
) {
463 if (nh
* moveresize_client
->max_ratio
< nw
)
464 nh
= (gint
)(nw
/ moveresize_client
->max_ratio
);
469 /* see its actual size (apply aspect ratios) */
470 client_try_configure(moveresize_client
, &x
, &y
, &nw
, &nh
, &lw
, &lh
,
476 /* resist_size_* needs the frame size */
477 nw
+= moveresize_client
->frame
->size
.left
+
478 moveresize_client
->frame
->size
.right
;
479 nh
+= moveresize_client
->frame
->size
.top
+
480 moveresize_client
->frame
->size
.bottom
;
482 if (keyboard
) resist
= keydist
- 1; /* resist for one key press */
483 else resist
= config_resist_win
;
484 resist_size_windows(moveresize_client
, resist
, &nw
, &nh
, dir
);
485 if (!keyboard
) resist
= config_resist_edge
;
486 resist_size_monitors(moveresize_client
, resist
, &nw
, &nh
, dir
);
488 nw
-= moveresize_client
->frame
->size
.left
+
489 moveresize_client
->frame
->size
.right
;
490 nh
-= moveresize_client
->frame
->size
.top
+
491 moveresize_client
->frame
->size
.bottom
;
496 /* take aspect ratios into account for resistance */
498 (moveresize_client
->max_ratio
|| moveresize_client
->min_ratio
))
500 if (*dh
!= trydh
) { /* got resisted */
501 /* resize the width based on the height */
502 if (moveresize_client
->min_ratio
) {
503 if (nh
* moveresize_client
->min_ratio
> nw
)
504 nw
= (gint
)(nh
* moveresize_client
->min_ratio
);
506 if (moveresize_client
->max_ratio
) {
507 if (nh
* moveresize_client
->max_ratio
< nw
)
508 nw
= (gint
)(nh
* moveresize_client
->max_ratio
);
511 if (*dw
!= trydw
) { /* got resisted */
512 /* resize the height based on the width */
513 if (moveresize_client
->min_ratio
) {
514 if (nh
* moveresize_client
->min_ratio
> nw
)
515 nh
= (gint
)(nw
/ moveresize_client
->min_ratio
);
517 if (moveresize_client
->max_ratio
) {
518 if (nh
* moveresize_client
->max_ratio
< nw
)
519 nh
= (gint
)(nw
/ moveresize_client
->max_ratio
);
524 /* make sure it's all valid */
525 client_try_configure(moveresize_client
, &x
, &y
, &nw
, &nh
, &lw
, &lh
, TRUE
);
531 static gboolean
edge_warp_delay_func(gpointer data
)
535 /* only fire every second time. so it's fast the first time, but slower
538 d
= screen_find_desktop(screen_desktop
, edge_warp_dir
, TRUE
, FALSE
);
539 if (d
!= screen_desktop
) screen_set_desktop(d
, TRUE
);
541 edge_warp_odd
= !edge_warp_odd
;
543 return TRUE
; /* do repeat ! */
546 static void do_edge_warp(gint x
, gint y
)
551 if (!config_mouse_screenedgetime
) return;
555 for (i
= 0; i
< screen_num_monitors
; ++i
) {
556 Rect
*a
= screen_physical_area_monitor(i
);
557 if (x
== RECT_LEFT(*a
)) dir
= OB_DIRECTION_WEST
;
558 if (x
== RECT_RIGHT(*a
)) dir
= OB_DIRECTION_EAST
;
559 if (y
== RECT_TOP(*a
)) dir
= OB_DIRECTION_NORTH
;
560 if (y
== RECT_BOTTOM(*a
)) dir
= OB_DIRECTION_SOUTH
;
562 /* try check for xinerama boundaries */
563 if ((x
+ 1 == RECT_LEFT(*a
) || x
- 1 == RECT_RIGHT(*a
)) &&
564 (dir
== OB_DIRECTION_WEST
|| dir
== OB_DIRECTION_EAST
))
568 if ((y
+ 1 == RECT_TOP(*a
) || y
- 1 == RECT_BOTTOM(*a
)) &&
569 (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(gint keycode
, gint 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
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
605 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
606 dir
= OB_DIRECTION_EAST
;
607 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
608 dir
= OB_DIRECTION_WEST
;
609 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
610 dir
= OB_DIRECTION_SOUTH
;
611 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
612 dir
= OB_DIRECTION_NORTH
;
614 client_find_move_directional(moveresize_client
, dir
, &x
, &y
);
615 dx
= x
- moveresize_client
->area
.x
;
616 dy
= y
- moveresize_client
->area
.y
;
618 /* control means fine grained */
619 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
))
624 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
626 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
628 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
630 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
634 screen_pointer_pos(&opx
, &opy
);
635 XWarpPointer(obt_display
, None
, None
, 0, 0, 0, 0, dx
, dy
);
636 /* steal the motion events this causes */
637 XSync(obt_display
, FALSE
);
640 while (XCheckTypedEvent(obt_display
, MotionNotify
, &ce
));
642 screen_pointer_pos(&px
, &py
);
648 /* because the cursor moves even though the window does
649 not nessesarily (resistance), this adjusts where the curor
650 thinks it started so that it keeps up with where the window
652 start_x
+= (px
- opx
) - (cur_x
- ox
);
653 start_y
+= (py
- opy
) - (cur_y
- oy
);
656 static void resize_with_keys(gint keycode
, gint state
)
658 gint dw
= 0, dh
= 0, pdx
= 0, pdy
= 0, opx
, opy
, px
, py
;
659 gint dist
= 0, resist
= 0;
662 /* pick the edge if it needs to move */
663 if (keycode
== ob_keycode(OB_KEY_RIGHT
)) {
664 dir
= OB_DIRECTION_EAST
;
665 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
666 key_resize_edge
!= OB_DIRECTION_EAST
)
668 key_resize_edge
= OB_DIRECTION_EAST
;
672 if (keycode
== ob_keycode(OB_KEY_LEFT
)) {
673 dir
= OB_DIRECTION_WEST
;
674 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
675 key_resize_edge
!= OB_DIRECTION_EAST
)
677 key_resize_edge
= OB_DIRECTION_WEST
;
681 if (keycode
== ob_keycode(OB_KEY_UP
)) {
682 dir
= OB_DIRECTION_NORTH
;
683 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
684 key_resize_edge
!= OB_DIRECTION_SOUTH
)
686 key_resize_edge
= OB_DIRECTION_NORTH
;
690 if (keycode
== ob_keycode(OB_KEY_DOWN
)) {
691 dir
= OB_DIRECTION_SOUTH
;
692 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
693 key_resize_edge
!= OB_DIRECTION_SOUTH
)
695 key_resize_edge
= OB_DIRECTION_SOUTH
;
700 /* shift means jump to edge */
701 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
704 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
705 dir
= OB_DIRECTION_EAST
;
706 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
707 dir
= OB_DIRECTION_WEST
;
708 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
709 dir
= OB_DIRECTION_SOUTH
;
710 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
711 dir
= OB_DIRECTION_NORTH
;
713 client_find_resize_directional(moveresize_client
, key_resize_edge
,
714 key_resize_edge
== dir
,
716 dw
= w
- moveresize_client
->area
.width
;
717 dh
= h
- moveresize_client
->area
.height
;
721 /* control means fine grained */
722 if (moveresize_client
->size_inc
.width
> 1) {
723 distw
= moveresize_client
->size_inc
.width
;
726 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
734 if (moveresize_client
->size_inc
.height
> 1) {
735 disth
= moveresize_client
->size_inc
.height
;
738 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
747 if (key_resize_edge
== OB_DIRECTION_WEST
) {
748 if (dir
== OB_DIRECTION_WEST
)
751 dw
= -(dist
= distw
);
753 else if (key_resize_edge
== OB_DIRECTION_EAST
) {
754 if (dir
== OB_DIRECTION_EAST
)
757 dw
= -(dist
= distw
);
759 else if (key_resize_edge
== OB_DIRECTION_NORTH
) {
760 if (dir
== OB_DIRECTION_NORTH
)
763 dh
= -(dist
= disth
);
765 else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
766 if (dir
== OB_DIRECTION_SOUTH
)
769 dh
= -(dist
= disth
);
773 calc_resize(TRUE
, resist
, &dw
, &dh
, dir
);
774 if (key_resize_edge
== OB_DIRECTION_WEST
)
776 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
781 /* how to move the pointer to keep up with the change */
782 if (key_resize_edge
== OB_DIRECTION_WEST
)
784 else if (key_resize_edge
== OB_DIRECTION_EAST
)
786 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
788 else if (key_resize_edge
== OB_DIRECTION_SOUTH
)
791 screen_pointer_pos(&opx
, &opy
);
792 XWarpPointer(obt_display
, None
, None
, 0, 0, 0, 0, pdx
, pdy
);
793 /* steal the motion events this causes */
794 XSync(obt_display
, FALSE
);
797 while (XCheckTypedEvent(obt_display
, MotionNotify
, &ce
));
799 screen_pointer_pos(&px
, &py
);
803 /* because the cursor moves even though the window does
804 not nessesarily (resistance), this adjusts where the cursor
805 thinks it started so that it keeps up with where the window
807 start_x
+= (px
- opx
) - dw
;
808 start_y
+= (py
- opy
) - dh
;
812 gboolean
moveresize_event(XEvent
*e
)
814 gboolean used
= FALSE
;
816 if (!moveresize_in_progress
) return FALSE
;
818 if (e
->type
== ButtonPress
) {
820 start_x
= e
->xbutton
.x_root
;
821 start_y
= e
->xbutton
.y_root
;
822 button
= e
->xbutton
.button
; /* this will end it now */
824 used
= e
->xbutton
.button
== button
;
825 } else if (e
->type
== ButtonRelease
) {
826 if (!button
|| e
->xbutton
.button
== button
) {
827 moveresize_end(FALSE
);
830 } else if (e
->type
== MotionNotify
) {
832 cur_x
= start_cx
+ e
->xmotion
.x_root
- start_x
;
833 cur_y
= start_cy
+ e
->xmotion
.y_root
- start_y
;
835 do_edge_warp(e
->xmotion
.x_root
, e
->xmotion
.y_root
);
840 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
) {
841 dw
= -(e
->xmotion
.x_root
- start_x
);
842 dh
= -(e
->xmotion
.y_root
- start_y
);
843 dir
= OB_DIRECTION_NORTHWEST
;
844 } else if (corner
== prop_atoms
.net_wm_moveresize_size_top
) {
846 dh
= -(e
->xmotion
.y_root
- start_y
);
847 dir
= OB_DIRECTION_NORTH
;
848 } else if (corner
== prop_atoms
.net_wm_moveresize_size_topright
) {
849 dw
= (e
->xmotion
.x_root
- start_x
);
850 dh
= -(e
->xmotion
.y_root
- start_y
);
851 dir
= OB_DIRECTION_NORTHEAST
;
852 } else if (corner
== prop_atoms
.net_wm_moveresize_size_right
) {
853 dw
= (e
->xmotion
.x_root
- start_x
);
855 dir
= OB_DIRECTION_EAST
;
857 prop_atoms
.net_wm_moveresize_size_bottomright
) {
858 dw
= (e
->xmotion
.x_root
- start_x
);
859 dh
= (e
->xmotion
.y_root
- start_y
);
860 dir
= OB_DIRECTION_SOUTHEAST
;
861 } else if (corner
== prop_atoms
.net_wm_moveresize_size_bottom
) {
863 dh
= (e
->xmotion
.y_root
- start_y
);
864 dir
= OB_DIRECTION_SOUTH
;
866 prop_atoms
.net_wm_moveresize_size_bottomleft
) {
867 dw
= -(e
->xmotion
.x_root
- start_x
);
868 dh
= (e
->xmotion
.y_root
- start_y
);
869 dir
= OB_DIRECTION_SOUTHWEST
;
870 } else if (corner
== prop_atoms
.net_wm_moveresize_size_left
) {
871 dw
= -(e
->xmotion
.x_root
- start_x
);
873 dir
= OB_DIRECTION_WEST
;
874 } else if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
875 dw
= (e
->xmotion
.x_root
- start_x
);
876 dh
= (e
->xmotion
.y_root
- start_y
);
877 dir
= OB_DIRECTION_SOUTHEAST
;
879 g_assert_not_reached();
881 dw
-= cur_w
- start_cw
;
882 dh
-= cur_h
- start_ch
;
884 calc_resize(FALSE
, 0, &dw
, &dh
, dir
);
888 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
||
889 corner
== prop_atoms
.net_wm_moveresize_size_left
||
890 corner
== prop_atoms
.net_wm_moveresize_size_bottomleft
)
894 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
||
895 corner
== prop_atoms
.net_wm_moveresize_size_top
||
896 corner
== prop_atoms
.net_wm_moveresize_size_topright
)
904 } else if (e
->type
== KeyPress
) {
905 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_ESCAPE
)) {
906 moveresize_end(TRUE
);
908 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RETURN
)) {
909 moveresize_end(FALSE
);
911 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RIGHT
) ||
912 e
->xkey
.keycode
== ob_keycode(OB_KEY_LEFT
) ||
913 e
->xkey
.keycode
== ob_keycode(OB_KEY_DOWN
) ||
914 e
->xkey
.keycode
== ob_keycode(OB_KEY_UP
))
916 if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
917 resize_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
919 } else if (corner
== prop_atoms
.net_wm_moveresize_move_keyboard
) {
920 move_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
926 else if (e
->type
== obt_display_extension_sync_basep
+ XSyncAlarmNotify
)
928 waiting_for_sync
= FALSE
; /* we got our sync... */
929 do_resize(); /* ...so try resize if there is more change pending */