diff --git a/rdprail-shell/app-list.c b/rdprail-shell/app-list.c index ada1e8e0b..b699ea646 100644 --- a/rdprail-shell/app-list.c +++ b/rdprail-shell/app-list.c @@ -49,7 +49,6 @@ #include "shell.h" #include "shared/helpers.h" -#include "shared/image-loader.h" #ifdef HAVE_WINPR2 #include @@ -317,7 +316,7 @@ send_app_entry(struct desktop_shell *shell, char *key, struct app_entry *entry, if (!entry->icon_file) entry->icon_file = find_icon_file(entry->icon); if (entry->icon_file) - app_list_data.appIcon = load_image(entry->icon_file); + app_list_data.appIcon = load_icon_image(shell, entry->icon_file); detach_app_list_namespace(shell); } if (!app_list_data.appIcon) { @@ -837,7 +836,7 @@ app_list_monitor_thread(LPVOID arg) if (!entry->icon_file) entry->icon_file = find_icon_file(entry->icon); if (entry->icon_file) - context->load_icon.image = load_image(entry->icon_file); + context->load_icon.image = load_icon_image(shell, entry->icon_file); detach_app_list_namespace(shell); } shell_rdp_debug(shell, "app_list_monitor_thread: entry %p, image %p\n", entry, context->load_icon.image); @@ -1112,11 +1111,11 @@ void app_list_init(struct desktop_shell *shell) /* load default icon */ iconpath = getenv("WSL2_DEFAULT_APP_ICON"); if (iconpath && (strcmp(iconpath, "disabled") != 0)) - context->default_icon = load_image(iconpath); + context->default_icon = load_icon_image(shell, iconpath); iconpath = getenv("WSL2_DEFAULT_APP_OVERLAY_ICON"); if (iconpath && (strcmp(iconpath, "disabled") != 0)) - context->default_overlay_icon = load_image(iconpath); + context->default_overlay_icon = load_icon_image(shell, iconpath); /* set default language as "en_US". this will be updated once client connected */ strcpy(context->lang_info.requestedClientLanguageId, "en_US"); diff --git a/rdprail-shell/img-load.c b/rdprail-shell/img-load.c new file mode 100644 index 000000000..359779667 --- /dev/null +++ b/rdprail-shell/img-load.c @@ -0,0 +1,140 @@ +/* + * Copyright © 2020 Microsoft + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include + +#ifdef HAVE_LIBRSVG2 +#include +#endif // HAVE_LIBRSVG2 + +#include "shell.h" + +#include "shared/image-loader.h" + +#ifdef HAVE_LIBRSVG2 +static pixman_image_t * +load_svg(struct desktop_shell *shell, const char *filename) +{ + GError *error = NULL; + RsvgHandle *rsvg = NULL; + cairo_surface_t *surface = NULL; + cairo_t *cr = NULL; + pixman_image_t *image = NULL; + + /* DEPRECATED: g_type_init(); rsvg_init(); */ + /* rsvg_init has been deprecated since version 2.36 and should not be used + in newly-written code. Use g_type_init() */ + /* g_type_init has been deprecated since version 2.36 and should not be used + in newly-written code. the type system is now initialised automatically. */ + rsvg = rsvg_handle_new_from_file(filename, &error); + if (!rsvg) { + shell_rdp_debug(shell, "%s: rsvg_handle_new_from_file failed %s\n", + __func__, filename); + goto Exit; + } + + RsvgDimensionData dimensionData; + rsvg_handle_get_dimensions(rsvg, &dimensionData); + + image = pixman_image_create_bits(PIXMAN_a8r8g8b8, + dimensionData.width, + dimensionData.height, + NULL, + dimensionData.width * 4); + if (!image) { + shell_rdp_debug(shell, "%s: pixman_image_create_bits(%dx%d) failed %s\n", + __func__, dimensionData.width, dimensionData.height, filename); + goto Exit; + } + + surface = cairo_image_surface_create_for_data( + (unsigned char *)pixman_image_get_data(image), + CAIRO_FORMAT_ARGB32, + dimensionData.width, + dimensionData.height, + dimensionData.width * 4); + if (!surface) { + shell_rdp_debug(shell, "%s: cairo_image_surface_create(%dx%d) failed %s\n", + __func__, dimensionData.width, dimensionData.height, filename); + goto Exit; + } + + cr = cairo_create(surface); + if (!cr) { + shell_rdp_debug(shell, "%s: cairo_create failed %s\n", + __func__, filename); + goto Exit; + } + + if (!rsvg_handle_render_cairo(rsvg, cr)) { + shell_rdp_debug(shell, "%s: rsvg_handle_render_cairo failed %s\n", + __func__, filename); + goto Exit; + } + + pixman_image_ref(image); + +Exit: + if (cr) + cairo_destroy(cr); + + if (surface) + cairo_surface_destroy(surface); + + if (image) { + if (pixman_image_unref(image)) + image = NULL; + } + + /* DEPRECATED: rsvg_handle_free(rsvg); */ + /* rsvg_handle_free is deprecated and should not be used in + newly-written code. Use g_object_unref() instead. */ + if (rsvg) + g_object_unref(rsvg); + + /* DEPRECATED: rsvg_term(); */ + /* rsvg_term has been deprecated since version 2.36 and should not be used + in newly-written code. There is no need to de-initialize librsvg. */ + + return image; +} +#endif // HAVE_LIBRSVG2 + +pixman_image_t * +load_icon_image(struct desktop_shell *shell, const char *filename) +{ + pixman_image_t *image; + image = load_image(filename); +#ifdef HAVE_LIBRSVG2 + if (!image) + image = load_svg(shell, filename); +#endif // HAVE_LIBRSVG2 + return image; +} diff --git a/rdprail-shell/meson.build b/rdprail-shell/meson.build index 34a6486b0..c442b2b54 100644 --- a/rdprail-shell/meson.build +++ b/rdprail-shell/meson.build @@ -3,10 +3,15 @@ if get_option('shell-rdprail') if dep_winpr.found() config_h.set('HAVE_WINPR2', '1') endif + dep_librsvg = dependency('librsvg-2.0', version: '>= 2.36.0', required: false) + if dep_librsvg.found() + config_h.set('HAVE_LIBRSVG2', '1') + endif srcs_shell_rdprail = [ 'shell.c', 'input-panel.c', 'app-list.c', + 'img-load.c', weston_desktop_shell_server_protocol_h, weston_desktop_shell_protocol_c, input_method_unstable_v1_server_protocol_h, @@ -18,6 +23,7 @@ if get_option('shell-rdprail') dep_libshared, dep_lib_desktop, dep_libweston_public, + dep_librsvg, dep_winpr, ] plugin_shell_rdprail = shared_library( diff --git a/rdprail-shell/shell.c b/rdprail-shell/shell.c index 6f1db1bab..95d8fafd2 100644 --- a/rdprail-shell/shell.c +++ b/rdprail-shell/shell.c @@ -44,7 +44,6 @@ #include #include "shared/helpers.h" #include "shared/timespec-util.h" -#include "shared/image-loader.h" #include #include #include @@ -4232,12 +4231,12 @@ wet_shell_init(struct weston_compositor *ec, icon_path = getenv("WSL2_DEFAULT_APP_ICON"); if (icon_path && (strcmp(icon_path, "disabled") != 0)) - shell->image_default_app_icon = load_image(icon_path); + shell->image_default_app_icon = load_icon_image(shell, icon_path); shell_rdp_debug(shell, "WSL2_DEFAULT_APP_ICON:%s\n", icon_path); icon_path = getenv("WSL2_DEFAULT_APP_OVERLAY_ICON"); if (icon_path && (strcmp(icon_path, "disabled") != 0)) - shell->image_default_app_overlay_icon = load_image(icon_path); + shell->image_default_app_overlay_icon = load_icon_image(shell, icon_path); shell_rdp_debug(shell, "WSL2_DEFAULT_APP_OVERLAY_ICON:%s\n", icon_path); if (getenv("WESTON_RDPRAIL_SHELL_DISABLE_BLEND_OVERLAY_ICON_TASKBAR")) diff --git a/rdprail-shell/shell.h b/rdprail-shell/shell.h index e8508a837..2cb24b8c1 100644 --- a/rdprail-shell/shell.h +++ b/rdprail-shell/shell.h @@ -181,8 +181,11 @@ shell_blend_overlay_icon(struct desktop_shell *shell, void shell_rdp_debug_print(struct weston_log_scope *scope, bool cont, char *fmt, ...); +// app-list.c void app_list_init(struct desktop_shell *shell); void app_list_destroy(struct desktop_shell *shell); pixman_image_t *app_list_load_icon_file(struct desktop_shell *shell, const char *key); bool app_list_start_backend_update(struct desktop_shell *shell, char *clientLanguageId); void app_list_stop_backend_update(struct desktop_shell *shell); +// img-load.c +pixman_image_t *load_icon_image(struct desktop_shell *shell, const char *filename);