]> Dogcows Code - chaz/openbox/blob - openbox/moveresize.c
fix a mem leak, and make suer the menus arent visible when they are modified
[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 g_assert(!moveresize_in_progress);
76
77 if (!c->frame->visible)
78 return;
79
80 moveresize_client = c;
81 start_cx = c->frame->area.x;
82 start_cy = c->frame->area.y;
83 /* these adjustments for the size_inc make resizing a terminal more
84 friendly. you essentially start the resize in the middle of the
85 increment instead of at 0, so you have to move half an increment
86 either way instead of a full increment one and 1 px the other. and this
87 is one large mother fucking comment. */
88 start_cw = c->area.width + c->size_inc.width / 2;
89 start_ch = c->area.height + c->size_inc.height / 2;
90 start_x = x;
91 start_y = y;
92 corner = cnr;
93 button = b;
94
95 /*
96 have to change start_cx and start_cy if going to do this..
97 if (corner == prop_atoms.net_wm_moveresize_move_keyboard ||
98 corner == prop_atoms.net_wm_moveresize_size_keyboard)
99 XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
100 c->area.width / 2, c->area.height / 2);
101 */
102
103 if (corner == prop_atoms.net_wm_moveresize_move ||
104 corner == prop_atoms.net_wm_moveresize_move_keyboard) {
105 cur_x = start_cx;
106 cur_y = start_cy;
107 moving = TRUE;
108 } else {
109 cur_x = start_cw;
110 cur_y = start_ch;
111 moving = FALSE;
112 }
113
114 moveresize_in_progress = TRUE;
115
116 if (corner == prop_atoms.net_wm_moveresize_size_topleft)
117 cur = OB_CURSOR_NORTHWEST;
118 else if (corner == prop_atoms.net_wm_moveresize_size_top)
119 cur = OB_CURSOR_NORTH;
120 else if (corner == prop_atoms.net_wm_moveresize_size_topright)
121 cur = OB_CURSOR_NORTHEAST;
122 else if (corner == prop_atoms.net_wm_moveresize_size_right)
123 cur = OB_CURSOR_EAST;
124 else if (corner == prop_atoms.net_wm_moveresize_size_bottomright)
125 cur = OB_CURSOR_SOUTHEAST;
126 else if (corner == prop_atoms.net_wm_moveresize_size_bottom)
127 cur = OB_CURSOR_SOUTH;
128 else if (corner == prop_atoms.net_wm_moveresize_size_bottomleft)
129 cur = OB_CURSOR_SOUTHWEST;
130 else if (corner == prop_atoms.net_wm_moveresize_size_left)
131 cur = OB_CURSOR_WEST;
132 else if (corner == prop_atoms.net_wm_moveresize_size_keyboard)
133 cur = OB_CURSOR_SOUTHEAST;
134 else if (corner == prop_atoms.net_wm_moveresize_move)
135 cur = OB_CURSOR_MOVE;
136 else if (corner == prop_atoms.net_wm_moveresize_move_keyboard)
137 cur = OB_CURSOR_MOVE;
138 else
139 g_assert_not_reached();
140
141 grab_pointer(TRUE, cur);
142 grab_keyboard(TRUE);
143 }
144
145 void moveresize_end(gboolean cancel)
146 {
147 grab_keyboard(FALSE);
148 grab_pointer(FALSE, OB_CURSOR_NONE);
149
150 popup_hide(popup);
151
152 if (moving) {
153 client_move(moveresize_client,
154 (cancel ? start_cx : cur_x),
155 (cancel ? start_cy : cur_y));
156 } else {
157 client_configure(moveresize_client, lockcorner,
158 moveresize_client->area.x,
159 moveresize_client->area.y,
160 (cancel ? start_cw : cur_x),
161 (cancel ? start_ch : cur_y), TRUE, TRUE);
162 }
163
164 moveresize_in_progress = FALSE;
165 moveresize_client = NULL;
166 }
167
168 static void do_move(gboolean resist)
169 {
170 if (resist)
171 resist_move_windows(moveresize_client, &cur_x, &cur_y);
172 resist_move_monitors(moveresize_client, &cur_x, &cur_y);
173
174 /* get where the client should be */
175 frame_frame_gravity(moveresize_client->frame, &cur_x, &cur_y);
176 client_configure(moveresize_client, OB_CORNER_TOPLEFT, cur_x, cur_y,
177 moveresize_client->area.width,
178 moveresize_client->area.height, TRUE, FALSE);
179 }
180
181 static void do_resize(gboolean resist)
182 {
183 /* resist_size_* needs the frame size */
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;
188
189 if (resist)
190 resist_size_windows(moveresize_client, &cur_x, &cur_y, lockcorner);
191 resist_size_monitors(moveresize_client, &cur_x, &cur_y, lockcorner);
192
193 cur_x -= moveresize_client->frame->size.left +
194 moveresize_client->frame->size.right;
195 cur_y -= moveresize_client->frame->size.top +
196 moveresize_client->frame->size.bottom;
197
198 client_configure(moveresize_client, lockcorner,
199 moveresize_client->area.x, moveresize_client->area.y,
200 cur_x, cur_y, TRUE, FALSE);
201
202 /* this would be better with a fixed width font ... XXX can do it better
203 if there are 2 text boxes */
204 if (moveresize_client->size_inc.width > 1 ||
205 moveresize_client->size_inc.height > 1)
206 popup_coords(moveresize_client, "%d x %d",
207 moveresize_client->logical_size.width,
208 moveresize_client->logical_size.height);
209 }
210
211 void moveresize_event(XEvent *e)
212 {
213 g_assert(moveresize_in_progress);
214
215 if (e->type == ButtonPress) {
216 if (!button) {
217 start_x = e->xbutton.x_root;
218 start_y = e->xbutton.y_root;
219 button = e->xbutton.button; /* this will end it now */
220 }
221 } else if (e->type == ButtonRelease) {
222 if (!button || e->xbutton.button == button) {
223 moveresize_end(FALSE);
224 }
225 } else if (e->type == MotionNotify) {
226 if (moving) {
227 cur_x = start_cx + e->xmotion.x_root - start_x;
228 cur_y = start_cy + e->xmotion.y_root - start_y;
229 do_move(TRUE);
230 } else {
231 if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
232 cur_x = start_cw - (e->xmotion.x_root - start_x);
233 cur_y = start_ch - (e->xmotion.y_root - start_y);
234 lockcorner = OB_CORNER_BOTTOMRIGHT;
235 } else if (corner == prop_atoms.net_wm_moveresize_size_top) {
236 cur_x = start_cw;
237 cur_y = start_ch - (e->xmotion.y_root - start_y);
238 lockcorner = OB_CORNER_BOTTOMRIGHT;
239 } else if (corner == prop_atoms.net_wm_moveresize_size_topright) {
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_BOTTOMLEFT;
243 } else if (corner == prop_atoms.net_wm_moveresize_size_right) {
244 cur_x = start_cw + (e->xmotion.x_root - start_x);
245 cur_y = start_ch;
246 lockcorner = OB_CORNER_BOTTOMLEFT;
247 } else if (corner ==
248 prop_atoms.net_wm_moveresize_size_bottomright) {
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_TOPLEFT;
252 } else if (corner == prop_atoms.net_wm_moveresize_size_bottom) {
253 cur_x = start_cw;
254 cur_y = start_ch + (e->xmotion.y_root - start_y);
255 lockcorner = OB_CORNER_TOPLEFT;
256 } else if (corner ==
257 prop_atoms.net_wm_moveresize_size_bottomleft) {
258 cur_x = start_cw - (e->xmotion.x_root - start_x);
259 cur_y = start_ch + (e->xmotion.y_root - start_y);
260 lockcorner = OB_CORNER_TOPRIGHT;
261 } else if (corner == prop_atoms.net_wm_moveresize_size_left) {
262 cur_x = start_cw - (e->xmotion.x_root - start_x);
263 cur_y = start_ch;
264 lockcorner = OB_CORNER_TOPRIGHT;
265 } else if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
266 cur_x = start_cw + (e->xmotion.x_root - start_x);
267 cur_y = start_ch + (e->xmotion.y_root - start_y);
268 lockcorner = OB_CORNER_TOPLEFT;
269 } else
270 g_assert_not_reached();
271
272 do_resize(TRUE);
273 }
274 } else if (e->type == KeyPress) {
275 if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE))
276 moveresize_end(TRUE);
277 else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN))
278 moveresize_end(FALSE);
279 else {
280 if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
281 int dx = 0, dy = 0, ox = cur_x, oy = cur_y;
282
283 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
284 dx = MAX(4, moveresize_client->size_inc.width);
285 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
286 dx = -MAX(4, moveresize_client->size_inc.width);
287 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
288 dy = MAX(4, moveresize_client->size_inc.height);
289 else if (e->xkey.keycode == ob_keycode(OB_KEY_UP))
290 dy = -MAX(4, moveresize_client->size_inc.height);
291 else
292 return;
293
294 cur_x += dx;
295 cur_y += dy;
296 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
297 /* steal the motion events this causes */
298 XSync(ob_display, FALSE);
299 {
300 XEvent ce;
301 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
302 }
303
304 do_resize(FALSE);
305
306 /* because the cursor moves even though the window does
307 not nessesarily (resistance), this adjusts where the curor
308 thinks it started so that it keeps up with where the window
309 actually is */
310 start_x += dx - (cur_x - ox);
311 start_y += dy - (cur_y - oy);
312 } else if (corner == prop_atoms.net_wm_moveresize_move_keyboard) {
313 int dx = 0, dy = 0, ox = cur_x, oy = cur_y;
314 int opx, px, opy, py;
315
316 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
317 dx = 4;
318 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
319 dx = -4;
320 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
321 dy = 4;
322 else if (e->xkey.keycode == ob_keycode(OB_KEY_UP))
323 dy = -4;
324 else
325 return;
326
327 cur_x += dx;
328 cur_y += dy;
329 screen_pointer_pos(&opx, &opy);
330 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
331 /* steal the motion events this causes */
332 XSync(ob_display, FALSE);
333 {
334 XEvent ce;
335 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
336 }
337 screen_pointer_pos(&px, &py);
338
339 do_move(FALSE);
340
341 /* because the cursor moves even though the window does
342 not nessesarily (resistance), this adjusts where the curor
343 thinks it started so that it keeps up with where the window
344 actually is */
345 start_x += (px - opx) - (cur_x - ox);
346 start_y += (py - opy) - (cur_y - oy);
347 }
348 }
349 }
350 }
This page took 0.051342 seconds and 4 git commands to generate.