2 #include "framerender.h"
10 #include "moveresize.h"
12 #include "render/render.h"
13 #include "render/theme.h"
18 gboolean moveresize_in_progress = FALSE;
19 ObClient *moveresize_client = NULL;
21 static gboolean moving = FALSE; /* TRUE - moving, FALSE - resizing */
23 static int start_x, start_y, start_cx, start_cy, start_cw, start_ch;
24 static int cur_x, cur_y;
26 static guint32 corner;
27 static ObCorner lockcorner;
29 static ObPopup *popup = NULL;
31 static void client_dest(gpointer client)
33 if (moveresize_client == client)
37 void moveresize_startup(gboolean reconfig)
39 popup = popup_new(FALSE);
42 client_add_destructor(client_dest);
45 void moveresize_shutdown(gboolean reconfig)
48 if (moveresize_in_progress)
49 moveresize_end(FALSE);
50 client_remove_destructor(client_dest);
57 static void popup_coords(ObClient *c, char *format, int a, int b)
61 text = g_strdup_printf(format, a, b);
62 popup_position(popup, CenterGravity,
63 c->frame->area.x + c->frame->size.left +
65 c->frame->area.y + c->frame->size.top +
67 popup_show(popup, text);
71 void moveresize_start(ObClient *c, int x, int y, guint b, guint32 cnr)
75 if (moveresize_in_progress || !c->frame->visible)
78 moveresize_client = c;
79 start_cx = c->frame->area.x;
80 start_cy = c->frame->area.y;
81 /* these adjustments for the size_inc make resizing a terminal more
82 friendly. you essentially start the resize in the middle of the
83 increment instead of at 0, so you have to move half an increment
84 either way instead of a full increment one and 1 px the other. and this
85 is one large mother fucking comment. */
86 start_cw = c->area.width + c->size_inc.width / 2;
87 start_ch = c->area.height + c->size_inc.height / 2;
94 have to change start_cx and start_cy if going to do this..
95 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
96 corner == prop_atoms.net_wm_moveresize_size_keyboard)
97 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
98 c->area.width / 2, c->area.height / 2);
101 if (corner == prop_atoms.net_wm_moveresize_move ||
102 corner == prop_atoms.net_wm_moveresize_move_keyboard) {
112 moveresize_in_progress = TRUE;
114 if (corner == prop_atoms.net_wm_moveresize_size_topleft)
115 cur = OB_CURSOR_NORTHWEST;
116 else if (corner == prop_atoms.net_wm_moveresize_size_top)
117 cur = OB_CURSOR_NORTH;
118 else if (corner == prop_atoms.net_wm_moveresize_size_topright)
119 cur = OB_CURSOR_NORTHEAST;
120 else if (corner == prop_atoms.net_wm_moveresize_size_right)
121 cur = OB_CURSOR_EAST;
122 else if (corner == prop_atoms.net_wm_moveresize_size_bottomright)
123 cur = OB_CURSOR_SOUTHEAST;
124 else if (corner == prop_atoms.net_wm_moveresize_size_bottom)
125 cur = OB_CURSOR_SOUTH;
126 else if (corner == prop_atoms.net_wm_moveresize_size_bottomleft)
127 cur = OB_CURSOR_SOUTHWEST;
128 else if (corner == prop_atoms.net_wm_moveresize_size_left)
129 cur = OB_CURSOR_WEST;
130 else if (corner == prop_atoms.net_wm_moveresize_size_keyboard)
131 cur = OB_CURSOR_SOUTHEAST;
132 else if (corner == prop_atoms.net_wm_moveresize_move)
133 cur = OB_CURSOR_MOVE;
134 else if (corner == prop_atoms.net_wm_moveresize_move_keyboard)
135 cur = OB_CURSOR_MOVE;
137 g_assert_not_reached();
139 grab_pointer(TRUE, cur);
143 void moveresize_end(gboolean cancel)
145 grab_keyboard(FALSE);
146 grab_pointer(FALSE, OB_CURSOR_NONE);
151 client_move(moveresize_client,
152 (cancel ? start_cx : cur_x),
153 (cancel ? start_cy : cur_y));
155 client_configure(moveresize_client, lockcorner,
156 moveresize_client->area.x,
157 moveresize_client->area.y,
158 (cancel ? start_cw : cur_x),
159 (cancel ? start_ch : cur_y), TRUE, TRUE);
162 moveresize_in_progress = FALSE;
163 moveresize_client = NULL;
166 static void do_move(gboolean resist)
169 resist_move_windows(moveresize_client, &cur_x, &cur_y);
170 resist_move_monitors(moveresize_client, &cur_x, &cur_y);
172 /* get where the client should be */
173 frame_frame_gravity(moveresize_client->frame, &cur_x, &cur_y);
174 client_configure(moveresize_client, OB_CORNER_TOPLEFT, cur_x, cur_y,
175 moveresize_client->area.width,
176 moveresize_client->area.height, TRUE, FALSE);
179 static void do_resize(gboolean resist)
181 /* resist_size_* needs the frame size */
182 cur_x += moveresize_client->frame->size.left +
183 moveresize_client->frame->size.right;
184 cur_y += moveresize_client->frame->size.top +
185 moveresize_client->frame->size.bottom;
188 resist_size_windows(moveresize_client, &cur_x, &cur_y, lockcorner);
189 resist_size_monitors(moveresize_client, &cur_x, &cur_y, lockcorner);
191 cur_x -= moveresize_client->frame->size.left +
192 moveresize_client->frame->size.right;
193 cur_y -= moveresize_client->frame->size.top +
194 moveresize_client->frame->size.bottom;
196 client_configure(moveresize_client, lockcorner,
197 moveresize_client->area.x, moveresize_client->area.y,
198 cur_x, cur_y, TRUE, FALSE);
200 /* this would be better with a fixed width font ... XXX can do it better
201 if there are 2 text boxes */
202 if (moveresize_client->size_inc.width > 1 ||
203 moveresize_client->size_inc.height > 1)
204 popup_coords(moveresize_client, "%d x %d",
205 moveresize_client->logical_size.width,
206 moveresize_client->logical_size.height);
209 void moveresize_event(XEvent *e)
211 g_assert(moveresize_in_progress);
213 if (e->type == ButtonPress) {
215 start_x = e->xbutton.x_root;
216 start_y = e->xbutton.y_root;
217 button = e->xbutton.button; /* this will end it now */
219 } else if (e->type == ButtonRelease) {
220 if (!button || e->xbutton.button == button) {
221 moveresize_end(FALSE);
223 } else if (e->type == MotionNotify) {
225 cur_x = start_cx + e->xmotion.x_root - start_x;
226 cur_y = start_cy + e->xmotion.y_root - start_y;
229 if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
230 cur_x = start_cw - (e->xmotion.x_root - start_x);
231 cur_y = start_ch - (e->xmotion.y_root - start_y);
232 lockcorner = OB_CORNER_BOTTOMRIGHT;
233 } else if (corner == prop_atoms.net_wm_moveresize_size_top) {
235 cur_y = start_ch - (e->xmotion.y_root - start_y);
236 lockcorner = OB_CORNER_BOTTOMRIGHT;
237 } else if (corner == prop_atoms.net_wm_moveresize_size_topright) {
238 cur_x = start_cw + (e->xmotion.x_root - start_x);
239 cur_y = start_ch - (e->xmotion.y_root - start_y);
240 lockcorner = OB_CORNER_BOTTOMLEFT;
241 } else if (corner == prop_atoms.net_wm_moveresize_size_right) {
242 cur_x = start_cw + (e->xmotion.x_root - start_x);
244 lockcorner = OB_CORNER_BOTTOMLEFT;
246 prop_atoms.net_wm_moveresize_size_bottomright) {
247 cur_x = start_cw + (e->xmotion.x_root - start_x);
248 cur_y = start_ch + (e->xmotion.y_root - start_y);
249 lockcorner = OB_CORNER_TOPLEFT;
250 } else if (corner == prop_atoms.net_wm_moveresize_size_bottom) {
252 cur_y = start_ch + (e->xmotion.y_root - start_y);
253 lockcorner = OB_CORNER_TOPLEFT;
255 prop_atoms.net_wm_moveresize_size_bottomleft) {
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_TOPRIGHT;
259 } else if (corner == prop_atoms.net_wm_moveresize_size_left) {
260 cur_x = start_cw - (e->xmotion.x_root - start_x);
262 lockcorner = OB_CORNER_TOPRIGHT;
263 } else if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
264 cur_x = start_cw + (e->xmotion.x_root - start_x);
265 cur_y = start_ch + (e->xmotion.y_root - start_y);
266 lockcorner = OB_CORNER_TOPLEFT;
268 g_assert_not_reached();
272 } else if (e->type == KeyPress) {
273 if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE))
274 moveresize_end(TRUE);
275 else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN))
276 moveresize_end(FALSE);
278 if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
279 int dx = 0, dy = 0, ox = cur_x, oy = cur_y;
281 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
282 dx = MAX(4, moveresize_client->size_inc.width);
283 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
284 dx = -MAX(4, moveresize_client->size_inc.width);
285 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
286 dy = MAX(4, moveresize_client->size_inc.height);
287 else if (e->xkey.keycode == ob_keycode(OB_KEY_UP))
288 dy = -MAX(4, moveresize_client->size_inc.height);
294 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
295 /* steal the motion events this causes */
296 XSync(ob_display, FALSE);
299 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
304 /* because the cursor moves even though the window does
305 not nessesarily (resistance), this adjusts where the curor
306 thinks it started so that it keeps up with where the window
308 start_x += dx - (cur_x - ox);
309 start_y += dy - (cur_y - oy);
310 } else if (corner == prop_atoms.net_wm_moveresize_move_keyboard) {
311 int dx = 0, dy = 0, ox = cur_x, oy = cur_y;
312 int opx, px, opy, py;
314 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
316 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
318 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
320 else if (e->xkey.keycode == ob_keycode(OB_KEY_UP))
327 screen_pointer_pos(&opx, &opy);
328 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
329 /* steal the motion events this causes */
330 XSync(ob_display, FALSE);
333 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
335 screen_pointer_pos(&px, &py);
339 /* because the cursor moves even though the window does
340 not nessesarily (resistance), this adjusts where the curor
341 thinks it started so that it keeps up with where the window
343 start_x += (px - opx) - (cur_x - ox);
344 start_y += (py - opy) - (cur_y - oy);