summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2015-08-22 09:03:43 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2015-08-22 09:03:43 -0400
commitade634bb04027a6ea5f053330e044638f135c147 (patch)
treeb446198afb8d5ea2d9e32e5953c9e1d4cf445485
parentMerge pull request #117 from Luminarys/master (diff)
parentAdded in bspwm like view swapping (diff)
downloadsway-ade634bb04027a6ea5f053330e044638f135c147.tar.gz
sway-ade634bb04027a6ea5f053330e044638f135c147.tar.zst
sway-ade634bb04027a6ea5f053330e044638f135c147.zip
Merge pull request #118 from Luminarys/master
Refactored resizing functions into resize.c
-rw-r--r--include/handlers.h1
-rw-r--r--include/layout.h3
-rw-r--r--include/resize.h8
-rw-r--r--sway/commands.c225
-rw-r--r--sway/handlers.c297
-rw-r--r--sway/layout.c2
-rw-r--r--sway/resize.c491
7 files changed, 556 insertions, 471 deletions
diff --git a/include/handlers.h b/include/handlers.h
index c25c3309..4c71f953 100644
--- a/include/handlers.h
+++ b/include/handlers.h
@@ -5,6 +5,7 @@
5#include <wlc/wlc.h> 5#include <wlc/wlc.h>
6 6
7extern struct wlc_interface interface; 7extern struct wlc_interface interface;
8extern struct wlc_origin mouse_origin;
8extern uint32_t keys_pressed[32]; 9extern uint32_t keys_pressed[32];
9 10
10// set focus to current pointer location and return focused container 11// set focus to current pointer location and return focused container
diff --git a/include/layout.h b/include/layout.h
index 7b8829ed..f8aebe0a 100644
--- a/include/layout.h
+++ b/include/layout.h
@@ -8,6 +8,9 @@
8 8
9extern swayc_t root_container; 9extern swayc_t root_container;
10 10
11extern int min_sane_w;
12extern int min_sane_h;
13
11void init_layout(void); 14void init_layout(void);
12 15
13void add_child(swayc_t *parent, swayc_t *child); 16void add_child(swayc_t *parent, swayc_t *child);
diff --git a/include/resize.h b/include/resize.h
new file mode 100644
index 00000000..4ace1815
--- /dev/null
+++ b/include/resize.h
@@ -0,0 +1,8 @@
1#ifndef _SWAY_RESIZE_H
2#define _SWAY_RESIZE_H
3
4bool mouse_resize_tiled(struct wlc_origin prev_pos);
5bool resize_floating(struct wlc_origin prev_pos);
6bool resize_tiled(int amount, bool use_width);
7
8#endif
diff --git a/sway/commands.c b/sway/commands.c
index 36299c8d..62794111 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -16,6 +16,7 @@
16#include "container.h" 16#include "container.h"
17#include "handlers.h" 17#include "handlers.h"
18#include "sway.h" 18#include "sway.h"
19#include "resize.h"
19 20
20struct modifier_key { 21struct modifier_key {
21 char *name; 22 char *name;
@@ -448,240 +449,26 @@ static bool cmd_resize(struct sway_config *config, int argc, char **argv) {
448 return false; 449 return false;
449 } 450 }
450 char *end; 451 char *end;
451 int min_sane_w = 100;
452 int min_sane_h = 60;
453 int amount = (int)strtol(argv[2], &end, 10); 452 int amount = (int)strtol(argv[2], &end, 10);
454 if (errno == ERANGE || amount == 0) { 453 if (errno == ERANGE || amount == 0) {
455 errno = 0; 454 errno = 0;
456 return false; 455 return false;
457 } 456 }
457
458 if (strcmp(argv[0], "shrink") != 0 && strcmp(argv[0], "grow") != 0) { 458 if (strcmp(argv[0], "shrink") != 0 && strcmp(argv[0], "grow") != 0) {
459 return false; 459 return false;
460 } 460 }
461
461 if (strcmp(argv[0], "shrink") == 0) { 462 if (strcmp(argv[0], "shrink") == 0) {
462 amount *= -1; 463 amount *= -1;
463 } 464 }
464 465
465 swayc_t *parent = get_focused_view(swayc_active_workspace());
466 swayc_t *focused = parent;
467 swayc_t *sibling;
468 if (!parent) {
469 return true;
470 }
471 // Find the closest parent container which has siblings of the proper layout.
472 // Then apply the resize to all of them.
473 int i;
474 if (strcmp(argv[1], "width") == 0) { 466 if (strcmp(argv[1], "width") == 0) {
475 int lnumber = 0; 467 return resize_tiled(amount, true);
476 int rnumber = 0;
477 while (parent->parent) {
478 if (parent->parent->layout == L_HORIZ) {
479 for (i = 0; i < parent->parent->children->length; i++) {
480 sibling = parent->parent->children->items[i];
481 if (sibling->x != focused->x) {
482 if (sibling->x < parent->x) {
483 lnumber++;
484 } else if (sibling->x > parent->x) {
485 rnumber++;
486 }
487 }
488 }
489 if (rnumber || lnumber) {
490 break;
491 }
492 }
493 parent = parent->parent;
494 }
495 if (parent == &root_container) {
496 return true;
497 }
498 sway_log(L_DEBUG, "Found the proper parent: %p. It has %d l conts, and %d r conts", parent->parent, lnumber, rnumber);
499 //TODO: Ensure rounding is done in such a way that there are NO pixel leaks
500 bool valid = true;
501 for (i = 0; i < parent->parent->children->length; i++) {
502 sibling = parent->parent->children->items[i];
503 if (sibling->x != focused->x) {
504 if (sibling->x < parent->x) {
505 double pixels = -1 * amount;
506 pixels /= lnumber;
507 if (rnumber) {
508 if ((sibling->width + pixels/2) < min_sane_w) {
509 valid = false;
510 break;
511 }
512 } else {
513 if ((sibling->width + pixels) < min_sane_w) {
514 valid = false;
515 break;
516 }
517 }
518 } else if (sibling->x > parent->x) {
519 double pixels = -1 * amount;
520 pixels /= rnumber;
521 if (lnumber) {
522 if ((sibling->width + pixels/2) < min_sane_w) {
523 valid = false;
524 break;
525 }
526 } else {
527 if ((sibling->width + pixels) < min_sane_w) {
528 valid = false;
529 break;
530 }
531 }
532 }
533 } else {
534 double pixels = amount;
535 if (parent->width + pixels < min_sane_w) {
536 valid = false;
537 break;
538 }
539 }
540 }
541 if (valid) {
542 for (i = 0; i < parent->parent->children->length; i++) {
543 sibling = parent->parent->children->items[i];
544 if (sibling->x != focused->x) {
545 if (sibling->x < parent->x) {
546 double pixels = -1 * amount;
547 pixels /= lnumber;
548 if (rnumber) {
549 recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_RIGHT);
550 } else {
551 recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_RIGHT);
552 }
553 } else if (sibling->x > parent->x) {
554 double pixels = -1 * amount;
555 pixels /= rnumber;
556 if (lnumber) {
557 recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_LEFT);
558 } else {
559 recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_LEFT);
560 }
561 }
562 } else {
563 if (rnumber != 0 && lnumber != 0) {
564 double pixels = amount;
565 pixels /= 2;
566 recursive_resize(parent, pixels, WLC_RESIZE_EDGE_LEFT);
567 recursive_resize(parent, pixels, WLC_RESIZE_EDGE_RIGHT);
568 } else if (rnumber) {
569 recursive_resize(parent, amount, WLC_RESIZE_EDGE_RIGHT);
570 } else if (lnumber) {
571 recursive_resize(parent, amount, WLC_RESIZE_EDGE_LEFT);
572 }
573 }
574 }
575 // Recursive resize does not handle positions, let arrange_windows
576 // take care of that.
577 arrange_windows(swayc_active_workspace(), -1, -1);
578 }
579 return true;
580 } else if (strcmp(argv[1], "height") == 0) { 468 } else if (strcmp(argv[1], "height") == 0) {
581 int tnumber = 0; 469 return resize_tiled(amount, false);
582 int bnumber = 0;
583 while (parent->parent) {
584 if (parent->parent->layout == L_VERT) {
585 for (i = 0; i < parent->parent->children->length; i++) {
586 sibling = parent->parent->children->items[i];
587 if (sibling->y != focused->y) {
588 if (sibling->y < parent->y) {
589 bnumber++;
590 } else if (sibling->y > parent->y) {
591 tnumber++;
592 }
593 }
594 }
595 if (bnumber || tnumber) {
596 break;
597 }
598 }
599 parent = parent->parent;
600 }
601 if (parent == &root_container) {
602 return true;
603 }
604 sway_log(L_DEBUG, "Found the proper parent: %p. It has %d b conts, and %d t conts", parent->parent, bnumber, tnumber);
605 //TODO: Ensure rounding is done in such a way that there are NO pixel leaks
606 bool valid = true;
607 for (i = 0; i < parent->parent->children->length; i++) {
608 sibling = parent->parent->children->items[i];
609 if (sibling->y != focused->y) {
610 if (sibling->y < parent->y) {
611 double pixels = -1 * amount;
612 pixels /= bnumber;
613 if (tnumber) {
614 if ((sibling->height + pixels/2) < min_sane_h) {
615 valid = false;
616 break;
617 }
618 } else {
619 if ((sibling->height + pixels) < min_sane_h) {
620 valid = false;
621 break;
622 }
623 }
624 } else if (sibling->y > parent->y) {
625 double pixels = -1 * amount;
626 pixels /= tnumber;
627 if (bnumber) {
628 if ((sibling->height + pixels/2) < min_sane_h) {
629 valid = false;
630 break;
631 }
632 } else {
633 if ((sibling->height + pixels) < min_sane_h) {
634 valid = false;
635 break;
636 }
637 }
638 }
639 } else {
640 double pixels = amount;
641 if (parent->height + pixels < min_sane_h) {
642 valid = false;
643 break;
644 }
645 }
646 }
647 if (valid) {
648 for (i = 0; i < parent->parent->children->length; i++) {
649 sibling = parent->parent->children->items[i];
650 if (sibling->y != focused->y) {
651 if (sibling->y < parent->y) {
652 double pixels = -1 * amount;
653 pixels /= bnumber;
654 if (tnumber) {
655 recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_BOTTOM);
656 } else {
657 recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_BOTTOM);
658 }
659 } else if (sibling->x > parent->x) {
660 double pixels = -1 * amount;
661 pixels /= tnumber;
662 if (bnumber) {
663 recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_TOP);
664 } else {
665 recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_TOP);
666 }
667 }
668 } else {
669 if (bnumber != 0 && tnumber != 0) {
670 double pixels = amount/2;
671 recursive_resize(parent, pixels, WLC_RESIZE_EDGE_TOP);
672 recursive_resize(parent, pixels, WLC_RESIZE_EDGE_BOTTOM);
673 } else if (tnumber) {
674 recursive_resize(parent, amount, WLC_RESIZE_EDGE_TOP);
675 } else if (bnumber) {
676 recursive_resize(parent, amount, WLC_RESIZE_EDGE_BOTTOM);
677 }
678 }
679 }
680 arrange_windows(swayc_active_workspace(), -1, -1);
681 }
682 return true;
683 } 470 }
684 return true; 471 return false;
685} 472}
686 473
687static bool cmd_set(struct sway_config *config, int argc, char **argv) { 474static bool cmd_set(struct sway_config *config, int argc, char **argv) {
diff --git a/sway/handlers.c b/sway/handlers.c
index d8f9e987..cb42196f 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -15,8 +15,9 @@
15#include "container.h" 15#include "container.h"
16#include "focus.h" 16#include "focus.h"
17#include "input_state.h" 17#include "input_state.h"
18#include "resize.h"
18 19
19static struct wlc_origin mouse_origin; 20struct wlc_origin mouse_origin;
20 21
21static bool pointer_test(swayc_t *view, void *_origin) { 22static bool pointer_test(swayc_t *view, void *_origin) {
22 const struct wlc_origin *origin = _origin; 23 const struct wlc_origin *origin = _origin;
@@ -338,261 +339,65 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct
338 mouse_origin = *origin; 339 mouse_origin = *origin;
339 bool changed_floating = false; 340 bool changed_floating = false;
340 bool changed_tiling = false; 341 bool changed_tiling = false;
341 int min_sane_w = 100;
342 int min_sane_h = 60;
343 if (!swayc_active_workspace()) { 342 if (!swayc_active_workspace()) {
344 return false; 343 return false;
345 } 344 }
346 // Do checks to determine if proper keys are being held 345 // Do checks to determine if proper keys are being held
347 swayc_t *view = container_under_pointer(); 346 swayc_t *view = container_under_pointer();
348 uint32_t edge = 0;
349 if (pointer_state.floating.drag && view) { 347 if (pointer_state.floating.drag && view) {
350 if (view->is_floating) { 348 if (view->is_floating) {
351 int dx = mouse_origin.x - prev_pos.x; 349 int dx = mouse_origin.x - prev_pos.x;
352 int dy = mouse_origin.y - prev_pos.y; 350 int dy = mouse_origin.y - prev_pos.y;
353 view->x += dx; 351 view->x += dx;
354 view->y += dy; 352 view->y += dy;
355 changed_floating = true; 353 struct wlc_geometry geometry = {
356 } 354 .origin = {
357 } else if (pointer_state.floating.resize && view) { 355 .x = view->x,
358 if (view->is_floating) { 356 .y = view->y
359 int dx = mouse_origin.x - prev_pos.x; 357 },
360 int dy = mouse_origin.y - prev_pos.y; 358 .size = {
361 359 .w = view->width,
362 // Move and resize the view based on the dx/dy and mouse position 360 .h = view->height
363 int midway_x = view->x + view->width/2;
364 int midway_y = view->y + view->height/2;
365 if (dx < 0) {
366 if (!pointer_state.lock.right) {
367 if (view->width > min_sane_w) {
368 changed_floating = true;
369 view->width += dx;
370 edge += WLC_RESIZE_EDGE_RIGHT;
371 }
372 } else if (mouse_origin.x < midway_x && !pointer_state.lock.left) {
373 changed_floating = true;
374 view->x += dx;
375 view->width -= dx;
376 edge += WLC_RESIZE_EDGE_LEFT;
377 } 361 }
378 } else if (dx > 0) { 362 };
379 if (mouse_origin.x > midway_x && !pointer_state.lock.right) { 363 wlc_view_set_geometry(view->handle, 0, &geometry);
380 changed_floating = true; 364 changed_floating = true;
381 view->width += dx; 365 } else {
382 edge += WLC_RESIZE_EDGE_RIGHT; 366 swayc_t *init_view = pointer_state.tiling.init_view;
383 } else if (!pointer_state.lock.left) { 367 if (view != init_view && view->type == C_VIEW) {
384 if (view->width > min_sane_w) { 368 changed_tiling = true;
385 changed_floating = true; 369 int i, j;
386 view->x += dx; 370 for (i = 0; i < view->parent->children->length; i++) {
387 view->width -= dx; 371 if (view->parent->children->items[i] == view) {
388 edge += WLC_RESIZE_EDGE_LEFT; 372 for (j = 0; j < init_view->parent->children->length; j++) {
389 } 373 if (init_view->parent->children->items[j] == init_view) {
390 } 374 double temp_w = view->width;
391 } 375 double temp_h = view->height;
392 376 view->width = init_view->width;
393 if (dy < 0) { 377 view->height = init_view->height;
394 if (!pointer_state.lock.bottom) { 378 init_view->width = temp_w;
395 if (view->height > min_sane_h) { 379 init_view->height = temp_h;
396 changed_floating = true; 380
397 view->height += dy; 381 init_view->parent->children->items[j] = view;
398 edge += WLC_RESIZE_EDGE_BOTTOM; 382 view->parent->children->items[i] = init_view;
399 } 383
400 } else if (mouse_origin.y < midway_y && !pointer_state.lock.top) { 384 swayc_t *temp = view->parent;
401 changed_floating = true; 385 view->parent = init_view->parent;
402 view->y += dy; 386 init_view->parent = temp;
403 view->height -= dy; 387
404 edge += WLC_RESIZE_EDGE_TOP; 388 arrange_windows(&root_container, -1, -1);
405 } 389 break;
406 } else if (dy > 0) {
407 if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) {
408 changed_floating = true;
409 view->height += dy;
410 edge += WLC_RESIZE_EDGE_BOTTOM;
411 } else if (!pointer_state.lock.top) {
412 if (view->height > min_sane_h) {
413 changed_floating = true;
414 view->y += dy;
415 view->height -= dy;
416 edge += WLC_RESIZE_EDGE_TOP;
417 }
418 }
419 }
420 }
421 } else if (pointer_state.tiling.resize && view) {
422 bool valid = true;
423 double dx = mouse_origin.x - prev_pos.x;
424 double dy = mouse_origin.y - prev_pos.y;
425 if (view != pointer_state.tiling.init_view) {
426 changed_tiling = true;
427 valid = false;
428 if (view->type != C_WORKSPACE) {
429 if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_LEFT) == view) {
430 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20;
431 pointer_state.lock.temp_left = true;
432 } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_RIGHT) == view) {
433 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20;
434 pointer_state.lock.temp_right = true;
435 } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_UP) == view) {
436 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
437 pointer_state.lock.temp_up = true;
438 } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_DOWN) == view) {
439 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
440 pointer_state.lock.temp_down = true;
441 }
442 }
443 }
444
445 if ((dx < 0 || mouse_origin.x < pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_left) {
446 changed_tiling = true;
447 valid = false;
448 } else if (dx > 0 && pointer_state.lock.temp_left) {
449 pointer_state.lock.temp_left = false;
450 pointer_state.tiling.lock_pos.x = 0;
451 }
452
453 if ((dx > 0 || mouse_origin.x > pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_right) {
454 changed_tiling = true;
455 valid = false;
456 } else if (dx < 0 && pointer_state.lock.temp_right) {
457 pointer_state.lock.temp_right = false;
458 pointer_state.tiling.lock_pos.x = 0;
459 }
460
461 if ((dy < 0 || mouse_origin.y < pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_up) {
462 changed_tiling = true;
463 valid = false;
464 } else if (dy > 0 && pointer_state.lock.temp_up) {
465 pointer_state.lock.temp_up = false;
466 pointer_state.tiling.lock_pos.y = 0;
467 }
468
469 if ((dy > 0 || mouse_origin.y > pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_down) {
470 changed_tiling = true;
471 valid = false;
472 } else if (dy < 0 && pointer_state.lock.temp_down) {
473 pointer_state.lock.temp_down = false;
474 pointer_state.tiling.lock_pos.y = 0;
475 }
476
477 if (!view->is_floating && valid) {
478 // Handle layout resizes -- Find the biggest parent container then apply resizes to that
479 // and its bordering siblings
480 swayc_t *parent = view;
481 if (!pointer_state.lock.bottom) {
482 while (parent->type != C_WORKSPACE) {
483 // TODO: Absolute value is a bad hack here to compensate for rounding. Find a better
484 // way of doing this.
485 if (fabs(parent->parent->y + parent->parent->height - (view->y + view->height)) <= 1) {
486 parent = parent->parent;
487 } else {
488 break;
489 }
490 }
491 if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) {
492 swayc_t *sibling = get_swayc_in_direction(parent, MOVE_DOWN);
493 if (sibling) {
494 if ((parent->height > min_sane_h || dy > 0) && (sibling->height > min_sane_h || dy < 0)) {
495 recursive_resize(parent, dy, WLC_RESIZE_EDGE_BOTTOM);
496 recursive_resize(sibling, -1 * dy, WLC_RESIZE_EDGE_TOP);
497 changed_tiling = true;
498 } else {
499 if (parent->height < min_sane_h) {
500 //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
501 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
502 pointer_state.lock.temp_up = true;
503 } else if (sibling->height < min_sane_h) {
504 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
505 pointer_state.lock.temp_down = true;
506 }
507 }
508 }
509 }
510 } else if (!pointer_state.lock.top) {
511 while (parent->type != C_WORKSPACE) {
512 if (fabs(parent->parent->y - view->y) <= 1) {
513 parent = parent->parent;
514 } else {
515 break;
516 }
517 }
518 if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) {
519 swayc_t *sibling = get_swayc_in_direction(parent, MOVE_UP);
520 if (sibling) {
521 if ((parent->height > min_sane_h || dy < 0) && (sibling->height > min_sane_h || dy > 0)) {
522 recursive_resize(parent, -1 * dy, WLC_RESIZE_EDGE_TOP);
523 recursive_resize(sibling, dy, WLC_RESIZE_EDGE_BOTTOM);
524 changed_tiling = true;
525 } else {
526 if (parent->height < min_sane_h) {
527 //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
528 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
529 pointer_state.lock.temp_down = true;
530 } else if (sibling->height < min_sane_h) {
531 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
532 pointer_state.lock.temp_up = true;
533 }
534 }
535 }
536 }
537 }
538
539 parent = view;
540 if (!pointer_state.lock.right) {
541 while (parent->type != C_WORKSPACE) {
542 if (fabs(parent->parent->x + parent->parent->width - (view->x + view->width)) <= 1) {
543 parent = parent->parent;
544 } else {
545 sway_log(L_DEBUG, "view: %f vs parent: %f", view->x + view->width, parent->parent->x + parent->parent->width);
546 break;
547 }
548 }
549 if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) {
550 swayc_t *sibling = get_swayc_in_direction(parent, MOVE_RIGHT);
551 if (sibling) {
552 if ((parent->width > min_sane_w || dx > 0) && (sibling->width > min_sane_w || dx < 0)) {
553 recursive_resize(parent, dx, WLC_RESIZE_EDGE_RIGHT);
554 recursive_resize(sibling, -1 * dx, WLC_RESIZE_EDGE_LEFT);
555 changed_tiling = true;
556 } else {
557 if (parent->width < min_sane_w) {
558 pointer_state.lock.temp_left = true;
559 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20;
560 } else if (sibling->width < min_sane_w) {
561 pointer_state.lock.temp_right = true;
562 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20;
563 } 390 }
564 } 391 }
565 }
566 }
567 } else if (!pointer_state.lock.left) {
568 while (parent->type != C_WORKSPACE) {
569 if (fabs(parent->parent->x - view->x) <= 1 && parent->parent) {
570 parent = parent->parent;
571 } else {
572 break; 392 break;
573 } 393 }
574 } 394 }
575 if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) {
576 swayc_t *sibling = get_swayc_in_direction(parent, MOVE_LEFT);
577 if (sibling) {
578 if ((parent->width > min_sane_w || dx < 0) && (sibling->width > min_sane_w || dx > 0)) {
579 recursive_resize(parent, -1 * dx, WLC_RESIZE_EDGE_LEFT);
580 recursive_resize(sibling, dx, WLC_RESIZE_EDGE_RIGHT);
581 changed_tiling = true;
582 } else {
583 if (parent->width < min_sane_w) {
584 pointer_state.lock.temp_right = true;
585 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20;
586 } else if (sibling->width < min_sane_w) {
587 pointer_state.lock.temp_left = true;
588 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20;
589 }
590 }
591 }
592 }
593 } 395 }
594 arrange_windows(swayc_active_workspace(), -1, -1);
595 } 396 }
397 } else if (pointer_state.floating.resize && view) {
398 changed_floating = resize_floating(prev_pos);
399 } else if (pointer_state.tiling.resize && view) {
400 changed_tiling = mouse_resize_tiled(prev_pos);
596 } 401 }
597 if (config->focus_follows_mouse && prev_handle != handle) { 402 if (config->focus_follows_mouse && prev_handle != handle) {
598 // Dont change focus if fullscreen 403 // Dont change focus if fullscreen
@@ -604,21 +409,7 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct
604 } 409 }
605 prev_handle = handle; 410 prev_handle = handle;
606 prev_pos = mouse_origin; 411 prev_pos = mouse_origin;
607 if (changed_floating) { 412 if (changed_tiling || changed_floating) {
608 struct wlc_geometry geometry = {
609 .origin = {
610 .x = view->x,
611 .y = view->y
612 },
613 .size = {
614 .w = view->width,
615 .h = view->height
616 }
617 };
618 wlc_view_set_geometry(view->handle, edge, &geometry);
619 return true;
620 }
621 if (changed_tiling) {
622 return true; 413 return true;
623 } 414 }
624 return false; 415 return false;
@@ -670,6 +461,7 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w
670 return (pointer_state.floating.drag || pointer_state.floating.resize); 461 return (pointer_state.floating.drag || pointer_state.floating.resize);
671 } else { 462 } else {
672 if (modifiers->mods & config->floating_mod) { 463 if (modifiers->mods & config->floating_mod) {
464 pointer_state.floating.drag = pointer_state.l_held;
673 pointer_state.tiling.resize = pointer_state.r_held; 465 pointer_state.tiling.resize = pointer_state.r_held;
674 pointer_state.tiling.init_view = pointer; 466 pointer_state.tiling.init_view = pointer;
675 // Dont want pointer sent when resizing 467 // Dont want pointer sent when resizing
@@ -682,6 +474,7 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w
682 if (button == M_LEFT_CLICK) { 474 if (button == M_LEFT_CLICK) {
683 pointer_state.l_held = false; 475 pointer_state.l_held = false;
684 pointer_state.floating.drag = false; 476 pointer_state.floating.drag = false;
477 pointer_state.tiling.init_view = NULL;
685 } 478 }
686 if (button == M_RIGHT_CLICK) { 479 if (button == M_RIGHT_CLICK) {
687 pointer_state.r_held = false; 480 pointer_state.r_held = false;
diff --git a/sway/layout.c b/sway/layout.c
index 70d9eb21..18ecb1e7 100644
--- a/sway/layout.c
+++ b/sway/layout.c
@@ -10,6 +10,8 @@
10#include "focus.h" 10#include "focus.h"
11 11
12swayc_t root_container; 12swayc_t root_container;
13int min_sane_h = 60;
14int min_sane_w = 100;
13 15
14void init_layout(void) { 16void init_layout(void) {
15 root_container.type = C_ROOT; 17 root_container.type = C_ROOT;
diff --git a/sway/resize.c b/sway/resize.c
new file mode 100644
index 00000000..a08ef4a1
--- /dev/null
+++ b/sway/resize.c
@@ -0,0 +1,491 @@
1#include <wlc/wlc.h>
2#include <math.h>
3#include "layout.h"
4#include "focus.h"
5#include "log.h"
6#include "input_state.h"
7#include "handlers.h"
8
9bool mouse_resize_tiled(struct wlc_origin prev_pos) {
10 swayc_t *view = container_under_pointer();
11 bool valid = true;
12 bool changed_tiling = false;
13 double dx = mouse_origin.x - prev_pos.x;
14 double dy = mouse_origin.y - prev_pos.y;
15 if (view != pointer_state.tiling.init_view) {
16 changed_tiling = true;
17 valid = false;
18 if (view->type != C_WORKSPACE) {
19 if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_LEFT) == view) {
20 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20;
21 pointer_state.lock.temp_left = true;
22 } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_RIGHT) == view) {
23 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20;
24 pointer_state.lock.temp_right = true;
25 } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_UP) == view) {
26 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
27 pointer_state.lock.temp_up = true;
28 } else if (get_swayc_in_direction(pointer_state.tiling.init_view, MOVE_DOWN) == view) {
29 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
30 pointer_state.lock.temp_down = true;
31 }
32 }
33 }
34
35 if ((dx < 0 || mouse_origin.x < pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_left) {
36 changed_tiling = true;
37 valid = false;
38 } else if (dx > 0 && pointer_state.lock.temp_left) {
39 pointer_state.lock.temp_left = false;
40 pointer_state.tiling.lock_pos.x = 0;
41 }
42
43 if ((dx > 0 || mouse_origin.x > pointer_state.tiling.lock_pos.x) && pointer_state.lock.temp_right) {
44 changed_tiling = true;
45 valid = false;
46 } else if (dx < 0 && pointer_state.lock.temp_right) {
47 pointer_state.lock.temp_right = false;
48 pointer_state.tiling.lock_pos.x = 0;
49 }
50
51 if ((dy < 0 || mouse_origin.y < pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_up) {
52 changed_tiling = true;
53 valid = false;
54 } else if (dy > 0 && pointer_state.lock.temp_up) {
55 pointer_state.lock.temp_up = false;
56 pointer_state.tiling.lock_pos.y = 0;
57 }
58
59 if ((dy > 0 || mouse_origin.y > pointer_state.tiling.lock_pos.y) && pointer_state.lock.temp_down) {
60 changed_tiling = true;
61 valid = false;
62 } else if (dy < 0 && pointer_state.lock.temp_down) {
63 pointer_state.lock.temp_down = false;
64 pointer_state.tiling.lock_pos.y = 0;
65 }
66
67 if (!view->is_floating && valid) {
68 // Handle layout resizes -- Find the biggest parent container then apply resizes to that
69 // and its bordering siblings
70 swayc_t *parent = view;
71 if (!pointer_state.lock.bottom) {
72 while (parent->type != C_WORKSPACE) {
73 // TODO: Absolute value is a bad hack here to compensate for rounding. Find a better
74 // way of doing this.
75 if (fabs(parent->parent->y + parent->parent->height - (view->y + view->height)) <= 1) {
76 parent = parent->parent;
77 } else {
78 break;
79 }
80 }
81 if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) {
82 swayc_t *sibling = get_swayc_in_direction(parent, MOVE_DOWN);
83 if (sibling) {
84 if ((parent->height > min_sane_h || dy > 0) && (sibling->height > min_sane_h || dy < 0)) {
85 recursive_resize(parent, dy, WLC_RESIZE_EDGE_BOTTOM);
86 recursive_resize(sibling, -1 * dy, WLC_RESIZE_EDGE_TOP);
87 changed_tiling = true;
88 } else {
89 if (parent->height < min_sane_h) {
90 //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
91 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
92 pointer_state.lock.temp_up = true;
93 } else if (sibling->height < min_sane_h) {
94 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
95 pointer_state.lock.temp_down = true;
96 }
97 }
98 }
99 }
100 } else if (!pointer_state.lock.top) {
101 while (parent->type != C_WORKSPACE) {
102 if (fabs(parent->parent->y - view->y) <= 1) {
103 parent = parent->parent;
104 } else {
105 break;
106 }
107 }
108 if (parent->parent->children->length > 1 && parent->parent->layout == L_VERT) {
109 swayc_t *sibling = get_swayc_in_direction(parent, MOVE_UP);
110 if (sibling) {
111 if ((parent->height > min_sane_h || dy < 0) && (sibling->height > min_sane_h || dy > 0)) {
112 recursive_resize(parent, -1 * dy, WLC_RESIZE_EDGE_TOP);
113 recursive_resize(sibling, dy, WLC_RESIZE_EDGE_BOTTOM);
114 changed_tiling = true;
115 } else {
116 if (parent->height < min_sane_h) {
117 //pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + pointer_state.tiling.init_view->height - 20;
118 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
119 pointer_state.lock.temp_down = true;
120 } else if (sibling->height < min_sane_h) {
121 pointer_state.tiling.lock_pos.y = pointer_state.tiling.init_view->y + 20;
122 pointer_state.lock.temp_up = true;
123 }
124 }
125 }
126 }
127 }
128
129 parent = view;
130 if (!pointer_state.lock.right) {
131 while (parent->type != C_WORKSPACE) {
132 if (fabs(parent->parent->x + parent->parent->width - (view->x + view->width)) <= 1) {
133 parent = parent->parent;
134 } else {
135 sway_log(L_DEBUG, "view: %f vs parent: %f", view->x + view->width, parent->parent->x + parent->parent->width);
136 break;
137 }
138 }
139 if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) {
140 swayc_t *sibling = get_swayc_in_direction(parent, MOVE_RIGHT);
141 if (sibling) {
142 if ((parent->width > min_sane_w || dx > 0) && (sibling->width > min_sane_w || dx < 0)) {
143 recursive_resize(parent, dx, WLC_RESIZE_EDGE_RIGHT);
144 recursive_resize(sibling, -1 * dx, WLC_RESIZE_EDGE_LEFT);
145 changed_tiling = true;
146 } else {
147 if (parent->width < min_sane_w) {
148 pointer_state.lock.temp_left = true;
149 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20;
150 } else if (sibling->width < min_sane_w) {
151 pointer_state.lock.temp_right = true;
152 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + pointer_state.tiling.init_view->width - 20;
153 }
154 }
155 }
156 }
157 } else if (!pointer_state.lock.left) {
158 while (parent->type != C_WORKSPACE) {
159 if (fabs(parent->parent->x - view->x) <= 1 && parent->parent) {
160 parent = parent->parent;
161 } else {
162 break;
163 }
164 }
165 if (parent->parent->children->length > 1 && parent->parent->layout == L_HORIZ) {
166 swayc_t *sibling = get_swayc_in_direction(parent, MOVE_LEFT);
167 if (sibling) {
168 if ((parent->width > min_sane_w || dx < 0) && (sibling->width > min_sane_w || dx > 0)) {
169 recursive_resize(parent, -1 * dx, WLC_RESIZE_EDGE_LEFT);
170 recursive_resize(sibling, dx, WLC_RESIZE_EDGE_RIGHT);
171 changed_tiling = true;
172 } else {
173 if (parent->width < min_sane_w) {
174 pointer_state.lock.temp_right = true;
175 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20;
176 } else if (sibling->width < min_sane_w) {
177 pointer_state.lock.temp_left = true;
178 pointer_state.tiling.lock_pos.x = pointer_state.tiling.init_view->x + 20;
179 }
180 }
181 }
182 }
183 }
184 arrange_windows(swayc_active_workspace(), -1, -1);
185 }
186 return changed_tiling;
187}
188
189bool resize_floating(struct wlc_origin prev_pos) {
190 bool changed = false;
191 swayc_t *view = container_under_pointer();
192 uint32_t edge = 0;
193 int dx = mouse_origin.x - prev_pos.x;
194 int dy = mouse_origin.y - prev_pos.y;
195
196 // Move and resize the view based on the dx/dy and mouse position
197 int midway_x = view->x + view->width/2;
198 int midway_y = view->y + view->height/2;
199 if (dx < 0) {
200 if (!pointer_state.lock.right) {
201 if (view->width > min_sane_w) {
202 changed = true;
203 view->width += dx;
204 edge += WLC_RESIZE_EDGE_RIGHT;
205 }
206 } else if (mouse_origin.x < midway_x && !pointer_state.lock.left) {
207 changed = true;
208 view->x += dx;
209 view->width -= dx;
210 edge += WLC_RESIZE_EDGE_LEFT;
211 }
212 } else if (dx > 0) {
213 if (mouse_origin.x > midway_x && !pointer_state.lock.right) {
214 changed = true;
215 view->width += dx;
216 edge += WLC_RESIZE_EDGE_RIGHT;
217 } else if (!pointer_state.lock.left) {
218 if (view->width > min_sane_w) {
219 changed = true;
220 view->x += dx;
221 view->width -= dx;
222 edge += WLC_RESIZE_EDGE_LEFT;
223 }
224 }
225 }
226
227 if (dy < 0) {
228 if (!pointer_state.lock.bottom) {
229 if (view->height > min_sane_h) {
230 changed = true;
231 view->height += dy;
232 edge += WLC_RESIZE_EDGE_BOTTOM;
233 }
234 } else if (mouse_origin.y < midway_y && !pointer_state.lock.top) {
235 changed = true;
236 view->y += dy;
237 view->height -= dy;
238 edge += WLC_RESIZE_EDGE_TOP;
239 }
240 } else if (dy > 0) {
241 if (mouse_origin.y > midway_y && !pointer_state.lock.bottom) {
242 changed = true;
243 view->height += dy;
244 edge += WLC_RESIZE_EDGE_BOTTOM;
245 } else if (!pointer_state.lock.top) {
246 if (view->height > min_sane_h) {
247 changed = true;
248 view->y += dy;
249 view->height -= dy;
250 edge += WLC_RESIZE_EDGE_TOP;
251 }
252 }
253 }
254 if (changed) {
255 struct wlc_geometry geometry = {
256 .origin = {
257 .x = view->x,
258 .y = view->y
259 },
260 .size = {
261 .w = view->width,
262 .h = view->height
263 }
264 };
265 wlc_view_set_geometry(view->handle, edge, &geometry);
266 }
267 return changed;
268}
269
270bool resize_tiled(int amount, bool use_width) {
271 swayc_t *parent = get_focused_view(swayc_active_workspace());
272 swayc_t *focused = parent;
273 swayc_t *sibling;
274 if (!parent) {
275 return true;
276 }
277 // Find the closest parent container which has siblings of the proper layout.
278 // Then apply the resize to all of them.
279 int i;
280 if (use_width) {
281 int lnumber = 0;
282 int rnumber = 0;
283 while (parent->parent) {
284 if (parent->parent->layout == L_HORIZ) {
285 for (i = 0; i < parent->parent->children->length; i++) {
286 sibling = parent->parent->children->items[i];
287 if (sibling->x != focused->x) {
288 if (sibling->x < parent->x) {
289 lnumber++;
290 } else if (sibling->x > parent->x) {
291 rnumber++;
292 }
293 }
294 }
295 if (rnumber || lnumber) {
296 break;
297 }
298 }
299 parent = parent->parent;
300 }
301 if (parent == &root_container) {
302 return true;
303 }
304 sway_log(L_DEBUG, "Found the proper parent: %p. It has %d l conts, and %d r conts", parent->parent, lnumber, rnumber);
305 //TODO: Ensure rounding is done in such a way that there are NO pixel leaks
306 bool valid = true;
307 for (i = 0; i < parent->parent->children->length; i++) {
308 sibling = parent->parent->children->items[i];
309 if (sibling->x != focused->x) {
310 if (sibling->x < parent->x) {
311 double pixels = -1 * amount;
312 pixels /= lnumber;
313 if (rnumber) {
314 if ((sibling->width + pixels/2) < min_sane_w) {
315 valid = false;
316 break;
317 }
318 } else {
319 if ((sibling->width + pixels) < min_sane_w) {
320 valid = false;
321 break;
322 }
323 }
324 } else if (sibling->x > parent->x) {
325 double pixels = -1 * amount;
326 pixels /= rnumber;
327 if (lnumber) {
328 if ((sibling->width + pixels/2) < min_sane_w) {
329 valid = false;
330 break;
331 }
332 } else {
333 if ((sibling->width + pixels) < min_sane_w) {
334 valid = false;
335 break;
336 }
337 }
338 }
339 } else {
340 double pixels = amount;
341 if (parent->width + pixels < min_sane_w) {
342 valid = false;
343 break;
344 }
345 }
346 }
347 if (valid) {
348 for (i = 0; i < parent->parent->children->length; i++) {
349 sibling = parent->parent->children->items[i];
350 if (sibling->x != focused->x) {
351 if (sibling->x < parent->x) {
352 double pixels = -1 * amount;
353 pixels /= lnumber;
354 if (rnumber) {
355 recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_RIGHT);
356 } else {
357 recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_RIGHT);
358 }
359 } else if (sibling->x > parent->x) {
360 double pixels = -1 * amount;
361 pixels /= rnumber;
362 if (lnumber) {
363 recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_LEFT);
364 } else {
365 recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_LEFT);
366 }
367 }
368 } else {
369 if (rnumber != 0 && lnumber != 0) {
370 double pixels = amount;
371 pixels /= 2;
372 recursive_resize(parent, pixels, WLC_RESIZE_EDGE_LEFT);
373 recursive_resize(parent, pixels, WLC_RESIZE_EDGE_RIGHT);
374 } else if (rnumber) {
375 recursive_resize(parent, amount, WLC_RESIZE_EDGE_RIGHT);
376 } else if (lnumber) {
377 recursive_resize(parent, amount, WLC_RESIZE_EDGE_LEFT);
378 }
379 }
380 }
381 // Recursive resize does not handle positions, let arrange_windows
382 // take care of that.
383 arrange_windows(swayc_active_workspace(), -1, -1);
384 }
385 return true;
386 } else {
387 int tnumber = 0;
388 int bnumber = 0;
389 while (parent->parent) {
390 if (parent->parent->layout == L_VERT) {
391 for (i = 0; i < parent->parent->children->length; i++) {
392 sibling = parent->parent->children->items[i];
393 if (sibling->y != focused->y) {
394 if (sibling->y < parent->y) {
395 bnumber++;
396 } else if (sibling->y > parent->y) {
397 tnumber++;
398 }
399 }
400 }
401 if (bnumber || tnumber) {
402 break;
403 }
404 }
405 parent = parent->parent;
406 }
407 if (parent == &root_container) {
408 return true;
409 }
410 sway_log(L_DEBUG, "Found the proper parent: %p. It has %d b conts, and %d t conts", parent->parent, bnumber, tnumber);
411 //TODO: Ensure rounding is done in such a way that there are NO pixel leaks
412 bool valid = true;
413 for (i = 0; i < parent->parent->children->length; i++) {
414 sibling = parent->parent->children->items[i];
415 if (sibling->y != focused->y) {
416 if (sibling->y < parent->y) {
417 double pixels = -1 * amount;
418 pixels /= bnumber;
419 if (tnumber) {
420 if ((sibling->height + pixels/2) < min_sane_h) {
421 valid = false;
422 break;
423 }
424 } else {
425 if ((sibling->height + pixels) < min_sane_h) {
426 valid = false;
427 break;
428 }
429 }
430 } else if (sibling->y > parent->y) {
431 double pixels = -1 * amount;
432 pixels /= tnumber;
433 if (bnumber) {
434 if ((sibling->height + pixels/2) < min_sane_h) {
435 valid = false;
436 break;
437 }
438 } else {
439 if ((sibling->height + pixels) < min_sane_h) {
440 valid = false;
441 break;
442 }
443 }
444 }
445 } else {
446 double pixels = amount;
447 if (parent->height + pixels < min_sane_h) {
448 valid = false;
449 break;
450 }
451 }
452 }
453 if (valid) {
454 for (i = 0; i < parent->parent->children->length; i++) {
455 sibling = parent->parent->children->items[i];
456 if (sibling->y != focused->y) {
457 if (sibling->y < parent->y) {
458 double pixels = -1 * amount;
459 pixels /= bnumber;
460 if (tnumber) {
461 recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_BOTTOM);
462 } else {
463 recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_BOTTOM);
464 }
465 } else if (sibling->x > parent->x) {
466 double pixels = -1 * amount;
467 pixels /= tnumber;
468 if (bnumber) {
469 recursive_resize(sibling, pixels/2, WLC_RESIZE_EDGE_TOP);
470 } else {
471 recursive_resize(sibling, pixels, WLC_RESIZE_EDGE_TOP);
472 }
473 }
474 } else {
475 if (bnumber != 0 && tnumber != 0) {
476 double pixels = amount/2;
477 recursive_resize(parent, pixels, WLC_RESIZE_EDGE_TOP);
478 recursive_resize(parent, pixels, WLC_RESIZE_EDGE_BOTTOM);
479 } else if (tnumber) {
480 recursive_resize(parent, amount, WLC_RESIZE_EDGE_TOP);
481 } else if (bnumber) {
482 recursive_resize(parent, amount, WLC_RESIZE_EDGE_BOTTOM);
483 }
484 }
485 }
486 arrange_windows(swayc_active_workspace(), -1, -1);
487 }
488 return true;
489 }
490 return true;
491}