summaryrefslogtreecommitdiffstats
path: root/sway/input_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/input_state.c')
-rw-r--r--sway/input_state.c281
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
77struct pointer_state pointer_state; 79struct pointer_state pointer_state;
78 80
79static struct wlc_geometry saved_floating; 81static 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
105static struct {
106 bool left;
107 bool top;
108} lock;
109
110// initial set/unset
111
112static 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
120static 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
140static 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
149static 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
161static 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
170static 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
189void 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
81void 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
90void reset_floating(swayc_t *view) { 234void 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
334void 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}