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
) {
529 if (dir
== (ObDirection
)-1)
532 edge_warp_odd
= TRUE
; /* switch on the first timeout */
533 ob_main_loop_timeout_add(ob_main_loop
,
534 config_mouse_screenedgetime
* 1000,
535 edge_warp_delay_func
,
542 static void cancel_edge_warp()
544 ob_main_loop_timeout_remove(ob_main_loop
, edge_warp_delay_func
);
547 static void move_with_keys(gint keycode
, gint state
)
549 gint dx
= 0, dy
= 0, ox
= cur_x
, oy
= cur_y
;
550 gint opx
, px
, opy
, py
;
553 /* shift means jump to edge */
554 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
558 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
559 dir
= OB_DIRECTION_EAST
;
560 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
561 dir
= OB_DIRECTION_WEST
;
562 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
563 dir
= OB_DIRECTION_SOUTH
;
564 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
565 dir
= OB_DIRECTION_NORTH
;
567 client_find_move_directional(moveresize_client
, dir
, &x
, &y
);
568 dx
= x
- moveresize_client
->area
.x
;
569 dy
= y
- moveresize_client
->area
.y
;
571 /* control means fine grained */
572 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
))
577 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
579 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
581 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
583 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
587 screen_pointer_pos(&opx
, &opy
);
588 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, dx
, dy
);
589 /* steal the motion events this causes */
590 XSync(ob_display
, FALSE
);
593 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
595 screen_pointer_pos(&px
, &py
);
601 /* because the cursor moves even though the window does
602 not nessesarily (resistance), this adjusts where the curor
603 thinks it started so that it keeps up with where the window
605 start_x
+= (px
- opx
) - (cur_x
- ox
);
606 start_y
+= (py
- opy
) - (cur_y
- oy
);
609 static void resize_with_keys(gint keycode
, gint state
)
611 gint dw
= 0, dh
= 0, pdx
= 0, pdy
= 0, opx
, opy
, px
, py
;
612 gint dist
= 0, resist
= 0;
615 /* pick the edge if it needs to move */
616 if (keycode
== ob_keycode(OB_KEY_RIGHT
)) {
617 dir
= OB_DIRECTION_EAST
;
618 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
619 key_resize_edge
!= OB_DIRECTION_EAST
)
621 key_resize_edge
= OB_DIRECTION_EAST
;
625 if (keycode
== ob_keycode(OB_KEY_LEFT
)) {
626 dir
= OB_DIRECTION_WEST
;
627 if (key_resize_edge
!= OB_DIRECTION_WEST
&&
628 key_resize_edge
!= OB_DIRECTION_EAST
)
630 key_resize_edge
= OB_DIRECTION_WEST
;
634 if (keycode
== ob_keycode(OB_KEY_UP
)) {
635 dir
= OB_DIRECTION_NORTH
;
636 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
637 key_resize_edge
!= OB_DIRECTION_SOUTH
)
639 key_resize_edge
= OB_DIRECTION_NORTH
;
643 if (keycode
== ob_keycode(OB_KEY_DOWN
)) {
644 dir
= OB_DIRECTION_SOUTH
;
645 if (key_resize_edge
!= OB_DIRECTION_NORTH
&&
646 key_resize_edge
!= OB_DIRECTION_SOUTH
)
648 key_resize_edge
= OB_DIRECTION_SOUTH
;
653 /* shift means jump to edge */
654 if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_SHIFT
)) {
657 if (keycode
== ob_keycode(OB_KEY_RIGHT
))
658 dir
= OB_DIRECTION_EAST
;
659 else if (keycode
== ob_keycode(OB_KEY_LEFT
))
660 dir
= OB_DIRECTION_WEST
;
661 else if (keycode
== ob_keycode(OB_KEY_DOWN
))
662 dir
= OB_DIRECTION_SOUTH
;
663 else /* if (keycode == ob_keycode(OB_KEY_UP)) */
664 dir
= OB_DIRECTION_NORTH
;
666 client_find_resize_directional(moveresize_client
, key_resize_edge
,
667 key_resize_edge
== dir
,
669 dw
= w
- moveresize_client
->area
.width
;
670 dh
= h
- moveresize_client
->area
.height
;
674 /* control means fine grained */
675 if (moveresize_client
->size_inc
.width
> 1) {
676 distw
= moveresize_client
->size_inc
.width
;
679 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
687 if (moveresize_client
->size_inc
.height
> 1) {
688 disth
= moveresize_client
->size_inc
.height
;
691 else if (state
& modkeys_key_to_mask(OB_MODKEY_KEY_CONTROL
)) {
700 if (key_resize_edge
== OB_DIRECTION_WEST
) {
701 if (dir
== OB_DIRECTION_WEST
)
704 dw
= -(dist
= distw
);
706 else if (key_resize_edge
== OB_DIRECTION_EAST
) {
707 if (dir
== OB_DIRECTION_EAST
)
710 dw
= -(dist
= distw
);
712 else if (key_resize_edge
== OB_DIRECTION_NORTH
) {
713 if (dir
== OB_DIRECTION_NORTH
)
716 dh
= -(dist
= disth
);
718 else /*if (key_resize_edge == OB_DIRECTION_SOUTH)*/ {
719 if (dir
== OB_DIRECTION_SOUTH
)
722 dh
= -(dist
= disth
);
726 calc_resize(TRUE
, resist
, &dw
, &dh
, dir
);
727 if (key_resize_edge
== OB_DIRECTION_WEST
)
729 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
734 /* how to move the pointer to keep up with the change */
735 if (key_resize_edge
== OB_DIRECTION_WEST
)
737 else if (key_resize_edge
== OB_DIRECTION_EAST
)
739 else if (key_resize_edge
== OB_DIRECTION_NORTH
)
741 else if (key_resize_edge
== OB_DIRECTION_SOUTH
)
744 screen_pointer_pos(&opx
, &opy
);
745 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, pdx
, pdy
);
746 /* steal the motion events this causes */
747 XSync(ob_display
, FALSE
);
750 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
752 screen_pointer_pos(&px
, &py
);
756 /* because the cursor moves even though the window does
757 not nessesarily (resistance), this adjusts where the cursor
758 thinks it started so that it keeps up with where the window
760 start_x
+= (px
- opx
) - dw
;
761 start_y
+= (py
- opy
) - dh
;
765 gboolean
moveresize_event(XEvent
*e
)
767 gboolean used
= FALSE
;
769 if (!moveresize_in_progress
) return FALSE
;
771 if (e
->type
== ButtonPress
) {
773 start_x
= e
->xbutton
.x_root
;
774 start_y
= e
->xbutton
.y_root
;
775 button
= e
->xbutton
.button
; /* this will end it now */
777 used
= e
->xbutton
.button
== button
;
778 } else if (e
->type
== ButtonRelease
) {
779 if (!button
|| e
->xbutton
.button
== button
) {
780 moveresize_end(FALSE
);
783 } else if (e
->type
== MotionNotify
) {
785 cur_x
= start_cx
+ e
->xmotion
.x_root
- start_x
;
786 cur_y
= start_cy
+ e
->xmotion
.y_root
- start_y
;
788 do_edge_warp(e
->xmotion
.x_root
, e
->xmotion
.y_root
);
793 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
) {
794 dw
= -(e
->xmotion
.x_root
- start_x
);
795 dh
= -(e
->xmotion
.y_root
- start_y
);
796 dir
= OB_DIRECTION_NORTHWEST
;
797 } else if (corner
== prop_atoms
.net_wm_moveresize_size_top
) {
799 dh
= -(e
->xmotion
.y_root
- start_y
);
800 dir
= OB_DIRECTION_NORTH
;
801 } else if (corner
== prop_atoms
.net_wm_moveresize_size_topright
) {
802 dw
= (e
->xmotion
.x_root
- start_x
);
803 dh
= -(e
->xmotion
.y_root
- start_y
);
804 dir
= OB_DIRECTION_NORTHEAST
;
805 } else if (corner
== prop_atoms
.net_wm_moveresize_size_right
) {
806 dw
= (e
->xmotion
.x_root
- start_x
);
808 dir
= OB_DIRECTION_EAST
;
810 prop_atoms
.net_wm_moveresize_size_bottomright
) {
811 dw
= (e
->xmotion
.x_root
- start_x
);
812 dh
= (e
->xmotion
.y_root
- start_y
);
813 dir
= OB_DIRECTION_SOUTHEAST
;
814 } else if (corner
== prop_atoms
.net_wm_moveresize_size_bottom
) {
816 dh
= (e
->xmotion
.y_root
- start_y
);
817 dir
= OB_DIRECTION_SOUTH
;
819 prop_atoms
.net_wm_moveresize_size_bottomleft
) {
820 dw
= -(e
->xmotion
.x_root
- start_x
);
821 dh
= (e
->xmotion
.y_root
- start_y
);
822 dir
= OB_DIRECTION_SOUTHWEST
;
823 } else if (corner
== prop_atoms
.net_wm_moveresize_size_left
) {
824 dw
= -(e
->xmotion
.x_root
- start_x
);
826 dir
= OB_DIRECTION_WEST
;
827 } else if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
828 dw
= (e
->xmotion
.x_root
- start_x
);
829 dh
= (e
->xmotion
.y_root
- start_y
);
830 dir
= OB_DIRECTION_SOUTHEAST
;
832 g_assert_not_reached();
834 dw
-= cur_w
- start_cw
;
835 dh
-= cur_h
- start_ch
;
837 calc_resize(FALSE
, 0, &dw
, &dh
, dir
);
841 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
||
842 corner
== prop_atoms
.net_wm_moveresize_size_left
||
843 corner
== prop_atoms
.net_wm_moveresize_size_bottomleft
)
847 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
||
848 corner
== prop_atoms
.net_wm_moveresize_size_top
||
849 corner
== prop_atoms
.net_wm_moveresize_size_topright
)
857 } else if (e
->type
== KeyPress
) {
858 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_ESCAPE
)) {
859 moveresize_end(TRUE
);
861 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RETURN
)) {
862 moveresize_end(FALSE
);
864 } else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RIGHT
) ||
865 e
->xkey
.keycode
== ob_keycode(OB_KEY_LEFT
) ||
866 e
->xkey
.keycode
== ob_keycode(OB_KEY_DOWN
) ||
867 e
->xkey
.keycode
== ob_keycode(OB_KEY_UP
))
869 if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
870 resize_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
872 } else if (corner
== prop_atoms
.net_wm_moveresize_move_keyboard
) {
873 move_with_keys(e
->xkey
.keycode
, e
->xkey
.state
);
879 else if (e
->type
== extensions_sync_event_basep
+ XSyncAlarmNotify
)
881 waiting_for_sync
= FALSE
; /* we got our sync... */
882 do_resize(); /* ...so try resize if there is more change pending */