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"
29 #include "moveresize.h"
33 #include "render/render.h"
34 #include "render/theme.h"
35 #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
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE
) ||
171 cnr
== OBT_PROP_ATOM(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
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT
)) {
182 cur
= OB_CURSOR_NORTHWEST
;
185 else if (cnr
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP
)) {
186 cur
= OB_CURSOR_NORTH
;
189 else if (cnr
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT
)) {
190 cur
= OB_CURSOR_NORTHEAST
;
193 else if (cnr
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT
))
194 cur
= OB_CURSOR_EAST
;
195 else if (cnr
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
))
196 cur
= OB_CURSOR_SOUTHEAST
;
197 else if (cnr
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM
))
198 cur
= OB_CURSOR_SOUTH
;
199 else if (cnr
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
)) {
200 cur
= OB_CURSOR_SOUTHWEST
;
203 else if (cnr
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT
)) {
204 cur
= OB_CURSOR_WEST
;
207 else if (cnr
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD
))
208 cur
= OB_CURSOR_SOUTHEAST
;
209 else if (cnr
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE
))
210 cur
= OB_CURSOR_MOVE
;
211 else if (cnr
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD
))
212 cur
= OB_CURSOR_MOVE
;
214 g_assert_not_reached();
216 /* keep the pointer bounded to the screen for move/resize */
217 if (!grab_pointer(FALSE
, TRUE
, cur
))
219 if (!grab_keyboard()) {
224 frame_end_iconify_animation(c
->frame
);
227 moveresize_client
= c
;
228 start_cx
= c
->area
.x
;
229 start_cy
= c
->area
.y
;
230 start_cw
= c
->area
.width
;
231 start_ch
= c
->area
.height
;
232 /* these adjustments for the size_inc make resizing a terminal more
233 friendly. you essentially start the resize in the middle of the
234 increment instead of at 0, so you have to move half an increment
235 either way instead of a full increment one and 1 px the other. */
236 start_x
= x
- (mv
? 0 : left
* c
->size_inc
.width
/ 2);
237 start_y
= y
- (mv
? 0 : up
* c
->size_inc
.height
/ 2);
240 key_resize_edge
= -1;
243 have to change start_cx and start_cy if going to do this..
244 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
245 corner == prop_atoms.net_wm_moveresize_size_keyboard)
246 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
247 c->area.width / 2, c->area.height / 2);
255 moveresize_in_progress
= TRUE
;
258 if (config_resize_redraw
&& !moving
&& obt_display_extension_sync
&&
259 moveresize_client
->sync_request
&& moveresize_client
->sync_counter
)
261 /* Initialize values for the resize syncing, and create an alarm for
262 the client's xsync counter */
265 XSyncAlarmAttributes aa
;
267 /* set the counter to an initial value */
268 XSyncIntToValue(&val
, 0);
269 XSyncSetCounter(obt_display
, moveresize_client
->sync_counter
, val
);
271 /* this will be incremented when we tell the client what we're
273 moveresize_client
->sync_counter_value
= 0;
275 /* the next sequence we're waiting for with the alarm */
276 XSyncIntToValue(&val
, 1);
278 /* set an alarm on the counter */
279 aa
.trigger
.counter
= moveresize_client
->sync_counter
;
280 aa
.trigger
.wait_value
= val
;
281 aa
.trigger
.value_type
= XSyncAbsolute
;
282 aa
.trigger
.test_type
= XSyncPositiveTransition
;
284 XSyncIntToValue(&aa
.delta
, 1);
285 moveresize_alarm
= XSyncCreateAlarm(obt_display
,
294 waiting_for_sync
= FALSE
;
299 void moveresize_end(gboolean cancel
)
307 client_move(moveresize_client
,
308 (cancel
? start_cx
: cur_x
),
309 (cancel
? start_cy
: cur_y
));
312 /* turn off the alarm */
313 if (moveresize_alarm
!= None
) {
314 XSyncDestroyAlarm(obt_display
, moveresize_alarm
);
315 moveresize_alarm
= None
;
318 obt_main_loop_timeout_remove(ob_main_loop
, sync_timeout_func
);
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
),
329 /* dont edge warp after its ended */
332 moveresize_in_progress
= FALSE
;
333 moveresize_client
= NULL
;
336 static void do_move(gboolean keyboard
, gint keydist
)
340 if (keyboard
) resist
= keydist
- 1; /* resist for one key press */
341 else resist
= config_resist_win
;
342 resist_move_windows(moveresize_client
, resist
, &cur_x
, &cur_y
);
343 if (!keyboard
) resist
= config_resist_edge
;
344 resist_move_monitors(moveresize_client
, resist
, &cur_x
, &cur_y
);
346 client_configure(moveresize_client
, cur_x
, cur_y
, cur_w
, cur_h
,
348 if (config_resize_popup_show
== 2) /* == "Always" */
349 popup_coords(moveresize_client
, "%d x %d",
350 moveresize_client
->frame
->area
.x
,
351 moveresize_client
->frame
->area
.y
);
355 static void do_resize(void)
357 gint x
, y
, w
, h
, lw
, lh
;
359 /* see if it is actually going to resize */
364 client_try_configure(moveresize_client
, &x
, &y
, &w
, &h
,
366 if (w
== moveresize_client
->area
.width
&&
367 h
== moveresize_client
->area
.height
)
373 if (config_resize_redraw
&& obt_display_extension_sync
&&
374 moveresize_client
->sync_request
&& moveresize_client
->sync_counter
)
379 /* are we already waiting for the sync counter to catch up? */
380 if (waiting_for_sync
)
383 /* increment the value we're waiting for */
384 ++moveresize_client
->sync_counter_value
;
385 XSyncIntToValue(&val
, moveresize_client
->sync_counter_value
);
387 /* tell the client what we're waiting for */
388 ce
.xclient
.type
= ClientMessage
;
389 ce
.xclient
.message_type
= OBT_PROP_ATOM(WM_PROTOCOLS
);
390 ce
.xclient
.display
= obt_display
;
391 ce
.xclient
.window
= moveresize_client
->window
;
392 ce
.xclient
.format
= 32;
393 ce
.xclient
.data
.l
[0] = OBT_PROP_ATOM(NET_WM_SYNC_REQUEST
);
394 ce
.xclient
.data
.l
[1] = event_curtime
;
395 ce
.xclient
.data
.l
[2] = XSyncValueLow32(val
);
396 ce
.xclient
.data
.l
[3] = XSyncValueHigh32(val
);
397 ce
.xclient
.data
.l
[4] = 0l;
398 XSendEvent(obt_display
, moveresize_client
->window
, FALSE
,
401 waiting_for_sync
= TRUE
;
403 obt_main_loop_timeout_remove(ob_main_loop
, sync_timeout_func
);
404 obt_main_loop_timeout_add(ob_main_loop
, G_USEC_PER_SEC
* 2,
410 client_configure(moveresize_client
, cur_x
, cur_y
, cur_w
, cur_h
,
413 /* this would be better with a fixed width font ... XXX can do it better
414 if there are 2 text boxes */
415 if (config_resize_popup_show
== 2 || /* == "Always" */
416 (config_resize_popup_show
== 1 && /* == "Nonpixel" */
417 moveresize_client
->size_inc
.width
> 1 &&
418 moveresize_client
->size_inc
.height
> 1))
419 popup_coords(moveresize_client
, "%d x %d",
420 moveresize_client
->logical_size
.width
,
421 moveresize_client
->logical_size
.height
);
425 static gboolean
sync_timeout_func(gpointer data
)
427 waiting_for_sync
= FALSE
; /* we timed out waiting for our sync... */
428 do_resize(); /* ...so let any pending resizes through */
430 return FALSE
; /* don't repeat */
434 static void calc_resize(gboolean keyboard
, gint keydist
, gint
*dw
, gint
*dh
,
437 gint resist
, x
= 0, y
= 0, lw
, lh
, ow
, oh
, nw
, nh
;
446 (moveresize_client
->max_ratio
|| moveresize_client
->min_ratio
))
449 case OB_DIRECTION_NORTH
:
450 case OB_DIRECTION_SOUTH
:
451 /* resize the width based on the height */
452 if (moveresize_client
->min_ratio
) {
453 if (nh
* moveresize_client
->min_ratio
> nw
)
454 nw
= (gint
)(nh
* moveresize_client
->min_ratio
);
456 if (moveresize_client
->max_ratio
) {
457 if (nh
* moveresize_client
->max_ratio
< nw
)
458 nw
= (gint
)(nh
* moveresize_client
->max_ratio
);
462 /* resize the height based on the width */
463 if (moveresize_client
->min_ratio
) {
464 if (nh
* moveresize_client
->min_ratio
> nw
)
465 nh
= (gint
)(nw
/ moveresize_client
->min_ratio
);
467 if (moveresize_client
->max_ratio
) {
468 if (nh
* moveresize_client
->max_ratio
< nw
)
469 nh
= (gint
)(nw
/ moveresize_client
->max_ratio
);
474 /* see its actual size (apply aspect ratios) */
475 client_try_configure(moveresize_client
, &x
, &y
, &nw
, &nh
, &lw
, &lh
,
481 /* resist_size_* needs the frame size */
482 nw
+= moveresize_client
->frame
->size
.left
+
483 moveresize_client
->frame
->size
.right
;
484 nh
+= moveresize_client
->frame
->size
.top
+
485 moveresize_client
->frame
->size
.bottom
;
487 if (keyboard
) resist
= keydist
- 1; /* resist for one key press */
488 else resist
= config_resist_win
;
489 resist_size_windows(moveresize_client
, resist
, &nw
, &nh
, dir
);
490 if (!keyboard
) resist
= config_resist_edge
;
491 resist_size_monitors(moveresize_client
, resist
, &nw
, &nh
, dir
);
493 nw
-= moveresize_client
->frame
->size
.left
+
494 moveresize_client
->frame
->size
.right
;
495 nh
-= moveresize_client
->frame
->size
.top
+
496 moveresize_client
->frame
->size
.bottom
;
501 /* take aspect ratios into account for resistance */
503 (moveresize_client
->max_ratio
|| moveresize_client
->min_ratio
))
505 if (*dh
!= trydh
) { /* got resisted */
506 /* resize the width based on the height */
507 if (moveresize_client
->min_ratio
) {
508 if (nh
* moveresize_client
->min_ratio
> nw
)
509 nw
= (gint
)(nh
* moveresize_client
->min_ratio
);
511 if (moveresize_client
->max_ratio
) {
512 if (nh
* moveresize_client
->max_ratio
< nw
)
513 nw
= (gint
)(nh
* moveresize_client
->max_ratio
);
516 if (*dw
!= trydw
) { /* got resisted */
517 /* resize the height based on the width */
518 if (moveresize_client
->min_ratio
) {
519 if (nh
* moveresize_client
->min_ratio
> nw
)
520 nh
= (gint
)(nw
/ moveresize_client
->min_ratio
);
522 if (moveresize_client
->max_ratio
) {
523 if (nh
* moveresize_client
->max_ratio
< nw
)
524 nh
= (gint
)(nw
/ moveresize_client
->max_ratio
);
529 /* make sure it's all valid */
530 client_try_configure(moveresize_client
, &x
, &y
, &nw
, &nh
, &lw
, &lh
, TRUE
);
536 static gboolean
edge_warp_delay_func(gpointer data
)
540 /* only fire every second time. so it's fast the first time, but slower
543 d
= screen_find_desktop(screen_desktop
, edge_warp_dir
, TRUE
, FALSE
);
544 if (d
!= screen_desktop
) screen_set_desktop(d
, TRUE
);
546 edge_warp_odd
= !edge_warp_odd
;
548 return TRUE
; /* do repeat ! */
551 static void do_edge_warp(gint x
, gint y
)
556 if (!config_mouse_screenedgetime
) return;
560 for (i
= 0; i
< screen_num_monitors
; ++i
) {
561 Rect
*a
= screen_physical_area_monitor(i
);
562 if (x
== RECT_LEFT(*a
)) dir
= OB_DIRECTION_WEST
;
563 if (x
== RECT_RIGHT(*a
)) dir
= OB_DIRECTION_EAST
;
564 if (y
== RECT_TOP(*a
)) dir
= OB_DIRECTION_NORTH
;
565 if (y
== RECT_BOTTOM(*a
)) dir
= OB_DIRECTION_SOUTH
;
567 /* try check for xinerama boundaries */
568 if ((x
+ 1 == RECT_LEFT(*a
) || x
- 1 == RECT_RIGHT(*a
)) &&
569 (dir
== OB_DIRECTION_WEST
|| dir
== OB_DIRECTION_EAST
))
573 if ((y
+ 1 == RECT_TOP(*a
) || y
- 1 == RECT_BOTTOM(*a
)) &&
574 (dir
== OB_DIRECTION_NORTH
|| dir
== OB_DIRECTION_SOUTH
))
581 if (dir
!= edge_warp_dir
) {
583 if (dir
!= (ObDirection
)-1) {
584 edge_warp_odd
= TRUE
; /* switch on the first timeout */
585 obt_main_loop_timeout_add(ob_main_loop
,
586 config_mouse_screenedgetime
* 1000,
587 edge_warp_delay_func
,
594 static void cancel_edge_warp(void)
596 obt_main_loop_timeout_remove(ob_main_loop
, edge_warp_delay_func
);
599 static void move_with_keys(gint keycode
, gint state
)
601 gint dx
= 0, dy
= 0, ox
= cur_x
, oy
= cur_y
;
602 gint opx
, px
, opy
, py
;
605 /* shift means jump to edge */
606 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
610 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
611 dir
= OB_DIRECTION_EAST
;
612 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
613 dir
= OB_DIRECTION_WEST
;
614 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
615 dir
= OB_DIRECTION_SOUTH
;
616 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
617 dir
= OB_DIRECTION_NORTH
;
619 client_find_move_directional(moveresize_client
, dir
, &x
, &y
);
620 dx
= x
- moveresize_client
->area
.x
;
621 dy
= y
- moveresize_client
->area
.y
;
623 /* control means fine grained */
624 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
))
629 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
631 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
633 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
635 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
639 screen_pointer_pos(&opx
, &opy
);
640 XWarpPointer(obt_display
, None
, None
, 0, 0, 0, 0, dx
, dy
);
641 /* steal the motion events this causes */
642 XSync(obt_display
, FALSE
);
645 while (XCheckTypedEvent(obt_display
, MotionNotify
, &ce
));
647 screen_pointer_pos(&px
, &py
);
653 /* because the cursor moves even though the window does
654 not nessesarily (resistance), this adjusts where the curor
655 thinks it started so that it keeps up with where the window
657 start_x
+= (px
- opx
) - (cur_x
- ox
);
658 start_y
+= (py
- opy
) - (cur_y
- oy
);
661 static void resize_with_keys(gint keycode
, gint state
)
663 gint dw
= 0, dh
= 0, pdx
= 0, pdy
= 0, opx
, opy
, px
, py
;
664 gint dist
= 0, resist
= 0;
667 /* pick the edge if it needs to move */
668 if (keycode
== ob_keycode(OB_KEY_RIGHT
)) {
669 dir
= OB_DIRECTION_EAST
;
670 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
671 key_resize_edge
!= OB_DIRECTION_EAST
)
673 key_resize_edge
= OB_DIRECTION_EAST
;
677 if (keycode
== ob_keycode(OB_KEY_LEFT
)) {
678 dir
= OB_DIRECTION_WEST
;
679 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
680 key_resize_edge
!= OB_DIRECTION_EAST
)
682 key_resize_edge
= OB_DIRECTION_WEST
;
686 if (keycode
== ob_keycode(OB_KEY_UP
)) {
687 dir
= OB_DIRECTION_NORTH
;
688 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
689 key_resize_edge
!= OB_DIRECTION_SOUTH
)
691 key_resize_edge
= OB_DIRECTION_NORTH
;
695 if (keycode
== ob_keycode(OB_KEY_DOWN
)) {
696 dir
= OB_DIRECTION_SOUTH
;
697 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
698 key_resize_edge
!= OB_DIRECTION_SOUTH
)
700 key_resize_edge
= OB_DIRECTION_SOUTH
;
705 /* shift means jump to edge */
706 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
709 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
710 dir
= OB_DIRECTION_EAST
;
711 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
712 dir
= OB_DIRECTION_WEST
;
713 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
714 dir
= OB_DIRECTION_SOUTH
;
715 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
716 dir
= OB_DIRECTION_NORTH
;
718 client_find_resize_directional(moveresize_client
, key_resize_edge
,
719 key_resize_edge
== dir
,
721 dw
= w
- moveresize_client
->area
.width
;
722 dh
= h
- moveresize_client
->area
.height
;
726 /* control means fine grained */
727 if (moveresize_client
->size_inc
.width
> 1) {
728 distw
= moveresize_client
->size_inc
.width
;
731 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
739 if (moveresize_client
->size_inc
.height
> 1) {
740 disth
= moveresize_client
->size_inc
.height
;
743 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
752 if (key_resize_edge
== OB_DIRECTION_WEST
) {
753 if (dir
== OB_DIRECTION_WEST
)
756 dw
= -(dist
= distw
);
758 else if (key_resize_edge
== OB_DIRECTION_EAST
) {
759 if (dir
== OB_DIRECTION_EAST
)
762 dw
= -(dist
= distw
);
764 else if (key_resize_edge
== OB_DIRECTION_NORTH
) {
765 if (dir
== OB_DIRECTION_NORTH
)
768 dh
= -(dist
= disth
);
770 else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
771 if (dir
== OB_DIRECTION_SOUTH
)
774 dh
= -(dist
= disth
);
778 calc_resize(TRUE
, resist
, &dw
, &dh
, dir
);
779 if (key_resize_edge
== OB_DIRECTION_WEST
)
781 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
786 /* how to move the pointer to keep up with the change */
787 if (key_resize_edge
== OB_DIRECTION_WEST
)
789 else if (key_resize_edge
== OB_DIRECTION_EAST
)
791 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
793 else if (key_resize_edge
== OB_DIRECTION_SOUTH
)
796 screen_pointer_pos(&opx
, &opy
);
797 XWarpPointer(obt_display
, None
, None
, 0, 0, 0, 0, pdx
, pdy
);
798 /* steal the motion events this causes */
799 XSync(obt_display
, FALSE
);
802 while (XCheckTypedEvent(obt_display
, MotionNotify
, &ce
));
804 screen_pointer_pos(&px
, &py
);
808 /* because the cursor moves even though the window does
809 not nessesarily (resistance), this adjusts where the cursor
810 thinks it started so that it keeps up with where the window
812 start_x
+= (px
- opx
) - dw
;
813 start_y
+= (py
- opy
) - dh
;
817 gboolean
moveresize_event(XEvent
*e
)
819 gboolean used
= FALSE
;
821 if (!moveresize_in_progress
) return FALSE
;
823 if (e
->type
== ButtonPress
) {
825 start_x
= e
->xbutton
.x_root
;
826 start_y
= e
->xbutton
.y_root
;
827 button
= e
->xbutton
.button
; /* this will end it now */
829 used
= e
->xbutton
.button
== button
;
830 } else if (e
->type
== ButtonRelease
) {
831 if (!button
|| e
->xbutton
.button
== button
) {
832 moveresize_end(FALSE
);
835 } else if (e
->type
== MotionNotify
) {
837 cur_x
= start_cx
+ e
->xmotion
.x_root
- start_x
;
838 cur_y
= start_cy
+ e
->xmotion
.y_root
- start_y
;
840 do_edge_warp(e
->xmotion
.x_root
, e
->xmotion
.y_root
);
845 if (corner
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT
)) {
846 dw
= -(e
->xmotion
.x_root
- start_x
);
847 dh
= -(e
->xmotion
.y_root
- start_y
);
848 dir
= OB_DIRECTION_NORTHWEST
;
849 } else if (corner
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP
)) {
851 dh
= -(e
->xmotion
.y_root
- start_y
);
852 dir
= OB_DIRECTION_NORTH
;
854 OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT
)) {
855 dw
= (e
->xmotion
.x_root
- start_x
);
856 dh
= -(e
->xmotion
.y_root
- start_y
);
857 dir
= OB_DIRECTION_NORTHEAST
;
858 } else if (corner
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_RIGHT
)) {
859 dw
= (e
->xmotion
.x_root
- start_x
);
861 dir
= OB_DIRECTION_EAST
;
863 OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
)) {
864 dw
= (e
->xmotion
.x_root
- start_x
);
865 dh
= (e
->xmotion
.y_root
- start_y
);
866 dir
= OB_DIRECTION_SOUTHEAST
;
867 } else if (corner
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOM
))
870 dh
= (e
->xmotion
.y_root
- start_y
);
871 dir
= OB_DIRECTION_SOUTH
;
873 OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
)) {
874 dw
= -(e
->xmotion
.x_root
- start_x
);
875 dh
= (e
->xmotion
.y_root
- start_y
);
876 dir
= OB_DIRECTION_SOUTHWEST
;
877 } else if (corner
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT
)) {
878 dw
= -(e
->xmotion
.x_root
- start_x
);
880 dir
= OB_DIRECTION_WEST
;
882 OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD
)) {
883 dw
= (e
->xmotion
.x_root
- start_x
);
884 dh
= (e
->xmotion
.y_root
- start_y
);
885 dir
= OB_DIRECTION_SOUTHEAST
;
887 g_assert_not_reached();
889 dw
-= cur_w
- start_cw
;
890 dh
-= cur_h
- start_ch
;
892 calc_resize(FALSE
, 0, &dw
, &dh
, dir
);
896 if (corner
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT
) ||
897 corner
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_LEFT
) ||
898 corner
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
))
902 if (corner
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPLEFT
) ||
903 corner
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOP
) ||
904 corner
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_TOPRIGHT
))
912 } else if (e
->type
== KeyPress
) {
913 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_ESCAPE
)) {
914 moveresize_end(TRUE
);
916 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RETURN
)) {
917 moveresize_end(FALSE
);
919 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RIGHT
) ||
920 e
->xkey
.keycode
== ob_keycode(OB_KEY_LEFT
) ||
921 e
->xkey
.keycode
== ob_keycode(OB_KEY_DOWN
) ||
922 e
->xkey
.keycode
== ob_keycode(OB_KEY_UP
))
924 if (corner
== OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD
)) {
925 resize_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
928 OBT_PROP_ATOM(NET_WM_MOVERESIZE_MOVE_KEYBOARD
))
930 move_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
936 else if (e
->type
== obt_display_extension_sync_basep
+ XSyncAlarmNotify
)
938 waiting_for_sync
= FALSE
; /* we got our sync... */
939 do_resize(); /* ...so try resize if there is more change pending */