Commit 8e7cd6b5da2302d1898a64c611a2f8e857c5f55a

Alex Szpakowski 2016-02-03T20:32:55

iOS: Implemented clipboard support.

diff --git a/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj b/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj
index 9f0d62e..b0830bf 100755
--- a/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj
+++ b/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj
@@ -143,7 +143,9 @@
 		AABCC3941640643D00AB8930 /* SDL_uikitmessagebox.h in Headers */ = {isa = PBXBuildFile; fileRef = AABCC3921640643D00AB8930 /* SDL_uikitmessagebox.h */; };
 		AABCC3951640643D00AB8930 /* SDL_uikitmessagebox.m in Sources */ = {isa = PBXBuildFile; fileRef = AABCC3931640643D00AB8930 /* SDL_uikitmessagebox.m */; };
 		AADA5B8F16CCAB7C00107CF7 /* SDL_bits.h in Headers */ = {isa = PBXBuildFile; fileRef = AADA5B8E16CCAB7C00107CF7 /* SDL_bits.h */; };
-		FAD4F7021BA3C4E8008346CE /* SDL_sysjoystick_c.h in Headers */ = {isa = PBXBuildFile; fileRef = FAD4F7011BA3C4E8008346CE /* SDL_sysjoystick_c.h */; settings = {ASSET_TAGS = (); }; };
+		FA1DC2721C62BE65008F99A0 /* SDL_uikitclipboard.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1DC2701C62BE65008F99A0 /* SDL_uikitclipboard.h */; };
+		FA1DC2731C62BE65008F99A0 /* SDL_uikitclipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = FA1DC2711C62BE65008F99A0 /* SDL_uikitclipboard.m */; };
+		FAD4F7021BA3C4E8008346CE /* SDL_sysjoystick_c.h in Headers */ = {isa = PBXBuildFile; fileRef = FAD4F7011BA3C4E8008346CE /* SDL_sysjoystick_c.h */; };
 		FD3F4A760DEA620800C5B771 /* SDL_getenv.c in Sources */ = {isa = PBXBuildFile; fileRef = FD3F4A700DEA620800C5B771 /* SDL_getenv.c */; };
 		FD3F4A770DEA620800C5B771 /* SDL_iconv.c in Sources */ = {isa = PBXBuildFile; fileRef = FD3F4A710DEA620800C5B771 /* SDL_iconv.c */; };
 		FD3F4A780DEA620800C5B771 /* SDL_malloc.c in Sources */ = {isa = PBXBuildFile; fileRef = FD3F4A720DEA620800C5B771 /* SDL_malloc.c */; };
@@ -340,6 +342,8 @@
 		AABCC3921640643D00AB8930 /* SDL_uikitmessagebox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitmessagebox.h; sourceTree = "<group>"; };
 		AABCC3931640643D00AB8930 /* SDL_uikitmessagebox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitmessagebox.m; sourceTree = "<group>"; };
 		AADA5B8E16CCAB7C00107CF7 /* SDL_bits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_bits.h; sourceTree = "<group>"; };
+		FA1DC2701C62BE65008F99A0 /* SDL_uikitclipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitclipboard.h; sourceTree = "<group>"; };
+		FA1DC2711C62BE65008F99A0 /* SDL_uikitclipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitclipboard.m; sourceTree = "<group>"; };
 		FAD4F7011BA3C4E8008346CE /* SDL_sysjoystick_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysjoystick_c.h; sourceTree = "<group>"; };
 		FD0BBFEF0E3933DD00D833B1 /* SDL_uikitview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitview.h; sourceTree = "<group>"; };
 		FD3F4A700DEA620800C5B771 /* SDL_getenv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_getenv.c; sourceTree = "<group>"; };
@@ -648,6 +652,8 @@
 				FDC261780E3A3FC8001C4554 /* keyinfotable.h */,
 				FD689FCD0E26E9D400F90B21 /* SDL_uikitappdelegate.h */,
 				FD689FCC0E26E9D400F90B21 /* SDL_uikitappdelegate.m */,
