summaryrefslogtreecommitdiffstats
path: root/platform/macos/display_server_macos.mm
diff options
context:
space:
mode:
Diffstat (limited to 'platform/macos/display_server_macos.mm')
-rw-r--r--platform/macos/display_server_macos.mm286
1 files changed, 253 insertions, 33 deletions
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 5ccef68e7f..d64bb5211e 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -44,8 +44,10 @@
#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"
+#include "scene/resources/atlas_texture.h"
+#include "scene/resources/image_texture.h"
#if defined(GLES3_ENABLED)
#include "drivers/gles3/rasterizer_gles3.h"
@@ -1847,6 +1849,176 @@ Error DisplayServerMacOS::dialog_show(String p_title, String p_description, Vect
return OK;
}
+Error DisplayServerMacOS::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) {
+ _THREAD_SAFE_METHOD_
+
+ NSString *url = [NSString stringWithUTF8String:p_current_directory.utf8().get_data()];
+ NSMutableArray *allowed_types = [[NSMutableArray alloc] init];
+ bool allow_other = false;
+ for (int i = 0; i < p_filters.size(); i++) {
+ Vector<String> tokens = p_filters[i].split(";");
+ if (tokens.size() > 0) {
+ if (tokens[0].strip_edges() == "*.*") {
+ allow_other = true;
+ } else {
+ [allowed_types addObject:[NSString stringWithUTF8String:tokens[0].replace("*.", "").strip_edges().utf8().get_data()]];
+ }
+ }
+ }
+
+ Callable callback = p_callback; // Make a copy for async completion handler.
+ switch (p_mode) {
+ case FILE_DIALOG_MODE_SAVE_FILE: {
+ NSSavePanel *panel = [NSSavePanel savePanel];
+
+ [panel setDirectoryURL:[NSURL fileURLWithPath:url]];
+ if ([allowed_types count]) {
+ [panel setAllowedFileTypes:allowed_types];
+ }
+ [panel setAllowsOtherFileTypes:allow_other];
+ [panel setExtensionHidden:YES];
+ [panel setCanSelectHiddenExtension:YES];
+ [panel setCanCreateDirectories:YES];
+ [panel setShowsHiddenFiles:p_show_hidden];
+ if (p_filename != "") {
+ NSString *fileurl = [NSString stringWithUTF8String:p_filename.utf8().get_data()];
+ [panel setNameFieldStringValue:fileurl];
+ }
+
+ [panel beginSheetModalForWindow:[[NSApplication sharedApplication] mainWindow]
+ completionHandler:^(NSInteger ret) {
+ if (ret == NSModalResponseOK) {
+ // Save bookmark for folder.
+ if (OS::get_singleton()->is_sandboxed()) {
+ NSArray *bookmarks = [[NSUserDefaults standardUserDefaults] arrayForKey:@"sec_bookmarks"];
+ bool skip = false;
+ for (id bookmark in bookmarks) {
+ NSError *error = nil;
+ BOOL isStale = NO;
+ NSURL *exurl = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:&error];
+ if (!error && !isStale && ([[exurl path] compare:[[panel directoryURL] path]] == NSOrderedSame)) {
+ skip = true;
+ break;
+ }
+ }
+ if (!skip) {
+ NSError *error = nil;
+ NSData *bookmark = [[panel directoryURL] bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:&error];
+ if (!error) {
+ NSArray *new_bookmarks = [bookmarks arrayByAddingObject:bookmark];
+ [[NSUserDefaults standardUserDefaults] setObject:new_bookmarks forKey:@"sec_bookmarks"];
+ }
+ }
+ }
+ // Callback.
+ Vector<String> files;
+ String url;
+ url.parse_utf8([[[panel URL] path] UTF8String]);
+ files.push_back(url);
+ if (!callback.is_null()) {
+ Variant v_status = true;
+ Variant v_files = files;
+ Variant *v_args[2] = { &v_status, &v_files };
+ Variant ret;
+ Callable::CallError ce;
+ callback.callp((const Variant **)&v_args, 2, ret, ce);
+ }
+ } else {
+ if (!callback.is_null()) {
+ Variant v_status = false;
+ Variant v_files = Vector<String>();
+ Variant *v_args[2] = { &v_status, &v_files };
+ Variant ret;
+ Callable::CallError ce;
+ callback.callp((const Variant **)&v_args, 2, ret, ce);
+ }
+ }
+ }];
+ } break;
+ case FILE_DIALOG_MODE_OPEN_ANY:
+ case FILE_DIALOG_MODE_OPEN_FILE:
+ case FILE_DIALOG_MODE_OPEN_FILES:
+ case FILE_DIALOG_MODE_OPEN_DIR: {
+ NSOpenPanel *panel = [NSOpenPanel openPanel];
+
+ [panel setDirectoryURL:[NSURL fileURLWithPath:url]];
+ if ([allowed_types count]) {
+ [panel setAllowedFileTypes:allowed_types];
+ }
+ [panel setAllowsOtherFileTypes:allow_other];
+ [panel setExtensionHidden:YES];
+ [panel setCanSelectHiddenExtension:YES];
+ [panel setCanCreateDirectories:YES];
+ [panel setCanChooseFiles:(p_mode != FILE_DIALOG_MODE_OPEN_DIR)];
+ [panel setCanChooseDirectories:(p_mode == FILE_DIALOG_MODE_OPEN_DIR || p_mode == FILE_DIALOG_MODE_OPEN_ANY)];
+ [panel setShowsHiddenFiles:p_show_hidden];
+ if (p_filename != "") {
+ NSString *fileurl = [NSString stringWithUTF8String:p_filename.utf8().get_data()];
+ [panel setNameFieldStringValue:fileurl];
+ }
+ [panel setAllowsMultipleSelection:(p_mode == FILE_DIALOG_MODE_OPEN_FILES)];
+
+ [panel beginSheetModalForWindow:[[NSApplication sharedApplication] mainWindow]
+ completionHandler:^(NSInteger ret) {
+ if (ret == NSModalResponseOK) {
+ // Save bookmark for folder.
+ NSArray *urls = [(NSOpenPanel *)panel URLs];
+ if (OS::get_singleton()->is_sandboxed()) {
+ NSArray *bookmarks = [[NSUserDefaults standardUserDefaults] arrayForKey:@"sec_bookmarks"];
+ NSMutableArray *new_bookmarks = [bookmarks mutableCopy];
+ for (NSUInteger i = 0; i != [urls count]; ++i) {
+ bool skip = false;
+ for (id bookmark in bookmarks) {
+ NSError *error = nil;
+ BOOL isStale = NO;
+ NSURL *exurl = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:&error];
+ if (!error && !isStale && ([[exurl path] compare:[[urls objectAtIndex:i] path]] == NSOrderedSame)) {
+ skip = true;
+ break;
+ }
+ }
+ if (!skip) {
+ NSError *error = nil;
+ NSData *bookmark = [[urls objectAtIndex:i] bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:&error];
+ if (!error) {
+ [new_bookmarks addObject:bookmark];
+ }
+ }
+ }
+ [[NSUserDefaults standardUserDefaults] setObject:new_bookmarks forKey:@"sec_bookmarks"];
+ }
+ // Callback.
+ Vector<String> files;
+ for (NSUInteger i = 0; i != [urls count]; ++i) {
+ String url;
+ url.parse_utf8([[[urls objectAtIndex:i] path] UTF8String]);
+ files.push_back(url);
+ }
+ if (!callback.is_null()) {
+ Variant v_status = true;
+ Variant v_files = files;
+ Variant *v_args[2] = { &v_status, &v_files };
+ Variant ret;
+ Callable::CallError ce;
+ callback.callp((const Variant **)&v_args, 2, ret, ce);
+ }
+ } else {
+ if (!callback.is_null()) {
+ Variant v_status = false;
+ Variant v_files = Vector<String>();
+ Variant *v_args[2] = { &v_status, &v_files };
+ Variant ret;
+ Callable::CallError ce;
+ callback.callp((const Variant **)&v_args, 2, ret, ce);
+ }
+ }
+ }];
+ } break;
+ }
+
+ return OK;
+}
+
Error DisplayServerMacOS::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) {
_THREAD_SAFE_METHOD_
@@ -2100,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_
@@ -3085,14 +3288,14 @@ bool DisplayServerMacOS::window_is_focused(WindowID p_window) const {
}
bool DisplayServerMacOS::window_can_draw(WindowID p_window) const {
- return window_get_mode(p_window) != WINDOW_MODE_MINIMIZED;
+ return (window_get_mode(p_window) != WINDOW_MODE_MINIMIZED) && [windows[p_window].window_object isOnActiveSpace];
}
bool DisplayServerMacOS::can_any_window_draw() const {
_THREAD_SAFE_METHOD_
for (const KeyValue<WindowID, WindowData> &E : windows) {
- if (window_get_mode(E.key) != WINDOW_MODE_MINIMIZED) {
+ if ((window_get_mode(E.key) != WINDOW_MODE_MINIMIZED) && [E.value.window_object isOnActiveSpace]) {
return true;
}
}
@@ -3499,6 +3702,17 @@ Key DisplayServerMacOS::keyboard_get_keycode_from_physical(Key p_keycode) const
return (Key)(KeyMappingMacOS::remap_key(macos_keycode, 0, false) | modifiers);
}
+Key DisplayServerMacOS::keyboard_get_label_from_physical(Key p_keycode) const {
+ if (p_keycode == Key::PAUSE || p_keycode == Key::NONE) {
+ return p_keycode;
+ }
+
+ Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK;
+ Key keycode_no_mod = p_keycode & KeyModifierMask::CODE_MASK;
+ unsigned int macos_keycode = KeyMappingMacOS::unmap_key(keycode_no_mod);
+ return (Key)(KeyMappingMacOS::remap_key(macos_keycode, 0, true) | modifiers);
+}
+
void DisplayServerMacOS::process_events() {
_THREAD_SAFE_METHOD_
@@ -3609,40 +3823,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) {