diff options
author | Yuri Sizov <yuris@humnom.net> | 2023-07-12 15:09:14 +0200 |
---|---|---|
committer | Yuri Sizov <yuris@humnom.net> | 2023-07-12 15:09:14 +0200 |
commit | 2b47f6715e7df588a30ac665aac60e22c67e62ca (patch) | |
tree | 37b650734b0c4810b30108761222befdc93b0c10 | |
parent | b54d6cf46657dccd5b66cc1661a2ce0a6d99e1d7 (diff) | |
parent | 9c5a0c6c102556c229825e053153d02fb7141668 (diff) | |
download | redot-engine-2b47f6715e7df588a30ac665aac60e22c67e62ca.tar.gz |
Merge pull request #78437 from bruvzg/set_icon
Add error checks and harmonize behavior of the `set_icon` method.
-rw-r--r-- | platform/linuxbsd/x11/display_server_x11.cpp | 2 | ||||
-rw-r--r-- | platform/macos/display_server_macos.mm | 66 | ||||
-rw-r--r-- | platform/web/display_server_web.cpp | 51 | ||||
-rw-r--r-- | platform/web/js/libs/library_godot_display.js | 25 | ||||
-rw-r--r-- | platform/windows/display_server_windows.cpp | 98 |
5 files changed, 136 insertions, 106 deletions
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index d9e18720dc..bdb160e6a6 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -4880,6 +4880,8 @@ void DisplayServerX11::set_icon(const Ref<Image> &p_icon) { Atom net_wm_icon = XInternAtom(x11_display, "_NET_WM_ICON", False); if (p_icon.is_valid()) { + ERR_FAIL_COND(p_icon->get_width() <= 0 || p_icon->get_height() <= 0); + Ref<Image> img = p_icon->duplicate(); img->convert(Image::FORMAT_RGBA8); diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 5ccef68e7f..fb691c93ef 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -3609,40 +3609,46 @@ void DisplayServerMacOS::set_native_icon(const String &p_filename) { void DisplayServerMacOS::set_icon(const Ref<Image> &p_icon) { _THREAD_SAFE_METHOD_ - Ref<Image> img = p_icon; - img = img->duplicate(); - img->convert(Image::FORMAT_RGBA8); - NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc] - initWithBitmapDataPlanes:nullptr - pixelsWide:img->get_width() - pixelsHigh:img->get_height() - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:img->get_width() * 4 - bitsPerPixel:32]; - ERR_FAIL_COND(imgrep == nil); - uint8_t *pixels = [imgrep bitmapData]; + if (p_icon.is_valid()) { + ERR_FAIL_COND(p_icon->get_width() <= 0 || p_icon->get_height() <= 0); - int len = img->get_width() * img->get_height(); - const uint8_t *r = img->get_data().ptr(); + Ref<Image> img = p_icon->duplicate(); + img->convert(Image::FORMAT_RGBA8); - /* Premultiply the alpha channel */ - for (int i = 0; i < len; i++) { - uint8_t alpha = r[i * 4 + 3]; - pixels[i * 4 + 0] = (uint8_t)(((uint16_t)r[i * 4 + 0] * alpha) / 255); - pixels[i * 4 + 1] = (uint8_t)(((uint16_t)r[i * 4 + 1] * alpha) / 255); - pixels[i * 4 + 2] = (uint8_t)(((uint16_t)r[i * 4 + 2] * alpha) / 255); - pixels[i * 4 + 3] = alpha; - } + NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc] + initWithBitmapDataPlanes:nullptr + pixelsWide:img->get_width() + pixelsHigh:img->get_height() + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:img->get_width() * 4 + bitsPerPixel:32]; + ERR_FAIL_COND(imgrep == nil); + uint8_t *pixels = [imgrep bitmapData]; - NSImage *nsimg = [[NSImage alloc] initWithSize:NSMakeSize(img->get_width(), img->get_height())]; - ERR_FAIL_COND(nsimg == nil); + int len = img->get_width() * img->get_height(); + const uint8_t *r = img->get_data().ptr(); - [nsimg addRepresentation:imgrep]; - [NSApp setApplicationIconImage:nsimg]; + /* Premultiply the alpha channel */ + for (int i = 0; i < len; i++) { + uint8_t alpha = r[i * 4 + 3]; + pixels[i * 4 + 0] = (uint8_t)(((uint16_t)r[i * 4 + 0] * alpha) / 255); + pixels[i * 4 + 1] = (uint8_t)(((uint16_t)r[i * 4 + 1] * alpha) / 255); + pixels[i * 4 + 2] = (uint8_t)(((uint16_t)r[i * 4 + 2] * alpha) / 255); + pixels[i * 4 + 3] = alpha; + } + + NSImage *nsimg = [[NSImage alloc] initWithSize:NSMakeSize(img->get_width(), img->get_height())]; + ERR_FAIL_COND(nsimg == nil); + + [nsimg addRepresentation:imgrep]; + [NSApp setApplicationIconImage:nsimg]; + } else { + [NSApp setApplicationIconImage:nil]; + } } DisplayServer *DisplayServerMacOS::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) { diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp index 951ce110e0..941f2c7ef3 100644 --- a/platform/web/display_server_web.cpp +++ b/platform/web/display_server_web.cpp @@ -731,35 +731,40 @@ void DisplayServerWeb::send_window_event_callback(int p_notification) { } void DisplayServerWeb::set_icon(const Ref<Image> &p_icon) { - ERR_FAIL_COND(p_icon.is_null()); - Ref<Image> icon = p_icon; - if (icon->is_compressed()) { - icon = icon->duplicate(); - ERR_FAIL_COND(icon->decompress() != OK); - } - if (icon->get_format() != Image::FORMAT_RGBA8) { - if (icon == p_icon) { + if (p_icon.is_valid()) { + ERR_FAIL_COND(p_icon->get_width() <= 0 || p_icon->get_height() <= 0); + + Ref<Image> icon = p_icon; + if (icon->is_compressed()) { icon = icon->duplicate(); + ERR_FAIL_COND(icon->decompress() != OK); + } + if (icon->get_format() != Image::FORMAT_RGBA8) { + if (icon == p_icon) { + icon = icon->duplicate(); + } + icon->convert(Image::FORMAT_RGBA8); } - icon->convert(Image::FORMAT_RGBA8); - } - png_image png_meta; - memset(&png_meta, 0, sizeof png_meta); - png_meta.version = PNG_IMAGE_VERSION; - png_meta.width = icon->get_width(); - png_meta.height = icon->get_height(); - png_meta.format = PNG_FORMAT_RGBA; + png_image png_meta; + memset(&png_meta, 0, sizeof png_meta); + png_meta.version = PNG_IMAGE_VERSION; + png_meta.width = icon->get_width(); + png_meta.height = icon->get_height(); + png_meta.format = PNG_FORMAT_RGBA; - PackedByteArray png; - size_t len; - PackedByteArray data = icon->get_data(); - ERR_FAIL_COND(!png_image_write_get_memory_size(png_meta, len, 0, data.ptr(), 0, nullptr)); + PackedByteArray png; + size_t len; + PackedByteArray data = icon->get_data(); + ERR_FAIL_COND(!png_image_write_get_memory_size(png_meta, len, 0, data.ptr(), 0, nullptr)); - png.resize(len); - ERR_FAIL_COND(!png_image_write_to_memory(&png_meta, png.ptrw(), &len, 0, data.ptr(), 0, nullptr)); + png.resize(len); + ERR_FAIL_COND(!png_image_write_to_memory(&png_meta, png.ptrw(), &len, 0, data.ptr(), 0, nullptr)); - godot_js_display_window_icon_set(png.ptr(), len); + godot_js_display_window_icon_set(png.ptr(), len); + } else { + godot_js_display_window_icon_set(nullptr, 0); + } } void DisplayServerWeb::_dispatch_input_event(const Ref<InputEvent> &p_event) { diff --git a/platform/web/js/libs/library_godot_display.js b/platform/web/js/libs/library_godot_display.js index ea2a846f90..746f858923 100644 --- a/platform/web/js/libs/library_godot_display.js +++ b/platform/web/js/libs/library_godot_display.js @@ -568,16 +568,23 @@ const GodotDisplay = { godot_js_display_window_icon_set__sig: 'vii', godot_js_display_window_icon_set: function (p_ptr, p_len) { let link = document.getElementById('-gd-engine-icon'); - if (link === null) { - link = document.createElement('link'); - link.rel = 'icon'; - link.id = '-gd-engine-icon'; - document.head.appendChild(link); - } const old_icon = GodotDisplay.window_icon; - const png = new Blob([GodotRuntime.heapSlice(HEAPU8, p_ptr, p_len)], { type: 'image/png' }); - GodotDisplay.window_icon = URL.createObjectURL(png); - link.href = GodotDisplay.window_icon; + if (p_ptr) { + if (link === null) { + link = document.createElement('link'); + link.rel = 'icon'; + link.id = '-gd-engine-icon'; + document.head.appendChild(link); + } + const png = new Blob([GodotRuntime.heapSlice(HEAPU8, p_ptr, p_len)], { type: 'image/png' }); + GodotDisplay.window_icon = URL.createObjectURL(png); + link.href = GodotDisplay.window_icon; + } else { + if (link) { + link.remove(); + } + GodotDisplay.window_icon = null; + } if (old_icon) { URL.revokeObjectURL(old_icon); } diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 4138f53a9d..4ef6bf6cb1 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -2194,55 +2194,65 @@ void DisplayServerWindows::set_native_icon(const String &p_filename) { void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) { _THREAD_SAFE_METHOD_ - ERR_FAIL_COND(!p_icon.is_valid()); - if (icon != p_icon) { - icon = p_icon->duplicate(); - if (icon->get_format() != Image::FORMAT_RGBA8) { - icon->convert(Image::FORMAT_RGBA8); + if (p_icon.is_valid()) { + ERR_FAIL_COND(p_icon->get_width() <= 0 || p_icon->get_height() <= 0); + + Ref<Image> img = p_icon; + if (img != icon) { + img = img->duplicate(); + img->convert(Image::FORMAT_RGBA8); } - } - int w = icon->get_width(); - int h = icon->get_height(); - - // Create temporary bitmap buffer. - int icon_len = 40 + h * w * 4; - Vector<BYTE> v; - v.resize(icon_len); - BYTE *icon_bmp = v.ptrw(); - - encode_uint32(40, &icon_bmp[0]); - encode_uint32(w, &icon_bmp[4]); - encode_uint32(h * 2, &icon_bmp[8]); - encode_uint16(1, &icon_bmp[12]); - encode_uint16(32, &icon_bmp[14]); - encode_uint32(BI_RGB, &icon_bmp[16]); - encode_uint32(w * h * 4, &icon_bmp[20]); - encode_uint32(0, &icon_bmp[24]); - encode_uint32(0, &icon_bmp[28]); - encode_uint32(0, &icon_bmp[32]); - encode_uint32(0, &icon_bmp[36]); - - uint8_t *wr = &icon_bmp[40]; - const uint8_t *r = icon->get_data().ptr(); - - for (int i = 0; i < h; i++) { - for (int j = 0; j < w; j++) { - const uint8_t *rpx = &r[((h - i - 1) * w + j) * 4]; - uint8_t *wpx = &wr[(i * w + j) * 4]; - wpx[0] = rpx[2]; - wpx[1] = rpx[1]; - wpx[2] = rpx[0]; - wpx[3] = rpx[3]; + + int w = img->get_width(); + int h = img->get_height(); + + // Create temporary bitmap buffer. + int icon_len = 40 + h * w * 4; + Vector<BYTE> v; + v.resize(icon_len); + BYTE *icon_bmp = v.ptrw(); + + encode_uint32(40, &icon_bmp[0]); + encode_uint32(w, &icon_bmp[4]); + encode_uint32(h * 2, &icon_bmp[8]); + encode_uint16(1, &icon_bmp[12]); + encode_uint16(32, &icon_bmp[14]); + encode_uint32(BI_RGB, &icon_bmp[16]); + encode_uint32(w * h * 4, &icon_bmp[20]); + encode_uint32(0, &icon_bmp[24]); + encode_uint32(0, &icon_bmp[28]); + encode_uint32(0, &icon_bmp[32]); + encode_uint32(0, &icon_bmp[36]); + + uint8_t *wr = &icon_bmp[40]; + const uint8_t *r = img->get_data().ptr(); + + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + const uint8_t *rpx = &r[((h - i - 1) * w + j) * 4]; + uint8_t *wpx = &wr[(i * w + j) * 4]; + wpx[0] = rpx[2]; + wpx[1] = rpx[1]; + wpx[2] = rpx[0]; + wpx[3] = rpx[3]; + } } - } - HICON hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000); + HICON hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000); + ERR_FAIL_COND(!hicon); + + icon = img; - // Set the icon for the window. - SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon); + // Set the icon for the window. + SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon); - // Set the icon in the task manager (should we do this?). - SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_BIG, (LPARAM)hicon); + // Set the icon in the task manager (should we do this?). + SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_BIG, (LPARAM)hicon); + } else { + icon = Ref<Image>(); + SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_SMALL, NULL); + SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_SETICON, ICON_BIG, NULL); + } } void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { |