diff options
Diffstat (limited to 'sway/input_state.c')
-rw-r--r-- | sway/input_state.c | 281 |
1 files changed, 265 insertions, 16 deletions
diff --git a/sway/input_state.c b/sway/input_state.c index 9e065e60..e911d9cf 100644 --- a/sway/input_state.c +++ b/sway/input_state.c | |||
@@ -74,27 +74,276 @@ void release_key(uint32_t key_sym, uint32_t key_code) { | |||
74 | } | 74 | } |
75 | } | 75 | } |
76 | 76 | ||
77 | // Pointer state and mode | ||
78 | |||
77 | struct pointer_state pointer_state; | 79 | struct pointer_state pointer_state; |
78 | 80 | ||
79 | static struct wlc_geometry saved_floating; | 81 | static struct mode_state { |
82 | // initial view state | ||
83 | double x, y, w, h; | ||
84 | swayc_t *ptr; | ||
85 | // Containers used for resizing horizontally | ||
86 | struct { | ||
87 | double w; | ||
88 | swayc_t *ptr; | ||
89 | struct { | ||
90 | double w; | ||
91 | swayc_t *ptr; | ||
92 | } parent; | ||
93 | } horiz; | ||
94 | // Containers used for resizing vertically | ||
95 | struct { | ||
96 | double h; | ||
97 | swayc_t *ptr; | ||
98 | struct { | ||
99 | double h; | ||
100 | swayc_t *ptr; | ||
101 | } parent; | ||
102 | } vert; | ||
103 | } initial; | ||
104 | |||
105 | static struct { | ||
106 | bool left; | ||
107 | bool top; | ||
108 | } lock; | ||
109 | |||
110 | // initial set/unset | ||
111 | |||
112 | static void set_initial_view(swayc_t *view) { | ||
113 | initial.ptr = view; | ||
114 | initial.x = view->x; | ||
115 | initial.y = view->y; | ||
116 | initial.w = view->width; | ||
117 | initial.h = view->height; | ||
118 | } | ||
119 | |||
120 | static void set_initial_sibling(void) { | ||
121 | bool reset = true; | ||
122 | if ((initial.horiz.ptr = get_swayc_in_direction(initial.ptr, lock.left ? MOVE_RIGHT: MOVE_LEFT))) { | ||
123 | initial.horiz.w = initial.horiz.ptr->width; | ||
124 | initial.horiz.parent.ptr = get_swayc_in_direction(initial.horiz.ptr, lock.left ? MOVE_LEFT : MOVE_RIGHT); | ||
125 | initial.horiz.parent.w = initial.horiz.parent.ptr->width; | ||
126 | reset = false; | ||
127 | } | ||
128 | if ((initial.vert.ptr = get_swayc_in_direction(initial.ptr, lock.top ? MOVE_DOWN: MOVE_UP))) { | ||
129 | initial.vert.h = initial.vert.ptr->height; | ||
130 | initial.vert.parent.ptr = get_swayc_in_direction(initial.vert.ptr, lock.top ? MOVE_UP : MOVE_DOWN); | ||
131 | initial.vert.parent.h = initial.vert.parent.ptr->height; | ||
132 | reset = false; | ||
133 | } | ||
134 | // If nothing will change just undo the mode | ||
135 | if (reset) { | ||
136 | pointer_state.mode = 0; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | static void reset_initial_view(void) { | ||
141 | initial.ptr->x = initial.x; | ||
142 | initial.ptr->y = initial.y; | ||
143 | initial.ptr->width = initial.w; | ||
144 | initial.ptr->height = initial.h; | ||
145 | arrange_windows(initial.ptr, -1, -1); | ||
146 | pointer_state.mode = 0; | ||
147 | } | ||
148 | |||
149 | static void reset_initial_sibling(void) { | ||
150 | initial.horiz.ptr->width = initial.horiz.w; | ||
151 | initial.horiz.parent.ptr->width = initial.horiz.parent.w; | ||
152 | initial.vert.ptr->height = initial.vert.h; | ||
153 | initial.vert.parent.ptr->height = initial.vert.parent.h; | ||
154 | arrange_windows(initial.horiz.ptr->parent, -1, -1); | ||
155 | arrange_windows(initial.vert.ptr->parent, -1, -1); | ||
156 | pointer_state.mode = 0; | ||
157 | } | ||
158 | |||
159 | // Mode set left/right click | ||
160 | |||
161 | static void pointer_mode_set_left(void) { | ||
162 | set_initial_view(pointer_state.left.view); | ||
163 | if (initial.ptr->is_floating) { | ||
164 | pointer_state.mode = M_DRAGGING | M_FLOATING; | ||
165 | } else { | ||
166 | pointer_state.mode = M_DRAGGING | M_TILING; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | static void pointer_mode_set_right(void) { | ||
171 | set_initial_view(pointer_state.right.view); | ||
172 | // Setup locking information | ||
173 | int midway_x = initial.ptr->x + initial.ptr->width/2; | ||
174 | int midway_y = initial.ptr->y + initial.ptr->height/2; | ||
175 | |||
176 | lock.left = pointer_state.origin.x > midway_x; | ||
177 | lock.top = pointer_state.origin.y > midway_y; | ||
178 | |||
179 | if (initial.ptr->is_floating) { | ||
180 | pointer_state.mode = M_RESIZING | M_FLOATING; | ||
181 | } else { | ||
182 | pointer_state.mode = M_RESIZING | M_TILING; | ||
183 | set_initial_sibling(); | ||
184 | } | ||
185 | } | ||
186 | |||
187 | // Mode set/update/reset | ||
188 | |||
189 | void pointer_mode_set(uint32_t button, bool condition) { | ||
190 | // switch on drag/resize mode | ||
191 | switch (pointer_state.mode & (M_DRAGGING | M_RESIZING)) { | ||
192 | case M_DRAGGING: | ||
193 | // end drag mode when left click is unpressed | ||
194 | if (!pointer_state.left.held) { | ||
195 | pointer_state.mode = 0; | ||
196 | } | ||
197 | break; | ||
198 | |||
199 | case M_RESIZING: | ||
200 | // end resize mode when right click is unpressed | ||
201 | if (!pointer_state.right.held) { | ||
202 | pointer_state.mode = 0; | ||
203 | } | ||
204 | break; | ||
205 | |||
206 | // No mode case | ||
207 | default: | ||
208 | // return if failed condition, or no view | ||
209 | if (!condition || !pointer_state.view) { | ||
210 | break; | ||
211 | } | ||
80 | 212 | ||
81 | void start_floating(swayc_t *view) { | 213 | // Set mode depending on current button press |
82 | if (view->is_floating) { | 214 | switch (button) { |
83 | saved_floating.origin.x = view->x; | 215 | // Start dragging mode |
84 | saved_floating.origin.y = view->y; | 216 | case M_LEFT_CLICK: |
85 | saved_floating.size.w = view->width; | 217 | // if button release dont do anything |
86 | saved_floating.size.h = view->height; | 218 | if (pointer_state.left.held) { |
219 | pointer_mode_set_left(); | ||
220 | } | ||
221 | break; | ||
222 | |||
223 | // Start resize mode | ||
224 | case M_RIGHT_CLICK: | ||
225 | // if button release dont do anyhting | ||
226 | if (pointer_state.right.held) { | ||
227 | pointer_mode_set_right(); | ||
228 | } | ||
229 | break; | ||
230 | } | ||
87 | } | 231 | } |
88 | } | 232 | } |
89 | 233 | ||
90 | void reset_floating(swayc_t *view) { | 234 | void pointer_mode_update(void) { |
91 | if (view->is_floating) { | 235 | if (initial.ptr->type != C_VIEW) { |
92 | view->x = saved_floating.origin.x; | 236 | pointer_state.mode = 0; |
93 | view->y = saved_floating.origin.y; | 237 | return; |
94 | view->width = saved_floating.size.w; | 238 | } |
95 | view->height = saved_floating.size.h; | 239 | int dx = pointer_state.origin.x; |
96 | arrange_windows(view->parent, -1, -1); | 240 | int dy = pointer_state.origin.y; |
241 | |||
242 | switch (pointer_state.mode) { | ||
243 | case M_FLOATING | M_DRAGGING: | ||
244 | // Update position | ||
245 | dx -= pointer_state.left.x; | ||
246 | dy -= pointer_state.left.y; | ||
247 | if (initial.x + dx != initial.ptr->x) { | ||
248 | initial.ptr->x = initial.x + dx; | ||
249 | } | ||
250 | if (initial.y + dy != initial.ptr->y) { | ||
251 | initial.ptr->y = initial.y + dy; | ||
252 | } | ||
253 | update_geometry(initial.ptr); | ||
254 | break; | ||
255 | |||
256 | case M_FLOATING | M_RESIZING: | ||
257 | dx -= pointer_state.right.x; | ||
258 | dy -= pointer_state.right.y; | ||
259 | initial.ptr = pointer_state.right.view; | ||
260 | if (lock.left) { | ||
261 | if (initial.w + dx > min_sane_w) { | ||
262 | initial.ptr->width = initial.w + dx; | ||
263 | } | ||
264 | } else { // lock.right | ||
265 | if (initial.w - dx > min_sane_w) { | ||
266 | initial.ptr->width = initial.w - dx; | ||
267 | initial.ptr->x = initial.x + dx; | ||
268 | } | ||
269 | } | ||
270 | if (lock.top) { | ||
271 | if (initial.h + dy > min_sane_h) { | ||
272 | initial.ptr->height = initial.h + dy; | ||
273 | } | ||
274 | } else { // lock.bottom | ||
275 | if (initial.h - dy > min_sane_h) { | ||
276 | initial.ptr->height = initial.h - dy; | ||
277 | initial.ptr->y = initial.y + dy; | ||
278 | } | ||
279 | } | ||
280 | update_geometry(initial.ptr); | ||
281 | break; | ||
282 | |||
283 | case M_TILING | M_DRAGGING: | ||
284 | // swap current view under pointer with dragged view | ||
285 | if (pointer_state.view && pointer_state.view->type == C_VIEW | ||
286 | && pointer_state.view != initial.ptr) { | ||
287 | // Swap them around | ||
288 | swap_container(pointer_state.view, initial.ptr); | ||
289 | update_geometry(pointer_state.view); | ||
290 | update_geometry(initial.ptr); | ||
291 | // Set focus back to initial view | ||
292 | set_focused_container(initial.ptr); | ||
293 | } | ||
294 | break; | ||
295 | |||
296 | case M_TILING | M_RESIZING: | ||
297 | dx -= pointer_state.right.x; | ||
298 | dy -= pointer_state.right.y; | ||
299 | // resize if we can | ||
300 | if (initial.horiz.ptr) { | ||
301 | if (lock.left) { | ||
302 | // Check whether its fine to resize | ||
303 | if (initial.w + dx > min_sane_w && initial.horiz.w - dx > min_sane_w) { | ||
304 | initial.horiz.ptr->width = initial.horiz.w - dx; | ||
305 | initial.horiz.parent.ptr->width = initial.horiz.parent.w + dx; | ||
306 | } | ||
307 | } else { // lock.right | ||
308 | if (initial.w - dx > min_sane_w && initial.horiz.w + dx > min_sane_w) { | ||
309 | initial.horiz.ptr->width = initial.horiz.w + dx; | ||
310 | initial.horiz.parent.ptr->width = initial.horiz.parent.w - dx; | ||
311 | } | ||
312 | } | ||
313 | arrange_windows(initial.horiz.ptr->parent, -1, -1); | ||
314 | } | ||
315 | if (initial.vert.ptr) { | ||
316 | if (lock.top) { | ||
317 | if (initial.h + dy > min_sane_h && initial.vert.h - dy > min_sane_h) { | ||
318 | initial.vert.ptr->height = initial.vert.h - dy; | ||
319 | initial.vert.parent.ptr->height = initial.vert.parent.h + dy; | ||
320 | } | ||
321 | } else { // lock.bottom | ||
322 | if (initial.h - dy > min_sane_h && initial.vert.h + dy > min_sane_h) { | ||
323 | initial.vert.ptr->height = initial.vert.h + dy; | ||
324 | initial.vert.parent.ptr->height = initial.vert.parent.h - dy; | ||
325 | } | ||
326 | } | ||
327 | arrange_windows(initial.vert.ptr->parent, -1, -1); | ||
328 | } | ||
329 | default: | ||
330 | return; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | void pointer_mode_reset(void) { | ||
335 | switch (pointer_state.mode) { | ||
336 | case M_FLOATING | M_RESIZING: | ||
337 | case M_FLOATING | M_DRAGGING: | ||
338 | reset_initial_view(); | ||
339 | break; | ||
340 | |||
341 | case M_TILING | M_RESIZING: | ||
342 | (void) reset_initial_sibling; | ||
343 | break; | ||
344 | |||
345 | case M_TILING | M_DRAGGING: | ||
346 | default: | ||
347 | break; | ||
97 | } | 348 | } |
98 | pointer_state.floating = (struct pointer_floating){0, 0}; | ||
99 | pointer_state.lock = (struct pointer_lock){0, 0, 0, 0, 0, 0, 0, 0}; | ||
100 | } | 349 | } |