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 Popup *popup = NULL;
31 static void client_dest(gpointer client)
33 if (moveresize_client == client)
37 void moveresize_startup()
39 popup = popup_new(FALSE);
41 client_add_destructor(client_dest);
44 void moveresize_shutdown()
46 client_remove_destructor(client_dest);
52 static void popup_coords(ObClient *c, char *format, int a, int b)
56 text = g_strdup_printf(format, a, b);
57 popup_position(popup, CenterGravity,
58 c->frame->area.x + c->frame->size.left +
60 c->frame->area.y + c->frame->size.top +
62 popup_show(popup, text, NULL);
66 void moveresize_start(ObClient *c, int x, int y, guint b, guint32 cnr)
70 g_assert(!moveresize_in_progress);
72 moveresize_client = c;
73 start_cx = c->frame->area.x;
74 start_cy = c->frame->area.y;
75 /* these adjustments for the size_inc make resizing a terminal more
76 friendly. you essentially start the resize in the middle of the
77 increment instead of at 0, so you have to move half an increment
78 either way instead of a full increment one and 1 px the other. and this
79 is one large mother fucking comment. */
80 start_cw = c->area.width + (c->size_inc.width + 1) / 2;
81 start_ch = c->area.height + (c->size_inc.height + 1) / 2;
88 have to change start_cx and start_cy if going to do this..
89 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
90 corner == prop_atoms.net_wm_moveresize_size_keyboard)
91 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
92 c->area.width / 2, c->area.height / 2);
95 if (corner == prop_atoms.net_wm_moveresize_move ||
96 corner == prop_atoms.net_wm_moveresize_move_keyboard) {
106 moveresize_in_progress = TRUE;
108 if (corner == prop_atoms.net_wm_moveresize_size_topleft)
109 cur = OB_CURSOR_NORTHWEST;
110 else if (corner == prop_atoms.net_wm_moveresize_size_top)
111 cur = OB_CURSOR_NORTH;
112 else if (corner == prop_atoms.net_wm_moveresize_size_topright)
113 cur = OB_CURSOR_NORTHEAST;
114 else if (corner == prop_atoms.net_wm_moveresize_size_right)
115 cur = OB_CURSOR_EAST;
116 else if (corner == prop_atoms.net_wm_moveresize_size_bottomright)
117 cur = OB_CURSOR_SOUTHEAST;
118 else if (corner == prop_atoms.net_wm_moveresize_size_bottom)
119 cur = OB_CURSOR_SOUTH;
120 else if (corner == prop_atoms.net_wm_moveresize_size_bottomleft)
121 cur = OB_CURSOR_SOUTHWEST;
122 else if (corner == prop_atoms.net_wm_moveresize_size_left)
123 cur = OB_CURSOR_WEST;
124 else if (corner == prop_atoms.net_wm_moveresize_size_keyboard)
125 cur = OB_CURSOR_SOUTHEAST;
126 else if (corner == prop_atoms.net_wm_moveresize_move)
127 cur = OB_CURSOR_MOVE;
128 else if (corner == prop_atoms.net_wm_moveresize_move_keyboard)
129 cur = OB_CURSOR_MOVE;
131 g_assert_not_reached();
133 grab_pointer(TRUE, cur);
137 void moveresize_end(gboolean cancel)
139 grab_keyboard(FALSE);
140 grab_pointer(FALSE, None);
145 client_move(moveresize_client,
146 (cancel ? start_cx : cur_x),
147 (cancel ? start_cy : cur_y));
149 client_configure(moveresize_client, lockcorner,
150 moveresize_client->area.x,
151 moveresize_client->area.y,
152 (cancel ? start_cw : cur_x),
153 (cancel ? start_ch : cur_y), TRUE, TRUE);
156 moveresize_in_progress = FALSE;
157 moveresize_client = NULL;
160 static void do_move(gboolean resist)
163 resist_move_windows(moveresize_client, &cur_x, &cur_y);
164 resist_move_monitors(moveresize_client, &cur_x, &cur_y);
166 /* get where the client should be */
167 frame_frame_gravity(moveresize_client->frame, &cur_x, &cur_y);
168 client_configure(moveresize_client, OB_CORNER_TOPLEFT, cur_x, cur_y,
169 start_cw, start_ch, TRUE, FALSE);
172 static void do_resize(gboolean resist)
174 /* resist_size_* needs the frame size */
175 cur_x += moveresize_client->frame->size.left +
176 moveresize_client->frame->size.right;
177 cur_y += moveresize_client->frame->size.top +
178 moveresize_client->frame->size.bottom;
181 resist_size_windows(moveresize_client, &cur_x, &cur_y, lockcorner);
182 resist_size_monitors(moveresize_client, &cur_x, &cur_y, lockcorner);
184 cur_x -= moveresize_client->frame->size.left +
185 moveresize_client->frame->size.right;
186 cur_y -= moveresize_client->frame->size.top +
187 moveresize_client->frame->size.bottom;
189 client_configure(moveresize_client, lockcorner,
190 moveresize_client->area.x, moveresize_client->area.y,
191 cur_x, cur_y, TRUE, FALSE);
193 /* this would be better with a fixed width font ... XXX can do it better
194 if there are 2 text boxes */
195 if (moveresize_client->size_inc.width > 1 ||
196 moveresize_client->size_inc.height > 1)
197 popup_coords(moveresize_client, "%d x %d",
198 moveresize_client->logical_size.width,
199 moveresize_client->logical_size.height);
202 void moveresize_event(XEvent *e)
204 g_assert(moveresize_in_progress);
206 if (e->type == ButtonPress) {
208 start_x = e->xbutton.x_root;
209 start_y = e->xbutton.y_root;
210 button = e->xbutton.button; /* this will end it now */
212 } else if (e->type == ButtonRelease) {
213 if (!button || e->xbutton.button == button) {
214 moveresize_end(FALSE);
216 } else if (e->type == MotionNotify) {
218 cur_x = start_cx + e->xmotion.x_root - start_x;
219 cur_y = start_cy + e->xmotion.y_root - start_y;
222 if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
223 cur_x = start_cw - (e->xmotion.x_root - start_x);
224 cur_y = start_ch - (e->xmotion.y_root - start_y);
225 lockcorner = OB_CORNER_BOTTOMRIGHT;
226 } else if (corner == prop_atoms.net_wm_moveresize_size_top) {
228 cur_y = start_ch - (e->xmotion.y_root - start_y);
229 lockcorner = OB_CORNER_BOTTOMRIGHT;
230 } else if (corner == prop_atoms.net_wm_moveresize_size_topright) {
231 cur_x = start_cw + (e->xmotion.x_root - start_x);
232 cur_y = start_ch - (e->xmotion.y_root - start_y);
233 lockcorner = OB_CORNER_BOTTOMLEFT;
234 } else if (corner == prop_atoms.net_wm_moveresize_size_right) {
235 cur_x = start_cw + (e->xmotion.x_root - start_x);
237 lockcorner = OB_CORNER_BOTTOMLEFT;
239 prop_atoms.net_wm_moveresize_size_bottomright) {
240 cur_x = start_cw + (e->xmotion.x_root - start_x);
241 cur_y = start_ch + (e->xmotion.y_root - start_y);
242 lockcorner = OB_CORNER_TOPLEFT;
243 } else if (corner == prop_atoms.net_wm_moveresize_size_bottom) {
245 cur_y = start_ch + (e->xmotion.y_root - start_y);
246 lockcorner = OB_CORNER_TOPLEFT;
248 prop_atoms.net_wm_moveresize_size_bottomleft) {
249 cur_x = start_cw - (e->xmotion.x_root - start_x);
250 cur_y = start_ch + (e->xmotion.y_root - start_y);
251 lockcorner = OB_CORNER_TOPRIGHT;
252 } else if (corner == prop_atoms.net_wm_moveresize_size_left) {
253 cur_x = start_cw - (e->xmotion.x_root - start_x);
255 lockcorner = OB_CORNER_TOPRIGHT;
256 } else if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
257 cur_x = start_cw + (e->xmotion.x_root - start_x);
258 cur_y = start_ch + (e->xmotion.y_root - start_y);
259 lockcorner = OB_CORNER_TOPLEFT;
261 g_assert_not_reached();
265 } else if (e->type == KeyPress) {
266 if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE))
267 moveresize_end(TRUE);
268 else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN))
269 moveresize_end(FALSE);
271 if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
272 int dx = 0, dy = 0, ox = cur_x, oy = cur_y;
274 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
275 dx = MAX(4, moveresize_client->size_inc.width);
276 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
277 dx = -MAX(4, moveresize_client->size_inc.width);
278 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
279 dy = MAX(4, moveresize_client->size_inc.height);
280 else if (e->xkey.keycode == ob_keycode(OB_KEY_UP))
281 dy = -MAX(4, moveresize_client->size_inc.height);
287 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
288 /* steal the motion events this causes */
289 XSync(ob_display, FALSE);
292 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
297 /* because the cursor moves even though the window does
298 not nessesarily (resistance), this adjusts where the curor
299 thinks it started so that it keeps up with where the window
301 start_x += dx - (cur_x - ox);
302 start_y += dy - (cur_y - oy);
303 } else if (corner == prop_atoms.net_wm_moveresize_move_keyboard) {
304 int dx = 0, dy = 0, ox = cur_x, oy = cur_y;
305 int opx, px, opy, py;
307 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
309 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
311 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
313 else if (e->xkey.keycode == ob_keycode(OB_KEY_UP))
320 screen_pointer_pos(&opx, &opy);
321 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
322 /* steal the motion events this causes */
323 XSync(ob_display, FALSE);
326 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
328 screen_pointer_pos(&px, &py);
332 /* because the cursor moves even though the window does
333 not nessesarily (resistance), this adjusts where the curor
334 thinks it started so that it keeps up with where the window
336 start_x += (px - opx) - (cur_x - ox);
337 start_y += (py - opy) - (cur_y - oy);