From c13e3a9fb00f2935d45e7c1fc877ae5db9ef3655 Mon Sep 17 00:00:00 2001 From: Vincent D <40196601+deakcor@users.noreply.github.com> Date: Tue, 2 Aug 2022 14:05:37 +0200 Subject: [PATCH] add clipboard get image methods for windows and macos Co-Authored-By: RedworkDE <10944644+RedworkDE@users.noreply.github.com> Co-Authored-By: bruvzg <7645683+bruvzg@users.noreply.github.com> --- doc/classes/DisplayServer.xml | 14 ++++- platform/macos/display_server_macos.h | 3 + platform/macos/display_server_macos.mm | 32 +++++++++++ platform/windows/display_server_windows.cpp | 63 +++++++++++++++++++++ platform/windows/display_server_windows.h | 3 + servers/display_server.cpp | 10 ++++ servers/display_server.h | 2 + 7 files changed, 126 insertions(+), 1 deletion(-) diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index b74dbdce5473..052240053297 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 93fa93b2592e..33b597759a9a 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -326,6 +326,9 @@ class DisplayServerMacOS : public DisplayServer { 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 5ccef68e7f0c..def790d834c6 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/texture.h" @@ -2100,6 +2101,37 @@ 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 4138f53a9d9b..61520d014c46 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -33,6 +33,7 @@ #include "os_windows.h" #include "core/io/marshalls.h" +#include "drivers/png/png_driver_common.h" #include "main/main.h" #include "scene/resources/texture.h" @@ -341,6 +342,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 7228de7d317b..0cd546a60b13 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -520,6 +520,9 @@ class DisplayServerWindows : public DisplayServer { 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 41fa0d2d4770..3dcbc47f8922 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."); } @@ -640,7 +648,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 fc8207f2d366..aa97bbbd5b61 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -245,7 +245,9 @@ class DisplayServer : public Object { 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;