Skip to content

Commit a6afff2

Browse files
committed
Merge pull request kivy#2743 from kivy/clipboard_os_specific
Clipboard os specific
2 parents 283063d + a41c75d commit a6afff2

File tree

5 files changed

+144
-3
lines changed

5 files changed

+144
-3
lines changed

kivy/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ def kivy_usage():
189189
'image': ('tex', 'imageio', 'dds', 'gif', 'pil', 'pygame', 'ffpy', 'sdl2'),
190190
'camera': ('opencv', 'gi', 'pygst', 'videocapture', 'avfoundation'),
191191
'spelling': ('enchant', 'osxappkit', ),
192-
'clipboard': ('android', 'pygame', 'dummy', 'sdl2'), }
192+
'clipboard': ('android', 'winctypes', 'dbusklipper', 'nspaste', 'pygame', 'sdl2', 'dummy'), }
193193

194194
# Read environment
195195
for option in kivy_options:
@@ -209,6 +209,7 @@ def kivy_usage():
209209
#: Kivy directory
210210
kivy_base_dir = dirname(sys.modules[__name__].__file__)
211211
#: Kivy modules directory
212+
212213
kivy_modules_dir = environ.get('KIVY_MODULES_DIR',
213214
join(kivy_base_dir, 'modules'))
214215
#: Kivy extension directory

kivy/core/clipboard/__init__.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
'''
23
Clipboard
34
=========
@@ -120,14 +121,25 @@ def _paste(self):
120121
_clipboards.append(
121122
('android', 'clipboard_android', 'ClipboardAndroid'))
122123
elif _platform in ('macosx', 'linux', 'win'):
124+
if _platform == 'macosx':
125+
_clipboards.append(
126+
('nspaste', 'clipboard_nspaste', 'ClipboardNSPaste'))
127+
elif _platform == 'win':
128+
_clipboards.append(
129+
('winctypes', 'clipboard_winctypes', 'ClipboardWindows'))
130+
elif _platform == 'linux':
131+
_clipboards.append(('dbusklipper', 'clipboard_dbusklipper', 'ClipboardDbusKlipper'))
132+
123133
_clipboards.append(
124134
('pygame', 'clipboard_pygame', 'ClipboardPygame'))
125-
_clipboards.append(
126-
('sdl2', 'clipboard_sdl2', 'ClipboardSDL2'))
135+
136+
_clipboards.append(
137+
('sdl2', 'clipboard_sdl2', 'ClipboardSDL2'))
127138
_clipboards.append(
128139
('dummy', 'clipboard_dummy', 'ClipboardDummy'))
129140

130141
Clipboard = core_select_lib('clipboard', _clipboards, True)
131142

132143
del _clipboards
133144
del _platform
145+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'''
2+
Clipboard Dbus: an implementation of the Clipboard using dbus and klipper.
3+
'''
4+
5+
__all__ = ('ClipboardDbusKlipper', )
6+
7+
from kivy.utils import platform
8+
from kivy.core.clipboard import ClipboardBase
9+
10+
if platform != 'linux':
11+
raise SystemError('unsupported platform for dbus kde clipboard')
12+
13+
try:
14+
import dbus
15+
bus = dbus.SessionBus()
16+
proxy = bus.get_object("org.kde.klipper", "/klipper")
17+
except:
18+
raise
19+
20+
21+
class ClipboardDbusKlipper(ClipboardBase):
22+
23+
_is_init = False
24+
25+
def init(self):
26+
if ClipboardDbusKlipper._is_init:
27+
return
28+
self.iface = dbus.Interface(proxy, "org.kde.klipper.klipper")
29+
ClipboardDbusKlipper._is_init = True
30+
31+
def get(self, mimetype='text/plain'):
32+
self.init()
33+
return str(self.iface.getClipboardContents())
34+
35+
def put(self, data, mimetype='text/plain'):
36+
self.init()
37+
self.iface.setClipboardContents(data.replace('\x00', ''))
38+
39+
def get_types(self):
40+
self.init()
41+
return 'text/plain'
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'''
2+
Clipboard OsX: implementation of clipboard using Appkit
3+
'''
4+
5+
__all__ = ('ClipboardNSPaste', )
6+
7+
from kivy.core.clipboard import ClipboardBase
8+
from kivy.utils import platform
9+
10+
if platform != 'macosx':
11+
raise SystemError('Unsupported platform for appkit clipboard.')
12+
try:
13+
from pyobjus import autoclass
14+
from pyobjus.dylib_manager import load_framework, INCLUDE
15+
load_framework(INCLUDE.AppKit)
16+
except ImportError:
17+
raise SystemError('Pyobjus not installed. Please run the following'
18+
' command to install it. `pip install --user pyobjus`')
19+
20+
NSPasteboard = autoclass('NSPasteboard')
21+
NSString = autoclass('NSString')
22+
23+
24+
class ClipboardNSPaste(ClipboardBase):
25+
26+
def __init__(self):
27+
super(ClipboardNSPaste, self).__init__()
28+
self._clipboard = NSPasteboard.generalPasteboard()
29+
30+
def get(self, mimetype='text/plain'):
31+
pb = self._clipboard
32+
return pb.stringForType_('public.utf8-plain-text').UTF8String()
33+
34+
def put(self, data, mimetype='text/plain'):
35+
pb = self._clipboard
36+
pb.clearContents()
37+
pb.writeObjects_([data])
38+
39+
def get_types(self):
40+
return list('text/plain',)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
'''
2+
Clipboard windows: an implementation of the Clipboard using ctypes.
3+
'''
4+
5+
__all__ = ('ClipboardWindows', )
6+
7+
from kivy.utils import platform
8+
from kivy.core.clipboard import ClipboardBase
9+
10+
if platform != 'win':
11+
raise SystemError('unsupported platform for Windows clipboard')
12+
13+
import ctypes
14+
user32 = ctypes.windll.user32
15+
kernel32 = ctypes.windll.kernel32
16+
msvcrt = ctypes.cdll.msvcrt
17+
c_char_p = ctypes.c_char_p
18+
c_wchar_p = ctypes.c_wchar_p
19+
20+
21+
class ClipboardWindows(ClipboardBase):
22+
23+
def get(self, mimetype='text/plain'):
24+
user32.OpenClipboard(0)
25+
# 1 is CF_TEXT
26+
pcontents = user32.GetClipboardData(13)
27+
data = c_wchar_p(pcontents).value.encode('utf-16')
28+
#ctypes.windll.kernel32.GlobalUnlock(pcontents)
29+
user32.CloseClipboard()
30+
return data
31+
32+
def put(self, text, mimetype='text/plain'):
33+
GMEM_DDESHARE = 0x2000
34+
CF_UNICODETEXT = 13
35+
user32.OpenClipboard(None)
36+
user32.EmptyClipboard()
37+
hCd = kernel32.GlobalAlloc(GMEM_DDESHARE, len(text) + 2)
38+
pchData = kernel32.GlobalLock(hCd)
39+
msvcrt.wcscpy(c_wchar_p(pchData), text)
40+
kernel32.GlobalUnlock(hCd)
41+
user32.SetClipboardData(CF_UNICODETEXT, hCd)
42+
user32.CloseClipboard()
43+
44+
def get_types(self):
45+
return list('text/plain',)
46+
47+

0 commit comments

Comments
 (0)