output-management-v1: support applying configuration
This commit is contained in:
parent
d71ebde545
commit
8136605cfb
|
@ -61,6 +61,8 @@ void output_for_each_surface(struct roots_output *output,
|
||||||
roots_surface_iterator_func_t iterator, void *user_data);
|
roots_surface_iterator_func_t iterator, void *user_data);
|
||||||
|
|
||||||
void handle_new_output(struct wl_listener *listener, void *data);
|
void handle_new_output(struct wl_listener *listener, void *data);
|
||||||
|
void handle_output_manager_apply(struct wl_listener *listener, void *data);
|
||||||
|
void handle_output_manager_test(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
struct roots_view;
|
struct roots_view;
|
||||||
struct roots_drag_icon;
|
struct roots_drag_icon;
|
||||||
|
|
|
@ -56,11 +56,12 @@ struct wlr_output_head_v1 {
|
||||||
struct wlr_output_configuration_v1 {
|
struct wlr_output_configuration_v1 {
|
||||||
struct wl_list heads; // wlr_output_configuration_head_v1::link
|
struct wl_list heads; // wlr_output_configuration_head_v1::link
|
||||||
|
|
||||||
|
// client state
|
||||||
struct wlr_output_manager_v1 *manager;
|
struct wlr_output_manager_v1 *manager;
|
||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
bool finalized; // client has requested to apply the config
|
bool finalized; // client has requested to apply the config
|
||||||
bool finished; // feedback has been sent by the compositor
|
bool finished; // feedback has been sent by the compositor
|
||||||
struct wl_resource *resource; // can be NULL
|
struct wl_resource *resource; // can be NULL if destroyed early
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_output_configuration_head_v1 {
|
struct wlr_output_configuration_head_v1 {
|
||||||
|
@ -68,7 +69,8 @@ struct wlr_output_configuration_head_v1 {
|
||||||
struct wlr_output_configuration_v1 *config;
|
struct wlr_output_configuration_v1 *config;
|
||||||
struct wl_list link; // wlr_output_configuration_v1::heads
|
struct wl_list link; // wlr_output_configuration_v1::heads
|
||||||
|
|
||||||
struct wl_resource *resource; // can be NULL
|
// client state
|
||||||
|
struct wl_resource *resource; // can be NULL if finalized or disabled
|
||||||
|
|
||||||
struct wl_listener output_destroy;
|
struct wl_listener output_destroy;
|
||||||
};
|
};
|
||||||
|
|
|
@ -294,26 +294,6 @@ static void handle_pointer_constraint(struct wl_listener *listener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_output_manager_apply(struct wl_listener *listener,
|
|
||||||
void *data) {
|
|
||||||
struct roots_desktop *desktop =
|
|
||||||
wl_container_of(listener, desktop, output_manager_apply);
|
|
||||||
struct wlr_output_configuration_v1 *config = data;
|
|
||||||
(void)config;
|
|
||||||
wlr_log(WLR_DEBUG, "APPLY"); // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_output_manager_test(struct wl_listener *listener,
|
|
||||||
void *data) {
|
|
||||||
struct roots_desktop *desktop =
|
|
||||||
wl_container_of(listener, desktop, output_manager_test);
|
|
||||||
struct wlr_output_configuration_v1 *config = data;
|
|
||||||
|
|
||||||
// TODO: implement test-only mode
|
|
||||||
wlr_output_configuration_v1_send_succeeded(config);
|
|
||||||
wlr_output_configuration_v1_destroy(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct roots_desktop *desktop_create(struct roots_server *server,
|
struct roots_desktop *desktop_create(struct roots_server *server,
|
||||||
struct roots_config *config) {
|
struct roots_config *config) {
|
||||||
wlr_log(WLR_DEBUG, "Initializing roots desktop");
|
wlr_log(WLR_DEBUG, "Initializing roots desktop");
|
||||||
|
|
|
@ -430,14 +430,54 @@ static void update_output_manager_config(struct roots_desktop *desktop) {
|
||||||
|
|
||||||
struct roots_output *output;
|
struct roots_output *output;
|
||||||
wl_list_for_each(output, &desktop->outputs, link) {
|
wl_list_for_each(output, &desktop->outputs, link) {
|
||||||
struct wlr_output_configuration_head_v1 *head =
|
|
||||||
wlr_output_configuration_head_v1_create(config, output->wlr_output);
|
wlr_output_configuration_head_v1_create(config, output->wlr_output);
|
||||||
(void)head;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_output_manager_v1_set_configuration(desktop->output_manager_v1, config);
|
wlr_output_manager_v1_set_configuration(desktop->output_manager_v1, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_output_manager_apply(struct wl_listener *listener, void *data) {
|
||||||
|
struct roots_desktop *desktop =
|
||||||
|
wl_container_of(listener, desktop, output_manager_apply);
|
||||||
|
struct wlr_output_configuration_v1 *config = data;
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
struct wlr_output_configuration_head_v1 *config_head;
|
||||||
|
wl_list_for_each(config_head, &config->heads, link) {
|
||||||
|
struct wlr_output *wlr_output = config_head->state.output;
|
||||||
|
ok &= wlr_output_enable(wlr_output, config_head->state.enabled);
|
||||||
|
if (!config_head->state.enabled) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (config_head->state.mode != NULL) {
|
||||||
|
ok &= wlr_output_set_mode(wlr_output, config_head->state.mode);
|
||||||
|
}
|
||||||
|
wlr_output_layout_add(desktop->layout, wlr_output,
|
||||||
|
config_head->state.x, config_head->state.y);
|
||||||
|
wlr_output_set_transform(wlr_output, config_head->state.transform);
|
||||||
|
wlr_output_set_scale(wlr_output, config_head->state.scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
wlr_output_configuration_v1_send_succeeded(config);
|
||||||
|
} else {
|
||||||
|
wlr_output_configuration_v1_send_failed(config);
|
||||||
|
}
|
||||||
|
wlr_output_configuration_v1_destroy(config);
|
||||||
|
|
||||||
|
update_output_manager_config(desktop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_output_manager_test(struct wl_listener *listener, void *data) {
|
||||||
|
struct roots_desktop *desktop =
|
||||||
|
wl_container_of(listener, desktop, output_manager_test);
|
||||||
|
struct wlr_output_configuration_v1 *config = data;
|
||||||
|
|
||||||
|
// TODO: implement test-only mode
|
||||||
|
wlr_output_configuration_v1_send_succeeded(config);
|
||||||
|
wlr_output_configuration_v1_destroy(config);
|
||||||
|
}
|
||||||
|
|
||||||
static void output_destroy(struct roots_output *output) {
|
static void output_destroy(struct roots_output *output) {
|
||||||
// TODO: cursor
|
// TODO: cursor
|
||||||
//example_config_configure_cursor(sample->config, sample->cursor,
|
//example_config_configure_cursor(sample->config, sample->cursor,
|
||||||
|
|
|
@ -132,12 +132,94 @@ static const struct zwlr_output_configuration_head_v1_interface config_head_impl
|
||||||
static struct wlr_output_configuration_head_v1 *config_head_from_resource(
|
static struct wlr_output_configuration_head_v1 *config_head_from_resource(
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource) {
|
||||||
assert(wl_resource_instance_of(resource,
|
assert(wl_resource_instance_of(resource,
|
||||||
&zwlr_output_head_v1_interface, &config_head_impl));
|
&zwlr_output_configuration_head_v1_interface, &config_head_impl));
|
||||||
return wl_resource_get_user_data(resource);
|
return wl_resource_get_user_data(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void config_head_handle_set_mode(struct wl_client *client,
|
||||||
|
struct wl_resource *config_head_resource,
|
||||||
|
struct wl_resource *mode_resource) {
|
||||||
|
struct wlr_output_configuration_head_v1 *config_head =
|
||||||
|
config_head_from_resource(config_head_resource);
|
||||||
|
if (config_head == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_output_mode *mode = mode_from_resource(mode_resource);
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
struct wlr_output_mode *m;
|
||||||
|
wl_list_for_each(m, &config_head->state.output->modes, link) {
|
||||||
|
if (mode == m) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
wl_resource_post_error(config_head_resource,
|
||||||
|
ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_MODE,
|
||||||
|
"mode doesn't belong to head");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
config_head->state.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void config_head_handle_set_position(struct wl_client *client,
|
||||||
|
struct wl_resource *config_head_resource, int32_t x, int32_t y) {
|
||||||
|
struct wlr_output_configuration_head_v1 *config_head =
|
||||||
|
config_head_from_resource(config_head_resource);
|
||||||
|
if (config_head == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
config_head->state.x = x;
|
||||||
|
config_head->state.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void config_head_handle_set_transform(struct wl_client *client,
|
||||||
|
struct wl_resource *config_head_resource, int32_t transform) {
|
||||||
|
struct wlr_output_configuration_head_v1 *config_head =
|
||||||
|
config_head_from_resource(config_head_resource);
|
||||||
|
if (config_head == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transform < WL_OUTPUT_TRANSFORM_NORMAL ||
|
||||||
|
transform > WL_OUTPUT_TRANSFORM_FLIPPED_270) {
|
||||||
|
wl_resource_post_error(config_head_resource,
|
||||||
|
ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_TRANSFORM,
|
||||||
|
"invalid transform");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
config_head->state.transform = transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void config_head_handle_set_scale(struct wl_client *client,
|
||||||
|
struct wl_resource *config_head_resource, int32_t scale) {
|
||||||
|
struct wlr_output_configuration_head_v1 *config_head =
|
||||||
|
config_head_from_resource(config_head_resource);
|
||||||
|
if (config_head == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scale <= 0) {
|
||||||
|
wl_resource_post_error(config_head_resource,
|
||||||
|
ZWLR_OUTPUT_CONFIGURATION_HEAD_V1_ERROR_INVALID_SCALE,
|
||||||
|
"invalid scale");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
config_head->state.scale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct zwlr_output_configuration_head_v1_interface config_head_impl = {
|
static const struct zwlr_output_configuration_head_v1_interface config_head_impl = {
|
||||||
0 // TODO
|
.set_mode = config_head_handle_set_mode,
|
||||||
|
.set_position = config_head_handle_set_position,
|
||||||
|
.set_transform = config_head_handle_set_transform,
|
||||||
|
.set_scale = config_head_handle_set_scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void config_head_handle_resource_destroy(struct wl_resource *resource) {
|
static void config_head_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
|
@ -252,10 +334,13 @@ static void config_finalize(struct wlr_output_configuration_v1 *config) {
|
||||||
// this point anyway
|
// this point anyway
|
||||||
struct wlr_output_configuration_head_v1 *config_head, *tmp;
|
struct wlr_output_configuration_head_v1 *config_head, *tmp;
|
||||||
wl_list_for_each_safe(config_head, tmp, &config->heads, link) {
|
wl_list_for_each_safe(config_head, tmp, &config->heads, link) {
|
||||||
|
// Resource is NULL if head has been disabled
|
||||||
|
if (config_head->resource != NULL) {
|
||||||
wl_resource_set_user_data(config_head->resource, NULL);
|
wl_resource_set_user_data(config_head->resource, NULL);
|
||||||
wl_resource_destroy(config_head->resource);
|
wl_resource_destroy(config_head->resource);
|
||||||
config_head->resource = NULL;
|
config_head->resource = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
config->finalized = true;
|
config->finalized = true;
|
||||||
}
|
}
|
||||||
|
@ -385,13 +470,26 @@ void wlr_output_configuration_v1_send_failed(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct zwlr_output_manager_v1_interface manager_impl;
|
||||||
|
|
||||||
|
static struct wlr_output_manager_v1 *manager_from_resource(
|
||||||
|
struct wl_resource *resource) {
|
||||||
|
assert(wl_resource_instance_of(resource,
|
||||||
|
&zwlr_output_manager_v1_interface, &manager_impl));
|
||||||
|
return wl_resource_get_user_data(resource);
|
||||||
|
}
|
||||||
|
|
||||||
static void manager_handle_create_configuration(struct wl_client *client,
|
static void manager_handle_create_configuration(struct wl_client *client,
|
||||||
struct wl_resource *manager_resource, uint32_t id, uint32_t serial) {
|
struct wl_resource *manager_resource, uint32_t id, uint32_t serial) {
|
||||||
|
struct wlr_output_manager_v1 *manager =
|
||||||
|
manager_from_resource(manager_resource);
|
||||||
|
|
||||||
struct wlr_output_configuration_v1 *config = config_create(false);
|
struct wlr_output_configuration_v1 *config = config_create(false);
|
||||||
if (config == NULL) {
|
if (config == NULL) {
|
||||||
wl_resource_post_no_memory(manager_resource);
|
wl_resource_post_no_memory(manager_resource);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
config->manager = manager;
|
||||||
config->serial = serial;
|
config->serial = serial;
|
||||||
|
|
||||||
uint32_t version = wl_resource_get_version(manager_resource);
|
uint32_t version = wl_resource_get_version(manager_resource);
|
||||||
|
|
Loading…
Reference in New Issue