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 Popup
*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 client_remove_destructor(client_dest
);
54 static void popup_coords(ObClient
*c
, char *format
, int a
, int b
)
58 text
= g_strdup_printf(format
, a
, b
);
59 popup_position(popup
, CenterGravity
,
60 c
->frame
->area
.x
+ c
->frame
->size
.left
+
62 c
->frame
->area
.y
+ c
->frame
->size
.top
+
64 popup_show(popup
, text
, NULL
);
68 void moveresize_start(ObClient
*c
, int x
, int y
, guint b
, guint32 cnr
)
72 g_assert(!moveresize_in_progress
);
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;
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);
97 if (corner
== prop_atoms
.net_wm_moveresize_move
||
98 corner
== prop_atoms
.net_wm_moveresize_move_keyboard
) {
108 moveresize_in_progress
= TRUE
;
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
;
133 g_assert_not_reached();
135 grab_pointer(TRUE
, cur
);
139 void moveresize_end(gboolean cancel
)
141 grab_keyboard(FALSE
);
142 grab_pointer(FALSE
, None
);
147 client_move(moveresize_client
,
148 (cancel
? start_cx
: cur_x
),
149 (cancel
? start_cy
: cur_y
));
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
);
158 moveresize_in_progress
= FALSE
;
159 moveresize_client
= NULL
;
162 static void do_move(gboolean resist
)
165 resist_move_windows(moveresize_client
, &cur_x
, &cur_y
);
166 resist_move_monitors(moveresize_client
, &cur_x
, &cur_y
);
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
);
174 static void do_resize(gboolean resist
)
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
;
183 resist_size_windows(moveresize_client
, &cur_x
, &cur_y
, lockcorner
);
184 resist_size_monitors(moveresize_client
, &cur_x
, &cur_y
, lockcorner
);
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
;
191 client_configure(moveresize_client
, lockcorner
,
192 moveresize_client
->area
.x
, moveresize_client
->area
.y
,
193 cur_x
, cur_y
, TRUE
, FALSE
);
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
);
204 void moveresize_event(XEvent
*e
)
206 g_assert(moveresize_in_progress
);
208 if (e
->type
== ButtonPress
) {
210 start_x
= e
->xbutton
.x_root
;
211 start_y
= e
->xbutton
.y_root
;
212 button
= e
->xbutton
.button
; /* this will end it now */
214 } else if (e
->type
== ButtonRelease
) {
215 if (!button
|| e
->xbutton
.button
== button
) {
216 moveresize_end(FALSE
);
218 } else if (e
->type
== MotionNotify
) {
220 cur_x
= start_cx
+ e
->xmotion
.x_root
- start_x
;
221 cur_y
= start_cy
+ e
->xmotion
.y_root
- start_y
;
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
) {
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
);
239 lockcorner
= OB_CORNER_BOTTOMLEFT
;
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
) {
247 cur_y
= start_ch
+ (e
->xmotion
.y_root
- start_y
);
248 lockcorner
= OB_CORNER_TOPLEFT
;
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
);
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
;
263 g_assert_not_reached();
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
);
273 if (corner
== prop_atoms
.net_wm_moveresize_size_keyboard
) {
274 int dx
= 0, dy
= 0, ox
= cur_x
, oy
= cur_y
;
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
);
289 XWarpPointer(ob_display
, None
, None
, 0, 0, 0, 0, dx
, dy
);
290 /* steal the motion events this causes */
291 XSync(ob_display
, FALSE
);
294 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
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
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
;
309 if (e
->xkey
.keycode
== ob_keycode(OB_KEY_RIGHT
))
311 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_LEFT
))
313 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_DOWN
))
315 else if (e
->xkey
.keycode
== ob_keycode(OB_KEY_UP
))
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
);
328 while (XCheckTypedEvent(ob_display
, MotionNotify
, &ce
));
330 screen_pointer_pos(&px
, &py
);
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
338 start_x
+= (px
- opx
) - (cur_x
- ox
);
339 start_y
+= (py
- opy
) - (cur_y
- oy
);