+				FA1DC2701C62BE65008F99A0 /* SDL_uikitclipboard.h */,
+				FA1DC2711C62BE65008F99A0 /* SDL_uikitclipboard.m */,
 				FD689F0C0E26E5D900F90B21 /* SDL_uikitevents.h */,
 				FD689F0D0E26E5D900F90B21 /* SDL_uikitevents.m */,
 				AABCC3921640643D00AB8930 /* SDL_uikitmessagebox.h */,
@@ -994,6 +1000,7 @@
 				04F7808012FB751400FC43C0 /* SDL_drawpoint.h in Headers */,
 				04F7808412FB753F00FC43C0 /* SDL_nullframebuffer_c.h in Headers */,
 				0442EC5012FE1C1E004C9285 /* SDL_render_sw_c.h in Headers */,
+				FA1DC2721C62BE65008F99A0 /* SDL_uikitclipboard.h in Headers */,
 				0402A85A12FE70C600CECEE3 /* SDL_shaders_gles2.h in Headers */,
 				04BAC09C1300C1290055DE28 /* SDL_assert_c.h in Headers */,
 				56EA86FC13E9EC2B002E47EB /* SDL_coreaudio.h in Headers */,
@@ -1139,6 +1146,7 @@
 				FD65266A0DE8FCDD002AD96B /* SDL_audiotypecvt.c in Sources */,
 				FD65266B0DE8FCDD002AD96B /* SDL_mixer.c in Sources */,
 				FD65266F0DE8FCDD002AD96B /* SDL_wave.c in Sources */,
+				FA1DC2731C62BE65008F99A0 /* SDL_uikitclipboard.m in Sources */,
 				FD6526700DE8FCDD002AD96B /* SDL_cpuinfo.c in Sources */,
 				FD6526710DE8FCDD002AD96B /* SDL_events.c in Sources */,
 				FD6526720DE8FCDD002AD96B /* SDL_keyboard.c in Sources */,
diff --git a/src/video/uikit/SDL_uikitclipboard.h b/src/video/uikit/SDL_uikitclipboard.h
new file mode 100644
index 0000000..2b19f15
--- /dev/null
+++ b/src/video/uikit/SDL_uikitclipboard.h
@@ -0,0 +1,35 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty.  In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+#ifndef _SDL_uikitclipboard_h
+#define _SDL_uikitclipboard_h
+
+#include "../SDL_sysvideo.h"
+
+extern int UIKit_SetClipboardText(_THIS, const char *text);
+extern char *UIKit_GetClipboardText(_THIS);
+extern SDL_bool UIKit_HasClipboardText(_THIS);
+
+extern void UIKit_InitClipboard(_THIS);
+extern void UIKit_QuitClipboard(_THIS);
+
+#endif /* _SDL_uikitclipboard_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/uikit/SDL_uikitclipboard.m b/src/video/uikit/SDL_uikitclipboard.m
new file mode 100644
index 0000000..a1c3016
--- /dev/null
+++ b/src/video/uikit/SDL_uikitclipboard.m
@@ -0,0 +1,99 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty.  In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_UIKIT
+
+#include "SDL_uikitvideo.h"
+#include "../../events/SDL_clipboardevents_c.h"
+
+#import <UIKit/UIPasteboard.h>
+
+int
+UIKit_SetClipboardText(_THIS, const char *text)
+{
+    @autoreleasepool {
+        [UIPasteboard generalPasteboard].string = @(text);
+        return 0;
+    }
+}
+
+char *
+UIKit_GetClipboardText(_THIS)
+{
+    @autoreleasepool {
+        UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
+        NSString *string = pasteboard.string;
+
+        if (string != nil) {
+            return SDL_strdup(string.UTF8String);
+        } else {
+            return SDL_strdup("");
+        }
+    }
+}
+
+SDL_bool
+UIKit_HasClipboardText(_THIS)
+{
+    @autoreleasepool {
+        if ([UIPasteboard generalPasteboard].string != nil) {
+            return SDL_TRUE;
+        }
+        return SDL_FALSE;
+    }
+}
+
+void
+UIKit_InitClipboard(_THIS)
+{
+    @autoreleasepool {
+        SDL_VideoData *data = (__bridge SDL_VideoData *) _this->driverdata;
+        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+
+        id observer = [center addObserverForName:UIPasteboardChangedNotification
+                                         object:nil
+                                          queue:nil
+                                     usingBlock:^(NSNotification *note) {
+                                         SDL_SendClipboardUpdate();
+                                     }];
+
+        data.pasteboardObserver = observer;
+    }
+}
+
+void
+UIKit_QuitClipboard(_THIS)
+{
+    @autoreleasepool {
+        SDL_VideoData *data = (__bridge SDL_VideoData *) _this->driverdata;
+
+        if (data.pasteboardObserver != nil) {
+            [[NSNotificationCenter defaultCenter] removeObserver:data.pasteboardObserver];
+        }
+
+        data.pasteboardObserver = nil;
+    }
+}
+
+#endif /* SDL_VIDEO_DRIVER_UIKIT */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/uikit/SDL_uikitvideo.h b/src/video/uikit/SDL_uikitvideo.h
index 3fbaf92..836cf18 100644
--- a/src/video/uikit/SDL_uikitvideo.h
+++ b/src/video/uikit/SDL_uikitvideo.h
@@ -25,6 +25,12 @@
 
 #include "../SDL_sysvideo.h"
 
