From d7d060552f84cec68a6608c86f2dbe48fea05674 Mon Sep 17 00:00:00 2001 From: akshayaurora Date: Sun, 2 Nov 2014 01:05:28 +0530 Subject: [PATCH 1/6] core:Introduce native clipboard for most target OS --- kivy/core/clipboard/__init__.py | 14 +++++++++ kivy/core/clipboard/clipboard_nspaste.py | 40 ++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 kivy/core/clipboard/clipboard_nspaste.py diff --git a/kivy/core/clipboard/__init__.py b/kivy/core/clipboard/__init__.py index c87171e1b..e247669cd 100644 --- a/kivy/core/clipboard/__init__.py +++ b/kivy/core/clipboard/__init__.py @@ -119,7 +119,21 @@ _platform = platform if _platform == 'android': _clipboards.append( ('android', 'clipboard_android', 'ClipboardAndroid')) + _clipboards.append( + ('sdl2', 'clipboard_sdl2', 'ClipboardSDL2')) +elif _platform == 'ios': + _clipboards.append( + ('sdl2', 'clipboard_sdl2', 'ClipboardSDL2')) elif _platform in ('macosx', 'linux', 'win'): + if _platform == 'macosx': + _clipboards.append( + ('nspaste', 'clipboard_nspaste', 'ClipboardNSPaste')) + elif _platform == 'win': + _clipboards.append( + ('winctypes', 'clipboard_winctypes', 'ClipboardWindows')) + elif _platform == 'linux': + _clipboards.append(('dbusklipper', 'clipboard_dbusklipper', 'Clipboard_DbusKlipper')) + _clipboards.append( ('pygame', 'clipboard_pygame', 'ClipboardPygame')) _clipboards.append( diff --git a/kivy/core/clipboard/clipboard_nspaste.py b/kivy/core/clipboard/clipboard_nspaste.py new file mode 100644 index 000000000..f251a7a32 --- /dev/null +++ b/kivy/core/clipboard/clipboard_nspaste.py @@ -0,0 +1,40 @@ +''' +Clipboard OsX: implementation of clipboard using Appkit +''' + +__all__ = ('ClipboardNSPaste', ) + +from kivy.core.clipboard import ClipboardBase +from kivy.utils import platform + +if platform != 'macosx': + raise SystemError('Unsupported platform for appkit clipboard.') +try: + from pyobjus import autoclass + from pyobjus.dylib_manager import load_framework, INCLUDE + load_framework(INCLUDE.AppKit) +except ImportError: + raise SystemError('Pyobjus not installed. Please run the following' + ' command to install it. `pip install --user pyobjus`') + +NSPasteboard = autoclass('NSPasteboard') +NSString = autoclass('NSString') + + +class ClipboardNSPaste(ClipboardBase): + + def __init__(self): + super(ClipboardNSPaste, self).__init__() + self._clipboard = NSPasteboard.generalPasteboard() + + def get(self, mimetype='text/plain'): + pb = self._clipboard + return pb.stringForType_('public.utf8-plain-text').UTF8String() + + def put(self, data, mimetype='text/plain'): + pb = self._clipboard + pb.clearContents() + pb.writeObjects_([data]) + + def get_types(self): + return list('text/plain',) From 347dbab2a2017b79f3e3f3f85155ea252e7ce39c Mon Sep 17 00:00:00 2001 From: akshayaurora Date: Sun, 2 Nov 2014 01:07:18 +0530 Subject: [PATCH 2/6] core:clipboard add missing files for windows and kde target --- kivy/core/clipboard/clipboard_dbusclipper.py | 41 +++++++++++++++ kivy/core/clipboard/clipboard_winctypes.py | 52 ++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 kivy/core/clipboard/clipboard_dbusclipper.py create mode 100644 kivy/core/clipboard/clipboard_winctypes.py diff --git a/kivy/core/clipboard/clipboard_dbusclipper.py b/kivy/core/clipboard/clipboard_dbusclipper.py new file mode 100644 index 000000000..f7891281a --- /dev/null +++ b/kivy/core/clipboard/clipboard_dbusclipper.py @@ -0,0 +1,41 @@ +''' +Clipboard Dbus: an implementation of the Clipboard using dbus and klipper. +''' + +__all__ = ('ClipboardDbusKlipper', ) + +from kivy.utils import platform +from kivy.core.clipboard import ClipboardBase + +if platform != 'linux': + raise SystemError('unsupported platform for dbus kde clipboard') + +try: + import dbus + bus = dbus.SessionBus() + proxy = bus.get_object("org.kde.klipper", "/klipper") +except: + raise + + +class ClipboardDbusKlipper(ClipboardBase): + + _is_init = False + + def init(self): + if ClipboardDbusKlipper._is_init: + return + self.iface = dbus.Interface(proxy, "org.kde.klipper.klipper") + ClipboardDbusKlipper._is_init = True + + def get(self, mimetype='text/plain'): + self.init() + return str(self.iface.getClipboardContents()) + + def put(self, data, mimetype='text/plain'): + self.init() + self.iface.setClipboardContents(data.replace('\x00', '')) + + def get_types(self): + self.init() + return 'text/plain' diff --git a/kivy/core/clipboard/clipboard_winctypes.py b/kivy/core/clipboard/clipboard_winctypes.py new file mode 100644 index 000000000..130823e5c --- /dev/null +++ b/kivy/core/clipboard/clipboard_winctypes.py @@ -0,0 +1,52 @@ +''' +Clipboard windows: an implementation of the Clipboard using ctypes. +''' + +__all__ = ('ClipboardWindows', ) + +from kivy.utils import platform +from kivy.core.clipboard import ClipboardBase + +if platform != 'win': + raise SystemError('unsupported platform for Windows clipboard') + + +class ClipboardWindows(ClipboardBase): + + def get(self, mimetype='text/plain'): + ctypes.windll.user32.OpenClipboard(0) + # 1 is CF_TEXT + pcontents = ctypes.windll.user32.GetClipboardData(1) + data = ctypes.c_char_p(pcontents).value + #ctypes.windll.kernel32.GlobalUnlock(pcontents) + ctypes.windll.user32.CloseClipboard() + return data + + def put(self, data, mimetype='text/plain'): + GMEM_DDESHARE = 0x2000 + ctypes.windll.user32.OpenClipboard(0) + ctypes.windll.user32.EmptyClipboard() + try: + # works on Python 2 (bytes() only takes one argument) + hCd = ctypes.windll.kernel32.GlobalAlloc( + GMEM_DDESHARE, len(bytes(text)) + 1) + except TypeError: + # works on Python 3 (bytes() requires an encoding) + hCd = ctypes.windll.kernel32.GlobalAlloc( + GMEM_DDESHARE, len(bytes(text, 'ascii')) + 1) + pchData = ctypes.windll.kernel32.GlobalLock(hCd) + try: + # works on Python 2 (bytes() only takes one argument) + ctypes.cdll.msvcrt.strcpy( + ctypes.c_char_p(pchData), bytes(text)) + except TypeError: + # works on Python 3 (bytes() requires an encoding) + ctypes.cdll.msvcrt.strcpy( + ctypes.c_char_p(pchData), bytes(text, 'ascii')) + ctypes.windll.kernel32.GlobalUnlock(hCd) + ctypes.windll.user32.SetClipboardData(1, hCd) + ctypes.windll.user32.CloseClipboard() + + def get_types(self): + return list('text/plain',) + From 6ebd51e2920fd4e02e2f59a7cda67e334265f2b5 Mon Sep 17 00:00:00 2001 From: akshayaurora Date: Sun, 2 Nov 2014 01:13:53 +0530 Subject: [PATCH 3/6] core:clipboard. Minor optimisation. --- kivy/core/clipboard/clipboard_winctypes.py | 37 ++++++++++++---------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/kivy/core/clipboard/clipboard_winctypes.py b/kivy/core/clipboard/clipboard_winctypes.py index 130823e5c..58d1f5c43 100644 --- a/kivy/core/clipboard/clipboard_winctypes.py +++ b/kivy/core/clipboard/clipboard_winctypes.py @@ -10,42 +10,47 @@ from kivy.core.clipboard import ClipboardBase if platform != 'win': raise SystemError('unsupported platform for Windows clipboard') +user32 = ctypes.windll.user32 +kernel32 = ctypes.windll.kernel32 +msvcrt = ctypes.cdll.msvcrt +c_char_p = ctypes.c_char_p + class ClipboardWindows(ClipboardBase): def get(self, mimetype='text/plain'): - ctypes.windll.user32.OpenClipboard(0) + user32.OpenClipboard(0) # 1 is CF_TEXT - pcontents = ctypes.windll.user32.GetClipboardData(1) - data = ctypes.c_char_p(pcontents).value + pcontents = user32.GetClipboardData(1) + data = c_char_p(pcontents).value #ctypes.windll.kernel32.GlobalUnlock(pcontents) - ctypes.windll.user32.CloseClipboard() + user32.CloseClipboard() return data def put(self, data, mimetype='text/plain'): GMEM_DDESHARE = 0x2000 - ctypes.windll.user32.OpenClipboard(0) - ctypes.windll.user32.EmptyClipboard() + user32.OpenClipboard(0) + user32.EmptyClipboard() try: # works on Python 2 (bytes() only takes one argument) - hCd = ctypes.windll.kernel32.GlobalAlloc( + hCd = kernel32.GlobalAlloc( GMEM_DDESHARE, len(bytes(text)) + 1) except TypeError: # works on Python 3 (bytes() requires an encoding) - hCd = ctypes.windll.kernel32.GlobalAlloc( + hCd = kernel32.GlobalAlloc( GMEM_DDESHARE, len(bytes(text, 'ascii')) + 1) - pchData = ctypes.windll.kernel32.GlobalLock(hCd) + pchData = kernel32.GlobalLock(hCd) try: # works on Python 2 (bytes() only takes one argument) - ctypes.cdll.msvcrt.strcpy( - ctypes.c_char_p(pchData), bytes(text)) + msvcrt.strcpy( + c_char_p(pchData), bytes(text)) except TypeError: # works on Python 3 (bytes() requires an encoding) - ctypes.cdll.msvcrt.strcpy( - ctypes.c_char_p(pchData), bytes(text, 'ascii')) - ctypes.windll.kernel32.GlobalUnlock(hCd) - ctypes.windll.user32.SetClipboardData(1, hCd) - ctypes.windll.user32.CloseClipboard() + msvcrt.strcpy( + c_char_p(pchData), bytes(text, 'ascii')) + kernel32.GlobalUnlock(hCd) + user32.SetClipboardData(1, hCd) + user32.CloseClipboard() def get_types(self): return list('text/plain',) From faefe5629c2e47b81d088d56dfc29a2d4e40d9af Mon Sep 17 00:00:00 2001 From: gabriel pettier Date: Sun, 2 Nov 2014 14:36:49 +0100 Subject: [PATCH 4/6] fixes for clipboard_dbusklipper --- kivy/core/clipboard/__init__.py | 2 +- .../{clipboard_dbusclipper.py => clipboard_dbusklipper.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename kivy/core/clipboard/{clipboard_dbusclipper.py => clipboard_dbusklipper.py} (100%) diff --git a/kivy/core/clipboard/__init__.py b/kivy/core/clipboard/__init__.py index e247669cd..304cbbb41 100644 --- a/kivy/core/clipboard/__init__.py +++ b/kivy/core/clipboard/__init__.py @@ -132,7 +132,7 @@ elif _platform in ('macosx', 'linux', 'win'): _clipboards.append( ('winctypes', 'clipboard_winctypes', 'ClipboardWindows')) elif _platform == 'linux': - _clipboards.append(('dbusklipper', 'clipboard_dbusklipper', 'Clipboard_DbusKlipper')) + _clipboards.append(('dbusklipper', 'clipboard_dbusklipper', 'ClipboardDbusKlipper')) _clipboards.append( ('pygame', 'clipboard_pygame', 'ClipboardPygame')) diff --git a/kivy/core/clipboard/clipboard_dbusclipper.py b/kivy/core/clipboard/clipboard_dbusklipper.py similarity index 100% rename from kivy/core/clipboard/clipboard_dbusclipper.py rename to kivy/core/clipboard/clipboard_dbusklipper.py From 605601636fd4c1d440a85b3d0adb4270428b8616 Mon Sep 17 00:00:00 2001 From: akshayaurora Date: Sun, 14 Dec 2014 01:04:23 +0530 Subject: [PATCH 5/6] clipboard_winctype fixes for windows --- kivy/core/clipboard/__init__.py | 12 ++++---- kivy/core/clipboard/clipboard_winctypes.py | 33 ++++++++-------------- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/kivy/core/clipboard/__init__.py b/kivy/core/clipboard/__init__.py index 304cbbb41..8caee16d8 100644 --- a/kivy/core/clipboard/__init__.py +++ b/kivy/core/clipboard/__init__.py @@ -1,3 +1,4 @@ + ''' Clipboard ========= @@ -119,11 +120,6 @@ _platform = platform if _platform == 'android': _clipboards.append( ('android', 'clipboard_android', 'ClipboardAndroid')) - _clipboards.append( - ('sdl2', 'clipboard_sdl2', 'ClipboardSDL2')) -elif _platform == 'ios': - _clipboards.append( - ('sdl2', 'clipboard_sdl2', 'ClipboardSDL2')) elif _platform in ('macosx', 'linux', 'win'): if _platform == 'macosx': _clipboards.append( @@ -136,8 +132,9 @@ elif _platform in ('macosx', 'linux', 'win'): _clipboards.append( ('pygame', 'clipboard_pygame', 'ClipboardPygame')) - _clipboards.append( - ('sdl2', 'clipboard_sdl2', 'ClipboardSDL2')) + +_clipboards.append( + ('sdl2', 'clipboard_sdl2', 'ClipboardSDL2')) _clipboards.append( ('dummy', 'clipboard_dummy', 'ClipboardDummy')) @@ -145,3 +142,4 @@ Clipboard = core_select_lib('clipboard', _clipboards, True) del _clipboards del _platform + diff --git a/kivy/core/clipboard/clipboard_winctypes.py b/kivy/core/clipboard/clipboard_winctypes.py index 58d1f5c43..ebbcd1b63 100644 --- a/kivy/core/clipboard/clipboard_winctypes.py +++ b/kivy/core/clipboard/clipboard_winctypes.py @@ -10,10 +10,12 @@ from kivy.core.clipboard import ClipboardBase if platform != 'win': raise SystemError('unsupported platform for Windows clipboard') +import ctypes user32 = ctypes.windll.user32 kernel32 = ctypes.windll.kernel32 msvcrt = ctypes.cdll.msvcrt c_char_p = ctypes.c_char_p +c_wchar_p = ctypes.c_wchar_p class ClipboardWindows(ClipboardBase): @@ -21,37 +23,26 @@ class ClipboardWindows(ClipboardBase): def get(self, mimetype='text/plain'): user32.OpenClipboard(0) # 1 is CF_TEXT - pcontents = user32.GetClipboardData(1) - data = c_char_p(pcontents).value + pcontents = user32.GetClipboardData(13) + data = c_wchar_p(pcontents).value.encode('utf-16') #ctypes.windll.kernel32.GlobalUnlock(pcontents) user32.CloseClipboard() return data - def put(self, data, mimetype='text/plain'): + def put(self, text, mimetype='text/plain'): + print text, type(text) GMEM_DDESHARE = 0x2000 - user32.OpenClipboard(0) + CF_UNICODETEXT = 13 + user32.OpenClipboard(None) user32.EmptyClipboard() - try: - # works on Python 2 (bytes() only takes one argument) - hCd = kernel32.GlobalAlloc( - GMEM_DDESHARE, len(bytes(text)) + 1) - except TypeError: - # works on Python 3 (bytes() requires an encoding) - hCd = kernel32.GlobalAlloc( - GMEM_DDESHARE, len(bytes(text, 'ascii')) + 1) + hCd = kernel32.GlobalAlloc(GMEM_DDESHARE, len(text) + 2) pchData = kernel32.GlobalLock(hCd) - try: - # works on Python 2 (bytes() only takes one argument) - msvcrt.strcpy( - c_char_p(pchData), bytes(text)) - except TypeError: - # works on Python 3 (bytes() requires an encoding) - msvcrt.strcpy( - c_char_p(pchData), bytes(text, 'ascii')) + msvcrt.wcscpy(c_wchar_p(pchData), text) kernel32.GlobalUnlock(hCd) - user32.SetClipboardData(1, hCd) + user32.SetClipboardData(CF_UNICODETEXT, hCd) user32.CloseClipboard() def get_types(self): return list('text/plain',) + From a41c75d45ebf3254e71382bbef1f170bd9d3993a Mon Sep 17 00:00:00 2001 From: akshayaurora Date: Sun, 14 Dec 2014 02:48:04 +0530 Subject: [PATCH 6/6] make sure platform specific clipboard implementations are preferred --- kivy/__init__.py | 3 ++- kivy/core/clipboard/clipboard_winctypes.py | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kivy/__init__.py b/kivy/__init__.py index f38019308..c4bf46034 100644 --- a/kivy/__init__.py +++ b/kivy/__init__.py @@ -189,7 +189,7 @@ kivy_options = { 'image': ('tex', 'imageio', 'dds', 'gif', 'pil', 'pygame', 'ffpy', 'sdl2'), 'camera': ('opencv', 'gi', 'pygst', 'videocapture', 'avfoundation'), 'spelling': ('enchant', 'osxappkit', ), - 'clipboard': ('android', 'pygame', 'dummy', 'sdl2'), } + 'clipboard': ('android', 'winctypes', 'dbusklipper', 'nspaste', 'pygame', 'sdl2', 'dummy'), } # Read environment for option in kivy_options: @@ -209,6 +209,7 @@ for option in kivy_options: #: Kivy directory kivy_base_dir = dirname(sys.modules[__name__].__file__) #: Kivy modules directory + kivy_modules_dir = environ.get('KIVY_MODULES_DIR', join(kivy_base_dir, 'modules')) #: Kivy extension directory diff --git a/kivy/core/clipboard/clipboard_winctypes.py b/kivy/core/clipboard/clipboard_winctypes.py index ebbcd1b63..23b275bf6 100644 --- a/kivy/core/clipboard/clipboard_winctypes.py +++ b/kivy/core/clipboard/clipboard_winctypes.py @@ -30,7 +30,6 @@ class ClipboardWindows(ClipboardBase): return data def put(self, text, mimetype='text/plain'): - print text, type(text) GMEM_DDESHARE = 0x2000 CF_UNICODETEXT = 13 user32.OpenClipboard(None)