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
)
80 popup
= popup_new(FALSE
);
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
== 1) /* == "Top" */
105 popup_position(popup
, SouthGravity
,
107 + c
->frame
->area
.width
/2,
108 c
->frame
->area
.y
- ob_rr_theme
->fbwidth
);
109 else /* == "Center" */
110 popup_position(popup
, CenterGravity
,
111 c
->frame
->area
.x
+ c
->frame
->size
.left
+
113 c
->frame
->area
.y
+ c
->frame
->size
.top
+
115 popup_show(popup
, text
);
119 void moveresize_start(ObClient
*c
, gint x
, gint y
, guint b
, guint32 cnr
)
122 gboolean mv
= (cnr
== prop_atoms
.net_wm_moveresize_move
||
123 cnr
== prop_atoms
.net_wm_moveresize_move_keyboard
);
127 if (moveresize_in_progress
|| !c
->frame
->visible
||
129 (c
->functions
& OB_CLIENT_FUNC_MOVE
) :
130 (c
->functions
& OB_CLIENT_FUNC_RESIZE
)))
133 if (cnr
== prop_atoms
.net_wm_moveresize_size_topleft
) {
134 cur
= OB_CURSOR_NORTHWEST
;
136 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_top
) {
137 cur
= OB_CURSOR_NORTH
;
139 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_topright
) {
140 cur
= OB_CURSOR_NORTHEAST
;
142 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_right
)
143 cur
= OB_CURSOR_EAST
;
144 else if (cnr
== prop_atoms
.net_wm_moveresize_size_bottomright
)
145 cur
= OB_CURSOR_SOUTHEAST
;
146 else if (cnr
== prop_atoms
.net_wm_moveresize_size_bottom
)
147 cur
= OB_CURSOR_SOUTH
;
148 else if (cnr
== prop_atoms
.net_wm_moveresize_size_bottomleft
) {
149 cur
= OB_CURSOR_SOUTHWEST
;
151 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_left
) {
152 cur
= OB_CURSOR_WEST
;
154 } else if (cnr
== prop_atoms
.net_wm_moveresize_size_keyboard
)
155 cur
= OB_CURSOR_SOUTHEAST
;
156 else if (cnr
== prop_atoms
.net_wm_moveresize_move
)
157 cur
= OB_CURSOR_MOVE
;
158 else if (cnr
== prop_atoms
.net_wm_moveresize_move_keyboard
)
159 cur
= OB_CURSOR_MOVE
;
161 g_assert_not_reached();
163 /* keep the pointer bounded to the screen for move/resize */
164 if (!grab_pointer(FALSE
, TRUE
, cur
))
166 if (!grab_keyboard()) {
171 frame_end_iconify_animation(c
->frame
);
174 moveresize_client
= c
;
175 start_cx
= c
->area
.x
;
176 start_cy
= c
->area
.y
;
177 start_cw
= c
->area
.width
;
178 start_ch
= c
->area
.height
;
179 /* these adjustments for the size_inc make resizing a terminal more
180 friendly. you essentially start the resize in the middle of the
181 increment instead of at 0, so you have to move half an increment
182 either way instead of a full increment one and 1 px the other. */
183 start_x
= x
- (mv
? 0 : left
* c
->size_inc
.width
/ 2);
184 start_y
= y
- (mv
? 0 : up
* c
->size_inc
.height
/ 2);
187 key_resize_edge
= -1;
190 have to change start_cx and start_cy if going to do this..
191 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
192 corner == prop_atoms.net_wm_moveresize_size_keyboard)
193 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
194 c->area.width / 2, c->area.height / 2);
202 moveresize_in_progress
= TRUE
;
205 if (config_resize_redraw
&& !moving
&& extensions_sync
&&
206 moveresize_client
->sync_request
&& moveresize_client
->sync_counter
)
208 /* Initialize values for the resize syncing, and create an alarm for
209 the client's xsync counter */
212 XSyncAlarmAttributes aa
;
214 /* set the counter to an initial value */
215 XSyncIntToValue(&val
, 0);
216 XSyncSetCounter(ob_display
, moveresize_client
->sync_counter
, val
);
218 /* this will be incremented when we tell the client what we're
220 moveresize_client
->sync_counter_value
= 0;
222 /* the next sequence we're waiting for with the alarm */
223 XSyncIntToValue(&val
, 1);
225 /* set an alarm on the counter */
226 aa
.trigger
.counter
= moveresize_client
->sync_counter
;
227 aa
.trigger
.wait_value
= val
;
228 aa
.trigger
.value_type
= XSyncAbsolute
;
229 aa
.trigger
.test_type
= XSyncPositiveTransition
;
231 XSyncIntToValue(&aa
.delta
, 1);
232 moveresize_alarm
= XSyncCreateAlarm(ob_display
,
241 waiting_for_sync
= FALSE
;
246 void moveresize_end(gboolean cancel
)
254 client_move(moveresize_client
,
255 (cancel
? start_cx
: cur_x
),
256 (cancel
? start_cy
: cur_y
));
259 /* turn off the alarm */
260 if (moveresize_alarm
!= None
) {
261 XSyncDestroyAlarm(ob_display
, moveresize_alarm
);
262 moveresize_alarm
= None
;
265 ob_main_loop_timeout_remove(ob_main_loop
, sync_timeout_func
);
268 client_configure(moveresize_client
,
269 (cancel
? start_cx
: cur_x
),
270 (cancel
? start_cy
: cur_y
),
271 (cancel
? start_cw
: cur_w
),
272 (cancel
? start_ch
: cur_h
),
276 /* dont edge warp after its ended */
279 moveresize_in_progress
= FALSE
;
280 moveresize_client
= NULL
;
283 static void do_move(gboolean keyboard
, gint keydist
)
287 if (keyboard
) resist
= keydist
- 1; /* resist for one key press */
288 else resist
= config_resist_win
;
289 resist_move_windows(moveresize_client
, resist
, &cur_x
, &cur_y
);
290 if (!keyboard
) resist
= config_resist_edge
;
291 resist_move_monitors(moveresize_client
, resist
, &cur_x
, &cur_y
);
293 client_configure(moveresize_client
, cur_x
, cur_y
, cur_w
, cur_h
,
295 if (config_resize_popup_show
== 2) /* == "Always" */
296 popup_coords(moveresize_client
, "%d x %d",
297 moveresize_client
->frame
->area
.x
,
298 moveresize_client
->frame
->area
.y
);
302 static void do_resize()
304 gint x
, y
, w
, h
, lw
, lh
;
306 /* see if it is actually going to resize */
311 client_try_configure(moveresize_client
, &x
, &y
, &w
, &h
,
313 if (w
== moveresize_client
->area
.width
&&
314 h
== moveresize_client
->area
.height
)
320 if (config_resize_redraw
&& extensions_sync
&&
321 moveresize_client
->sync_request
&& moveresize_client
->sync_counter
)
326 /* are we already waiting for the sync counter to catch up? */
327 if (waiting_for_sync
)
330 /* increment the value we're waiting for */
331 ++moveresize_client
->sync_counter_value
;
332 XSyncIntToValue(&val
, moveresize_client
->sync_counter_value
);
334 /* tell the client what we're waiting for */
335 ce
.xclient
.type
= ClientMessage
;
336 ce
.xclient
.message_type
= prop_atoms
.wm_protocols
;
337 ce
.xclient
.display
= ob_display
;
338 ce
.xclient
.window
= moveresize_client
->window
;
339 ce
.xclient
.format
= 32;
340 ce
.xclient
.data
.l
[0] = prop_atoms
.net_wm_sync_request
;
341 ce
.xclient
.data
.l
[1] = event_curtime
;
342 ce
.xclient
.data
.l
[2] = XSyncValueLow32(val
);
343 ce
.xclient
.data
.l
[3] = XSyncValueHigh32(val
);
344 ce
.xclient
.data
.l
[4] = 0l;
345 XSendEvent(ob_display
, moveresize_client
->window
, FALSE
,
348 waiting_for_sync
= TRUE
;
350 ob_main_loop_timeout_remove(ob_main_loop
, sync_timeout_func
);
351 ob_main_loop_timeout_add(ob_main_loop
, G_USEC_PER_SEC
* 2,
357 client_configure(moveresize_client
, cur_x
, cur_y
, cur_w
, cur_h
,
360 /* this would be better with a fixed width font ... XXX can do it better
361 if there are 2 text boxes */
362 if (config_resize_popup_show
== 2 || /* == "Always" */
363 (config_resize_popup_show
== 1 && /* == "Nonpixel" */
364 moveresize_client
->size_inc
.width
> 1 &&
365 moveresize_client
->size_inc
.height
> 1))
366 popup_coords(moveresize_client
, "%d x %d",
367 moveresize_client
->logical_size
.width
,
368 moveresize_client
->logical_size
.height
);
372 static gboolean
sync_timeout_func(gpointer data
)
374 waiting_for_sync
= FALSE
; /* we timed out waiting for our sync... */
375 do_resize(); /* ...so let any pending resizes through */
377 return FALSE
; /* don't repeat */
381 static void calc_resize(gboolean keyboard
, gint keydist
, gint
*dw
, gint
*dh
,
384 gint resist
, x
= 0, y
= 0, lw
, lh
, ow
, oh
, nw
, nh
;
393 (moveresize_client
->max_ratio
|| moveresize_client
->min_ratio
))
396 case OB_DIRECTION_NORTH
:
397 case OB_DIRECTION_SOUTH
:
398 /* resize the width based on the height */
399 if (moveresize_client
->min_ratio
) {
400 if (nh
* moveresize_client
->min_ratio
> nw
)
401 nw
= (gint
)(nh
* moveresize_client
->min_ratio
);
403 if (moveresize_client
->max_ratio
) {
404 if (nh
* moveresize_client
->max_ratio
< nw
)
405 nw
= (gint
)(nh
* moveresize_client
->max_ratio
);
409 /* resize the height based on the width */
410 if (moveresize_client
->min_ratio
) {
411 if (nh
* moveresize_client
->min_ratio
> nw
)
412 nh
= (gint
)(nw
/ moveresize_client
->min_ratio
);
414 if (moveresize_client
->max_ratio
) {
415 if (nh
* moveresize_client
->max_ratio
< nw
)
416 nh
= (gint
)(nw
/ moveresize_client
->max_ratio
);
421 /* see its actual size (apply aspect ratios) */
422 client_try_configure(moveresize_client
, &x
, &y
, &nw
, &nh
, &lw
, &lh
,
428 /* resist_size_* needs the frame size */
429 nw
+= moveresize_client
->frame
->size
.left
+
430 moveresize_client
->frame
->size
.right
;
431 nh
+= moveresize_client
->frame
->size
.top
+
432 moveresize_client
->frame
->size
.bottom
;
434 if (keyboard
) resist
= keydist
- 1; /* resist for one key press */
435 else resist
= config_resist_win
;
436 resist_size_windows(moveresize_client
, resist
, &nw
, &nh
, dir
);
437 if (!keyboard
) resist
= config_resist_edge
;
438 resist_size_monitors(moveresize_client
, resist
, &nw
, &nh
, dir
);
440 nw
-= moveresize_client
->frame
->size
.left
+
441 moveresize_client
->frame
->size
.right
;
442 nh
-= moveresize_client
->frame
->size
.top
+
443 moveresize_client
->frame
->size
.bottom
;
448 /* take aspect ratios into account for resistance */
450 (moveresize_client
->max_ratio
|| moveresize_client
->min_ratio
))
452 if (*dh
!= trydh
) { /* got resisted */
453 /* resize the width based on the height */
454 if (moveresize_client
->min_ratio
) {
455 if (nh
* moveresize_client
->min_ratio
> nw
)
456 nw
= (gint
)(nh
* moveresize_client
->min_ratio
);
458 if (moveresize_client
->max_ratio
) {
459 if (nh
* moveresize_client
->max_ratio
< nw
)
460 nw
= (gint
)(nh
* moveresize_client
->max_ratio
);
463 if (*dw
!= trydw
) { /* got resisted */
464 /* resize the height based on the width */
465 if (moveresize_client
->min_ratio
) {
466 if (nh
* moveresize_client
->min_ratio
> nw
)
467 nh
= (gint
)(nw
/ moveresize_client
->min_ratio
);
469 if (moveresize_client
->max_ratio
) {
470 if (nh
* moveresize_client
->max_ratio
< nw
)
471 nh
= (gint
)(nw
/ moveresize_client
->max_ratio
);
476 /* make sure it's all valid */
477 client_try_configure(moveresize_client
, &x
, &y
, &nw
, &nh
, &lw
, &lh
, TRUE
);
483 static gboolean
edge_warp_delay_func(gpointer data
)
487 /* only fire every second time. so it's fast the first time, but slower
490 d
= screen_find_desktop(screen_desktop
, edge_warp_dir
, TRUE
, FALSE
);
491 if (d
!= screen_desktop
) screen_set_desktop(d
, TRUE
);
493 edge_warp_odd
= !edge_warp_odd
;
495 return TRUE
; /* do repeat ! */
498 static void do_edge_warp(gint x
, gint y
)
503 if (!config_mouse_screenedgetime
) return;
507 for (i
= 0; i
< screen_num_monitors
; ++i
) {
508 Rect
*a
= screen_physical_area_monitor(i
);
509 if (x
== RECT_LEFT(*a
)) dir
= OB_DIRECTION_WEST
;
510 if (x
== RECT_RIGHT(*a
)) dir
= OB_DIRECTION_EAST
;
511 if (y
== RECT_TOP(*a
)) dir
= OB_DIRECTION_NORTH
;
512 if (y
== RECT_BOTTOM(*a
)) dir
= OB_DIRECTION_SOUTH
;
514 /* try check for xinerama boundaries */
515 if ((x
+ 1 == RECT_LEFT(*a
) || x
- 1 == RECT_RIGHT(*a
)) &&
516 (dir
== OB_DIRECTION_WEST
|| dir
== OB_DIRECTION_EAST
))
520 if ((y
+ 1 == RECT_TOP(*a
) || y
- 1 == RECT_BOTTOM(*a
)) &&
521 (dir
== OB_DIRECTION_NORTH
|| dir
== OB_DIRECTION_SOUTH
))
528 if (dir
!= edge_warp_dir
) {
530 if (dir
!= (ObDirection
)-1) {
531 edge_warp_odd
= TRUE
; /* switch on the first timeout */
532 ob_main_loop_timeout_add(ob_main_loop
,
533 config_mouse_screenedgetime
* 1000,
534 edge_warp_delay_func
,
541 static void cancel_edge_warp()
543 ob_main_loop_timeout_remove(ob_main_loop
, edge_warp_delay_func
);
546 static void move_with_keys(gint keycode
, gint state
)
548 gint dx
= 0, dy
= 0, ox
= cur_x
, oy
= cur_y
;
549 gint opx
, px
, opy
, py
;
552 /* shift means jump to edge */
553 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
557 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
558 dir
= OB_DIRECTION_EAST
;
559 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
560 dir
= OB_DIRECTION_WEST
;
561 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
562 dir
= OB_DIRECTION_SOUTH
;
563 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
564 dir
= OB_DIRECTION_NORTH
;
566 client_find_move_directional(moveresize_client
, dir
, &x
, &y
);
567 dx
= x
- moveresize_client
->area
.x
;
568 dy
= y
- moveresize_client
->area
.y
;
570 /* control means fine grained */
571 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
))
576 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
578 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
580 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
582 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
586 screen_pointer_pos(&opx
, &opy
);
587 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, dx
, dy
);
588 /* steal the motion events this causes */
589 XSync(ob_display
, FALSE
);
592 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
594 screen_pointer_pos(&px
, &py
);
600 /* because the cursor moves even though the window does
601 not nessesarily (resistance), this adjusts where the curor
602 thinks it started so that it keeps up with where the window
604 start_x
+= (px
- opx
) - (cur_x
- ox
);
605 start_y
+= (py
- opy
) - (cur_y
- oy
);
608 static void resize_with_keys(gint keycode
, gint state
)
610 gint dw
= 0, dh
= 0, pdx
= 0, pdy
= 0, opx
, opy
, px
, py
;
611 gint dist
= 0, resist
= 0;
614 /* pick the edge if it needs to move */
615 if (keycode
== ob_keycode(OB_KEY_RIGHT
)) {
616 dir
= OB_DIRECTION_EAST
;
617 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
618 key_resize_edge
!= OB_DIRECTION_EAST
)
620 key_resize_edge
= OB_DIRECTION_EAST
;
624 if (keycode
== ob_keycode(OB_KEY_LEFT
)) {
625 dir
= OB_DIRECTION_WEST
;
626 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
627 key_resize_edge
!= OB_DIRECTION_EAST
)
629 key_resize_edge
= OB_DIRECTION_WEST
;
633 if (keycode
== ob_keycode(OB_KEY_UP
)) {
634 dir
= OB_DIRECTION_NORTH
;
635 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
636 key_resize_edge
!= OB_DIRECTION_SOUTH
)
638 key_resize_edge
= OB_DIRECTION_NORTH
;
642 if (keycode
== ob_keycode(OB_KEY_DOWN
)) {
643 dir
= OB_DIRECTION_SOUTH
;
644 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
645 key_resize_edge
!= OB_DIRECTION_SOUTH
)
647 key_resize_edge
= OB_DIRECTION_SOUTH
;
652 /* shift means jump to edge */
653 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
656 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
657 dir
= OB_DIRECTION_EAST
;
658 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
659 dir
= OB_DIRECTION_WEST
;
660 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
661 dir
= OB_DIRECTION_SOUTH
;
662 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
663 dir
= OB_DIRECTION_NORTH
;
665 client_find_resize_directional(moveresize_client
, key_resize_edge
,
666 key_resize_edge
== dir
,
668 dw
= w
- moveresize_client
->area
.width
;
669 dh
= h
- moveresize_client
->area
.height
;
673 /* control means fine grained */
674 if (moveresize_client
->size_inc
.width
> 1) {
675 distw
= moveresize_client
->size_inc
.width
;
678 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
686 if (moveresize_client
->size_inc
.height
> 1) {
687 disth
= moveresize_client
->size_inc
.height
;
690 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
699 if (key_resize_edge
== OB_DIRECTION_WEST
) {
700 if (dir
== OB_DIRECTION_WEST
)
703 dw
= -(dist
= distw
);
705 else if (key_resize_edge
== OB_DIRECTION_EAST
) {
706 if (dir
== OB_DIRECTION_EAST
)
709 dw
= -(dist
= distw
);
711 else if (key_resize_edge
== OB_DIRECTION_NORTH
) {
712 if (dir
== OB_DIRECTION_NORTH
)
715 dh
= -(dist
= disth
);
717 else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
718 if (dir
== OB_DIRECTION_SOUTH
)
721 dh
= -(dist
= disth
);
725 calc_resize(TRUE
, resist
, &dw
, &dh
, dir
);
726 if (key_resize_edge
== OB_DIRECTION_WEST
)
728 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
733 /* how to move the pointer to keep up with the change */
734 if (key_resize_edge
== OB_DIRECTION_WEST
)
736 else if (key_resize_edge
== OB_DIRECTION_EAST
)
738 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
740 else if (key_resize_edge
== OB_DIRECTION_SOUTH
)
743 screen_pointer_pos(&opx
, &opy
);
744 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, pdx
, pdy
);
745 /* steal the motion events this causes */
746 XSync(ob_display
, FALSE
);
749 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
751 screen_pointer_pos(&px
, &py
);
755 /* because the cursor moves even though the window does
756 not nessesarily (resistance), this adjusts where the cursor
757 thinks it started so that it keeps up with where the window
759 start_x
+= (px
- opx
) - dw
;
760 start_y
+= (py
- opy
) - dh
;
764 gboolean
moveresize_event(XEvent
*e
)
766 gboolean used
= FALSE
;
768 if (!moveresize_in_progress
) return FALSE
;
770 if (e
->type
== ButtonPress
) {
772 start_x
= e
->xbutton
.x_root
;
773 start_y
= e
->xbutton
.y_root
;
774 button
= e
->xbutton
.button
; /* this will end it now */
776 used
= e
->xbutton
.button
== button
;
777 } else if (e
->type
== ButtonRelease
) {
778 if (!button
|| e
->xbutton
.button
== button
) {
779 moveresize_end(FALSE
);
782 } else if (e
->type
== MotionNotify
) {
784 cur_x
= start_cx
+ e
->xmotion
.x_root
- start_x
;
785 cur_y
= start_cy
+ e
->xmotion
.y_root
- start_y
;
787 do_edge_warp(e
->xmotion
.x_root
, e
->xmotion
.y_root
);
792 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
) {
793 dw
= -(e
->xmotion
.x_root
- start_x
);
794 dh
= -(e
->xmotion
.y_root
- start_y
);
795 dir
= OB_DIRECTION_NORTHWEST
;
796 } else if (corner
== prop_atoms
.net_wm_moveresize_size_top
) {
798 dh
= -(e
->xmotion
.y_root
- start_y
);
799 dir
= OB_DIRECTION_NORTH
;
800 } else if (corner
== prop_atoms
.net_wm_moveresize_size_topright
) {
801 dw
= (e
->xmotion
.x_root
- start_x
);
802 dh
= -(e
->xmotion
.y_root
- start_y
);
803 dir
= OB_DIRECTION_NORTHEAST
;
804 } else if (corner
== prop_atoms
.net_wm_moveresize_size_right
) {
805 dw
= (e
->xmotion
.x_root
- start_x
);
807 dir
= OB_DIRECTION_EAST
;
809 prop_atoms
.net_wm_moveresize_size_bottomright
) {
810 dw
= (e
->xmotion
.x_root
- start_x
);
811 dh
= (e
->xmotion
.y_root
- start_y
);
812 dir
= OB_DIRECTION_SOUTHEAST
;
813 } else if (corner
== prop_atoms
.net_wm_moveresize_size_bottom
) {
815 dh
= (e
->xmotion
.y_root
- start_y
);
816 dir
= OB_DIRECTION_SOUTH
;
818 prop_atoms
.net_wm_moveresize_size_bottomleft
) {
819 dw
= -(e
->xmotion
.x_root
- start_x
);
820 dh
= (e
->xmotion
.y_root
- start_y
);
821 dir
= OB_DIRECTION_SOUTHWEST
;
822 } else if (corner
== prop_atoms
.net_wm_moveresize_size_left
) {
823 dw
= -(e
->xmotion
.x_root
- start_x
);
825 dir
= OB_DIRECTION_WEST
;
826 } else if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
827 dw
= (e
->xmotion
.x_root
- start_x
);
828 dh
= (e
->xmotion
.y_root
- start_y
);
829 dir
= OB_DIRECTION_SOUTHEAST
;
831 g_assert_not_reached();
833 dw
-= cur_w
- start_cw
;
834 dh
-= cur_h
- start_ch
;
836 calc_resize(FALSE
, 0, &dw
, &dh
, dir
);
840 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
||
841 corner
== prop_atoms
.net_wm_moveresize_size_left
||
842 corner
== prop_atoms
.net_wm_moveresize_size_bottomleft
)
846 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
||
847 corner
== prop_atoms
.net_wm_moveresize_size_top
||
848 corner
== prop_atoms
.net_wm_moveresize_size_topright
)
856 } else if (e
->type
== KeyPress
) {
857 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_ESCAPE
)) {
858 moveresize_end(TRUE
);
860 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RETURN
)) {
861 moveresize_end(FALSE
);
863 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RIGHT
) ||
864 e
->xkey
.keycode
== ob_keycode(OB_KEY_LEFT
) ||
865 e
->xkey
.keycode
== ob_keycode(OB_KEY_DOWN
) ||
866 e
->xkey
.keycode
== ob_keycode(OB_KEY_UP
))
868 if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
869 resize_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
871 } else if (corner
== prop_atoms
.net_wm_moveresize_move_keyboard
) {
872 move_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
878 else if (e
->type
== extensions_sync_event_basep
+ XSyncAlarmNotify
)
880 waiting_for_sync
= FALSE
; /* we got our sync... */
881 do_resize(); /* ...so try resize if there is more change pending */