+@interface SDL_VideoData : NSObject
+
+@property (nonatomic) id pasteboardObserver;
+
+@end
+
 void UIKit_SuspendScreenSaver(_THIS);
 
 BOOL UIKit_IsSystemVersionAtLeast(double version);
diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m
index 1561343..045a74b 100644
--- a/src/video/uikit/SDL_uikitvideo.m
+++ b/src/video/uikit/SDL_uikitvideo.m
@@ -36,9 +36,14 @@
 #include "SDL_uikitmodes.h"
 #include "SDL_uikitwindow.h"
 #include "SDL_uikitopengles.h"
+#include "SDL_uikitclipboard.h"
 
 #define UIKITVID_DRIVER_NAME "uikit"
 
+@implementation SDL_VideoData
+
+@end
+
 /* Initialization/Query functions */
 static int UIKit_VideoInit(_THIS);
 static void UIKit_VideoQuit(_THIS);
@@ -53,61 +58,75 @@ UIKit_Available(void)
 
 static void UIKit_DeleteDevice(SDL_VideoDevice * device)
 {
-    SDL_free(device);
+    @autoreleasepool {
+        CFRelease(device->driverdata);
+        SDL_free(device);
+    }
 }
 
 static SDL_VideoDevice *
 UIKit_CreateDevice(int devindex)
 {
-    SDL_VideoDevice *device;
+    @autoreleasepool {
+        SDL_VideoDevice *device;
+        SDL_VideoData *data;
+
+        /* Initialize all variables that we clean on shutdown */
+        device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
+        if (device) {
+            data = [SDL_VideoData new];
+        } else {
+            SDL_free(device);
+            SDL_OutOfMemory();
+            return (0);
+        }
 
-    /* Initialize all variables that we clean on shutdown */
-    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
-    if (!device) {
-        SDL_free(device);
-        SDL_OutOfMemory();
-        return (0);
+        device->driverdata = (void *) CFBridgingRetain(data);
+
+        /* Set the function pointers */
+        device->VideoInit = UIKit_VideoInit;
+        device->VideoQuit = UIKit_VideoQuit;
+        device->GetDisplayModes = UIKit_GetDisplayModes;
+        device->SetDisplayMode = UIKit_SetDisplayMode;
+        device->PumpEvents = UIKit_PumpEvents;
+        device->SuspendScreenSaver = UIKit_SuspendScreenSaver;
+        device->CreateWindow = UIKit_CreateWindow;
+        device->SetWindowTitle = UIKit_SetWindowTitle;
+        device->ShowWindow = UIKit_ShowWindow;
+        device->HideWindow = UIKit_HideWindow;
+        device->RaiseWindow = UIKit_RaiseWindow;
+        device->SetWindowBordered = UIKit_SetWindowBordered;
+        device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
+        device->DestroyWindow = UIKit_DestroyWindow;
+        device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
+        device->GetDisplayUsableBounds = UIKit_GetDisplayUsableBounds;
+
+    #if SDL_IPHONE_KEYBOARD
+        device->HasScreenKeyboardSupport = UIKit_HasScreenKeyboardSupport;
+        device->ShowScreenKeyboard = UIKit_ShowScreenKeyboard;
+        device->HideScreenKeyboard = UIKit_HideScreenKeyboard;
+        device->IsScreenKeyboardShown = UIKit_IsScreenKeyboardShown;
+        device->SetTextInputRect = UIKit_SetTextInputRect;
+    #endif
+
+        device->SetClipboardText = UIKit_SetClipboardText;
+        device->GetClipboardText = UIKit_GetClipboardText;
+        device->HasClipboardText = UIKit_HasClipboardText;
+
+        /* OpenGL (ES) functions */
+        device->GL_MakeCurrent      = UIKit_GL_MakeCurrent;
+        device->GL_GetDrawableSize  = UIKit_GL_GetDrawableSize;
+        device->GL_SwapWindow       = UIKit_GL_SwapWindow;
+        device->GL_CreateContext    = UIKit_GL_CreateContext;
+        device->GL_DeleteContext    = UIKit_GL_DeleteContext;
+        device->GL_GetProcAddress   = UIKit_GL_GetProcAddress;
+        device->GL_LoadLibrary      = UIKit_GL_LoadLibrary;
+        device->free = UIKit_DeleteDevice;
+
+        device->gl_config.accelerated = 1;
+
+        return device;
     }
-
-    /* Set the function pointers */
-    device->VideoInit = UIKit_VideoInit;
-    device->VideoQuit = UIKit_VideoQuit;
-    device->GetDisplayModes = UIKit_GetDisplayModes;
-    device->SetDisplayMode = UIKit_SetDisplayMode;
-    device->PumpEvents = UIKit_PumpEvents;
-    device->SuspendScreenSaver = UIKit_SuspendScreenSaver;
-    device->CreateWindow = UIKit_CreateWindow;
-    device->SetWindowTitle = UIKit_SetWindowTitle;
-    device->ShowWindow = UIKit_ShowWindow;
-    device->HideWindow = UIKit_HideWindow;
-    device->RaiseWindow = UIKit_RaiseWindow;
-    device->SetWindowBordered = UIKit_SetWindowBordered;
-    device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
-    device->DestroyWindow = UIKit_DestroyWindow;
-    device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
-    device->GetDisplayUsableBounds = UIKit_GetDisplayUsableBounds;
-
-#if SDL_IPHONE_KEYBOARD
-    device->HasScreenKeyboardSupport = UIKit_HasScreenKeyboardSupport;
-    device->ShowScreenKeyboard = UIKit_ShowScreenKeyboard;
-    device->HideScreenKeyboard = UIKit_HideScreenKeyboard;
-    device->IsScreenKeyboardShown = UIKit_IsScreenKeyboardShown;
-    device->SetTextInputRect = UIKit_SetTextInputRect;
-#endif
-
-    /* OpenGL (ES) functions */
-    device->GL_MakeCurrent      = UIKit_GL_MakeCurrent;
-    device->GL_GetDrawableSize  = UIKit_GL_GetDrawableSize;
-    device->GL_SwapWindow       = UIKit_GL_SwapWindow;
-    device->GL_CreateContext    = UIKit_GL_CreateContext;
-    device->GL_DeleteContext    = UIKit_GL_DeleteContext;
-    device->GL_GetProcAddress   = UIKit_GL_GetProcAddress;
-    device->GL_LoadLibrary      = UIKit_GL_LoadLibrary;
-    device->free = UIKit_DeleteDevice;
-
-    device->gl_config.accelerated = 1;
-
-    return device;
 }
 
 VideoBootStrap UIKIT_bootstrap = {