diff options
Diffstat (limited to 'sway/handlers.c')
-rw-r--r-- | sway/handlers.c | 247 |
1 files changed, 108 insertions, 139 deletions
diff --git a/sway/handlers.c b/sway/handlers.c index acf3e6a4..27f6d294 100644 --- a/sway/handlers.c +++ b/sway/handlers.c | |||
@@ -17,10 +17,14 @@ | |||
17 | #include "input_state.h" | 17 | #include "input_state.h" |
18 | #include "resize.h" | 18 | #include "resize.h" |
19 | 19 | ||
20 | struct wlc_origin mouse_origin; | 20 | // Event should be sent to client |
21 | #define EVENT_PASSTHROUGH false | ||
22 | |||
23 | // Event handled by sway and should not be sent to client | ||
24 | #define EVENT_HANDLED true | ||
21 | 25 | ||
22 | static bool pointer_test(swayc_t *view, void *_origin) { | 26 | static bool pointer_test(swayc_t *view, void *_origin) { |
23 | const struct wlc_origin *origin = _origin; | 27 | const struct mouse_origin *origin = _origin; |
24 | // Determine the output that the view is under | 28 | // Determine the output that the view is under |
25 | swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT); | 29 | swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT); |
26 | if (origin->x >= view->x && origin->y >= view->y | 30 | if (origin->x >= view->x && origin->y >= view->y |
@@ -55,7 +59,7 @@ swayc_t *container_under_pointer(void) { | |||
55 | i = len = lookup->floating->length; | 59 | i = len = lookup->floating->length; |
56 | bool got_floating = false; | 60 | bool got_floating = false; |
57 | while (--i > -1) { | 61 | while (--i > -1) { |
58 | if (pointer_test(lookup->floating->items[i], &mouse_origin)) { | 62 | if (pointer_test(lookup->floating->items[i], &pointer_state.origin)) { |
59 | lookup = lookup->floating->items[i]; | 63 | lookup = lookup->floating->items[i]; |
60 | got_floating = true; | 64 | got_floating = true; |
61 | break; | 65 | break; |
@@ -68,7 +72,7 @@ swayc_t *container_under_pointer(void) { | |||
68 | // search children | 72 | // search children |
69 | len = lookup->children->length; | 73 | len = lookup->children->length; |
70 | for (i = 0; i < len; ++i) { | 74 | for (i = 0; i < len; ++i) { |
71 | if (pointer_test(lookup->children->items[i], &mouse_origin)) { | 75 | if (pointer_test(lookup->children->items[i], &pointer_state.origin)) { |
72 | lookup = lookup->children->items[i]; | 76 | lookup = lookup->children->items[i]; |
73 | break; | 77 | break; |
74 | } | 78 | } |
@@ -284,13 +288,12 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier | |||
284 | uint32_t key, uint32_t sym, enum wlc_key_state state) { | 288 | uint32_t key, uint32_t sym, enum wlc_key_state state) { |
285 | 289 | ||
286 | if (locked_view_focus && state == WLC_KEY_STATE_PRESSED) { | 290 | if (locked_view_focus && state == WLC_KEY_STATE_PRESSED) { |
287 | return false; | 291 | return EVENT_PASSTHROUGH; |
288 | } | 292 | } |
289 | 293 | ||
290 | // Revert floating container back to original position on keypress | 294 | // reset pointer mode on keypress |
291 | if (state == WLC_KEY_STATE_PRESSED && | 295 | if (state == WLC_KEY_STATE_PRESSED && pointer_state.mode) { |
292 | (pointer_state.floating.drag || pointer_state.floating.resize)) { | 296 | pointer_mode_reset(); |
293 | reset_floating(get_focused_view(&root_container)); | ||
294 | } | 297 | } |
295 | 298 | ||
296 | struct sway_mode *mode = config->current_mode; | 299 | struct sway_mode *mode = config->current_mode; |
@@ -319,125 +322,119 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier | |||
319 | if (match) { | 322 | if (match) { |
320 | if (state == WLC_KEY_STATE_PRESSED) { | 323 | if (state == WLC_KEY_STATE_PRESSED) { |
321 | handle_command(config, binding->command); | 324 | handle_command(config, binding->command); |
322 | return true; | 325 | return EVENT_HANDLED; |
323 | } else if (state == WLC_KEY_STATE_RELEASED) { | 326 | } else if (state == WLC_KEY_STATE_RELEASED) { |
324 | // TODO: --released | 327 | // TODO: --released |
325 | } | 328 | } |
326 | } | 329 | } |
327 | } | 330 | } |
328 | } | 331 | } |
329 | return false; | 332 | return EVENT_PASSTHROUGH; |
330 | } | 333 | } |
331 | 334 | ||
332 | static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) { | 335 | static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) { |
333 | static struct wlc_origin prev_pos; | 336 | // Update pointer origin |
334 | static wlc_handle prev_handle = 0; | 337 | pointer_state.delta.x = origin->x - pointer_state.origin.x; |
335 | mouse_origin = *origin; | 338 | pointer_state.delta.y = origin->y - pointer_state.origin.y; |
336 | bool changed_floating = false; | 339 | pointer_state.origin.x = origin->x; |
337 | bool changed_tiling = false; | 340 | pointer_state.origin.y = origin->y; |
338 | if (!swayc_active_workspace()) { | 341 | |
339 | return false; | 342 | // Update view under pointer |
340 | } | 343 | swayc_t *prev_view = pointer_state.view; |
341 | // Do checks to determine if proper keys are being held | 344 | pointer_state.view = container_under_pointer(); |
342 | swayc_t *view = container_under_pointer(); | 345 | |
343 | if (pointer_state.floating.drag && view) { | 346 | // If pointer is in a mode, update it |
344 | if (view->is_floating) { | 347 | if (pointer_state.mode) { |
345 | int dx = mouse_origin.x - prev_pos.x; | 348 | pointer_mode_update(); |
346 | int dy = mouse_origin.y - prev_pos.y; | ||
347 | view->x += dx; | ||
348 | view->y += dy; | ||
349 | struct wlc_geometry geometry = { | ||
350 | .origin = { | ||
351 | .x = view->x, | ||
352 | .y = view->y | ||
353 | }, | ||
354 | .size = { | ||
355 | .w = view->width, | ||
356 | .h = view->height | ||
357 | } | ||
358 | }; | ||
359 | wlc_view_set_geometry(view->handle, 0, &geometry); | ||
360 | changed_floating = true; | ||
361 | } else { | ||
362 | swayc_t *init_view = pointer_state.tiling.init_view; | ||
363 | if (view != init_view && view->type == C_VIEW) { | ||
364 | changed_tiling = true; | ||
365 | int i, j; | ||
366 | for (i = 0; i < view->parent->children->length; i++) { | ||
367 | if (view->parent->children->items[i] == view) { | ||
368 | for (j = 0; j < init_view->parent->children->length; j++) { | ||
369 | if (init_view->parent->children->items[j] == init_view) { | ||
370 | double temp_w = view->width; | ||
371 | double temp_h = view->height; | ||
372 | view->width = init_view->width; | ||
373 | view->height = init_view->height; | ||
374 | init_view->width = temp_w; | ||
375 | init_view->height = temp_h; | ||
376 | |||
377 | init_view->parent->children->items[j] = view; | ||
378 | view->parent->children->items[i] = init_view; | ||
379 | |||
380 | swayc_t *temp = view->parent; | ||
381 | view->parent = init_view->parent; | ||
382 | init_view->parent = temp; | ||
383 | |||
384 | arrange_windows(&root_container, -1, -1); | ||
385 | break; | ||
386 | } | ||
387 | } | ||
388 | break; | ||
389 | } | ||
390 | } | ||
391 | } | ||
392 | } | ||
393 | } else if (pointer_state.floating.resize && view) { | ||
394 | changed_floating = resize_floating(prev_pos); | ||
395 | } else if (pointer_state.tiling.resize && view) { | ||
396 | changed_tiling = mouse_resize_tiled(prev_pos); | ||
397 | } | 349 | } |
398 | if (config->focus_follows_mouse && prev_handle != handle) { | 350 | // Otherwise change focus if config is set an |
399 | // Dont change focus if fullscreen | 351 | else if (prev_view != pointer_state.view && config->focus_follows_mouse) { |
400 | swayc_t *focused = get_focused_view(view); | 352 | if (pointer_state.view && pointer_state.view->type == C_VIEW) { |
401 | if (!swayc_is_fullscreen(focused) | 353 | set_focused_container(pointer_state.view); |
402 | && !(pointer_state.l_held || pointer_state.r_held)) { | ||
403 | set_focused_container(container_under_pointer()); | ||
404 | } | 354 | } |
405 | } | 355 | } |
406 | prev_handle = handle; | 356 | return EVENT_PASSTHROUGH; |
407 | prev_pos = mouse_origin; | ||
408 | if (changed_tiling || changed_floating) { | ||
409 | return true; | ||
410 | } | ||
411 | return false; | ||
412 | } | 357 | } |
413 | 358 | ||
414 | 359 | ||
415 | static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, | 360 | static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct wlc_modifiers *modifiers, |
416 | uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) { | 361 | uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) { |
417 | swayc_t *focused = get_focused_container(&root_container); | 362 | |
418 | // dont change focus if fullscreen | 363 | // Update view pointer is on |
419 | if (swayc_is_fullscreen(focused)) { | 364 | pointer_state.view = container_under_pointer(); |
420 | return false; | 365 | |
421 | } | 366 | // Update pointer origin |
422 | if (state == WLC_BUTTON_STATE_PRESSED) { | 367 | pointer_state.origin.x = origin->x; |
423 | sway_log(L_DEBUG, "Mouse button %u pressed", button); | 368 | pointer_state.origin.y = origin->y; |
424 | if (button == M_LEFT_CLICK) { | 369 | |
425 | pointer_state.l_held = true; | 370 | // Update pointer_state |
371 | switch (button) { | ||
372 | case M_LEFT_CLICK: | ||
373 | if (state == WLC_BUTTON_STATE_PRESSED) { | ||
374 | pointer_state.left.held = true; | ||
375 | pointer_state.left.x = origin->x; | ||
376 | pointer_state.left.y = origin->y; | ||
377 | pointer_state.left.view = pointer_state.view; | ||
378 | } else { | ||
379 | pointer_state.left.held = false; | ||
426 | } | 380 | } |
427 | if (button == M_RIGHT_CLICK) { | 381 | break; |
428 | pointer_state.r_held = true; | 382 | |
383 | case M_RIGHT_CLICK: | ||
384 | if (state == WLC_BUTTON_STATE_PRESSED) { | ||
385 | pointer_state.right.held = true; | ||
386 | pointer_state.right.x = origin->x; | ||
387 | pointer_state.right.y = origin->y; | ||
388 | pointer_state.right.view = pointer_state.view; | ||
389 | } else { | ||
390 | pointer_state.right.held = false; | ||
429 | } | 391 | } |
430 | swayc_t *pointer = container_under_pointer(); | 392 | break; |
431 | if (pointer) { | 393 | |
432 | set_focused_container(pointer); | 394 | case M_SCROLL_CLICK: |
433 | int midway_x = pointer->x + pointer->width/2; | 395 | if (state == WLC_BUTTON_STATE_PRESSED) { |
434 | int midway_y = pointer->y + pointer->height/2; | 396 | pointer_state.scroll.held = true; |
435 | pointer_state.lock.bottom = origin->y < midway_y; | 397 | pointer_state.scroll.x = origin->x; |
436 | pointer_state.lock.top = !pointer_state.lock.bottom; | 398 | pointer_state.scroll.y = origin->y; |
437 | pointer_state.lock.right = origin->x < midway_x; | 399 | pointer_state.scroll.view = pointer_state.view; |
438 | pointer_state.lock.left = !pointer_state.lock.right; | 400 | } else { |
401 | pointer_state.scroll.held = false; | ||
439 | } | 402 | } |
403 | break; | ||
404 | |||
405 | //TODO scrolling behavior | ||
406 | case M_SCROLL_UP: | ||
407 | case M_SCROLL_DOWN: | ||
408 | break; | ||
409 | } | ||
410 | |||
411 | // get focused window and check if to change focus on mouse click | ||
412 | swayc_t *focused = get_focused_container(&root_container); | ||
413 | |||
414 | // dont change focus or mode if fullscreen | ||
415 | if (swayc_is_fullscreen(focused)) { | ||
416 | return EVENT_PASSTHROUGH; | ||
417 | } | ||
418 | |||
419 | // set pointer mode | ||
420 | pointer_mode_set(button, | ||
421 | (modifiers->mods & config->floating_mod) == config->floating_mod); | ||
440 | 422 | ||
423 | // Return if mode has been set | ||
424 | if (pointer_state.mode) { | ||
425 | return EVENT_HANDLED; | ||
426 | } | ||
427 | |||
428 | // Always send mouse release | ||
429 | if (state == WLC_BUTTON_STATE_RELEASED) { | ||
430 | return EVENT_PASSTHROUGH; | ||
431 | } | ||
432 | |||
433 | // Check whether to change focus | ||
434 | swayc_t *pointer = pointer_state.view; | ||
435 | if (pointer && focused != pointer) { | ||
436 | set_focused_container(pointer_state.view); | ||
437 | // Send to front if floating | ||
441 | if (pointer->is_floating) { | 438 | if (pointer->is_floating) { |
442 | int i; | 439 | int i; |
443 | for (i = 0; i < pointer->parent->floating->length; i++) { | 440 | for (i = 0; i < pointer->parent->floating->length; i++) { |
@@ -447,40 +444,12 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w | |||
447 | break; | 444 | break; |
448 | } | 445 | } |
449 | } | 446 | } |
450 | arrange_windows(pointer->parent, -1, -1); | 447 | wlc_view_bring_to_front(view); |
451 | if (modifiers->mods & config->floating_mod) { | ||
452 | pointer_state.floating.drag = pointer_state.l_held; | ||
453 | pointer_state.floating.resize = pointer_state.r_held; | ||
454 | start_floating(pointer); | ||
455 | } | ||
456 | // Dont want pointer sent to window while dragging or resizing | ||
457 | return (pointer_state.floating.drag || pointer_state.floating.resize); | ||
458 | } else { | ||
459 | if (modifiers->mods & config->floating_mod) { | ||
460 | pointer_state.floating.drag = pointer_state.l_held; | ||
461 | pointer_state.tiling.resize = pointer_state.r_held; | ||
462 | pointer_state.tiling.init_view = pointer; | ||
463 | // Dont want pointer sent when resizing | ||
464 | return (pointer_state.tiling.resize); | ||
465 | } | ||
466 | } | ||
467 | return (pointer && pointer != focused); | ||
468 | } else { | ||
469 | sway_log(L_DEBUG, "Mouse button %u released", button); | ||
470 | if (button == M_LEFT_CLICK) { | ||
471 | pointer_state.l_held = false; | ||
472 | pointer_state.floating.drag = false; | ||
473 | pointer_state.tiling.init_view = NULL; | ||
474 | } | ||
475 | if (button == M_RIGHT_CLICK) { | ||
476 | pointer_state.r_held = false; | ||
477 | pointer_state.floating.resize = false; | ||
478 | pointer_state.tiling.resize = false; | ||
479 | pointer_state.tiling.init_view = NULL; | ||
480 | pointer_state.lock = (struct pointer_lock){false ,false ,false ,false, false, false, false, false}; | ||
481 | } | 448 | } |
482 | } | 449 | } |
483 | return false; | 450 | |
451 | // Finally send click | ||
452 | return EVENT_PASSTHROUGH; | ||
484 | } | 453 | } |
485 | 454 | ||
486 | static void handle_wlc_ready(void) { | 455 | static void handle_wlc_ready(void) { |