]> icculus.org git repositories - dana/openbox.git/blob - openbox/moveresize.c
fix whitespace
[dana/openbox.git] / 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 "dispatch.h"
8 #include "openbox.h"
9 #include "resist.h"
10 #include "popup.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 #define POPUP_X (10)
32 #define POPUP_Y (10)
33
34 void moveresize_startup()
35 {
36     XSetWindowAttributes attrib;
37
38     popup = popup_new(FALSE);
39     popup_size_to_string(popup, "W:  0000  W:  0000");
40
41     attrib.save_under = True;
42 }
43
44 void moveresize_shutdown()
45 {
46     popup_free(popup);
47     popup = NULL;
48 }
49
50 static void popup_coords(char *format, int a, int b)
51 {
52     char *text;
53     Rect *area;
54
55     text = g_strdup_printf(format, a, b);
56     area = screen_physical_area_monitor(0);
57     popup_position(popup, NorthWestGravity,
58                    POPUP_X + area->x, POPUP_Y + area->y);
59     popup_show(popup, text, NULL);
60     g_free(text);
61 }
62
63 void moveresize_start(ObClient *c, int x, int y, guint b, guint32 cnr)
64 {
65     ObCursor cur;
66
67     g_assert(!moveresize_in_progress);
68
69     moveresize_client = c;
70     start_cx = c->frame->area.x;
71     start_cy = c->frame->area.y;
72     start_cw = c->area.width;
73     start_ch = c->area.height;
74     start_x = x;
75     start_y = y;
76     corner = cnr;
77     button = b;
78
79     if (corner == prop_atoms.net_wm_moveresize_move ||
80         corner == prop_atoms.net_wm_moveresize_move_keyboard) {
81         cur_x = start_cx;
82         cur_y = start_cy;
83         moving = TRUE;
84     } else {
85         cur_x = start_cw;
86         cur_y = start_ch;
87         moving = FALSE;
88     }
89
90     moveresize_in_progress = TRUE;
91
92     if (corner == prop_atoms.net_wm_moveresize_size_topleft)
93         cur = OB_CURSOR_NORTHWEST;
94     else if (corner == prop_atoms.net_wm_moveresize_size_top)
95         cur = OB_CURSOR_NORTH;
96     else if (corner == prop_atoms.net_wm_moveresize_size_topright)
97         cur = OB_CURSOR_NORTHEAST;
98     else if (corner == prop_atoms.net_wm_moveresize_size_right)
99         cur = OB_CURSOR_EAST;
100     else if (corner == prop_atoms.net_wm_moveresize_size_bottomright)
101         cur = OB_CURSOR_SOUTHEAST;
102     else if (corner == prop_atoms.net_wm_moveresize_size_bottom)
103         cur = OB_CURSOR_SOUTH;
104     else if (corner == prop_atoms.net_wm_moveresize_size_bottomleft)
105         cur = OB_CURSOR_SOUTHWEST;
106     else if (corner == prop_atoms.net_wm_moveresize_size_left)
107         cur = OB_CURSOR_WEST;
108     else if (corner == prop_atoms.net_wm_moveresize_size_keyboard)
109         cur = OB_CURSOR_SOUTHEAST;
110     else if (corner == prop_atoms.net_wm_moveresize_move)
111         cur = OB_CURSOR_MOVE;
112     else if (corner == prop_atoms.net_wm_moveresize_move_keyboard)
113         cur = OB_CURSOR_MOVE;
114     else
115         g_assert_not_reached();
116
117     grab_pointer(TRUE, cur);
118     grab_keyboard(TRUE);
119 }
120
121 void moveresize_end(gboolean cancel)
122 {
123     grab_keyboard(FALSE);
124     grab_pointer(FALSE, None);
125
126     popup_hide(popup);
127
128     if (moving) {
129         client_configure(moveresize_client, OB_CORNER_TOPLEFT,
130                          (cancel ? start_cx : cur_x),
131                          (cancel ? start_cy : cur_y),
132                          start_cw, start_ch, TRUE, TRUE);
133     } else {
134         client_configure(moveresize_client, lockcorner,
135                          moveresize_client->area.x,
136                          moveresize_client->area.y,
137                          (cancel ? start_cw : cur_x),
138                          (cancel ? start_ch : cur_y), TRUE, TRUE);
139     }
140
141     moveresize_in_progress = FALSE;
142     moveresize_client = NULL;
143 }
144
145 static void do_move(gboolean resist)
146 {
147     Rect *a;
148
149     if (resist)
150         resist_move(moveresize_client, &cur_x, &cur_y);
151
152     dispatch_move(moveresize_client, &cur_x, &cur_y);
153
154     /* get where the client should be */
155     frame_frame_gravity(moveresize_client->frame, &cur_x, &cur_y);
156     client_configure(moveresize_client, OB_CORNER_TOPLEFT, cur_x, cur_y,
157                      start_cw, start_ch, TRUE, FALSE);
158
159     /* this would be better with a fixed width font ... XXX can do it better
160        if there are 2 text boxes */
161     a = screen_area(screen_desktop);
162     popup_coords("X:  %4d  Y:  %4d",
163                  moveresize_client->frame->area.x - a->x,
164                  moveresize_client->frame->area.y - a->y);
165 }
166
167 static void do_resize(gboolean resist)
168 {
169     /* dispatch_resize needs the frame size */
170     cur_x += moveresize_client->frame->size.left +
171         moveresize_client->frame->size.right;
172     cur_y += moveresize_client->frame->size.top +
173         moveresize_client->frame->size.bottom;
174
175     if (resist)
176         resist_size(moveresize_client, &cur_x, &cur_y, lockcorner);
177
178     dispatch_resize(moveresize_client, &cur_x, &cur_y, lockcorner);
179
180     cur_x -= moveresize_client->frame->size.left +
181         moveresize_client->frame->size.right;
182     cur_y -= moveresize_client->frame->size.top +
183         moveresize_client->frame->size.bottom;
184     
185     client_configure(moveresize_client, lockcorner, 
186                      moveresize_client->area.x, moveresize_client->area.y,
187                      cur_x, cur_y, TRUE, FALSE);
188
189     /* this would be better with a fixed width font ... XXX can do it better
190        if there are 2 text boxes */
191     popup_coords("W:  %4d  H:  %4d", moveresize_client->logical_size.width,
192                  moveresize_client->logical_size.height);
193 }
194
195 void moveresize_event(XEvent *e)
196 {
197     g_assert(moveresize_in_progress);
198
199     if (e->type == ButtonPress) {
200         if (!button) {
201             start_x = e->xbutton.x_root;
202             start_y = e->xbutton.y_root;
203             button = e->xbutton.button; /* this will end it now */
204         }
205     } else if (e->type == ButtonRelease) {
206         if (!button || e->xbutton.button == button) {
207             moveresize_end(FALSE);
208         }
209     } else if (e->type == MotionNotify) {
210         if (moving) {
211             cur_x = start_cx + e->xmotion.x_root - start_x;
212             cur_y = start_cy + e->xmotion.y_root - start_y;
213             do_move(TRUE);
214         } else {
215             if (corner == prop_atoms.net_wm_moveresize_size_topleft) {
216                 cur_x = start_cw - (e->xmotion.x_root - start_x);
217                 cur_y = start_ch - (e->xmotion.y_root - start_y);
218                 lockcorner = OB_CORNER_BOTTOMRIGHT;
219             } else if (corner == prop_atoms.net_wm_moveresize_size_top) {
220                 cur_x = start_cw;
221                 cur_y = start_ch - (e->xmotion.y_root - start_y);
222                 lockcorner = OB_CORNER_BOTTOMRIGHT;
223             } else if (corner == prop_atoms.net_wm_moveresize_size_topright) {
224                 cur_x = start_cw + (e->xmotion.x_root - start_x);
225                 cur_y = start_ch - (e->xmotion.y_root - start_y);
226                 lockcorner = OB_CORNER_BOTTOMLEFT;
227             } else if (corner == prop_atoms.net_wm_moveresize_size_right) { 
228                 cur_x = start_cw + (e->xmotion.x_root - start_x);
229                 cur_y = start_ch;
230                 lockcorner = OB_CORNER_BOTTOMLEFT;
231             } else if (corner ==
232                        prop_atoms.net_wm_moveresize_size_bottomright) {
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_TOPLEFT;
236             } else if (corner == prop_atoms.net_wm_moveresize_size_bottom) {
237                 cur_x = start_cw;
238                 cur_y = start_ch + (e->xmotion.y_root - start_y);
239                 lockcorner = OB_CORNER_TOPLEFT;
240             } else if (corner ==
241                        prop_atoms.net_wm_moveresize_size_bottomleft) {
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_TOPRIGHT;
245             } else if (corner == prop_atoms.net_wm_moveresize_size_left) {
246                 cur_x = start_cw - (e->xmotion.x_root - start_x);
247                 cur_y = start_ch;
248                 lockcorner = OB_CORNER_TOPRIGHT;
249             } else if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
250                 cur_x = start_cw + (e->xmotion.x_root - start_x);
251                 cur_y = start_ch + (e->xmotion.y_root - start_y);
252                 lockcorner = OB_CORNER_TOPLEFT;
253             } else
254                 g_assert_not_reached();
255
256             do_resize(TRUE);
257         }
258     } else if (e->type == KeyPress) {
259         if (e->xkey.keycode == ob_keycode(OB_KEY_ESCAPE))
260             moveresize_end(TRUE);
261         else if (e->xkey.keycode == ob_keycode(OB_KEY_RETURN))
262             moveresize_end(FALSE);
263         else {
264             if (corner == prop_atoms.net_wm_moveresize_size_keyboard) {
265                 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
266                     cur_x += MAX(4, moveresize_client->size_inc.width);
267                 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
268                     cur_x -= MAX(4, moveresize_client->size_inc.width);
269                 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
270                     cur_y += MAX(4, moveresize_client->size_inc.height);
271                 else if (e->xkey.keycode == ob_keycode(OB_KEY_UP))
272                     cur_y -= MAX(4, moveresize_client->size_inc.height);
273                 else
274                     return;
275                 do_resize(FALSE);
276             } else if (corner == prop_atoms.net_wm_moveresize_move_keyboard) {
277                 if (e->xkey.keycode == ob_keycode(OB_KEY_RIGHT))
278                     cur_x += 4;
279                 else if (e->xkey.keycode == ob_keycode(OB_KEY_LEFT))
280                     cur_x -= 4;
281                 else if (e->xkey.keycode == ob_keycode(OB_KEY_DOWN))
282                     cur_y += 4;
283                 else if (e->xkey.keycode == ob_keycode(OB_KEY_UP))
284                     cur_y -= 4;
285                 else
286                     return;
287                 do_move(FALSE);
288             }
289         }
290     }
291 }