diff --git a/include/sway/config.h b/include/sway/config.h index 3c380933e..16b822fea 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -267,6 +267,12 @@ enum render_bit_depth { RENDER_BIT_DEPTH_10, }; +enum color_profile { + COLOR_PROFILE_DEFAULT, // default is Transform with NULL color_transform + COLOR_PROFILE_TRANSFORM, // use color_transform from output_config + COLOR_PROFILE_TRANSFORM_WITH_DEVICE_PRIMARIES, // create transform from wlr_output +}; + /** * Size and position configuration for a particular output. * @@ -288,7 +294,7 @@ struct output_config { int max_render_time; // In milliseconds int adaptive_sync; enum render_bit_depth render_bit_depth; - bool set_color_transform; + enum color_profile color_profile; struct wlr_color_transform *color_transform; int allow_tearing; int hdr; diff --git a/include/sway/server.h b/include/sway/server.h index a5b6d3320..61cb08586 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -160,7 +160,7 @@ struct sway_debug { extern struct sway_debug debug; -extern bool allow_unsupported_gpu; +extern bool unsupported_gpu_detected; void sway_terminate(int exit_code); diff --git a/protocols/idle.xml b/protocols/idle.xml deleted file mode 100644 index 92d9989c7..000000000 --- a/protocols/idle.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - . - ]]> - - - This interface allows to monitor user idle time on a given seat. The interface - allows to register timers which trigger after no user activity was registered - on the seat for a given interval. It notifies when user activity resumes. - - This is useful for applications wanting to perform actions when the user is not - interacting with the system, e.g. chat applications setting the user as away, power - management features to dim screen, etc.. - - - - - - - - - - - - - - - - - - - - - - diff --git a/protocols/meson.build b/protocols/meson.build index e7ada59b8..a1cb35344 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -12,7 +12,6 @@ protocols = [ wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml', 'wlr-layer-shell-unstable-v1.xml', - 'idle.xml', 'wlr-output-power-management-unstable-v1.xml', ] diff --git a/sway/commands/bar/colors.c b/sway/commands/bar/colors.c index 275fa3c64..da606c1b8 100644 --- a/sway/commands/bar/colors.c +++ b/sway/commands/bar/colors.c @@ -72,6 +72,10 @@ static struct cmd_results *parse_three_colors(char ***colors, } struct cmd_results *bar_cmd_colors(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "colors", EXPECTED_AT_LEAST, 1))) { + return error; + } return config_subcommand(argv, argc, bar_colors_handlers, sizeof(bar_colors_handlers)); } diff --git a/sway/commands/layout.c b/sway/commands/layout.c index a32c908b8..22dfdf3d7 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -137,11 +137,15 @@ struct cmd_results *cmd_layout(int argc, char **argv) { // If parent has only a singe child operate on its parent and // flatten once, like i3 if (container && container->pending.children->length == 1) { - struct sway_container *child = container->pending.children->items[0]; + // Also check grandparent to avoid restricting layouts struct sway_container *parent = container->pending.parent; - container_replace(container, child); - container_begin_destroy(container); - container = parent; + if (parent && parent->pending.children->length == 1) { + struct sway_container *child = container->pending.children->items[0]; + struct sway_container *parent = container->pending.parent; + container_replace(container, child); + container_begin_destroy(container); + container = parent; + } } } diff --git a/sway/commands/output/color_profile.c b/sway/commands/output/color_profile.c index 98481329b..0456b19b7 100644 --- a/sway/commands/output/color_profile.c +++ b/sway/commands/output/color_profile.c @@ -55,14 +55,30 @@ struct cmd_results *output_cmd_color_profile(int argc, char **argv) { if (!config->handler_context.output_config) { return cmd_results_new(CMD_FAILURE, "Missing output config"); } + + enum color_profile new_mode = COLOR_PROFILE_TRANSFORM; + if (argc >= 2 && strcmp(*argv, "--device-primaries") == 0) { + new_mode = COLOR_PROFILE_TRANSFORM_WITH_DEVICE_PRIMARIES; + argc--; + argv++; + } + if (!argc) { return cmd_results_new(CMD_INVALID, "Missing color_profile first argument."); } - if (strcmp(*argv, "srgb") == 0) { + if (strcmp(*argv, "gamma22") == 0) { wlr_color_transform_unref(config->handler_context.output_config->color_transform); config->handler_context.output_config->color_transform = NULL; - config->handler_context.output_config->set_color_transform = true; + config->handler_context.output_config->color_profile = new_mode; + + config->handler_context.leftovers.argc = argc - 1; + config->handler_context.leftovers.argv = argv + 1; + } else if (strcmp(*argv, "srgb") == 0) { + wlr_color_transform_unref(config->handler_context.output_config->color_transform); + config->handler_context.output_config->color_transform = + wlr_color_transform_init_linear_to_inverse_eotf(WLR_COLOR_TRANSFER_FUNCTION_SRGB); + config->handler_context.output_config->color_profile = new_mode; config->handler_context.leftovers.argc = argc - 1; config->handler_context.leftovers.argv = argv + 1; @@ -71,6 +87,10 @@ struct cmd_results *output_cmd_color_profile(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "Invalid color profile specification: icc type requires a file"); } + if (new_mode != COLOR_PROFILE_TRANSFORM) { + return cmd_results_new(CMD_INVALID, + "Invalid color profile specification: --device-primaries cannot be used with icc"); + } char *icc_path = strdup(argv[1]); if (!expand_path(&icc_path)) { @@ -100,13 +120,14 @@ struct cmd_results *output_cmd_color_profile(int argc, char **argv) { wlr_color_transform_unref(config->handler_context.output_config->color_transform); config->handler_context.output_config->color_transform = tmp; - config->handler_context.output_config->set_color_transform = true; + config->handler_context.output_config->color_profile = COLOR_PROFILE_TRANSFORM; config->handler_context.leftovers.argc = argc - 2; config->handler_context.leftovers.argv = argv + 2; } else { return cmd_results_new(CMD_INVALID, - "Invalid color profile specification: first argument should be icc|srgb"); + "Invalid color profile specification: " + "first argument should be gamma22|icc|srgb"); } return NULL; diff --git a/sway/config/output.c b/sway/config/output.c index ed8147b8b..3d25b46c7 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -75,7 +75,7 @@ struct output_config *new_output_config(const char *name) { oc->max_render_time = -1; oc->adaptive_sync = -1; oc->render_bit_depth = RENDER_BIT_DEPTH_DEFAULT; - oc->set_color_transform = false; + oc->color_profile = COLOR_PROFILE_DEFAULT; oc->color_transform = NULL; oc->power = -1; oc->allow_tearing = -1; @@ -130,12 +130,12 @@ static void supersede_output_config(struct output_config *dst, struct output_con if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) { dst->render_bit_depth = RENDER_BIT_DEPTH_DEFAULT; } - if (src->set_color_transform) { + if (src->color_profile != COLOR_PROFILE_DEFAULT) { if (dst->color_transform) { wlr_color_transform_unref(dst->color_transform); dst->color_transform = NULL; } - dst->set_color_transform = false; + dst->color_profile = COLOR_PROFILE_DEFAULT; } if (src->background) { free(dst->background); @@ -207,12 +207,12 @@ static void merge_output_config(struct output_config *dst, struct output_config if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) { dst->render_bit_depth = src->render_bit_depth; } - if (src->set_color_transform) { + if (src->color_profile != COLOR_PROFILE_DEFAULT) { if (src->color_transform) { wlr_color_transform_ref(src->color_transform); } wlr_color_transform_unref(dst->color_transform); - dst->set_color_transform = true; + dst->color_profile = src->color_profile; dst->color_transform = src->color_transform; } if (src->background) { @@ -562,8 +562,75 @@ static void queue_output_config(struct output_config *oc, set_hdr(wlr_output, pending, hdr); } +struct config_output_state { + struct wlr_color_transform *color_transform; +}; + +static void config_output_state_finish(struct config_output_state *state) { + wlr_color_transform_unref(state->color_transform); +} + +static struct wlr_color_transform *color_profile_from_device(struct wlr_output *wlr_output, + struct wlr_color_transform *transfer_function) { + struct wlr_color_primaries srgb_primaries; + wlr_color_primaries_from_named(&srgb_primaries, WLR_COLOR_NAMED_PRIMARIES_SRGB); + + const struct wlr_color_primaries *primaries = wlr_output->default_primaries; + if (primaries == NULL) { + sway_log(SWAY_INFO, "output has no reported color information"); + if (transfer_function) { + wlr_color_transform_ref(transfer_function); + } + return transfer_function; + } else if (memcmp(primaries, &srgb_primaries, sizeof(*primaries)) == 0) { + sway_log(SWAY_INFO, "output reports sRGB colors, no correction needed"); + if (transfer_function) { + wlr_color_transform_ref(transfer_function); + } + return transfer_function; + } else { + sway_log(SWAY_INFO, "Creating color profile from reported color primaries: " + "R(%f, %f) G(%f, %f) B(%f, %f) W(%f, %f)", + primaries->red.x, primaries->red.y, primaries->green.x, primaries->green.y, + primaries->blue.x, primaries->blue.y, primaries->white.x, primaries->white.y); + float matrix[9]; + wlr_color_primaries_transform_absolute_colorimetric(&srgb_primaries, primaries, matrix); + struct wlr_color_transform *matrix_transform = wlr_color_transform_init_matrix(matrix); + if (matrix_transform == NULL) { + return NULL; + } + struct wlr_color_transform *resolved_tf = transfer_function ? + wlr_color_transform_ref(transfer_function) : + wlr_color_transform_init_linear_to_inverse_eotf(WLR_COLOR_TRANSFER_FUNCTION_GAMMA22); + if (resolved_tf == NULL) { + wlr_color_transform_unref(matrix_transform); + return NULL; + } + struct wlr_color_transform *transforms[] = { matrix_transform, resolved_tf }; + size_t transforms_len = sizeof(transforms) / sizeof(transforms[0]); + struct wlr_color_transform *result = wlr_color_transform_init_pipeline(transforms, transforms_len); + wlr_color_transform_unref(matrix_transform); + wlr_color_transform_unref(resolved_tf); + return result; + } +} + +static struct wlr_color_transform *get_color_profile(struct wlr_output *output, + struct output_config *oc) { + if (oc && oc->color_profile == COLOR_PROFILE_TRANSFORM) { + if (oc->color_transform) { + wlr_color_transform_ref(oc->color_transform); + } + return oc->color_transform; + } else if (oc && oc->color_profile == COLOR_PROFILE_TRANSFORM_WITH_DEVICE_PRIMARIES) { + return color_profile_from_device(output, oc->color_transform); + } else { + return NULL; + } +} + static bool finalize_output_config(struct output_config *oc, struct sway_output *output, - const struct wlr_output_state *applied) { + const struct wlr_output_state *applied, const struct config_output_state *config_applied) { if (output == root->fallback_output) { return false; } @@ -609,16 +676,11 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output output_enable(output); } - if (oc && oc->set_color_transform) { - if (oc->color_transform) { - wlr_color_transform_ref(oc->color_transform); - } - wlr_color_transform_unref(output->color_transform); - output->color_transform = oc->color_transform; - } else { - wlr_color_transform_unref(output->color_transform); - output->color_transform = NULL; + wlr_color_transform_unref(output->color_transform); + if (config_applied->color_transform != NULL) { + wlr_color_transform_ref(config_applied->color_transform); } + output->color_transform = config_applied->color_transform; output->max_render_time = oc && oc->max_render_time > 0 ? oc->max_render_time : 0; output->allow_tearing = oc && oc->allow_tearing > 0; @@ -935,17 +997,25 @@ static bool apply_resolved_output_configs(struct matched_output_config *configs, if (!states) { return false; } + struct config_output_state *config_states = calloc(configs_len, sizeof(*config_states)); + if (!config_states) { + free(states); + return false; + } sway_log(SWAY_DEBUG, "Committing %zd outputs", configs_len); for (size_t idx = 0; idx < configs_len; idx++) { struct matched_output_config *cfg = &configs[idx]; struct wlr_backend_output_state *backend_state = &states[idx]; + struct config_output_state *config_state = &config_states[idx]; backend_state->output = cfg->output->wlr_output; wlr_output_state_init(&backend_state->base); queue_output_config(cfg->config, cfg->output, &backend_state->base); dump_output_state(cfg->output->wlr_output, &backend_state->base); + + config_state->color_transform = get_color_profile(cfg->output->wlr_output, cfg->config); } struct wlr_output_swapchain_manager swapchain_mgr; @@ -975,11 +1045,12 @@ static bool apply_resolved_output_configs(struct matched_output_config *configs, for (size_t idx = 0; idx < configs_len; idx++) { struct matched_output_config *cfg = &configs[idx]; struct wlr_backend_output_state *backend_state = &states[idx]; + struct config_output_state *config_state = &config_states[idx]; struct wlr_scene_output_state_options opts = { .swapchain = wlr_output_swapchain_manager_get_swapchain( &swapchain_mgr, backend_state->output), - .color_transform = cfg->output->color_transform, + .color_transform = config_state->color_transform, }; struct wlr_scene_output *scene_output = cfg->output->scene_output; struct wlr_output_state *state = &backend_state->base; @@ -1003,9 +1074,10 @@ static bool apply_resolved_output_configs(struct matched_output_config *configs, for (size_t idx = 0; idx < configs_len; idx++) { struct matched_output_config *cfg = &configs[idx]; struct wlr_backend_output_state *backend_state = &states[idx]; + struct config_output_state *config_state = &config_states[idx]; sway_log(SWAY_DEBUG, "Finalizing config for %s", cfg->output->wlr_output->name); - finalize_output_config(cfg->config, cfg->output, &backend_state->base); + finalize_output_config(cfg->config, cfg->output, &backend_state->base, config_state); } // Output layout being applied in finalize_output_config can shift outputs @@ -1026,8 +1098,10 @@ out: for (size_t idx = 0; idx < configs_len; idx++) { struct wlr_backend_output_state *backend_state = &states[idx]; wlr_output_state_finish(&backend_state->base); + config_output_state_finish(&config_states[idx]); } free(states); + free(config_states); // Reconfigure all devices, since input config may have been applied before // this output came online, and some config items (like map_to_output) are diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 696a45ada..7217e1369 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -354,6 +354,7 @@ static void handle_set_title(struct wl_listener *listener, void *data) { struct sway_view *view = &xdg_shell_view->view; view_update_title(view, false); view_execute_criteria(view); + transaction_commit_dirty(); } static void handle_set_app_id(struct wl_listener *listener, void *data) { @@ -362,6 +363,7 @@ static void handle_set_app_id(struct wl_listener *listener, void *data) { struct sway_view *view = &xdg_shell_view->view; view_update_app_id(view); view_execute_criteria(view); + transaction_commit_dirty(); } static void handle_new_popup(struct wl_listener *listener, void *data) { @@ -384,6 +386,9 @@ static void handle_request_maximize(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, request_maximize); struct wlr_xdg_toplevel *toplevel = xdg_shell_view->view.wlr_xdg_toplevel; + if (!toplevel->base->surface->mapped) { + return; + } wlr_xdg_surface_schedule_configure(toplevel->base); } @@ -594,4 +599,5 @@ void xdg_toplevel_tag_manager_v1_handle_set_tag(struct wl_listener *listener, vo free(xdg_shell_view->tag); xdg_shell_view->tag = strdup(event->tag); view_execute_criteria(view); + transaction_commit_dirty(); } diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 76e63ce1f..65016b3b1 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -689,6 +689,7 @@ static void handle_set_title(struct wl_listener *listener, void *data) { } view_update_title(view, false); view_execute_criteria(view); + transaction_commit_dirty(); } static void handle_set_class(struct wl_listener *listener, void *data) { @@ -700,6 +701,7 @@ static void handle_set_class(struct wl_listener *listener, void *data) { return; } view_execute_criteria(view); + transaction_commit_dirty(); } static void handle_set_role(struct wl_listener *listener, void *data) { @@ -711,6 +713,7 @@ static void handle_set_role(struct wl_listener *listener, void *data) { return; } view_execute_criteria(view); + transaction_commit_dirty(); } static void handle_set_startup_id(struct wl_listener *listener, void *data) { @@ -747,6 +750,7 @@ static void handle_set_window_type(struct wl_listener *listener, void *data) { return; } view_execute_criteria(view); + transaction_commit_dirty(); } static void handle_set_hints(struct wl_listener *listener, void *data) { diff --git a/sway/input/cursor.c b/sway/input/cursor.c index df62ef41b..fc0f11fd8 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -644,6 +644,11 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { cursor_handle_activity_from_device(cursor, &event->tablet->base); struct sway_tablet_tool *sway_tool = event->tool->data; + if (!sway_tool) { + sway_log(SWAY_DEBUG, "tool tip before proximity"); + return; + } + struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2; struct sway_seat *seat = cursor->seat; diff --git a/sway/input/seat.c b/sway/input/seat.c index ba64babe3..d275c5f8d 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -1015,9 +1015,9 @@ void seat_configure_xcursor(struct sway_seat *seat) { server.xwayland.xcursor_manager, "default", 1); if (xcursor != NULL) { struct wlr_xcursor_image *image = xcursor->images[0]; + struct wlr_buffer *buffer = wlr_xcursor_image_get_buffer(image); wlr_xwayland_set_cursor( - server.xwayland.wlr_xwayland, image->buffer, - image->width * 4, image->width, image->height, + server.xwayland.wlr_xwayland, buffer, image->hotspot_x, image->hotspot_y); } } diff --git a/sway/input/seatop_resize_tiling.c b/sway/input/seatop_resize_tiling.c index 15fd333b3..be7b3c128 100644 --- a/sway/input/seatop_resize_tiling.c +++ b/sway/input/seatop_resize_tiling.c @@ -105,10 +105,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { static void handle_unref(struct sway_seat *seat, struct sway_container *con) { struct seatop_resize_tiling_event *e = seat->seatop_data; - if (e->con == con) { - seatop_begin_default(seat); - } - if (e->h_sib == con || e->v_sib == con) { + if (e->con == con || e->h_sib == con || e->v_sib == con) { seatop_begin_default(seat); } } diff --git a/sway/main.c b/sway/main.c index 44d07679e..a94389266 100644 --- a/sway/main.c +++ b/sway/main.c @@ -224,7 +224,7 @@ static const char usage[] = "\n"; int main(int argc, char **argv) { - static bool verbose = false, debug = false, validate = false; + bool verbose = false, debug = false, validate = false, allow_unsupported_gpu = false; char *config_path = NULL; @@ -286,6 +286,12 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } + char *unsupported_gpu_env = getenv("SWAY_UNSUPPORTED_GPU"); + // we let the flag override the environment variable + if (!allow_unsupported_gpu && unsupported_gpu_env) { + allow_unsupported_gpu = parse_boolean(unsupported_gpu_env, false); + } + // As the 'callback' function for wlr_log is equivalent to that for // sway, we do not need to override it. if (debug) { @@ -373,6 +379,20 @@ int main(int argc, char **argv) { swaynag_show(&config->swaynag_config_errors); } + struct swaynag_instance nag_gpu = (struct swaynag_instance){ + .args = "--type error " + "--message 'Proprietary GPU drivers are not supported by sway. Do not report issues.' " + "--detailed-message", + .detailed = true, + }; + + if (unsupported_gpu_detected && !allow_unsupported_gpu) { + swaynag_log(config->swaynag_command, &nag_gpu, + "To remove this message, launch sway with --unsupported-gpu " + "or set the environment variable SWAY_UNSUPPORTED_GPU=true."); + swaynag_show(&nag_gpu); + } + server_run(&server); shutdown: @@ -385,6 +405,10 @@ shutdown: free(config_path); free_config(config); + if (nag_gpu.client != NULL) { + wl_client_destroy(nag_gpu.client); + } + pango_cairo_font_map_set_default(NULL); return exit_value; diff --git a/sway/server.c b/sway/server.c index 4e606a391..aef0d0b0c 100644 --- a/sway/server.c +++ b/sway/server.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -77,7 +78,7 @@ #define SWAY_FOREIGN_TOPLEVEL_LIST_VERSION 1 #define SWAY_PRESENTATION_VERSION 2 -bool allow_unsupported_gpu = false; +bool unsupported_gpu_detected = false; #if WLR_HAS_DRM_BACKEND static void handle_drm_lease_request(struct wl_listener *listener, void *data) { @@ -160,27 +161,16 @@ static void detect_proprietary(struct wlr_backend *backend, void *data) { return; } - bool is_unsupported = false; if (strcmp(version->name, "nvidia-drm") == 0) { - is_unsupported = true; + unsupported_gpu_detected = true; sway_log(SWAY_ERROR, "!!! Proprietary Nvidia drivers are in use !!!"); - if (!allow_unsupported_gpu) { - sway_log(SWAY_ERROR, "Use Nouveau instead"); - } } if (strcmp(version->name, "evdi") == 0) { - is_unsupported = true; + unsupported_gpu_detected = true; sway_log(SWAY_ERROR, "!!! Proprietary DisplayLink drivers are in use !!!"); } - if (!allow_unsupported_gpu && is_unsupported) { - sway_log(SWAY_ERROR, - "Proprietary drivers are NOT supported. To launch sway anyway, " - "launch with --unsupported-gpu and DO NOT report issues."); - exit(EXIT_FAILURE); - } - drmFreeVersion(version); } @@ -458,17 +448,14 @@ bool server_init(struct sway_server *server) { const enum wp_color_manager_v1_render_intent render_intents[] = { WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL, }; - const enum wp_color_manager_v1_transfer_function transfer_functions[] = { - WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB, - WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ, - WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR, - }; - const enum wp_color_manager_v1_primaries primaries[] = { - WP_COLOR_MANAGER_V1_PRIMARIES_SRGB, - WP_COLOR_MANAGER_V1_PRIMARIES_BT2020, - }; + size_t transfer_functions_len = 0; + enum wp_color_manager_v1_transfer_function *transfer_functions = + wlr_color_manager_v1_transfer_function_list_from_renderer(server->renderer, &transfer_functions_len); + size_t primaries_len = 0; + enum wp_color_manager_v1_primaries *primaries = + wlr_color_manager_v1_primaries_list_from_renderer(server->renderer, &primaries_len); struct wlr_color_manager_v1 *cm = wlr_color_manager_v1_create( - server->wl_display, 1, &(struct wlr_color_manager_v1_options){ + server->wl_display, 2, &(struct wlr_color_manager_v1_options){ .features = { .parametric = true, .set_mastering_display_primaries = true, @@ -476,13 +463,18 @@ bool server_init(struct sway_server *server) { .render_intents = render_intents, .render_intents_len = sizeof(render_intents) / sizeof(render_intents[0]), .transfer_functions = transfer_functions, - .transfer_functions_len = sizeof(transfer_functions) / sizeof(transfer_functions[0]), + .transfer_functions_len = transfer_functions_len, .primaries = primaries, - .primaries_len = sizeof(primaries) / sizeof(primaries[0]), + .primaries_len = primaries_len, }); + free(transfer_functions); + free(primaries); wlr_scene_set_color_manager_v1(root->root_scene, cm); } + wlr_color_representation_manager_v1_create_with_renderer( + server->wl_display, 1, server->renderer); + wl_list_init(&server->pending_launcher_ctxs); // Avoid using "wayland-0" as display socket diff --git a/sway/sway-ipc.7.scd b/sway/sway-ipc.7.scd index 4b0d5c962..2658228a1 100644 --- a/sway/sway-ipc.7.scd +++ b/sway/sway-ipc.7.scd @@ -1116,7 +1116,7 @@ Returns the currently active binding mode. A single object that contains the property _name_, which is set to the currently active binding mode as a string. -*Exact Reply:* +*Example Reply:* ``` { "name": "default" diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd index cc48589c3..faf59a1f2 100644 --- a/sway/sway-output.5.scd +++ b/sway/sway-output.5.scd @@ -178,9 +178,19 @@ must be separated by one space. For example: updated to work with different bit depths. This command is experimental, and may be removed or changed in the future. -*output* color_profile srgb|[icc ] - Sets the color profile for an output. The default is _srgb_. should be a - path to a display ICC profile. +*output* color_profile [--device-primaries] gamma22|srgb + Sets the color profile for an output. The default is _gamma22_. + + _--device-primaries_ will use the output's self-reported color primaries + when available (e.g. from display EDID). + + Not all renderers support this feature; currently it only works with the + the Vulkan renderer. It is not compatible with HDR support features. + +*output* color_profile icc + Sets the color profile for an output. + + should be a path to a display ICC profile. Not all renderers support this feature; currently it only works with the the Vulkan renderer. Even where supported, the application of the color diff --git a/sway/tree/view.c b/sway/tree/view.c index 3d6211249..eab2a5e2b 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -43,21 +43,19 @@ bool view_init(struct sway_view *view, enum sway_view_type type, bool failed = false; view->scene_tree = alloc_scene_tree(root->staging, &failed); view->content_tree = alloc_scene_tree(view->scene_tree, &failed); + if (failed) { + goto err; + } - if (!failed && !scene_descriptor_assign(&view->scene_tree->node, - SWAY_SCENE_DESC_VIEW, view)) { - failed = true; + if (!scene_descriptor_assign(&view->scene_tree->node, SWAY_SCENE_DESC_VIEW, view)) { + goto err; } view->image_capture_scene = wlr_scene_create(); if (view->image_capture_scene == NULL) { - failed = true; - } - - if (failed) { - wlr_scene_node_destroy(&view->scene_tree->node); - return false; + goto err; } + view->image_capture_scene->restack_xwayland_surfaces = false; view->type = type; view->impl = impl; @@ -67,6 +65,10 @@ bool view_init(struct sway_view *view, enum sway_view_type type, view->tearing_mode = TEARING_WINDOW_HINT; wl_signal_init(&view->events.unmap); return true; + +err: + wlr_scene_node_destroy(&view->scene_tree->node); + return false; } void view_destroy(struct sway_view *view) { @@ -307,7 +309,7 @@ void view_autoconfigure(struct sway_view *view) { } struct sway_output *output = ws ? ws->output : NULL; - if (con->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) { + if (output && con->pending.fullscreen_mode == FULLSCREEN_WORKSPACE) { con->pending.content_x = output->lx; con->pending.content_y = output->ly; con->pending.content_width = output->width; diff --git a/swaynag/main.c b/swaynag/main.c index b68157ff2..53c2203ff 100644 --- a/swaynag/main.c +++ b/swaynag/main.c @@ -45,6 +45,7 @@ int main(int argc, char **argv) { if (config_path) { sway_log(SWAY_DEBUG, "Loading config file: %s", config_path); status = swaynag_load_config(config_path, &swaynag, types); + free(config_path); if (status != 0) { goto cleanup; }