diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index dceeb20f0e3..465855cc92d 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -16,6 +16,12 @@ Returns the user's clipboard as a string if possible. + + + + Returns the user's clipboard as an image if possible. + + @@ -26,7 +32,13 @@ - Returns [code]true[/code] if there is content on the user's clipboard. + Returns [code]true[/code] if there is a text content on the user's clipboard. + + + + + + Returns [code]true[/code] if there is an image content on the user's clipboard. diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index aef45e534f1..e5e0e53bfb9 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -328,6 +328,9 @@ public: virtual void clipboard_set(const String &p_text) override; virtual String clipboard_get() const override; + virtual Ref clipboard_get_image() const override; + virtual bool clipboard_has() const override; + virtual bool clipboard_has_image() const override; virtual int get_screen_count() const override; virtual int get_primary_screen() const override; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index ac0659ee7f0..d64bb5211e5 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -44,6 +44,7 @@ #include "core/io/marshalls.h" #include "core/math/geometry_2d.h" #include "core/os/keyboard.h" +#include "drivers/png/png_driver_common.h" #include "main/main.h" #include "scene/resources/atlas_texture.h" #include "scene/resources/image_texture.h" @@ -2271,6 +2272,37 @@ String DisplayServerMacOS::clipboard_get() const { return ret; } +Ref DisplayServerMacOS::clipboard_get_image() const { + Ref image; + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSString *result = [pasteboard availableTypeFromArray:[NSArray arrayWithObjects:NSPasteboardTypeTIFF, NSPasteboardTypePNG, nil]]; + if (!result) { + return image; + } + NSData *data = [pasteboard dataForType:result]; + if (!data) { + return image; + } + NSBitmapImageRep *bitmap = [NSBitmapImageRep imageRepWithData:data]; + NSData *pngData = [bitmap representationUsingType:NSPNGFileType properties:@{}]; + image.instantiate(); + PNGDriverCommon::png_to_image((const uint8_t *)pngData.bytes, pngData.length, false, image); + return image; +} + +bool DisplayServerMacOS::clipboard_has() const { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; + NSDictionary *options = [NSDictionary dictionary]; + return [pasteboard canReadObjectForClasses:classArray options:options]; +} + +bool DisplayServerMacOS::clipboard_has_image() const { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSString *result = [pasteboard availableTypeFromArray:[NSArray arrayWithObjects:NSPasteboardTypeTIFF, NSPasteboardTypePNG, nil]]; + return result; +} + int DisplayServerMacOS::get_screen_count() const { _THREAD_SAFE_METHOD_ diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index c664752c2fe..c073d6f028c 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -34,6 +34,7 @@ #include "core/config/project_settings.h" #include "core/io/marshalls.h" +#include "drivers/png/png_driver_common.h" #include "main/main.h" #include "scene/resources/atlas_texture.h" @@ -468,6 +469,68 @@ String DisplayServerWindows::clipboard_get() const { return ret; } +Ref DisplayServerWindows::clipboard_get_image() const { + Ref image; + if (!windows.has(last_focused_window)) { + return image; // No focused window? + } + if (!OpenClipboard(windows[last_focused_window].hWnd)) { + ERR_FAIL_V_MSG(image, "Unable to open clipboard."); + } + UINT png_format = RegisterClipboardFormatA("PNG"); + if (png_format && IsClipboardFormatAvailable(png_format)) { + HANDLE png_handle = GetClipboardData(png_format); + if (png_handle) { + size_t png_size = GlobalSize(png_handle); + uint8_t *png_data = (uint8_t *)GlobalLock(png_handle); + image.instantiate(); + + PNGDriverCommon::png_to_image(png_data, png_size, false, image); + + GlobalUnlock(png_handle); + } + } else if (IsClipboardFormatAvailable(CF_DIB)) { + HGLOBAL mem = GetClipboardData(CF_DIB); + if (mem != NULL) { + BITMAPINFO *ptr = static_cast(GlobalLock(mem)); + + if (ptr != NULL) { + BITMAPINFOHEADER *info = &ptr->bmiHeader; + PackedByteArray pba; + + for (LONG y = info->biHeight - 1; y > -1; y--) { + for (LONG x = 0; x < info->biWidth; x++) { + tagRGBQUAD *rgbquad = ptr->bmiColors + (info->biWidth * y) + x; + pba.append(rgbquad->rgbRed); + pba.append(rgbquad->rgbGreen); + pba.append(rgbquad->rgbBlue); + pba.append(rgbquad->rgbReserved); + } + } + image.instantiate(); + image->create_from_data(info->biWidth, info->biHeight, false, Image::Format::FORMAT_RGBA8, pba); + + GlobalUnlock(mem); + } + } + } + + CloseClipboard(); + + return image; +} + +bool DisplayServerWindows::clipboard_has() const { + return (IsClipboardFormatAvailable(CF_TEXT) || + IsClipboardFormatAvailable(CF_UNICODETEXT) || + IsClipboardFormatAvailable(CF_OEMTEXT)); +} + +bool DisplayServerWindows::clipboard_has_image() const { + UINT png_format = RegisterClipboardFormatA("PNG"); + return ((png_format && IsClipboardFormatAvailable(png_format)) || IsClipboardFormatAvailable(CF_DIB)); +} + typedef struct { int count; int screen; diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index bd47dee9ec9..59c44426041 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -522,6 +522,9 @@ public: virtual void clipboard_set(const String &p_text) override; virtual String clipboard_get() const override; + virtual Ref clipboard_get_image() const override; + virtual bool clipboard_has() const override; + virtual bool clipboard_has_image() const override; virtual int get_screen_count() const override; virtual int get_primary_screen() const override; diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 5822a630db2..f41238b0754 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -362,10 +362,18 @@ String DisplayServer::clipboard_get() const { ERR_FAIL_V_MSG(String(), "Clipboard is not supported by this display server."); } +Ref DisplayServer::clipboard_get_image() const { + ERR_FAIL_V_MSG(Ref(), "Clipboard is not supported by this display server."); +} + bool DisplayServer::clipboard_has() const { return !clipboard_get().is_empty(); } +bool DisplayServer::clipboard_has_image() const { + return clipboard_get_image().is_valid(); +} + void DisplayServer::clipboard_set_primary(const String &p_text) { WARN_PRINT("Primary clipboard is not supported by this display server."); } @@ -649,7 +657,9 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("clipboard_set", "clipboard"), &DisplayServer::clipboard_set); ClassDB::bind_method(D_METHOD("clipboard_get"), &DisplayServer::clipboard_get); + ClassDB::bind_method(D_METHOD("clipboard_get_image"), &DisplayServer::clipboard_get_image); ClassDB::bind_method(D_METHOD("clipboard_has"), &DisplayServer::clipboard_has); + ClassDB::bind_method(D_METHOD("clipboard_has_image"), &DisplayServer::clipboard_has_image); ClassDB::bind_method(D_METHOD("clipboard_set_primary", "clipboard_primary"), &DisplayServer::clipboard_set_primary); ClassDB::bind_method(D_METHOD("clipboard_get_primary"), &DisplayServer::clipboard_get_primary); diff --git a/servers/display_server.h b/servers/display_server.h index 5db9b3231f4..85f92706965 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -245,7 +245,9 @@ public: virtual void clipboard_set(const String &p_text); virtual String clipboard_get() const; + virtual Ref clipboard_get_image() const; virtual bool clipboard_has() const; + virtual bool clipboard_has_image() const; virtual void clipboard_set_primary(const String &p_text); virtual String clipboard_get_primary() const;