diff options
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r-- | sway/desktop/output.c | 124 |
1 files changed, 74 insertions, 50 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index b8f2d32d..2722e556 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -521,9 +521,7 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
521 | sway_session_lock_add_output(server->session_lock.lock, output); | 521 | sway_session_lock_add_output(server->session_lock.lock, output); |
522 | } | 522 | } |
523 | 523 | ||
524 | struct output_config *oc = find_output_config(output); | 524 | apply_all_output_configs(); |
525 | apply_output_config(oc, output); | ||
526 | free_output_config(oc); | ||
527 | 525 | ||
528 | transaction_commit_dirty(); | 526 | transaction_commit_dirty(); |
529 | 527 | ||
@@ -552,63 +550,89 @@ void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data) { | |||
552 | wlr_output_schedule_frame(output->wlr_output); | 550 | wlr_output_schedule_frame(output->wlr_output); |
553 | } | 551 | } |
554 | 552 | ||
553 | static struct output_config *output_config_for_config_head( | ||
554 | struct wlr_output_configuration_head_v1 *config_head, | ||
555 | struct sway_output *output) { | ||
556 | struct output_config *oc = new_output_config(output->wlr_output->name); | ||
557 | oc->enabled = config_head->state.enabled; | ||
558 | if (!oc->enabled) { | ||
559 | return oc; | ||
560 | } | ||
561 | |||
562 | if (config_head->state.mode != NULL) { | ||
563 | struct wlr_output_mode *mode = config_head->state.mode; | ||
564 | oc->width = mode->width; | ||
565 | oc->height = mode->height; | ||
566 | oc->refresh_rate = mode->refresh / 1000.f; | ||
567 | } else { | ||
568 | oc->width = config_head->state.custom_mode.width; | ||
569 | oc->height = config_head->state.custom_mode.height; | ||
570 | oc->refresh_rate = | ||
571 | config_head->state.custom_mode.refresh / 1000.f; | ||
572 | } | ||
573 | oc->x = config_head->state.x; | ||
574 | oc->y = config_head->state.y; | ||
575 | oc->transform = config_head->state.transform; | ||
576 | oc->scale = config_head->state.scale; | ||
577 | oc->adaptive_sync = config_head->state.adaptive_sync_enabled; | ||
578 | return oc; | ||
579 | } | ||
580 | |||
555 | static void output_manager_apply(struct sway_server *server, | 581 | static void output_manager_apply(struct sway_server *server, |
556 | struct wlr_output_configuration_v1 *config, bool test_only) { | 582 | struct wlr_output_configuration_v1 *config, bool test_only) { |
557 | // TODO: perform atomic tests on the whole backend atomically | 583 | size_t configs_len = wl_list_length(&root->all_outputs); |
558 | 584 | struct matched_output_config *configs = calloc(configs_len, sizeof(*configs)); | |
559 | struct wlr_output_configuration_head_v1 *config_head; | 585 | if (!configs) { |
560 | // First disable outputs we need to disable | 586 | return; |
561 | bool ok = true; | 587 | } |
562 | wl_list_for_each(config_head, &config->heads, link) { | 588 | |
563 | struct wlr_output *wlr_output = config_head->state.output; | 589 | int config_idx = 0; |
564 | struct sway_output *output = wlr_output->data; | 590 | struct sway_output *sway_output; |
565 | if (!output->enabled || config_head->state.enabled) { | 591 | wl_list_for_each(sway_output, &root->all_outputs, link) { |
592 | if (sway_output == root->fallback_output) { | ||
593 | configs_len--; | ||
566 | continue; | 594 | continue; |
567 | } | 595 | } |
568 | struct output_config *oc = new_output_config(output->wlr_output->name); | ||
569 | oc->enabled = false; | ||
570 | 596 | ||
571 | if (test_only) { | 597 | struct matched_output_config *cfg = &configs[config_idx++]; |
572 | ok &= test_output_config(oc, output); | 598 | cfg->output = sway_output; |
573 | } else { | 599 | |
574 | oc = store_output_config(oc); | 600 | struct wlr_output_configuration_head_v1 *config_head; |
575 | ok &= apply_output_config(oc, output); | 601 | wl_list_for_each(config_head, &config->heads, link) { |
602 | if (config_head->state.output == sway_output->wlr_output) { | ||
603 | cfg->config = output_config_for_config_head(config_head, sway_output); | ||
604 | break; | ||
605 | } | ||
606 | } | ||
607 | if (!cfg->config) { | ||
608 | cfg->config = find_output_config(sway_output); | ||
576 | } | 609 | } |
577 | } | 610 | } |
578 | 611 | ||
579 | // Then enable outputs that need to | 612 | sort_output_configs_by_priority(configs, configs_len); |
580 | wl_list_for_each(config_head, &config->heads, link) { | 613 | bool ok = apply_output_configs(configs, configs_len, test_only, false); |
581 | struct wlr_output *wlr_output = config_head->state.output; | 614 | for (size_t idx = 0; idx < configs_len; idx++) { |
582 | struct sway_output *output = wlr_output->data; | 615 | struct matched_output_config *cfg = &configs[idx]; |
583 | if (!config_head->state.enabled) { | 616 | |
584 | continue; | 617 | // Only store new configs for successful non-test commits. Old configs, |
585 | } | 618 | // test-only and failed commits just get freed. |
586 | struct output_config *oc = new_output_config(output->wlr_output->name); | 619 | bool store_config = false; |
587 | oc->enabled = true; | 620 | if (!test_only && ok) { |
588 | if (config_head->state.mode != NULL) { | 621 | struct wlr_output_configuration_head_v1 *config_head; |
589 | struct wlr_output_mode *mode = config_head->state.mode; | 622 | wl_list_for_each(config_head, &config->heads, link) { |
590 | oc->width = mode->width; | 623 | if (config_head->state.output == cfg->output->wlr_output) { |
591 | oc->height = mode->height; | 624 | store_config = true; |
592 | oc->refresh_rate = mode->refresh / 1000.f; | 625 | break; |
593 | } else { | 626 | } |
594 | oc->width = config_head->state.custom_mode.width; | 627 | } |
595 | oc->height = config_head->state.custom_mode.height; | ||
596 | oc->refresh_rate = | ||
597 | config_head->state.custom_mode.refresh / 1000.f; | ||
598 | } | 628 | } |
599 | oc->x = config_head->state.x; | 629 | if (store_config) { |
600 | oc->y = config_head->state.y; | 630 | store_output_config(cfg->config); |
601 | oc->transform = config_head->state.transform; | ||
602 | oc->scale = config_head->state.scale; | ||
603 | oc->adaptive_sync = config_head->state.adaptive_sync_enabled; | ||
604 | |||
605 | if (test_only) { | ||
606 | ok &= test_output_config(oc, output); | ||
607 | } else { | 631 | } else { |
608 | oc = store_output_config(oc); | 632 | free_output_config(cfg->config); |
609 | ok &= apply_output_config(oc, output); | ||
610 | } | 633 | } |
611 | } | 634 | } |
635 | free(configs); | ||
612 | 636 | ||
613 | if (ok) { | 637 | if (ok) { |
614 | wlr_output_configuration_v1_send_succeeded(config); | 638 | wlr_output_configuration_v1_send_succeeded(config); |
@@ -652,6 +676,6 @@ void handle_output_power_manager_set_mode(struct wl_listener *listener, | |||
652 | oc->power = 1; | 676 | oc->power = 1; |
653 | break; | 677 | break; |
654 | } | 678 | } |
655 | oc = store_output_config(oc); | 679 | store_output_config(oc); |
656 | apply_output_config(oc, output); | 680 | apply_all_output_configs(); |
657 | } | 681 | } |