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