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;