diff options
author | Yuri Sizov <yuris@humnom.net> | 2023-07-27 15:22:16 +0200 |
---|---|---|
committer | Yuri Sizov <yuris@humnom.net> | 2023-07-27 15:22:16 +0200 |
commit | 0c2399d6ecc69c923d0bc480c29767df29b5f68d (patch) | |
tree | 058d56cadad150beb601f8a54067046db1b4167d | |
parent | 41a7f6b38047773386710d5e49b64b173a3198de (diff) | |
parent | c13e3a9fb00f2935d45e7c1fc877ae5db9ef3655 (diff) | |
download | redot-engine-0c2399d6ecc69c923d0bc480c29767df29b5f68d.tar.gz |
Merge pull request #63826 from deakcor/dev_clipboard
Add `clipboard_has/get_image` methods to DisplayServer
-rw-r--r-- | doc/classes/DisplayServer.xml | 14 | ||||
-rw-r--r-- | platform/macos/display_server_macos.h | 3 | ||||
-rw-r--r-- | platform/macos/display_server_macos.mm | 32 | ||||
-rw-r--r-- | platform/windows/display_server_windows.cpp | 63 | ||||
-rw-r--r-- | platform/windows/display_server_windows.h | 3 | ||||
-rw-r--r-- | servers/display_server.cpp | 10 | ||||
-rw-r--r-- | servers/display_server.h | 2 |
7 files changed, 126 insertions, 1 deletions
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index dceeb20f0e..465855cc92 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. </description> </method> + <method name="clipboard_get_image" qualifiers="const"> + <return type="Image" /> + <description> + Returns the user's clipboard as an image if possible. + </description> + </method> <method name="clipboard_get_primary" qualifiers="const"> <return type="String" /> <description> @@ -26,7 +32,13 @@ <method name="clipboard_has" qualifiers="const"> <return type="bool" /> <description> - 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. + </description> + </method> + <method name="clipboard_has_image" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if there is an image content on the user's clipboard. </description> </method> <method name="clipboard_set"> diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index aef45e534f..e5e0e53bfb 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<Image> 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 ac0659ee7f..d64bb5211e 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<Image> DisplayServerMacOS::clipboard_get_image() const { + Ref<Image> 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 c664752c2f..c073d6f028 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<Image> DisplayServerWindows::clipboard_get_image() const { + Ref<Image> 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<BITMAPINFO *>(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 bd47dee9ec..59c4442604 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<Image> 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 5822a630db..f41238b075 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<Image> DisplayServer::clipboard_get_image() const { + ERR_FAIL_V_MSG(Ref<Image>(), "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 5db9b3231f..85f9270696 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<Image> 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; |