]> Dogcows Code - chaz/openbox/blob - openbox/moveresize.c
when the client for an interactive action is closed, kill the action
[chaz/openbox] / openbox / moveresize.c
1 #include "grab.h"
2 #include "framerender.h"
3 #include "screen.h"
4 #include "prop.h"
5 #include "client.h"
6 #include "frame.h"
7 #include "openbox.h"
8 #include "resist.h"
9 #include "popup.h"
10 #include "moveresize.h"
11 #include "config.h"
12 #include "render/render.h"
13 #include "render/theme.h"
14
15 #include <X11/Xlib.h>
16 #include <glib.h>
17
18 gboolean moveresize_in_progress = FALSE;
19 ObClient *moveresize_client = NULL;
20
21 static gboolean moving = FALSE; /* TRUE - moving, FALSE - resizing */
22
23 static int start_x, start_y, start_cx, start_cy, start_cw, start_ch;
24 static int cur_x, cur_y;
25 static guint button;
26 static guint32 corner;
27 static ObCorner lockcorner;
28
29 static Popup *popup = NULL;
30
31 static void client_dest(gpointer client)
32 {
33 if (moveresize_client == client)
34 moveresize_end(TRUE);
35 }
36
37 void moveresize_startup(gboolean reconfig)
38 {
39 popup = popup_new(FALSE);
40
41 if (!reconfig)
42 client_add_destructor(client_dest);
43 }
44
45 void moveresize_shutdown(gboolean reconfig)
46 {
47 if (!reconfig)
48 client_remove_destructor(client_dest);
49
50 popup_free(popup);
51 popup = NULL;
52 }
53
54 static void popup_coords(ObClient *c, char *format, int a, int b)
55 {
56 char *text;
57
58 text = g_strdup_printf(format, a, b);
59 popup_position(popup, CenterGravity,
60 c->frame->area.x + c->frame->size.left +
61 c->area.width / 2,
62 c->frame->area.y + c->frame->size.top +
63 c->area.height / 2);
64 popup_show(popup, text, NULL);
65 g_free(text);
66 }
67
68 void moveresize_start(ObClient *c, int x, int y, guint b, guint32 cnr)
69 {
70 ObCursor cur;
71
72 g_assert(!moveresize_in_progress);
73
74 if (!c->frame->visible)
75 return;
76
77 moveresize_client = c;
78 start_cx = c->frame->area.x;
79 start_cy = c->frame->area.y;
80 /* these adjustments for the size_inc make resizing a terminal more
81 friendly. you essentially start the resize in the middle of the
82 increment instead of at 0, so you have to move half an increment
83 either way instead of a full increment one and 1 px the other. and this
84 is one large mother fucking comment. */
85 start_cw = c->area.width + c->size_inc.width / 2;
86 start_ch = c->area.height + c->size_inc.height / 2;
87 start_x = x;
88 start_y = y;
89 corner = cnr;
90 button = b;
91
92 /*
93 have to change start_cx and start_cy if going to do this..
94 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
95 corner == prop_atoms.net_wm_moveresize_size_keyboard)
96 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
97 c->area.width / 2, c->area.height / 2);
98 */
99
100 if (corner == prop_atoms.net_wm_moveresize_move ||
101 corner == prop_atoms.net_wm_moveresize_move_keyboard) {
102 cur_x = start_cx;
103 cur_y = start_cy;
104 moving = TRUE;
105 } else {
106 cur_x = start_cw;
107 cur_y = start_ch;
108 moving = FALSE;
109 }
110
111 moveresize_in_progress = TRUE;
112
113 if (corner == prop_atoms.net_wm_moveresize_size_topleft)
114 cur = OB_CURSOR_NORTHWEST;
115 else if (corner == prop_atoms.net_wm_moveresize_size_top)
116 cur = OB_CURSOR_NORTH;
117 else if (corner == prop_atoms.net_wm_moveresize_size_topright)
118 cur = OB_CURSOR_NORTHEAST;
119 else if (corner == prop_atoms.net_wm_moveresize_size_right)
120 cur = OB_CURSOR_EAST;
121 else if (corner == prop_atoms.net_wm_moveresize_size_bottomright)
122 cur = OB_CURSOR_SOUTHEAST;
123 else if (corner == prop_atoms.net_wm_moveresize_size_bottom)
124 cur = OB_CURSOR_SOUTH;
125 else if (corner == prop_atoms.net_wm_moveresize_size_bottomleft)
126 cur = OB_CURSOR_SOUTHWEST;
127 else if (corner == prop_atoms.net_wm_moveresize_size_left)
128 cur = OB_CURSOR_WEST;
129 else if (corner == prop_atoms.net_wm_moveresize_size_keyboard)
130 cur = OB_CURSOR_SOUTHEAST;
131 else if (corner == prop_atoms.net_wm_moveresize_move)
132 cur = OB_CURSOR_MOVE;
133 else if (corner == prop_atoms.net_wm_moveresize_move_keyboard)
134 cur = OB_CURSOR_MOVE;
135 else
136 g_assert_not_reached();
137
138 grab_pointer(TRUE, cur);
139 grab_keyboard(TRUE);
140 }
141
142 void moveresize_end(gboolean cancel)
143 {
144 grab_keyboard(FALSE);
145 grab_pointer(FALSE, OB_CURSOR_NONE);
146
147 popup_hide(popup);
148
149 if (moving) {
150 client_move(moveresize_client,
151 (cancel ? start_cx : cur_x),
152 (cancel ? start_cy : cur_y));
153 } else {
154 client_configure(moveresize_client, lockcorner,
155 moveresize_client->area.x,
156 moveresize_client->area.y,
157 (cancel ? start_cw : cur_x),
158 (cancel ? start_ch : cur_y), TRUE, TRUE);
159 }
160
161 moveresize_in_progress = FALSE;
162 moveresize_client = NULL;
163 }
164
165 static void do_move(gboolean resist)
166 {
167 if (resist)
168 resist_move_windows(moveresize_client, &cur_x, &cur_y);
169 resist_move_monitors(moveresize_client, &cur_x, &cur_y);
170
171 /* get where the client should be */
172 frame_frame_gravity(moveresize_client->frame, &cur_x, &cur_y);
173 client_configure(moveresize_client, OB_CORNER_TOPLEFT, cur_x, cur_y,
174 moveresize_client->area.width,
175 moveresize_client->area.height, TRUE, FALSE);
176 }
177
178 static void do_resize(gboolean resist)
179 {
180 /* resist_size_* needs the frame size */
181 cur_x += moveresize_client->frame->size.left +
182 moveresize_client->frame->size.right;
183 cur_y += moveresize_client->frame->size.top +
184 moveresize_client->frame->size.bottom;
185
186 if (resist)
187 resist_size_windows(moveresize_client, &cur_x, &cur_y, lockcorner);
188 resist_size_monitors(moveresize_client, &cur_x, &cur_y, lockcorner);
189
190 cur_x -= moveresize_client->frame->size.left +
191 moveresize_client->frame->size.right;
192 cur_y -= moveresize_client->frame->size.top +
193 moveresize_client->frame->size.bottom;
194
195 client_configure(moveresize_client, lockcorner,
196 moveresize_client->area.x, moveresize_client->area.y,
197 cur_x, cur_y, TRUE, FALSE);
198
199 /* this would be better with a fixed width font ... XXX can do it better
200 if there are 2 text boxes */
201 if (moveresize_client->size_inc.width > 1 ||
202 moveresize_client->size_inc.height > 1)
203 popup_coords(moveresize_client, "%d x %d",
204 moveresize_client->logical_size.width,
205 moveresize_client->logical_size.height);
206 }
207
208 void moveresize_event(XEvent *e)
209 {
210 g_assert(moveresize_in_progress);
211
212 if (e->type == ButtonPress) {
213 if (!button) {
214 start_x = e->xbutton.x_root;
215 start_y = e->xbutton.y_root;
216 button = e->xbutton.button; /* this will end it now */
217 }
218 } else if (e->type == ButtonRelease) {
219 if (!button || e->xbutton.button == button) {
220 moveresize_end(FALSE);
221 }
222 } else if (e->type == MotionNotify) {
223 if (moving) {
224 cur_x = start_cx + e->xmotion.x_root - start_x;
225 cur_y = start_cy + e->xmotion.y_root - start_y;
226 do_move(TRUE);
227 } else {
228 if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
229 cur_x = start_cw - (e->xmotion.x_root - start_x);
230 cur_y = start_ch - (e->xmotion.y_root - start_y);
231 lockcorner = OB_CORNER_BOTTOMRIGHT;
232 } else if (corner == prop_atoms.net_wm_moveresize_size_top) {
233 cur_x = start_cw;
234 cur_y = start_ch - (e->xmotion.y_root - start_y);
235 lockcorner = OB_CORNER_BOTTOMRIGHT;
236 } else if (corner == prop_atoms.net_wm_moveresize_size_topright) {
237 cur_x = start_cw + (e->xmotion.x_root - start_x);
238 cur_y = start_ch - (e->xmotion.y_root - start_y);
239 lockcorner = OB_CORNER_BOTTOMLEFT;
240 } else if (corner == prop_atoms.net_wm_moveresize_size_right) {
241 cur_x = start_cw + (e->xmotion.x_root - start_x);
242 cur_y = start_ch;
243 lockcorner = OB_CORNER_BOTTOMLEFT;
244 } else if (corner ==
245 prop_atoms.net_wm_moveresize_size_bottomright) {
246 cur_x = start_cw + (e->xmotion.x_root - start_x);
247 cur_y = start_ch + (e->xmotion.y_root - start_y);
248 lockcorner = OB_CORNER_TOPLEFT;
249 } else if (corner == prop_atoms.net_wm_moveresize_size_bottom) {
250 cur_x = start_cw;
251 cur_y = start_ch + (e->xmotion.y_root - start_y);
252 lockcorner = OB_CORNER_TOPLEFT;
253 } else if (corner ==
254 prop_atoms.net_wm_moveresize_size_bottomleft) {
255 cur_x = start_cw - (e->xmotion.x_root - start_x);
256 cur_y = start_ch + (e->xmotion.y_root - start_y);
257 lockcorner = OB_CORNER_TOPRIGHT;
258 } else if (corner == prop_atoms.net_wm_moveresize_size_left) {
259 cur_x = start_cw - (e->xmotion.x_root - start_x);
260 cur_y = start_ch;
261 lockcorner = OB_CORNER_TOPRIGHT;
262 } else if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
263 cur_x = start_cw + (e->xmotion.x_root - start_x);
264 cur_y = start_ch + (e->xmotion.y_root - start_y);
265 lockcorner = OB_CORNER_TOPLEFT;
266 } else
267 g_assert_not_reached();
268
269 do_resize(TRUE);
270 }
271 } else if (e->type == KeyPress) {
272 if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE))
273 moveresize_end(TRUE);
274 else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN))
275 moveresize_end(FALSE);
276 else {
277 if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
278 int dx = 0, dy = 0, ox = cur_x, oy = cur_y;
279
280 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
281 dx = MAX(4, moveresize_client->size_inc.width);
282 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
283 dx = -MAX(4, moveresize_client->size_inc.width);
284 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
285 dy = MAX(4, moveresize_client->size_inc.height);
286 else if (e->xkey.keycode == ob_keycode(OB_KEY_UP))
287 dy = -MAX(4, moveresize_client->size_inc.height);
288 else
289 return;
290
291 cur_x += dx;
292 cur_y += dy;
293 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
294 /* steal the motion events this causes */
295 XSync(ob_display, FALSE);
296 {
297 XEvent ce;
298 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
299 }
300
301 do_resize(FALSE);
302
303 /* because the cursor moves even though the window does
304 not nessesarily (resistance), this adjusts where the curor
305 thinks it started so that it keeps up with where the window
306 actually is */
307 start_x += dx - (cur_x - ox);
308 start_y += dy - (cur_y - oy);
309 } else if (corner == prop_atoms.net_wm_moveresize_move_keyboard) {
310 int dx = 0, dy = 0, ox = cur_x, oy = cur_y;
311 int opx, px, opy, py;
312
313 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
314 dx = 4;
315 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
316 dx = -4;
317 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
318 dy = 4;
319 else if (e->xkey.keycode == ob_keycode(OB_KEY_UP))
320 dy = -4;
321 else
322 return;
323
324 cur_x += dx;
325 cur_y += dy;
326 screen_pointer_pos(&opx, &opy);
327 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
328 /* steal the motion events this causes */
329 XSync(ob_display, FALSE);
330 {
331 XEvent ce;
332 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
333 }
334 screen_pointer_pos(&px, &py);
335
336 do_move(FALSE);
337
338 /* because the cursor moves even though the window does
339 not nessesarily (resistance), this adjusts where the curor
340 thinks it started so that it keeps up with where the window
341 actually is */
342 start_x += (px - opx) - (cur_x - ox);
343 start_y += (py - opy) - (cur_y - oy);
344 }
345 }
346 }
347 }
This page took 0.049293 seconds and 4 git commands to generate.