aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/view.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-07-25 23:34:00 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-07-26 19:18:47 +1000
commita90f2dbde9866a34e91b242bb06071e471d32eb3 (patch)
tree9176e2b130151b4ea3aadfcbde64d18352bab517 /sway/tree/view.c
parentMerge pull request #2356 from RyanDwyer/fullscreen-containers (diff)
downloadsway-a90f2dbde9866a34e91b242bb06071e471d32eb3.tar.gz
sway-a90f2dbde9866a34e91b242bb06071e471d32eb3.tar.zst
sway-a90f2dbde9866a34e91b242bb06071e471d32eb3.zip
Refactor view_map
* Move workspace selection into separate function * Instead of keeping a `prev_focus` variable, do the check in `should_focus` (ie. views can only take focus if they're mapped into the active workspace) * Fix assign-to-output - it previously set `prev_focus` but should be `target_sibling` * Remove call to `workspace_switch` as we'll only ever focus the view if it's in the active workspace
Diffstat (limited to 'sway/tree/view.c')
-rw-r--r--sway/tree/view.c138
1 files changed, 75 insertions, 63 deletions
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 82c3ad4a..fec628e1 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -476,97 +476,112 @@ void view_execute_criteria(struct sway_view *view) {
476 seat_set_focus(seat, prior_focus); 476 seat_set_focus(seat, prior_focus);
477} 477}
478 478
479static bool should_focus(struct sway_view *view) { 479static struct sway_container *select_workspace(struct sway_view *view) {
480 // If the view is the only one in the focused workspace, it'll get focus
481 // regardless of any no_focus criteria.
482 struct sway_container *parent = view->swayc->parent;
483 struct sway_seat *seat = input_manager_current_seat(input_manager); 480 struct sway_seat *seat = input_manager_current_seat(input_manager);
484 if (parent->type == C_WORKSPACE && seat_get_focus(seat) == parent) { 481
485 size_t num_children = parent->children->length + 482 // Check if there's any `assign` criteria for the view
486 parent->sway_workspace->floating->children->length; 483 list_t *criterias = criteria_for_view(view,
487 if (num_children == 1) { 484 CT_ASSIGN_WORKSPACE | CT_ASSIGN_OUTPUT);
488 return true; 485 struct sway_container *ws = NULL;
486 for (int i = 0; i < criterias->length; ++i) {
487 struct criteria *criteria = criterias->items[i];
488 if (criteria->type == CT_ASSIGN_WORKSPACE) {
489 struct sway_container *ws = workspace_by_name(criteria->target);
490 if (!ws) {
491 ws = workspace_create(NULL, criteria->target);
492 }
493 break;
494 } else {
495 // CT_ASSIGN_OUTPUT
496 struct sway_container *output = output_by_name(criteria->target);
497 if (output) {
498 ws = seat_get_active_child(seat, output);
499 break;
500 }
489 } 501 }
490 } 502 }
491
492 // Check no_focus criteria
493 list_t *criterias = criteria_for_view(view, CT_NO_FOCUS);
494 size_t len = criterias->length;
495 list_free(criterias); 503 list_free(criterias);
496 return len == 0; 504 if (ws) {
497} 505 return ws;
498
499void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
500 if (!sway_assert(view->surface == NULL, "cannot map mapped view")) {
501 return;
502 } 506 }
503 507
508 // Check if there's a PID mapping
504 pid_t pid; 509 pid_t pid;
505#ifdef HAVE_XWAYLAND 510#ifdef HAVE_XWAYLAND
506 if (view->type == SWAY_VIEW_XWAYLAND) { 511 if (view->type == SWAY_VIEW_XWAYLAND) {
507 struct wlr_xwayland_surface *surf = 512 struct wlr_xwayland_surface *surf =
508 wlr_xwayland_surface_from_wlr_surface(wlr_surface); 513 wlr_xwayland_surface_from_wlr_surface(view->surface);
509 pid = surf->pid; 514 pid = surf->pid;
510 } else { 515 } else {
511 struct wl_client *client = 516 struct wl_client *client =
512 wl_resource_get_client(wlr_surface->resource); 517 wl_resource_get_client(view->surface->resource);
513 wl_client_get_credentials(client, &pid, NULL, NULL); 518 wl_client_get_credentials(client, &pid, NULL, NULL);
514 } 519 }
515#else 520#else
516 struct wl_client *client = 521 struct wl_client *client =
517 wl_resource_get_client(wlr_surface->resource); 522 wl_resource_get_client(view->surface->resource);
518 wl_client_get_credentials(client, &pid, NULL, NULL); 523 wl_client_get_credentials(client, &pid, NULL, NULL);
519#endif 524#endif
525 ws = workspace_for_pid(pid);
526 if (ws) {
527 return ws;
528 }
520 529
530 // Use the focused workspace
531 ws = seat_get_focus(seat);
532 if (ws->type != C_WORKSPACE) {
533 ws = container_parent(ws, C_WORKSPACE);
534 }
535 return ws;
536}
537
538static bool should_focus(struct sway_view *view) {
521 struct sway_seat *seat = input_manager_current_seat(input_manager); 539 struct sway_seat *seat = input_manager_current_seat(input_manager);
522 struct sway_container *target_sibling = 540 struct sway_container *prev_focus = seat_get_focus(seat);
523 seat_get_focus_inactive(seat, &root_container); 541 struct sway_container *prev_ws = prev_focus->type == C_WORKSPACE ?
524 struct sway_container *prev_focus = target_sibling; 542 prev_focus : container_parent(prev_focus, C_WORKSPACE);
525 struct sway_container *cont = NULL; 543 struct sway_container *map_ws = container_parent(view->swayc, C_WORKSPACE);
526 544
527 // Check if there's any `assign` criteria for the view 545 // Views can only take focus if they are mapped into the active workspace
528 list_t *criterias = criteria_for_view(view, 546 if (prev_ws != map_ws) {
529 CT_ASSIGN_WORKSPACE | CT_ASSIGN_OUTPUT); 547 return false;
530 struct sway_container *workspace = NULL; 548 }
531 if (criterias->length) { 549
532 struct criteria *criteria = criterias->items[0]; 550 // If the view is the only one in the focused workspace, it'll get focus
533 if (criteria->type == CT_ASSIGN_WORKSPACE) { 551 // regardless of any no_focus criteria.
534 workspace = workspace_by_name(criteria->target); 552 struct sway_container *parent = view->swayc->parent;
535 if (!workspace) { 553 if (parent->type == C_WORKSPACE && prev_focus == parent) {
536 workspace = workspace_create(NULL, criteria->target); 554 size_t num_children = parent->children->length +
537 } 555 parent->sway_workspace->floating->children->length;
538 prev_focus = target_sibling; 556 if (num_children == 1) {
539 target_sibling = seat_get_focus_inactive(seat, workspace); 557 return true;
540 } else {
541 // CT_ASSIGN_OUTPUT
542 struct sway_container *output = output_by_name(criteria->target);
543 if (output) {
544 prev_focus = seat_get_focus_inactive(seat, output);
545 }
546 } 558 }
547 } 559 }
560
561 // Check no_focus criteria
562 list_t *criterias = criteria_for_view(view, CT_NO_FOCUS);
563 size_t len = criterias->length;
548 list_free(criterias); 564 list_free(criterias);
565 return len == 0;
566}
549 567
550 if (!workspace) { 568void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
551 workspace = workspace_for_pid(pid); 569 if (!sway_assert(view->surface == NULL, "cannot map mapped view")) {
552 if (workspace) { 570 return;
553 prev_focus = target_sibling;
554 target_sibling = seat_get_focus_inactive(seat, workspace);
555 }
556 } 571 }
572 view->surface = wlr_surface;
573
574 struct sway_seat *seat = input_manager_current_seat(input_manager);
575 struct sway_container *ws = select_workspace(view);
576 struct sway_container *target_sibling = seat_get_focus_inactive(seat, ws);
577
557 // If we're about to launch the view into the floating container, then 578 // If we're about to launch the view into the floating container, then
558 // launch it as a tiled view in the root of the workspace instead. 579 // launch it as a tiled view in the root of the workspace instead.
559 if (container_is_floating(target_sibling)) { 580 if (container_is_floating(target_sibling)) {
560 if (prev_focus == target_sibling) {
561 prev_focus = target_sibling->parent->parent;
562 }
563 target_sibling = target_sibling->parent->parent; 581 target_sibling = target_sibling->parent->parent;
564 } 582 }
565 583
566 cont = container_view_create(target_sibling, view); 584 view->swayc = container_view_create(target_sibling, view);
567
568 view->surface = wlr_surface;
569 view->swayc = cont;
570 585
571 view_init_subsurfaces(view, wlr_surface); 586 view_init_subsurfaces(view, wlr_surface);
572 wl_signal_add(&wlr_surface->events.new_subsurface, 587 wl_signal_add(&wlr_surface->events.new_subsurface,
@@ -586,11 +601,8 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
586 view_set_tiled(view, true); 601 view_set_tiled(view, true);
587 } 602 }
588 603
589 if (should_focus(view) && prev_focus == target_sibling) { 604 if (should_focus(view)) {
590 input_manager_set_focus(input_manager, cont); 605 input_manager_set_focus(input_manager, view->swayc);
591 if (workspace) {
592 workspace_switch(workspace);
593 }
594 } 606 }
595 607
596 view_update_title(view, false); 608 view_update_title(view, false);