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_x
;
120 if (config_resize_popup_x_center
) x
= area
->x
+ area
->width
/2;
121 else if (config_resize_popup_x_opposite
) x
= RECT_RIGHT(*area
) - x
;
122 else x
= area
->x
+ x
;
124 y
= config_resize_popup_y
;
125 if (config_resize_popup_y_center
) y
= area
->y
+ area
->height
/2;
126 else if (config_resize_popup_y_opposite
) y
= RECT_BOTTOM(*area
) - y
;
127 else y
= area
->y
+ y
;
129 if (config_resize_popup_x_center
) {
130 if (config_resize_popup_y_center
)
131 gravity
= CenterGravity
;
132 else if (config_resize_popup_y_opposite
)
133 gravity
= SouthGravity
;
135 gravity
= NorthGravity
;
137 else if (config_resize_popup_x_opposite
) {
138 if (config_resize_popup_y_center
)
139 gravity
= EastGravity
;
140 else if (config_resize_popup_y_opposite
)
141 gravity
= SouthEastGravity
;
143 gravity
= NorthEastGravity
;
146 if (config_resize_popup_y_center
)
147 gravity
= WestGravity
;
148 else if (config_resize_popup_y_opposite
)
149 gravity
= SouthWestGravity
;
151 gravity
= NorthWestGravity
;
154 popup_position(popup
, gravity
, x
, y
);
158 popup_show(popup
, text
);
162 void moveresize_start(ObClient
*c
, gint x
, gint y
, guint b
, guint32 cnr
)
165 gboolean mv
= (cnr
== prop_atoms
.net_wm_moveresize_move
||
166 cnr
== prop_atoms
.net_wm_moveresize_move_keyboard
);
170 if (moveresize_in_progress
|| !c
->frame
->visible
||
172 (c
->functions
& OB_CLIENT_FUNC_MOVE
) :
173 (c
->functions
& OB_CLIENT_FUNC_RESIZE
)))
176 if (cnr
== prop_atoms
.net_wm_moveresize_size_topleft
) {
177 cur
= OB_CURSOR_NORTHWEST
;
179 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_top
) {
180 cur
= OB_CURSOR_NORTH
;
182 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_topright
) {
183 cur
= OB_CURSOR_NORTHEAST
;
185 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_right
)
186 cur
= OB_CURSOR_EAST
;
187 else if (cnr
== prop_atoms
.net_wm_moveresize_size_bottomright
)
188 cur
= OB_CURSOR_SOUTHEAST
;
189 else if (cnr
== prop_atoms
.net_wm_moveresize_size_bottom
)
190 cur
= OB_CURSOR_SOUTH
;
191 else if (cnr
== prop_atoms
.net_wm_moveresize_size_bottomleft
) {
192 cur
= OB_CURSOR_SOUTHWEST
;
194 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_left
) {
195 cur
= OB_CURSOR_WEST
;
197 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_keyboard
)
198 cur
= OB_CURSOR_SOUTHEAST
;
199 else if (cnr
== prop_atoms
.net_wm_moveresize_move
)
200 cur
= OB_CURSOR_MOVE
;
201 else if (cnr
== prop_atoms
.net_wm_moveresize_move_keyboard
)
202 cur
= OB_CURSOR_MOVE
;
204 g_assert_not_reached();
206 /* keep the pointer bounded to the screen for move/resize */
207 if (!grab_pointer(FALSE
, TRUE
, cur
))
209 if (!grab_keyboard()) {
214 frame_end_iconify_animation(c
->frame
);
217 moveresize_client
= c
;
218 start_cx
= c
->area
.x
;
219 start_cy
= c
->area
.y
;
220 start_cw
= c
->area
.width
;
221 start_ch
= c
->area
.height
;
222 /* these adjustments for the size_inc make resizing a terminal more
223 friendly. you essentially start the resize in the middle of the
224 increment instead of at 0, so you have to move half an increment
225 either way instead of a full increment one and 1 px the other. */
226 start_x
= x
- (mv
? 0 : left
* c
->size_inc
.width
/ 2);
227 start_y
= y
- (mv
? 0 : up
* c
->size_inc
.height
/ 2);
230 key_resize_edge
= -1;
233 have to change start_cx and start_cy if going to do this..
234 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
235 corner == prop_atoms.net_wm_moveresize_size_keyboard)
236 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
237 c->area.width / 2, c->area.height / 2);
245 moveresize_in_progress
= TRUE
;
248 if (config_resize_redraw
&& !moving
&& extensions_sync
&&
249 moveresize_client
->sync_request
&& moveresize_client
->sync_counter
)
251 /* Initialize values for the resize syncing, and create an alarm for
252 the client's xsync counter */
255 XSyncAlarmAttributes aa
;
257 /* set the counter to an initial value */
258 XSyncIntToValue(&val
, 0);
259 XSyncSetCounter(ob_display
, moveresize_client
->sync_counter
, val
);
261 /* this will be incremented when we tell the client what we're
263 moveresize_client
->sync_counter_value
= 0;
265 /* the next sequence we're waiting for with the alarm */
266 XSyncIntToValue(&val
, 1);
268 /* set an alarm on the counter */
269 aa
.trigger
.counter
= moveresize_client
->sync_counter
;
270 aa
.trigger
.wait_value
= val
;
271 aa
.trigger
.value_type
= XSyncAbsolute
;
272 aa
.trigger
.test_type
= XSyncPositiveTransition
;
274 XSyncIntToValue(&aa
.delta
, 1);
275 moveresize_alarm
= XSyncCreateAlarm(ob_display
,
284 waiting_for_sync
= FALSE
;
289 void moveresize_end(gboolean cancel
)
297 client_move(moveresize_client
,
298 (cancel
? start_cx
: cur_x
),
299 (cancel
? start_cy
: cur_y
));
302 /* turn off the alarm */
303 if (moveresize_alarm
!= None
) {
304 XSyncDestroyAlarm(ob_display
, moveresize_alarm
);
305 moveresize_alarm
= None
;
308 ob_main_loop_timeout_remove(ob_main_loop
, sync_timeout_func
);
311 client_configure(moveresize_client
,
312 (cancel
? start_cx
: cur_x
),
313 (cancel
? start_cy
: cur_y
),
314 (cancel
? start_cw
: cur_w
),
315 (cancel
? start_ch
: cur_h
),
319 /* dont edge warp after its ended */
322 moveresize_in_progress
= FALSE
;
323 moveresize_client
= NULL
;
326 static void do_move(gboolean keyboard
, gint keydist
)
330 if (keyboard
) resist
= keydist
- 1; /* resist for one key press */
331 else resist
= config_resist_win
;
332 resist_move_windows(moveresize_client
, resist
, &cur_x
, &cur_y
);
333 if (!keyboard
) resist
= config_resist_edge
;
334 resist_move_monitors(moveresize_client
, resist
, &cur_x
, &cur_y
);
336 client_configure(moveresize_client
, cur_x
, cur_y
, cur_w
, cur_h
,
338 if (config_resize_popup_show
== 2) /* == "Always" */
339 popup_coords(moveresize_client
, "%d x %d",
340 moveresize_client
->frame
->area
.x
,
341 moveresize_client
->frame
->area
.y
);
345 static void do_resize(void)
347 gint x
, y
, w
, h
, lw
, lh
;
349 /* see if it is actually going to resize */
354 client_try_configure(moveresize_client
, &x
, &y
, &w
, &h
,
356 if (w
== moveresize_client
->area
.width
&&
357 h
== moveresize_client
->area
.height
)
363 if (config_resize_redraw
&& extensions_sync
&&
364 moveresize_client
->sync_request
&& moveresize_client
->sync_counter
)
369 /* are we already waiting for the sync counter to catch up? */
370 if (waiting_for_sync
)
373 /* increment the value we're waiting for */
374 ++moveresize_client
->sync_counter_value
;
375 XSyncIntToValue(&val
, moveresize_client
->sync_counter_value
);
377 /* tell the client what we're waiting for */
378 ce
.xclient
.type
= ClientMessage
;
379 ce
.xclient
.message_type
= prop_atoms
.wm_protocols
;
380 ce
.xclient
.display
= ob_display
;
381 ce
.xclient
.window
= moveresize_client
->window
;
382 ce
.xclient
.format
= 32;
383 ce
.xclient
.data
.l
[0] = prop_atoms
.net_wm_sync_request
;
384 ce
.xclient
.data
.l
[1] = event_curtime
;
385 ce
.xclient
.data
.l
[2] = XSyncValueLow32(val
);
386 ce
.xclient
.data
.l
[3] = XSyncValueHigh32(val
);
387 ce
.xclient
.data
.l
[4] = 0l;
388 XSendEvent(ob_display
, moveresize_client
->window
, FALSE
,
391 waiting_for_sync
= TRUE
;
393 ob_main_loop_timeout_remove(ob_main_loop
, sync_timeout_func
);
394 ob_main_loop_timeout_add(ob_main_loop
, G_USEC_PER_SEC
* 2,
400 client_configure(moveresize_client
, cur_x
, cur_y
, cur_w
, cur_h
,
403 /* this would be better with a fixed width font ... XXX can do it better
404 if there are 2 text boxes */
405 if (config_resize_popup_show
== 2 || /* == "Always" */
406 (config_resize_popup_show
== 1 && /* == "Nonpixel" */
407 moveresize_client
->size_inc
.width
> 1 &&
408 moveresize_client
->size_inc
.height
> 1))
409 popup_coords(moveresize_client
, "%d x %d",
410 moveresize_client
->logical_size
.width
,
411 moveresize_client
->logical_size
.height
);
415 static gboolean
sync_timeout_func(gpointer data
)
417 waiting_for_sync
= FALSE
; /* we timed out waiting for our sync... */
418 do_resize(); /* ...so let any pending resizes through */
420 return FALSE
; /* don't repeat */
424 static void calc_resize(gboolean keyboard
, gint keydist
, gint
*dw
, gint
*dh
,
427 gint resist
, x
= 0, y
= 0, lw
, lh
, ow
, oh
, nw
, nh
;
436 (moveresize_client
->max_ratio
|| moveresize_client
->min_ratio
))
439 case OB_DIRECTION_NORTH
:
440 case OB_DIRECTION_SOUTH
:
441 /* resize the width based on the height */
442 if (moveresize_client
->min_ratio
) {
443 if (nh
* moveresize_client
->min_ratio
> nw
)
444 nw
= (gint
)(nh
* moveresize_client
->min_ratio
);
446 if (moveresize_client
->max_ratio
) {
447 if (nh
* moveresize_client
->max_ratio
< nw
)
448 nw
= (gint
)(nh
* moveresize_client
->max_ratio
);
452 /* resize the height based on the width */
453 if (moveresize_client
->min_ratio
) {
454 if (nh
* moveresize_client
->min_ratio
> nw
)
455 nh
= (gint
)(nw
/ moveresize_client
->min_ratio
);
457 if (moveresize_client
->max_ratio
) {
458 if (nh
* moveresize_client
->max_ratio
< nw
)
459 nh
= (gint
)(nw
/ moveresize_client
->max_ratio
);
464 /* see its actual size (apply aspect ratios) */
465 client_try_configure(moveresize_client
, &x
, &y
, &nw
, &nh
, &lw
, &lh
,
471 /* resist_size_* needs the frame size */
472 nw
+= moveresize_client
->frame
->size
.left
+
473 moveresize_client
->frame
->size
.right
;
474 nh
+= moveresize_client
->frame
->size
.top
+
475 moveresize_client
->frame
->size
.bottom
;
477 if (keyboard
) resist
= keydist
- 1; /* resist for one key press */
478 else resist
= config_resist_win
;
479 resist_size_windows(moveresize_client
, resist
, &nw
, &nh
, dir
);
480 if (!keyboard
) resist
= config_resist_edge
;
481 resist_size_monitors(moveresize_client
, resist
, &nw
, &nh
, dir
);
483 nw
-= moveresize_client
->frame
->size
.left
+
484 moveresize_client
->frame
->size
.right
;
485 nh
-= moveresize_client
->frame
->size
.top
+
486 moveresize_client
->frame
->size
.bottom
;
491 /* take aspect ratios into account for resistance */
493 (moveresize_client
->max_ratio
|| moveresize_client
->min_ratio
))
495 if (*dh
!= trydh
) { /* got resisted */
496 /* resize the width based on the height */
497 if (moveresize_client
->min_ratio
) {
498 if (nh
* moveresize_client
->min_ratio
> nw
)
499 nw
= (gint
)(nh
* moveresize_client
->min_ratio
);
501 if (moveresize_client
->max_ratio
) {
502 if (nh
* moveresize_client
->max_ratio
< nw
)
503 nw
= (gint
)(nh
* moveresize_client
->max_ratio
);
506 if (*dw
!= trydw
) { /* got resisted */
507 /* resize the height based on the width */
508 if (moveresize_client
->min_ratio
) {
509 if (nh
* moveresize_client
->min_ratio
> nw
)
510 nh
= (gint
)(nw
/ moveresize_client
->min_ratio
);
512 if (moveresize_client
->max_ratio
) {
513 if (nh
* moveresize_client
->max_ratio
< nw
)
514 nh
= (gint
)(nw
/ moveresize_client
->max_ratio
);
519 /* make sure it's all valid */
520 client_try_configure(moveresize_client
, &x
, &y
, &nw
, &nh
, &lw
, &lh
, TRUE
);
526 static gboolean
edge_warp_delay_func(gpointer data
)
530 /* only fire every second time. so it's fast the first time, but slower
533 d
= screen_find_desktop(screen_desktop
, edge_warp_dir
, TRUE
, FALSE
);
534 if (d
!= screen_desktop
) screen_set_desktop(d
, TRUE
);
536 edge_warp_odd
= !edge_warp_odd
;
538 return TRUE
; /* do repeat ! */
541 static void do_edge_warp(gint x
, gint y
)
546 if (!config_mouse_screenedgetime
) return;
550 for (i
= 0; i
< screen_num_monitors
; ++i
) {
551 Rect
*a
= screen_physical_area_monitor(i
);
552 if (x
== RECT_LEFT(*a
)) dir
= OB_DIRECTION_WEST
;
553 if (x
== RECT_RIGHT(*a
)) dir
= OB_DIRECTION_EAST
;
554 if (y
== RECT_TOP(*a
)) dir
= OB_DIRECTION_NORTH
;
555 if (y
== RECT_BOTTOM(*a
)) dir
= OB_DIRECTION_SOUTH
;
557 /* try check for xinerama boundaries */
558 if ((x
+ 1 == RECT_LEFT(*a
) || x
- 1 == RECT_RIGHT(*a
)) &&
559 (dir
== OB_DIRECTION_WEST
|| dir
== OB_DIRECTION_EAST
))
563 if ((y
+ 1 == RECT_TOP(*a
) || y
- 1 == RECT_BOTTOM(*a
)) &&
564 (dir
== OB_DIRECTION_NORTH
|| dir
== OB_DIRECTION_SOUTH
))
571 if (dir
!= edge_warp_dir
) {
573 if (dir
!= (ObDirection
)-1) {
574 edge_warp_odd
= TRUE
; /* switch on the first timeout */
575 ob_main_loop_timeout_add(ob_main_loop
,
576 config_mouse_screenedgetime
* 1000,
577 edge_warp_delay_func
,
584 static void cancel_edge_warp(void)
586 ob_main_loop_timeout_remove(ob_main_loop
, edge_warp_delay_func
);
589 static void move_with_keys(gint keycode
, gint state
)
591 gint dx
= 0, dy
= 0, ox
= cur_x
, oy
= cur_y
;
592 gint opx
, px
, opy
, py
;
595 /* shift means jump to edge */
596 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
600 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
601 dir
= OB_DIRECTION_EAST
;
602 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
603 dir
= OB_DIRECTION_WEST
;
604 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
605 dir
= OB_DIRECTION_SOUTH
;
606 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
607 dir
= OB_DIRECTION_NORTH
;
609 client_find_move_directional(moveresize_client
, dir
, &x
, &y
);
610 dx
= x
- moveresize_client
->area
.x
;
611 dy
= y
- moveresize_client
->area
.y
;
613 /* control means fine grained */
614 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
))
619 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
621 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
623 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
625 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
629 screen_pointer_pos(&opx
, &opy
);
630 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, dx
, dy
);
631 /* steal the motion events this causes */
632 XSync(ob_display
, FALSE
);
635 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
637 screen_pointer_pos(&px
, &py
);
643 /* because the cursor moves even though the window does
644 not nessesarily (resistance), this adjusts where the curor
645 thinks it started so that it keeps up with where the window
647 start_x
+= (px
- opx
) - (cur_x
- ox
);
648 start_y
+= (py
- opy
) - (cur_y
- oy
);
651 static void resize_with_keys(gint keycode
, gint state
)
653 gint dw
= 0, dh
= 0, pdx
= 0, pdy
= 0, opx
, opy
, px
, py
;
654 gint dist
= 0, resist
= 0;
657 /* pick the edge if it needs to move */
658 if (keycode
== ob_keycode(OB_KEY_RIGHT
)) {
659 dir
= OB_DIRECTION_EAST
;
660 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
661 key_resize_edge
!= OB_DIRECTION_EAST
)
663 key_resize_edge
= OB_DIRECTION_EAST
;
667 if (keycode
== ob_keycode(OB_KEY_LEFT
)) {
668 dir
= OB_DIRECTION_WEST
;
669 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
670 key_resize_edge
!= OB_DIRECTION_EAST
)
672 key_resize_edge
= OB_DIRECTION_WEST
;
676 if (keycode
== ob_keycode(OB_KEY_UP
)) {
677 dir
= OB_DIRECTION_NORTH
;
678 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
679 key_resize_edge
!= OB_DIRECTION_SOUTH
)
681 key_resize_edge
= OB_DIRECTION_NORTH
;
685 if (keycode
== ob_keycode(OB_KEY_DOWN
)) {
686 dir
= OB_DIRECTION_SOUTH
;
687 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
688 key_resize_edge
!= OB_DIRECTION_SOUTH
)
690 key_resize_edge
= OB_DIRECTION_SOUTH
;
695 /* shift means jump to edge */
696 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
699 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
700 dir
= OB_DIRECTION_EAST
;
701 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
702 dir
= OB_DIRECTION_WEST
;
703 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
704 dir
= OB_DIRECTION_SOUTH
;
705 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
706 dir
= OB_DIRECTION_NORTH
;
708 client_find_resize_directional(moveresize_client
, key_resize_edge
,
709 key_resize_edge
== dir
,
711 dw
= w
- moveresize_client
->area
.width
;
712 dh
= h
- moveresize_client
->area
.height
;
716 /* control means fine grained */
717 if (moveresize_client
->size_inc
.width
> 1) {
718 distw
= moveresize_client
->size_inc
.width
;
721 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
729 if (moveresize_client
->size_inc
.height
> 1) {
730 disth
= moveresize_client
->size_inc
.height
;
733 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
742 if (key_resize_edge
== OB_DIRECTION_WEST
) {
743 if (dir
== OB_DIRECTION_WEST
)
746 dw
= -(dist
= distw
);
748 else if (key_resize_edge
== OB_DIRECTION_EAST
) {
749 if (dir
== OB_DIRECTION_EAST
)
752 dw
= -(dist
= distw
);
754 else if (key_resize_edge
== OB_DIRECTION_NORTH
) {
755 if (dir
== OB_DIRECTION_NORTH
)
758 dh
= -(dist
= disth
);
760 else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
761 if (dir
== OB_DIRECTION_SOUTH
)
764 dh
= -(dist
= disth
);
768 calc_resize(TRUE
, resist
, &dw
, &dh
, dir
);
769 if (key_resize_edge
== OB_DIRECTION_WEST
)
771 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
776 /* how to move the pointer to keep up with the change */
777 if (key_resize_edge
== OB_DIRECTION_WEST
)
779 else if (key_resize_edge
== OB_DIRECTION_EAST
)
781 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
783 else if (key_resize_edge
== OB_DIRECTION_SOUTH
)
786 screen_pointer_pos(&opx
, &opy
);
787 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, pdx
, pdy
);
788 /* steal the motion events this causes */
789 XSync(ob_display
, FALSE
);
792 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
794 screen_pointer_pos(&px
, &py
);
798 /* because the cursor moves even though the window does
799 not nessesarily (resistance), this adjusts where the cursor
800 thinks it started so that it keeps up with where the window
802 start_x
+= (px
- opx
) - dw
;
803 start_y
+= (py
- opy
) - dh
;
807 gboolean
moveresize_event(XEvent
*e
)
809 gboolean used
= FALSE
;
811 if (!moveresize_in_progress
) return FALSE
;
813 if (e
->type
== ButtonPress
) {
815 start_x
= e
->xbutton
.x_root
;
816 start_y
= e
->xbutton
.y_root
;
817 button
= e
->xbutton
.button
; /* this will end it now */
819 used
= e
->xbutton
.button
== button
;
820 } else if (e
->type
== ButtonRelease
) {
821 if (!button
|| e
->xbutton
.button
== button
) {
822 moveresize_end(FALSE
);
825 } else if (e
->type
== MotionNotify
) {
827 cur_x
= start_cx
+ e
->xmotion
.x_root
- start_x
;
828 cur_y
= start_cy
+ e
->xmotion
.y_root
- start_y
;
830 do_edge_warp(e
->xmotion
.x_root
, e
->xmotion
.y_root
);
835 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
) {
836 dw
= -(e
->xmotion
.x_root
- start_x
);
837 dh
= -(e
->xmotion
.y_root
- start_y
);
838 dir
= OB_DIRECTION_NORTHWEST
;
839 } else if (corner
== prop_atoms
.net_wm_moveresize_size_top
) {
841 dh
= -(e
->xmotion
.y_root
- start_y
);
842 dir
= OB_DIRECTION_NORTH
;
843 } else if (corner
== prop_atoms
.net_wm_moveresize_size_topright
) {
844 dw
= (e
->xmotion
.x_root
- start_x
);
845 dh
= -(e
->xmotion
.y_root
- start_y
);
846 dir
= OB_DIRECTION_NORTHEAST
;
847 } else if (corner
== prop_atoms
.net_wm_moveresize_size_right
) {
848 dw
= (e
->xmotion
.x_root
- start_x
);
850 dir
= OB_DIRECTION_EAST
;
852 prop_atoms
.net_wm_moveresize_size_bottomright
) {
853 dw
= (e
->xmotion
.x_root
- start_x
);
854 dh
= (e
->xmotion
.y_root
- start_y
);
855 dir
= OB_DIRECTION_SOUTHEAST
;
856 } else if (corner
== prop_atoms
.net_wm_moveresize_size_bottom
) {
858 dh
= (e
->xmotion
.y_root
- start_y
);
859 dir
= OB_DIRECTION_SOUTH
;
861 prop_atoms
.net_wm_moveresize_size_bottomleft
) {
862 dw
= -(e
->xmotion
.x_root
- start_x
);
863 dh
= (e
->xmotion
.y_root
- start_y
);
864 dir
= OB_DIRECTION_SOUTHWEST
;
865 } else if (corner
== prop_atoms
.net_wm_moveresize_size_left
) {
866 dw
= -(e
->xmotion
.x_root
- start_x
);
868 dir
= OB_DIRECTION_WEST
;
869 } else if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
870 dw
= (e
->xmotion
.x_root
- start_x
);
871 dh
= (e
->xmotion
.y_root
- start_y
);
872 dir
= OB_DIRECTION_SOUTHEAST
;
874 g_assert_not_reached();
876 dw
-= cur_w
- start_cw
;
877 dh
-= cur_h
- start_ch
;
879 calc_resize(FALSE
, 0, &dw
, &dh
, dir
);
883 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
||
884 corner
== prop_atoms
.net_wm_moveresize_size_left
||
885 corner
== prop_atoms
.net_wm_moveresize_size_bottomleft
)
889 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
||
890 corner
== prop_atoms
.net_wm_moveresize_size_top
||
891 corner
== prop_atoms
.net_wm_moveresize_size_topright
)
899 } else if (e
->type
== KeyPress
) {
900 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_ESCAPE
)) {
901 moveresize_end(TRUE
);
903 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RETURN
)) {
904 moveresize_end(FALSE
);
906 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RIGHT
) ||
907 e
->xkey
.keycode
== ob_keycode(OB_KEY_LEFT
) ||
908 e
->xkey
.keycode
== ob_keycode(OB_KEY_DOWN
) ||
909 e
->xkey
.keycode
== ob_keycode(OB_KEY_UP
))
911 if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
912 resize_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
914 } else if (corner
== prop_atoms
.net_wm_moveresize_move_keyboard
) {
915 move_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
921 else if (e
->type
== extensions_sync_event_basep
+ XSyncAlarmNotify
)
923 waiting_for_sync
= FALSE
; /* we got our sync... */
924 do_resize(); /* ...so try resize if there is more change pending */