|
|
@ -550,63 +550,88 @@ void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data) {
|
|
|
|
wlr_output_schedule_frame(output->wlr_output);
|
|
|
|
wlr_output_schedule_frame(output->wlr_output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct output_config *output_config_for_config_head(
|
|
|
|
|
|
|
|
struct wlr_output_configuration_head_v1 *config_head,
|
|
|
|
|
|
|
|
struct sway_output *output) {
|
|
|
|
|
|
|
|
struct output_config *oc = new_output_config(output->wlr_output->name);
|
|
|
|
|
|
|
|
oc->enabled = config_head->state.enabled;
|
|
|
|
|
|
|
|
if (!oc->enabled) {
|
|
|
|
|
|
|
|
return oc;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (config_head->state.mode != NULL) {
|
|
|
|
|
|
|
|
struct wlr_output_mode *mode = config_head->state.mode;
|
|
|
|
|
|
|
|
oc->width = mode->width;
|
|
|
|
|
|
|
|
oc->height = mode->height;
|
|
|
|
|
|
|
|
oc->refresh_rate = mode->refresh / 1000.f;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
oc->width = config_head->state.custom_mode.width;
|
|
|
|
|
|
|
|
oc->height = config_head->state.custom_mode.height;
|
|
|
|
|
|
|
|
oc->refresh_rate =
|
|
|
|
|
|
|
|
config_head->state.custom_mode.refresh / 1000.f;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
oc->x = config_head->state.x;
|
|
|
|
|
|
|
|
oc->y = config_head->state.y;
|
|
|
|
|
|
|
|
oc->transform = config_head->state.transform;
|
|
|
|
|
|
|
|
oc->scale = config_head->state.scale;
|
|
|
|
|
|
|
|
oc->adaptive_sync = config_head->state.adaptive_sync_enabled;
|
|
|
|
|
|
|
|
return oc;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void output_manager_apply(struct sway_server *server,
|
|
|
|
static void output_manager_apply(struct sway_server *server,
|
|
|
|
struct wlr_output_configuration_v1 *config, bool test_only) {
|
|
|
|
struct wlr_output_configuration_v1 *config, bool test_only) {
|
|
|
|
// TODO: perform atomic tests on the whole backend atomically
|
|
|
|
size_t configs_len = wl_list_length(&root->all_outputs);
|
|
|
|
|
|
|
|
struct matched_output_config *configs = calloc(configs_len, sizeof(*configs));
|
|
|
|
struct wlr_output_configuration_head_v1 *config_head;
|
|
|
|
if (!configs) {
|
|
|
|
// First disable outputs we need to disable
|
|
|
|
return;
|
|
|
|
bool ok = true;
|
|
|
|
}
|
|
|
|
wl_list_for_each(config_head, &config->heads, link) {
|
|
|
|
|
|
|
|
struct wlr_output *wlr_output = config_head->state.output;
|
|
|
|
int config_idx = 0;
|
|
|
|
struct sway_output *output = wlr_output->data;
|
|
|
|
struct sway_output *sway_output;
|
|
|
|
if (!output->enabled || config_head->state.enabled) {
|
|
|
|
wl_list_for_each(sway_output, &root->all_outputs, link) {
|
|
|
|
|
|
|
|
if (sway_output == root->fallback_output) {
|
|
|
|
|
|
|
|
configs_len--;
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
struct output_config *oc = new_output_config(output->wlr_output->name);
|
|
|
|
|
|
|
|
oc->enabled = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (test_only) {
|
|
|
|
struct matched_output_config *cfg = &configs[config_idx++];
|
|
|
|
ok &= test_output_config(oc, output);
|
|
|
|
cfg->output = sway_output;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
oc = store_output_config(oc);
|
|
|
|
struct wlr_output_configuration_head_v1 *config_head;
|
|
|
|
ok &= apply_output_config(oc, output);
|
|
|
|
wl_list_for_each(config_head, &config->heads, link) {
|
|
|
|
|
|
|
|
if (config_head->state.output == sway_output->wlr_output) {
|
|
|
|
|
|
|
|
cfg->config = output_config_for_config_head(config_head, sway_output);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cfg->config) {
|
|
|
|
|
|
|
|
cfg->config = find_output_config(sway_output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Then enable outputs that need to
|
|
|
|
bool ok = apply_output_configs(configs, configs_len, test_only);
|
|
|
|
wl_list_for_each(config_head, &config->heads, link) {
|
|
|
|
for (size_t idx = 0; idx < configs_len; idx++) {
|
|
|
|
struct wlr_output *wlr_output = config_head->state.output;
|
|
|
|
struct matched_output_config *cfg = &configs[idx];
|
|
|
|
struct sway_output *output = wlr_output->data;
|
|
|
|
|
|
|
|
if (!config_head->state.enabled) {
|
|
|
|
// Only store new configs for successful non-test commits. Old configs,
|
|
|
|
continue;
|
|
|
|
// test-only and failed commits just get freed.
|
|
|
|
}
|
|
|
|
bool store_config = false;
|
|
|
|
struct output_config *oc = new_output_config(output->wlr_output->name);
|
|
|
|
if (!test_only && ok) {
|
|
|
|
oc->enabled = true;
|
|
|
|
struct wlr_output_configuration_head_v1 *config_head;
|
|
|
|
if (config_head->state.mode != NULL) {
|
|
|
|
wl_list_for_each(config_head, &config->heads, link) {
|
|
|
|
struct wlr_output_mode *mode = config_head->state.mode;
|
|
|
|
if (config_head->state.output == sway_output->wlr_output) {
|
|
|
|
oc->width = mode->width;
|
|
|
|
store_config = true;
|
|
|
|
oc->height = mode->height;
|
|
|
|
break;
|
|
|
|
oc->refresh_rate = mode->refresh / 1000.f;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
oc->width = config_head->state.custom_mode.width;
|
|
|
|
|
|
|
|
oc->height = config_head->state.custom_mode.height;
|
|
|
|
|
|
|
|
oc->refresh_rate =
|
|
|
|
|
|
|
|
config_head->state.custom_mode.refresh / 1000.f;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
oc->x = config_head->state.x;
|
|
|
|
if (store_config) {
|
|
|
|
oc->y = config_head->state.y;
|
|
|
|
store_output_config(cfg->config);
|
|
|
|
oc->transform = config_head->state.transform;
|
|
|
|
|
|
|
|
oc->scale = config_head->state.scale;
|
|
|
|
|
|
|
|
oc->adaptive_sync = config_head->state.adaptive_sync_enabled;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (test_only) {
|
|
|
|
|
|
|
|
ok &= test_output_config(oc, output);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
oc = store_output_config(oc);
|
|
|
|
free_output_config(cfg->config);
|
|
|
|
ok &= apply_output_config(oc, output);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(configs);
|
|
|
|
|
|
|
|
|
|
|
|
if (ok) {
|
|
|
|
if (ok) {
|
|
|
|
wlr_output_configuration_v1_send_succeeded(config);
|
|
|
|
wlr_output_configuration_v1_send_succeeded(config);
|
|
|
|