1 /* -*- indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*-
3 moveresize.c for the Openbox window manager
4 Copyright (c) 2003 Ben Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
20 #include "framerender.h"
28 #include "moveresize.h"
30 #include "render/render.h"
31 #include "render/theme.h"
36 gboolean moveresize_in_progress
= FALSE
;
37 ObClient
*moveresize_client
= NULL
;
39 static gboolean moving
= FALSE
; /* TRUE - moving, FALSE - resizing */
41 static int start_x
, start_y
, start_cx
, start_cy
, start_cw
, start_ch
;
42 static int cur_x
, cur_y
;
44 static guint32 corner
;
45 static ObCorner lockcorner
;
47 static ObPopup
*popup
= NULL
;
49 static void client_dest(gpointer client
)
51 if (moveresize_client
== client
)
55 void moveresize_startup(gboolean reconfig
)
57 popup
= popup_new(FALSE
);
60 client_add_destructor(client_dest
);
63 void moveresize_shutdown(gboolean reconfig
)
66 if (moveresize_in_progress
)
67 moveresize_end(FALSE
);
68 client_remove_destructor(client_dest
);
75 static void popup_coords(ObClient
*c
, char *format
, int a
, int b
)
79 text
= g_strdup_printf(format
, a
, b
);
80 popup_position(popup
, CenterGravity
,
81 c
->frame
->area
.x
+ c
->frame
->size
.left
+
83 c
->frame
->area
.y
+ c
->frame
->size
.top
+
85 popup_show(popup
, text
);
89 void moveresize_start(ObClient
*c
, int x
, int y
, guint b
, guint32 cnr
)
93 if (moveresize_in_progress
|| !c
->frame
->visible
)
96 moveresize_client
= c
;
97 start_cx
= c
->frame
->area
.x
;
98 start_cy
= c
->frame
->area
.y
;
99 /* these adjustments for the size_inc make resizing a terminal more
100 friendly. you essentially start the resize in the middle of the
101 increment instead of at 0, so you have to move half an increment
102 either way instead of a full increment one and 1 px the other. and this
103 is one large mother fucking comment. */
104 start_cw
= c
->area
.width
+ c
->size_inc
.width
/ 2;
105 start_ch
= c
->area
.height
+ c
->size_inc
.height
/ 2;
112 have to change start_cx and start_cy if going to do this..
113 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
114 corner == prop_atoms.net_wm_moveresize_size_keyboard)
115 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
116 c->area.width / 2, c->area.height / 2);
119 if (corner
== prop_atoms
.net_wm_moveresize_move
||
120 corner
== prop_atoms
.net_wm_moveresize_move_keyboard
) {
130 moveresize_in_progress
= TRUE
;
132 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
)
133 cur
= OB_CURSOR_NORTHWEST
;
134 else if (corner
== prop_atoms
.net_wm_moveresize_size_top
)
135 cur
= OB_CURSOR_NORTH
;
136 else if (corner
== prop_atoms
.net_wm_moveresize_size_topright
)
137 cur
= OB_CURSOR_NORTHEAST
;
138 else if (corner
== prop_atoms
.net_wm_moveresize_size_right
)
139 cur
= OB_CURSOR_EAST
;
140 else if (corner
== prop_atoms
.net_wm_moveresize_size_bottomright
)
141 cur
= OB_CURSOR_SOUTHEAST
;
142 else if (corner
== prop_atoms
.net_wm_moveresize_size_bottom
)
143 cur
= OB_CURSOR_SOUTH
;
144 else if (corner
== prop_atoms
.net_wm_moveresize_size_bottomleft
)
145 cur
= OB_CURSOR_SOUTHWEST
;
146 else if (corner
== prop_atoms
.net_wm_moveresize_size_left
)
147 cur
= OB_CURSOR_WEST
;
148 else if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
)
149 cur
= OB_CURSOR_SOUTHEAST
;
150 else if (corner
== prop_atoms
.net_wm_moveresize_move
)
151 cur
= OB_CURSOR_MOVE
;
152 else if (corner
== prop_atoms
.net_wm_moveresize_move_keyboard
)
153 cur
= OB_CURSOR_MOVE
;
155 g_assert_not_reached();
157 grab_pointer(TRUE
, cur
);
161 void moveresize_end(gboolean cancel
)
163 grab_keyboard(FALSE
);
164 grab_pointer(FALSE
, OB_CURSOR_NONE
);
169 client_move(moveresize_client
,
170 (cancel
? start_cx
: cur_x
),
171 (cancel
? start_cy
: cur_y
));
173 client_configure(moveresize_client
, lockcorner
,
174 moveresize_client
->area
.x
,
175 moveresize_client
->area
.y
,
176 (cancel
? start_cw
: cur_x
),
177 (cancel
? start_ch
: cur_y
), TRUE
, TRUE
);
180 moveresize_in_progress
= FALSE
;
181 moveresize_client
= NULL
;
184 static void do_move(gboolean resist
)
187 resist_move_windows(moveresize_client
, &cur_x
, &cur_y
);
188 resist_move_monitors(moveresize_client
, &cur_x
, &cur_y
);
190 /* get where the client should be */
191 frame_frame_gravity(moveresize_client
->frame
, &cur_x
, &cur_y
);
192 client_configure(moveresize_client
, OB_CORNER_TOPLEFT
, cur_x
, cur_y
,
193 moveresize_client
->area
.width
,
194 moveresize_client
->area
.height
, TRUE
, FALSE
);
197 static void do_resize(gboolean resist
)
199 /* resist_size_* needs the frame size */
200 cur_x
+= moveresize_client
->frame
->size
.left
+
201 moveresize_client
->frame
->size
.right
;
202 cur_y
+= moveresize_client
->frame
->size
.top
+
203 moveresize_client
->frame
->size
.bottom
;
206 resist_size_windows(moveresize_client
, &cur_x
, &cur_y
, lockcorner
);
207 resist_size_monitors(moveresize_client
, &cur_x
, &cur_y
, lockcorner
);
209 cur_x
-= moveresize_client
->frame
->size
.left
+
210 moveresize_client
->frame
->size
.right
;
211 cur_y
-= moveresize_client
->frame
->size
.top
+
212 moveresize_client
->frame
->size
.bottom
;
214 client_configure(moveresize_client
, lockcorner
,
215 moveresize_client
->area
.x
, moveresize_client
->area
.y
,
216 cur_x
, cur_y
, TRUE
, FALSE
);
218 /* this would be better with a fixed width font ... XXX can do it better
219 if there are 2 text boxes */
220 if (moveresize_client
->size_inc
.width
> 1 ||
221 moveresize_client
->size_inc
.height
> 1)
222 popup_coords(moveresize_client
, "%d x %d",
223 moveresize_client
->logical_size
.width
,
224 moveresize_client
->logical_size
.height
);
227 void moveresize_event(XEvent
*e
)
229 g_assert(moveresize_in_progress
);
231 if (e
->type
== ButtonPress
) {
233 start_x
= e
->xbutton
.x_root
;
234 start_y
= e
->xbutton
.y_root
;
235 button
= e
->xbutton
.button
; /* this will end it now */
237 } else if (e
->type
== ButtonRelease
) {
238 if (!button
|| e
->xbutton
.button
== button
) {
239 moveresize_end(FALSE
);
241 } else if (e
->type
== MotionNotify
) {
243 cur_x
= start_cx
+ e
->xmotion
.x_root
- start_x
;
244 cur_y
= start_cy
+ e
->xmotion
.y_root
- start_y
;
247 if (corner
== prop_atoms
.net_wm_moveresize_size_topleft
) {
248 cur_x
= start_cw
- (e
->xmotion
.x_root
- start_x
);
249 cur_y
= start_ch
- (e
->xmotion
.y_root
- start_y
);
250 lockcorner
= OB_CORNER_BOTTOMRIGHT
;
251 } else if (corner
== prop_atoms
.net_wm_moveresize_size_top
) {
253 cur_y
= start_ch
- (e
->xmotion
.y_root
- start_y
);
254 lockcorner
= OB_CORNER_BOTTOMRIGHT
;
255 } else if (corner
== prop_atoms
.net_wm_moveresize_size_topright
) {
256 cur_x
= start_cw
+ (e
->xmotion
.x_root
- start_x
);
257 cur_y
= start_ch
- (e
->xmotion
.y_root
- start_y
);
258 lockcorner
= OB_CORNER_BOTTOMLEFT
;
259 } else if (corner
== prop_atoms
.net_wm_moveresize_size_right
) {
260 cur_x
= start_cw
+ (e
->xmotion
.x_root
- start_x
);
262 lockcorner
= OB_CORNER_BOTTOMLEFT
;
264 prop_atoms
.net_wm_moveresize_size_bottomright
) {
265 cur_x
= start_cw
+ (e
->xmotion
.x_root
- start_x
);
266 cur_y
= start_ch
+ (e
->xmotion
.y_root
- start_y
);
267 lockcorner
= OB_CORNER_TOPLEFT
;
268 } else if (corner
== prop_atoms
.net_wm_moveresize_size_bottom
) {
270 cur_y
= start_ch
+ (e
->xmotion
.y_root
- start_y
);
271 lockcorner
= OB_CORNER_TOPLEFT
;
273 prop_atoms
.net_wm_moveresize_size_bottomleft
) {
274 cur_x
= start_cw
- (e
->xmotion
.x_root
- start_x
);
275 cur_y
= start_ch
+ (e
->xmotion
.y_root
- start_y
);
276 lockcorner
= OB_CORNER_TOPRIGHT
;
277 } else if (corner
== prop_atoms
.net_wm_moveresize_size_left
) {
278 cur_x
= start_cw
- (e
->xmotion
.x_root
- start_x
);
280 lockcorner
= OB_CORNER_TOPRIGHT
;
281 } else if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
282 cur_x
= start_cw
+ (e
->xmotion
.x_root
- start_x
);
283 cur_y
= start_ch
+ (e
->xmotion
.y_root
- start_y
);
284 lockcorner
= OB_CORNER_TOPLEFT
;
286 g_assert_not_reached();
290 } else if (e
->type
== KeyPress
) {
291 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_ESCAPE
))
292 moveresize_end(TRUE
);
293 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RETURN
))
294 moveresize_end(FALSE
);
296 if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
297 int dx
= 0, dy
= 0, ox
= cur_x
, oy
= cur_y
;
299 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RIGHT
))
300 dx
= MAX(4, moveresize_client
->size_inc
.width
);
301 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_LEFT
))
302 dx
= -MAX(4, moveresize_client
->size_inc
.width
);
303 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_DOWN
))
304 dy
= MAX(4, moveresize_client
->size_inc
.height
);
305 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_UP
))
306 dy
= -MAX(4, moveresize_client
->size_inc
.height
);
312 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, dx
, dy
);
313 /* steal the motion events this causes */
314 XSync(ob_display
, FALSE
);
317 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
322 /* because the cursor moves even though the window does
323 not nessesarily (resistance), this adjusts where the curor
324 thinks it started so that it keeps up with where the window
326 start_x
+= dx
- (cur_x
- ox
);
327 start_y
+= dy
- (cur_y
- oy
);
328 } else if (corner
== prop_atoms
.net_wm_moveresize_move_keyboard
) {
329 int dx
= 0, dy
= 0, ox
= cur_x
, oy
= cur_y
;
330 int opx
, px
, opy
, py
;
332 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RIGHT
))
334 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_LEFT
))
336 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_DOWN
))
338 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_UP
))
345 screen_pointer_pos(&opx
, &opy
);
346 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, dx
, dy
);
347 /* steal the motion events this causes */
348 XSync(ob_display
, FALSE
);
351 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
353 screen_pointer_pos(&px
, &py
);
357 /* because the cursor moves even though the window does
358 not nessesarily (resistance), this adjusts where the curor
359 thinks it started so that it keeps up with where the window
361 start_x
+= (px
- opx
) - (cur_x
- ox
);
362 start_y
+= (py
- opy
) - (cur_y
- oy
);