]> Dogcows Code - chaz/openbox/blob - openbox/moveresize.c
only show resize popups for clients with size increments. no move popup at all. waste...
[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(ObClient *c)
32 {
33 if (moveresize_client == c)
34 moveresize_end(TRUE);
35 }
36
37 void moveresize_startup()
38 {
39 popup = popup_new(FALSE);
40
41 client_add_destructor(client_dest);
42 }
43
44 void moveresize_shutdown()
45 {
46 client_remove_destructor(client_dest);
47
48 popup_free(popup);
49 popup = NULL;
50 }
51
52 static void popup_coords(ObClient *c, char *format, int a, int b)
53 {
54 char *text;
55
56 text = g_strdup_printf(format, a, b);
57 popup_position(popup, CenterGravity,
58 c->frame->area.x + c->frame->size.left +
59 c->area.width / 2,
60 c->frame->area.y + c->frame->size.top +
61 c->area.height / 2);
62 popup_show(popup, text, NULL);
63 g_free(text);
64 }
65
66 void moveresize_start(ObClient *c, int x, int y, guint b, guint32 cnr)
67 {
68 ObCursor cur;
69
70 g_assert(!moveresize_in_progress);
71
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;
82 start_x = x;
83 start_y = y;
84 corner = cnr;
85 button = b;
86
87 /*
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);
93 */
94
95 if (corner == prop_atoms.net_wm_moveresize_move ||
96 corner == prop_atoms.net_wm_moveresize_move_keyboard) {
97 cur_x = start_cx;
98 cur_y = start_cy;
99 moving = TRUE;
100 } else {
101 cur_x = start_cw;
102 cur_y = start_ch;
103 moving = FALSE;
104 }
105
106 moveresize_in_progress = TRUE;
107
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;
130 else
131 g_assert_not_reached();
132
133 grab_pointer(TRUE, cur);
134 grab_keyboard(TRUE);
135 }
136
137 void moveresize_end(gboolean cancel)
138 {
139 grab_keyboard(FALSE);
140 grab_pointer(FALSE, None);
141
142 popup_hide(popup);
143
144 if (moving) {
145 client_move(moveresize_client,
146 (cancel ? start_cx : cur_x),
147 (cancel ? start_cy : cur_y));
148 } else {
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);
154 }
155
156 moveresize_in_progress = FALSE;
157 moveresize_client = NULL;
158 }
159
160 static void do_move(gboolean resist)
161 {
162 if (resist)
163 resist_move_windows(moveresize_client, &cur_x, &cur_y);
164 resist_move_monitors(moveresize_client, &cur_x, &cur_y);
165
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);
170 }
171
172 static void do_resize(gboolean resist)
173 {
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;
179
180 if (resist)
181 resist_size_windows(moveresize_client, &cur_x, &cur_y, lockcorner);
182 resist_size_monitors(moveresize_client, &cur_x, &cur_y, lockcorner);
183
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 client_configure(moveresize_client, lockcorner,
190 moveresize_client->area.x, moveresize_client->area.y,
191 cur_x, cur_y, TRUE, FALSE);
192
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);
200 }
201
202 void moveresize_event(XEvent *e)
203 {
204 g_assert(moveresize_in_progress);
205
206 if (e->type == ButtonPress) {
207 if (!button) {
208 start_x = e->xbutton.x_root;
209 start_y = e->xbutton.y_root;
210 button = e->xbutton.button; /* this will end it now */
211 }
212 } else if (e->type == ButtonRelease) {
213 if (!button || e->xbutton.button == button) {
214 moveresize_end(FALSE);
215 }
216 } else if (e->type == MotionNotify) {
217 if (moving) {
218 cur_x = start_cx + e->xmotion.x_root - start_x;
219 cur_y = start_cy + e->xmotion.y_root - start_y;
220 do_move(TRUE);
221 } else {
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) {
227 cur_x = start_cw;
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);
236 cur_y = start_ch;
237 lockcorner = OB_CORNER_BOTTOMLEFT;
238 } else if (corner ==
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) {
244 cur_x = start_cw;
245 cur_y = start_ch + (e->xmotion.y_root - start_y);
246 lockcorner = OB_CORNER_TOPLEFT;
247 } else if (corner ==
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);
254 cur_y = start_ch;
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;
260 } else
261 g_assert_not_reached();
262
263 do_resize(TRUE);
264 }
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);
270 else {
271 if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
272 int dx = 0, dy = 0, ox = cur_x, oy = cur_y;
273
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);
282 else
283 return;
284
285 cur_x += dx;
286 cur_y += dy;
287 XWarpPointer(ob_display, None, None, 0, 0, 0, 0, dx, dy);
288 /* steal the motion events this causes */
289 XSync(ob_display, FALSE);
290 {
291 XEvent ce;
292 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
293 }
294
295 do_resize(FALSE);
296
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
300 actually is */
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;
306
307 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
308 dx = 4;
309 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
310 dx = -4;
311 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
312 dy = 4;
313 else if (e->xkey.keycode == ob_keycode(OB_KEY_UP))
314 dy = -4;
315 else
316 return;
317
318 cur_x += dx;
319 cur_y += dy;
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);
324 {
325 XEvent ce;
326 while (XCheckTypedEvent(ob_display, MotionNotify, &ce));
327 }
328 screen_pointer_pos(&px, &py);
329
330 do_move(FALSE);
331
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
335 actually is */
336 start_x += (px - opx) - (cur_x - ox);
337 start_y += (py - opy) - (cur_y - oy);
338 }
339 }
340 }
341 }
This page took 0.049278 seconds and 5 git commands to generate.