]> Dogcows Code - chaz/openbox/blob - openbox/moveresize.c
dont assert if a moveresize is started while one is in progress. apps could do this...
[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 ObPopup *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 if (moveresize_in_progress)
49 moveresize_end(FALSE);
50 client_remove_destructor(client_dest);
51 }
52
53 popup_free(popup);
54 popup = NULL;
55 }
56
57 static void popup_coords(ObClient *c, char *format, int a, int b)
58 {
59 char *text;
60
61 text = g_strdup_printf(format, a, b);
62 popup_position(popup, CenterGravity,
63 c->frame->area.x + c->frame->size.left +
64 c->area.width / 2,
65 c->frame->area.y + c->frame->size.top +
66 c->area.height / 2);
67 popup_show(popup, text);
68 g_free(text);
69 }
70
71 void moveresize_start(ObClient *c, int x, int y, guint b, guint32 cnr)
72 {
73 ObCursor cur;
74
75 if (moveresize_in_progress || !c->frame->visible)
76 return;
77
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;
88 start_x = x;
89 start_y = y;
90 corner = cnr;
91 button = b;
92
93 /*
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);
99 */
100
101 if (corner == prop_atoms.net_wm_moveresize_move ||
102 corner == prop_atoms.net_wm_moveresize_move_keyboard) {
103 cur_x = start_cx;
104 cur_y = start_cy;
105 moving = TRUE;
106 } else {
107 cur_x = start_cw;
108 cur_y = start_ch;
109 moving = FALSE;
110 }
111
112 moveresize_in_progress = TRUE;
113
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;
136 else
137 g_assert_not_reached();
138
139 grab_pointer(TRUE, cur);
140 grab_keyboard(TRUE);
141 }
142
143 void moveresize_end(gboolean cancel)
144 {
145 grab_keyboard(FALSE);
146 grab_pointer(FALSE, OB_CURSOR_NONE);
147
148 popup_hide(popup);
149
150 if (moving) {
151 client_move(moveresize_client,
152 (cancel ? start_cx : cur_x),
153 (cancel ? start_cy : cur_y));
154 } else {
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);
160 }
161
162 moveresize_in_progress = FALSE;
163 moveresize_client = NULL;
164 }
165
166 static void do_move(gboolean resist)
167 {
168 if (resist)
169 resist_move_windows(moveresize_client, &cur_x, &cur_y);
170 resist_move_monitors(moveresize_client, &cur_x, &cur_y);
171
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);
177 }
178
179 static void do_resize(gboolean resist)
180 {
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;
186
187 if (resist)
188 resist_size_windows(moveresize_client, &cur_x, &cur_y, lockcorner);
189 resist_size_monitors(moveresize_client, &cur_x, &cur_y, lockcorner);
190
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;
195
196 client_configure(moveresize_client, lockcorner,
197 moveresize_client->area.x, moveresize_client->area.y,
198 cur_x, cur_y, TRUE, FALSE);
199
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);
207 }
208
209 void moveresize_event(XEvent *e)
210 {
211 g_assert(moveresize_in_progress);
212
213 if (e->type == ButtonPress) {
214 if (!button) {
215 start_x = e->xbutton.x_root;
216 start_y = e->xbutton.y_root;
217 button = e->xbutton.button; /* this will end it now */
218 }
219 } else if (e->type == ButtonRelease) {
220 if (!button || e->xbutton.button == button) {
221 moveresize_end(FALSE);
222 }
223 } else if (e->type == MotionNotify) {
224 if (moving) {
225 cur_x = start_cx + e->xmotion.x_root - start_x;
226 cur_y = start_cy + e->xmotion.y_root - start_y;
227 do_move(TRUE);
228 } else {
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) {
234 cur_x = start_cw;
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);
243 cur_y = start_ch;
244 lockcorner = OB_CORNER_BOTTOMLEFT;
245 } else if (corner ==
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) {
251 cur_x = start_cw;
252 cur_y = start_ch + (e->xmotion.y_root - start_y);
253 lockcorner = OB_CORNER_TOPLEFT;
254 } else if (corner ==
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);
261 cur_y = start_ch;
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;
267 } else
268 g_assert_not_reached();
269
270 do_resize(TRUE);
271 }
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);
277 else {
278 if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
279 int dx = 0, dy = 0, ox = cur_x, oy = cur_y;
280
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);
289 else
290 return;
291
292 cur_x += dx;
293 cur_y += dy;
294 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
295 /* steal the motion events this causes */
296 XSync(ob_display, FALSE);
297 {
298 XEvent ce;
299 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
300 }
301
302 do_resize(FALSE);
303
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
307 actually is */
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;
313
314 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
315 dx = 4;
316 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
317 dx = -4;
318 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
319 dy = 4;
320 else if (e->xkey.keycode == ob_keycode(OB_KEY_UP))
321 dy = -4;
322 else
323 return;
324
325 cur_x += dx;
326 cur_y += dy;
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);
331 {
332 XEvent ce;
333 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
334 }
335 screen_pointer_pos(&px, &py);
336
337 do_move(FALSE);
338
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
342 actually is */
343 start_x += (px - opx) - (cur_x - ox);
344 start_y += (py - opy) - (cur_y - oy);
345 }
346 }
347 }
348 }
This page took 0.049134 seconds and 5 git commands to generate.