2 #include "framerender.h"
10 #include "moveresize.h"
12 #include "render/render.h"
13 #include "render/theme.h"
18 gboolean moveresize_in_progress
= FALSE
;
19 ObClient
*moveresize_client
= NULL
;
21 static gboolean moving
= FALSE
; /* TRUE - moving, FALSE - resizing */
23 static int start_x
, start_y
, start_cx
, start_cy
, start_cw
, start_ch
;
24 static int cur_x
, cur_y
;
26 static guint32 corner
;
27 static ObCorner lockcorner
;
29 static ObPopup
*popup
= NULL
;
31 static void client_dest(gpointer client
)
33 if (moveresize_client
== client
)
37 void moveresize_startup(gboolean reconfig
)
39 popup
= popup_new(FALSE
);
42 client_add_destructor(client_dest
);
45 void moveresize_shutdown(gboolean reconfig
)
48 if (moveresize_in_progress
)
49 moveresize_end(FALSE
);
50 client_remove_destructor(client_dest
);
57 static void popup_coords(ObClient
*c
, char *format
, int a
, int b
)
61 text
= g_strdup_printf(format
, a
, b
);
62 popup_position(popup
, CenterGravity
,
63 c
->frame
->area
.x
+ c
->frame
->size
.left
+
65 c
->frame
->area
.y
+ c
->frame
->size
.top
+
67 popup_show(popup
, text
);
71 void moveresize_start(ObClient
*c
, int x
, int y
, guint b
, guint32 cnr
)
75 g_assert(!moveresize_in_progress
);
77 if (!c
->frame
->visible
)
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;
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);
103 if (corner
== prop_atoms
.net_wm_moveresize_move
||
104 corner
== prop_atoms
.net_wm_moveresize_move_keyboard
) {
114 moveresize_in_progress
= TRUE
;
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
;
139 g_assert_not_reached();
141 grab_pointer(TRUE
, cur
);
145 void moveresize_end(gboolean cancel
)
147 grab_keyboard(FALSE
);
148 grab_pointer(FALSE
, OB_CURSOR_NONE
);
153 client_move(moveresize_client
,
154 (cancel
? start_cx
: cur_x
),
155 (cancel
? start_cy
: cur_y
));
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
);
164 moveresize_in_progress
= FALSE
;
165 moveresize_client
= NULL
;
168 static void do_move(gboolean resist
)
171 resist_move_windows(moveresize_client
, &cur_x
, &cur_y
);
172 resist_move_monitors(moveresize_client
, &cur_x
, &cur_y
);
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
);
181 static void do_resize(gboolean resist
)
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
;
190 resist_size_windows(moveresize_client
, &cur_x
, &cur_y
, lockcorner
);
191 resist_size_monitors(moveresize_client
, &cur_x
, &cur_y
, lockcorner
);
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
;
198 client_configure(moveresize_client
, lockcorner
,
199 moveresize_client
->area
.x
, moveresize_client
->area
.y
,
200 cur_x
, cur_y
, TRUE
, FALSE
);
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
);
211 void moveresize_event(XEvent
*e
)
213 g_assert(moveresize_in_progress
);
215 if (e
->type
== ButtonPress
) {
217 start_x
= e
->xbutton
.x_root
;
218 start_y
= e
->xbutton
.y_root
;
219 button
= e
->xbutton
.button
; /* this will end it now */
221 } else if (e
->type
== ButtonRelease
) {
222 if (!button
|| e
->xbutton
.button
== button
) {
223 moveresize_end(FALSE
);
225 } else if (e
->type
== MotionNotify
) {
227 cur_x
= start_cx
+ e
->xmotion
.x_root
- start_x
;
228 cur_y
= start_cy
+ e
->xmotion
.y_root
- start_y
;
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
) {
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
);
246 lockcorner
= OB_CORNER_BOTTOMLEFT
;
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
) {
254 cur_y
= start_ch
+ (e
->xmotion
.y_root
- start_y
);
255 lockcorner
= OB_CORNER_TOPLEFT
;
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
);
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
;
270 g_assert_not_reached();
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
);
280 if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
281 int dx
= 0, dy
= 0, ox
= cur_x
, oy
= cur_y
;
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
);
296 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, dx
, dy
);
297 /* steal the motion events this causes */
298 XSync(ob_display
, FALSE
);
301 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
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
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
;
316 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RIGHT
))
318 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_LEFT
))
320 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_DOWN
))
322 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_UP
))
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
);
335 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
337 screen_pointer_pos(&px
, &py
);
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
345 start_x
+= (px
- opx
) - (cur_x
- ox
);
346 start_y
+= (py
- opy
) - (cur_y
- oy
);