Repository: kivy/kivy

Issue:
MacOS: Clipboard nspaste make app crash when copying text
<!--
The issue tracker is a tool to address bugs.
Please use the #support Discord channel at https://chat.kivy.org/ or Stack Overflow for
support questions, more information at https://git.io/vM1yQ.

Before opening a new issue, make sure you do the following:
    * check that your issue isn't already filed: https://git.io/vM1iE
    * prepare a short, runnable example that reproduces the issue
    * reproduce the problem with the latest development version of Kivy
    * double-check that the issue is indeed a bug and not a support request
-->

### Versions

* Python: 3.7.1
* OS: MacOS 10.13.6
* Kivy: 1.10.1
* Kivy installation method: pypi

### Description

When I try copy text in TextInput, this make app crash. But paste is OK.

### Code and Logs

```log
Traceback (most recent call last):
   File "main.py", line 56, in <module>
     app.run()
   File "/Users/ivc/kivy/.env3/lib/python3.7/site-packages/kivy/app.py", line 826, in run
     runTouchApp()
   File "/Users/ivc/kivy/.env3/lib/python3.7/site-packages/kivy/base.py", line 502, in runTouchApp
     EventLoop.window.mainloop()
   File "/Users/ivc/kivy/.env3/lib/python3.7/site-packages/kivy/core/window/window_sdl2.py", line 727, in mainloop
     self._mainloop()
   File "/Users/ivc/kivy/.env3/lib/python3.7/site-packages/kivy/core/window/window_sdl2.py", line 662, in _mainloop
     self.modifiers):
   File "kivy/_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
   File "kivy/_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
   File "kivy/_event.pyx", line 1138, in kivy._event.EventObservers._dispatch
   File "/Users/ivc/kivy/.env3/lib/python3.7/site-packages/kivy/core/window/__init__.py", line 162, in _on_window_key_down
     return self.dispatch('on_key_down', keycode, text, modifiers)
   File "kivy/_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
   File "kivy/_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
   File "kivy/_event.pyx", line 1138, in kivy._event.EventObservers._dispatch
   File "/Users/ivc/kivy/.env3/lib/python3.7/site-packages/kivy/uix/textinput.py", line 2434, in keyboard_on_key_down
     self.copy()
   File "/Users/ivc/kivy/.env3/lib/python3.7/site-packages/kivy/uix/textinput.py", line 1727, in copy
     return Clipboard.copy(self.selection_text)
   File "/Users/ivc/kivy/.env3/lib/python3.7/site-packages/kivy/core/clipboard/__init__.py", line 73, in copy
     self._copy(data)
   File "/Users/ivc/kivy/.env3/lib/python3.7/site-packages/kivy/core/clipboard/__init__.py", line 87, in _copy
     self.put(data, self._clip_mime_type)
   File "/Users/ivc/kivy/.env3/lib/python3.7/site-packages/kivy/core/clipboard/clipboard_nspaste.py", line 40, in put
     pb.writeObjects_([data])
   File "pyobjus/pyobjus.pyx", line 393, in pyobjus.ObjcMethod.__call__
   File "pyobjus/pyobjus_conversions.pxi", line 617, in pyobjus.convert_py_arg_to_cy
   File "pyobjus/pyobjus_conversions.pxi", line 441, in pyobjus.convert_py_to_nsobject
   File "pyobjus/pyobjus.pyx", line 393, in pyobjus.ObjcMethod.__call__
   File "pyobjus/pyobjus_conversions.pxi", line 617, in pyobjus.convert_py_arg_to_cy
   File "pyobjus/pyobjus_conversions.pxi", line 452, in pyobjus.convert_py_to_nsobject
   File "pyobjus/pyobjus.pyx", line 974, in pyobjus.objc_create_delegate
 pyobjus.ObjcException: You've passed b'kivyproject' as delegate, but there is no @protocol methods declared.
```



Discussion:
You got a bug :)
In the meantime, you can avoid it by using `KIVY_CLIPBOARD=sdl2` as a environemnt variable.

Thanks for reporting!
😂 Thank, I already used this setting instead of nspaste.


Resolving patch:
diff --git a/kivy/core/clipboard/clipboard_nspaste.py b/kivy/core/clipboard/clipboard_nspaste.py
--- a/kivy/core/clipboard/clipboard_nspaste.py
+++ b/kivy/core/clipboard/clipboard_nspaste.py
@@ -37,7 +37,8 @@ def get(self, mimetype='text/plain'):
     def put(self, data, mimetype='text/plain'):
         pb = self._clipboard
         pb.clearContents()
-        pb.writeObjects_([data])
+        utf8 = NSString.alloc().initWithUTF8String_(data)
+        pb.setString_forType_(utf8, 'public.utf8-plain-text')
 
     def get_types(self):
         return list('text/plain',)


Test patch:
diff --git a/kivy/tests/test_clipboard.py b/kivy/tests/test_clipboard.py
--- a/kivy/tests/test_clipboard.py
+++ b/kivy/tests/test_clipboard.py
@@ -1,7 +1,7 @@
-import unittest
+from kivy.tests.common import GraphicUnitTest
 
 
-class ClipboardTestCase(unittest.TestCase):
+class ClipboardTestCase(GraphicUnitTest):
 
     def setUp(self):
         from kivy.core.clipboard import Clipboard
@@ -11,6 +11,7 @@ def setUp(self):
         if 'UTF8_STRING' in clippy_types:
             cliptype = 'UTF8_STRING'
         self._cliptype = cliptype
+        super(ClipboardTestCase, self).setUp()
 
     def test_clipboard_not_dummy(self):
         clippy = self._clippy
@@ -32,3 +33,10 @@ def test_clipboard_copy(self):
         except:
             self.fail(
                 'Can not get put data to clipboard')
+
+    def test_clipboard_copy_paste(self):
+        clippy = self._clippy
+        txt1 = u"Hello 1"
+        clippy.copy(txt1)
+        ret = clippy.paste()
+        self.assertEqual(txt1, ret)