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_move(gboolean keyboard
, gint keydist
);
67 static void do_resize(void);
68 static void do_edge_warp(gint x
, gint y
);
69 static void cancel_edge_warp();
71 static gboolean
sync_timeout_func(gpointer data
);
74 static void client_dest(ObClient
*client
, gpointer data
)
76 if (moveresize_client
== client
)
80 void moveresize_startup(gboolean reconfig
)
83 popup_set_text_align(popup
, RR_JUSTIFY_CENTER
);
86 client_add_destroy_notify(client_dest
, NULL
);
89 void moveresize_shutdown(gboolean reconfig
)
92 if (moveresize_in_progress
)
93 moveresize_end(FALSE
);
94 client_remove_destroy_notify(client_dest
);
101 static void popup_coords(ObClient
*c
, const gchar
*format
, gint a
, gint b
)
105 text
= g_strdup_printf(format
, a
, b
);
106 if (config_resize_popup_pos
== OB_RESIZE_POS_TOP
)
107 popup_position(popup
, SouthGravity
,
109 + c
->frame
->area
.width
/2,
110 c
->frame
->area
.y
- ob_rr_theme
->fbwidth
);
111 else if (config_resize_popup_pos
== OB_RESIZE_POS_CENTER
)
112 popup_position(popup
, CenterGravity
,
113 c
->frame
->area
.x
+ c
->frame
->area
.width
/ 2,
114 c
->frame
->area
.y
+ c
->frame
->area
.height
/ 2);
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
))
367 if (config_resize_redraw
&& extensions_sync
&&
368 moveresize_client
->sync_request
&&
369 moveresize_client
->sync_counter
&&
370 !moveresize_client
->not_responding
)
375 /* are we already waiting for the sync counter to catch up? */
376 if (waiting_for_sync
)
379 /* increment the value we're waiting for */
380 ++moveresize_client
->sync_counter_value
;
381 XSyncIntToValue(&val
, moveresize_client
->sync_counter_value
);
383 /* tell the client what we're waiting for */
384 ce
.xclient
.type
= ClientMessage
;
385 ce
.xclient
.message_type
= prop_atoms
.wm_protocols
;
386 ce
.xclient
.display
= ob_display
;
387 ce
.xclient
.window
= moveresize_client
->window
;
388 ce
.xclient
.format
= 32;
389 ce
.xclient
.data
.l
[0] = prop_atoms
.net_wm_sync_request
;
390 ce
.xclient
.data
.l
[1] = event_curtime
;
391 ce
.xclient
.data
.l
[2] = XSyncValueLow32(val
);
392 ce
.xclient
.data
.l
[3] = XSyncValueHigh32(val
);
393 ce
.xclient
.data
.l
[4] = 0l;
394 XSendEvent(ob_display
, moveresize_client
->window
, FALSE
,
397 waiting_for_sync
= TRUE
;
399 ob_main_loop_timeout_remove(ob_main_loop
, sync_timeout_func
);
400 ob_main_loop_timeout_add(ob_main_loop
, G_USEC_PER_SEC
* 2,
401 sync_timeout_func
, NULL
, NULL
, NULL
);
405 client_configure(moveresize_client
, cur_x
, cur_y
, cur_w
, cur_h
,
409 /* this would be better with a fixed width font ... XXX can do it better
410 if there are 2 text boxes */
411 if (config_resize_popup_show
== 2 || /* == "Always" */
412 (config_resize_popup_show
== 1 && /* == "Nonpixel" */
413 moveresize_client
->size_inc
.width
> 1 &&
414 moveresize_client
->size_inc
.height
> 1))
415 popup_coords(moveresize_client
, "%d x %d", lw
, lh
);
419 static gboolean
sync_timeout_func(gpointer data
)
421 waiting_for_sync
= FALSE
; /* we timed out waiting for our sync... */
422 do_resize(); /* ...so let any pending resizes through */
424 return FALSE
; /* don't repeat */
428 static void calc_resize(gboolean keyboard
, gint keydist
, gint
*dw
, gint
*dh
,
431 gint resist
, x
= 0, y
= 0, lw
, lh
, ow
, oh
, nw
, nh
;
440 (moveresize_client
->max_ratio
|| moveresize_client
->min_ratio
))
443 case OB_DIRECTION_NORTH
:
444 case OB_DIRECTION_SOUTH
:
445 /* resize the width based on the height */
446 if (moveresize_client
->min_ratio
) {
447 if (nh
* moveresize_client
->min_ratio
> nw
)
448 nw
= (gint
)(nh
* moveresize_client
->min_ratio
);
450 if (moveresize_client
->max_ratio
) {
451 if (nh
* moveresize_client
->max_ratio
< nw
)
452 nw
= (gint
)(nh
* moveresize_client
->max_ratio
);
456 /* resize the height based on the width */
457 if (moveresize_client
->min_ratio
) {
458 if (nh
* moveresize_client
->min_ratio
> nw
)
459 nh
= (gint
)(nw
/ moveresize_client
->min_ratio
);
461 if (moveresize_client
->max_ratio
) {
462 if (nh
* moveresize_client
->max_ratio
< nw
)
463 nh
= (gint
)(nw
/ moveresize_client
->max_ratio
);
468 /* see its actual size (apply aspect ratios) */
469 client_try_configure(moveresize_client
, &x
, &y
, &nw
, &nh
, &lw
, &lh
,
475 /* resist_size_* needs the frame size */
476 nw
+= moveresize_client
->frame
->size
.left
+
477 moveresize_client
->frame
->size
.right
;
478 nh
+= moveresize_client
->frame
->size
.top
+
479 moveresize_client
->frame
->size
.bottom
;
481 if (keyboard
) resist
= keydist
- 1; /* resist for one key press */
482 else resist
= config_resist_win
;
483 resist_size_windows(moveresize_client
, resist
, &nw
, &nh
, dir
);
484 if (!keyboard
) resist
= config_resist_edge
;
485 resist_size_monitors(moveresize_client
, resist
, &nw
, &nh
, dir
);
487 nw
-= moveresize_client
->frame
->size
.left
+
488 moveresize_client
->frame
->size
.right
;
489 nh
-= moveresize_client
->frame
->size
.top
+
490 moveresize_client
->frame
->size
.bottom
;
495 /* take aspect ratios into account for resistance */
497 (moveresize_client
->max_ratio
|| moveresize_client
->min_ratio
))
499 if (*dh
!= trydh
) { /* got resisted */
500 /* resize the width based on the height */
501 if (moveresize_client
->min_ratio
) {
502 if (nh
* moveresize_client
->min_ratio
> nw
)
503 nw
= (gint
)(nh
* moveresize_client
->min_ratio
);
505 if (moveresize_client
->max_ratio
) {
506 if (nh
* moveresize_client
->max_ratio
< nw
)
507 nw
= (gint
)(nh
* moveresize_client
->max_ratio
);
510 if (*dw
!= trydw
) { /* got resisted */
511 /* resize the height based on the width */
512 if (moveresize_client
->min_ratio
) {
513 if (nh
* moveresize_client
->min_ratio
> nw
)
514 nh
= (gint
)(nw
/ moveresize_client
->min_ratio
);
516 if (moveresize_client
->max_ratio
) {
517 if (nh
* moveresize_client
->max_ratio
< nw
)
518 nh
= (gint
)(nw
/ moveresize_client
->max_ratio
);
523 /* make sure it's all valid */
524 client_try_configure(moveresize_client
, &x
, &y
, &nw
, &nh
, &lw
, &lh
, TRUE
);
530 static gboolean
edge_warp_delay_func(gpointer data
)
534 /* only fire every second time. so it's fast the first time, but slower
537 d
= screen_find_desktop(screen_desktop
, edge_warp_dir
, TRUE
, FALSE
);
538 if (d
!= screen_desktop
) screen_set_desktop(d
, TRUE
);
540 edge_warp_odd
= !edge_warp_odd
;
542 return TRUE
; /* do repeat ! */
545 static void do_edge_warp(gint x
, gint y
)
550 if (!config_mouse_screenedgetime
) return;
554 for (i
= 0; i
< screen_num_monitors
; ++i
) {
555 Rect
*a
= screen_physical_area_monitor(i
);
556 if (x
== RECT_LEFT(*a
)) dir
= OB_DIRECTION_WEST
;
557 if (x
== RECT_RIGHT(*a
)) dir
= OB_DIRECTION_EAST
;
558 if (y
== RECT_TOP(*a
)) dir
= OB_DIRECTION_NORTH
;
559 if (y
== RECT_BOTTOM(*a
)) dir
= OB_DIRECTION_SOUTH
;
561 /* try check for xinerama boundaries */
562 if ((x
+ 1 == RECT_LEFT(*a
) || x
- 1 == RECT_RIGHT(*a
)) &&
563 (dir
== OB_DIRECTION_WEST
|| dir
== OB_DIRECTION_EAST
))
567 if ((y
+ 1 == RECT_TOP(*a
) || y
- 1 == RECT_BOTTOM(*a
)) &&
568 (dir
== OB_DIRECTION_NORTH
|| dir
== OB_DIRECTION_SOUTH
))
575 if (dir
!= edge_warp_dir
) {
577 if (dir
!= (ObDirection
)-1) {
578 edge_warp_odd
= TRUE
; /* switch on the first timeout */
579 ob_main_loop_timeout_add(ob_main_loop
,
580 config_mouse_screenedgetime
* 1000,
581 edge_warp_delay_func
,
588 static void cancel_edge_warp(void)
590 ob_main_loop_timeout_remove(ob_main_loop
, edge_warp_delay_func
);
593 static void move_with_keys(gint keycode
, gint state
)
595 gint dx
= 0, dy
= 0, ox
= cur_x
, oy
= cur_y
;
596 gint opx
, px
, opy
, py
;
599 /* shift means jump to edge */
600 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
604 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
605 dir
= OB_DIRECTION_EAST
;
606 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
607 dir
= OB_DIRECTION_WEST
;
608 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
609 dir
= OB_DIRECTION_SOUTH
;
610 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
611 dir
= OB_DIRECTION_NORTH
;
613 client_find_move_directional(moveresize_client
, dir
, &x
, &y
);
614 dx
= x
- moveresize_client
->area
.x
;
615 dy
= y
- moveresize_client
->area
.y
;
617 /* control means fine grained */
618 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
))
623 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
625 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
627 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
629 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
633 screen_pointer_pos(&opx
, &opy
);
634 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, dx
, dy
);
635 /* steal the motion events this causes */
636 XSync(ob_display
, FALSE
);
639 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
641 screen_pointer_pos(&px
, &py
);
647 /* because the cursor moves even though the window does
648 not nessesarily (resistance), this adjusts where the curor
649 thinks it started so that it keeps up with where the window
651 start_x
+= (px
- opx
) - (cur_x
- ox
);
652 start_y
+= (py
- opy
) - (cur_y
- oy
);
655 static void resize_with_keys(gint keycode
, gint state
)
657 gint dw
= 0, dh
= 0, pdx
= 0, pdy
= 0, opx
, opy
, px
, py
;
658 gint dist
= 0, resist
= 0;
661 /* pick the edge if it needs to move */
662 if (keycode
== ob_keycode(OB_KEY_RIGHT
)) {
663 dir
= OB_DIRECTION_EAST
;
664 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
665 key_resize_edge
!= OB_DIRECTION_EAST
)
667 key_resize_edge
= OB_DIRECTION_EAST
;
671 if (keycode
== ob_keycode(OB_KEY_LEFT
)) {
672 dir
= OB_DIRECTION_WEST
;
673 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
674 key_resize_edge
!= OB_DIRECTION_EAST
)
676 key_resize_edge
= OB_DIRECTION_WEST
;
680 if (keycode
== ob_keycode(OB_KEY_UP
)) {
681 dir
= OB_DIRECTION_NORTH
;
682 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
683 key_resize_edge
!= OB_DIRECTION_SOUTH
)
685 key_resize_edge
= OB_DIRECTION_NORTH
;
689 if (keycode
== ob_keycode(OB_KEY_DOWN
)) {
690 dir
= OB_DIRECTION_SOUTH
;
691 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
692 key_resize_edge
!= OB_DIRECTION_SOUTH
)
694 key_resize_edge
= OB_DIRECTION_SOUTH
;
699 /* shift means jump to edge */
700 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
703 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
704 dir
= OB_DIRECTION_EAST
;
705 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
706 dir
= OB_DIRECTION_WEST
;
707 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
708 dir
= OB_DIRECTION_SOUTH
;
709 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
710 dir
= OB_DIRECTION_NORTH
;
712 client_find_resize_directional(moveresize_client
, key_resize_edge
,
713 key_resize_edge
== dir
,
715 dw
= w
- moveresize_client
->area
.width
;
716 dh
= h
- moveresize_client
->area
.height
;
720 /* control means fine grained */
721 if (moveresize_client
->size_inc
.width
> 1) {
722 distw
= moveresize_client
->size_inc
.width
;
725 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
733 if (moveresize_client
->size_inc
.height
> 1) {
734 disth
= moveresize_client
->size_inc
.height
;
737 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
746 if (key_resize_edge
== OB_DIRECTION_WEST
) {
747 if (dir
== OB_DIRECTION_WEST
)
750 dw
= -(dist
= distw
);
752 else if (key_resize_edge
== OB_DIRECTION_EAST
) {
753 if (dir
== OB_DIRECTION_EAST
)
756 dw
= -(dist
= distw
);
758 else if (key_resize_edge
== OB_DIRECTION_NORTH
) {
759 if (dir
== OB_DIRECTION_NORTH
)
762 dh
= -(dist
= disth
);
764 else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
765 if (dir
== OB_DIRECTION_SOUTH
)
768 dh
= -(dist
= disth
);
772 calc_resize(TRUE
, resist
, &dw
, &dh
, dir
);
773 if (key_resize_edge
== OB_DIRECTION_WEST
)
775 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
780 /* how to move the pointer to keep up with the change */
781 if (key_resize_edge
== OB_DIRECTION_WEST
)
783 else if (key_resize_edge
== OB_DIRECTION_EAST
)
785 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
787 else if (key_resize_edge
== OB_DIRECTION_SOUTH
)
790 screen_pointer_pos(&opx
, &opy
);
791 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, pdx
, pdy
);
792 /* steal the motion events this causes */
793 XSync(ob_display
, FALSE
);
796 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
798 screen_pointer_pos(&px
, &py
);
802 /* because the cursor moves even though the window does
803 not nessesarily (resistance), this adjusts where the cursor
804 thinks it started so that it keeps up with where the window
806 start_x
+= (px
- opx
) - dw
;
807 start_y
+= (py
- opy
) - dh
;
811 gboolean
moveresize_event(XEvent
*e
)
813 gboolean used
= FALSE
;
815 if (!moveresize_in_progress
) return FALSE
;
817 if (e
->type
== ButtonPress
) {
819 start_x
= e
->xbutton
.x_root
;
820 start_y
= e
->xbutton
.y_root
;
821 button
= e
->xbutton
.button
; /* this will end it now */
823 used
= e
->xbutton
.button
== button
;
824 } else if (e
->type
== ButtonRelease
) {
825 if (!button
|| e
->xbutton
.button
== button
) {
826 moveresize_end(FALSE
);
829 } else if (e
->type
== MotionNotify
) {
831 cur_x
= start_cx
+ e
->xmotion
.x_root
- start_x
;
832 cur_y
= start_cy
+ e
->xmotion
.y_root
- start_y
;
834 do_edge_warp(e
->xmotion
.x_root
, e
->xmotion
.y_root
);
839 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
) {
840 dw
= -(e
->xmotion
.x_root
- start_x
);
841 dh
= -(e
->xmotion
.y_root
- start_y
);
842 dir
= OB_DIRECTION_NORTHWEST
;
843 } else if (corner
== prop_atoms
.net_wm_moveresize_size_top
) {
845 dh
= -(e
->xmotion
.y_root
- start_y
);
846 dir
= OB_DIRECTION_NORTH
;
847 } else if (corner
== prop_atoms
.net_wm_moveresize_size_topright
) {
848 dw
= (e
->xmotion
.x_root
- start_x
);
849 dh
= -(e
->xmotion
.y_root
- start_y
);
850 dir
= OB_DIRECTION_NORTHEAST
;
851 } else if (corner
== prop_atoms
.net_wm_moveresize_size_right
) {
852 dw
= (e
->xmotion
.x_root
- start_x
);
854 dir
= OB_DIRECTION_EAST
;
856 prop_atoms
.net_wm_moveresize_size_bottomright
) {
857 dw
= (e
->xmotion
.x_root
- start_x
);
858 dh
= (e
->xmotion
.y_root
- start_y
);
859 dir
= OB_DIRECTION_SOUTHEAST
;
860 } else if (corner
== prop_atoms
.net_wm_moveresize_size_bottom
) {
862 dh
= (e
->xmotion
.y_root
- start_y
);
863 dir
= OB_DIRECTION_SOUTH
;
865 prop_atoms
.net_wm_moveresize_size_bottomleft
) {
866 dw
= -(e
->xmotion
.x_root
- start_x
);
867 dh
= (e
->xmotion
.y_root
- start_y
);
868 dir
= OB_DIRECTION_SOUTHWEST
;
869 } else if (corner
== prop_atoms
.net_wm_moveresize_size_left
) {
870 dw
= -(e
->xmotion
.x_root
- start_x
);
872 dir
= OB_DIRECTION_WEST
;
873 } else if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
874 dw
= (e
->xmotion
.x_root
- start_x
);
875 dh
= (e
->xmotion
.y_root
- start_y
);
876 dir
= OB_DIRECTION_SOUTHEAST
;
878 g_assert_not_reached();
880 dw
-= cur_w
- start_cw
;
881 dh
-= cur_h
- start_ch
;
883 calc_resize(FALSE
, 0, &dw
, &dh
, dir
);
887 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
||
888 corner
== prop_atoms
.net_wm_moveresize_size_left
||
889 corner
== prop_atoms
.net_wm_moveresize_size_bottomleft
)
893 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
||
894 corner
== prop_atoms
.net_wm_moveresize_size_top
||
895 corner
== prop_atoms
.net_wm_moveresize_size_topright
)
903 } else if (e
->type
== KeyPress
) {
904 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_ESCAPE
)) {
905 moveresize_end(TRUE
);
907 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RETURN
)) {
908 moveresize_end(FALSE
);
910 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RIGHT
) ||
911 e
->xkey
.keycode
== ob_keycode(OB_KEY_LEFT
) ||
912 e
->xkey
.keycode
== ob_keycode(OB_KEY_DOWN
) ||
913 e
->xkey
.keycode
== ob_keycode(OB_KEY_UP
))
915 if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
916 resize_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
918 } else if (corner
== prop_atoms
.net_wm_moveresize_move_keyboard
) {
919 move_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
925 else if (e
->type
== extensions_sync_event_basep
+ XSyncAlarmNotify
)
927 waiting_for_sync
= FALSE
; /* we got our sync... */
928 do_resize(); /* ...so try resize if there is more change pending */