Skip to content

Commit 70c88c2

Browse files
committed
all: add darwin support
1 parent eb0cb20 commit 70c88c2

File tree

7 files changed

+136
-13
lines changed

7 files changed

+136
-13
lines changed

.github/workflows/clipboard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
strategy:
1414
fail-fast: false
1515
matrix:
16-
os: [ubuntu-latest, windows-latest, macos-latest]
16+
os: [ubuntu-latest, macos-latest]
1717

1818
steps:
1919
- name: install libx11-dev

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ clipboard.Write(clipboard.MIMEImage, []byte("image data"))
2727
clipboard.Read(clipboard.MIMEImage)
2828
```
2929

30+
## Notes
31+
32+
To obtain image data to the clipboard, you can:
33+
34+
- On macOS, Ctrl+Shift+Cmd+4
35+
- On Linux/Ubuntu, Ctrl+Shift+PrintScreen
36+
37+
The package currently supports read/write plain text string or image data
38+
with PNG format. The other types of data are not supported, as undefined
39+
behavior.
40+
3041
## License
3142

3243
GNU GPL-3 Copyright © 2021 The golang.design Initiative Authors, written by [Changkun Ou](https://changkun.de).

clipboard_darwin.go

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,61 @@
44
//
55
// Written by Changkun Ou <changkun.de>
66

7-
// +build !linux,darwin
7+
//go:build darwin
8+
// +build darwin
89

910
package clipboard
1011

11-
func readAll() (buf []byte) {
12-
panic("unsupported")
12+
/*
13+
#cgo CFLAGS: -x objective-c
14+
#cgo LDFLAGS: -framework Foundation -framework Cocoa
15+
#import <Foundation/Foundation.h>
16+
#import <Cocoa/Cocoa.h>
17+
18+
unsigned int clipboard_read_string(void **out);
19+
unsigned int clipboard_read_image(void **out);
20+
int clipboard_write_string(const void *bytes, NSInteger n);
21+
int clipboard_write_image(const void *bytes, NSInteger n);
22+
*/
23+
import "C"
24+
import "unsafe"
25+
26+
func read(t MIMEType) (buf []byte) {
27+
var (
28+
data unsafe.Pointer
29+
n C.uint
30+
)
31+
switch t {
32+
case MIMEText:
33+
n = C.clipboard_read_string(&data)
34+
case MIMEImage:
35+
n = C.clipboard_read_image(&data)
36+
}
37+
if data == nil {
38+
return nil
39+
}
40+
defer C.free(unsafe.Pointer(data))
41+
if n == 0 {
42+
return nil
43+
}
44+
return C.GoBytes(data, C.int(n))
1345
}
1446

15-
func writeAll(buf []byte) {
16-
panic("unsupported")
47+
// write writes the given data to clipboard and
48+
// returns true if success or false if failed.
49+
func write(t MIMEType, buf []byte) bool {
50+
var ok C.int
51+
52+
switch t {
53+
case MIMEText:
54+
ok = C.clipboard_write_string(unsafe.Pointer(&buf[0]),
55+
C.NSInteger(len(buf)))
56+
case MIMEImage:
57+
ok = C.clipboard_write_image(unsafe.Pointer(&buf[0]),
58+
C.NSInteger(len(buf)))
59+
}
60+
if ok != 0 {
61+
return false
62+
}
63+
return true
1764
}

clipboard_darwin.m

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2021 The golang.design Initiative authors.
2+
// All rights reserved. Use of this source code is governed
3+
// by a GNU GPL-3 license that can be found in the LICENSE file.
4+
//
5+
// Written by Changkun Ou <changkun.de>
6+
7+
// Interact with NSPasteboard using Objective-C
8+
// https://developer.apple.com/documentation/appkit/nspasteboard?language=objc
9+
10+
#import <Foundation/Foundation.h>
11+
#import <Cocoa/Cocoa.h>
12+
13+
unsigned int clipboard_read_string(void **out) {
14+
NSPasteboard * pasteboard = [NSPasteboard generalPasteboard];
15+
NSData *data = [pasteboard dataForType:NSPasteboardTypeString];
16+
if (data == nil) {
17+
return 0;
18+
}
19+
NSUInteger siz = [data length];
20+
*out = malloc(siz);
21+
[data getBytes: *out length: siz];
22+
return siz;
23+
}
24+
25+
unsigned int clipboard_read_image(void **out) {
26+
NSPasteboard * pasteboard = [NSPasteboard generalPasteboard];
27+
NSData *data = [pasteboard dataForType:NSPasteboardTypePNG];
28+
if (data == nil) {
29+
return 0;
30+
}
31+
NSUInteger siz = [data length];
32+
*out = malloc(siz);
33+
[data getBytes: *out length: siz];
34+
return siz;
35+
}
36+
37+
int clipboard_write_string(const void *bytes, NSInteger n) {
38+
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
39+
NSData *data = [NSData dataWithBytes: bytes length: n];
40+
[pasteboard clearContents];
41+
BOOL ok = [pasteboard setData: data forType:NSPasteboardTypeString];
42+
if (!ok) {
43+
return -1;
44+
}
45+
return 0;
46+
}
47+
int clipboard_write_image(const void *bytes, NSInteger n) {
48+
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
49+
NSData *data = [NSData dataWithBytes: bytes length: n];
50+
[pasteboard clearContents];
51+
BOOL ok = [pasteboard setData: data forType:NSPasteboardTypePNG];
52+
if (!ok) {
53+
return -1;
54+
}
55+
return 0;
56+
}

clipboard_linux.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
//
55
// Written by Changkun Ou <changkun.de>
66

7-
// +build linux,!darwin
7+
//go:build linux
8+
// +build linux
89

910
package clipboard
1011

@@ -71,7 +72,9 @@ func readc(t string) []byte {
7172
return C.GoBytes(unsafe.Pointer(data), C.int(n))
7273
}
7374

74-
func write(t MIMEType, buf []byte) {
75+
// write writes the given data to clipboard and
76+
// returns true if success or false if failed.
77+
func write(t MIMEType, buf []byte) bool {
7578
var s string
7679
switch t {
7780
case MIMEText:
@@ -97,6 +100,10 @@ func write(t MIMEType, buf []byte) {
97100
// should use an atomic version, and use atomic_load.
98101
for start == 0 {
99102
}
103+
104+
if start < 0 {
105+
return false
106+
}
100107
// wait until enter event loop
101-
return
108+
return true
102109
}

clipboard_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
)
1616

1717
func TestClipboard(t *testing.T) {
18-
1918
t.Run("image", func(t *testing.T) {
2019
data, err := os.ReadFile("testdata/clipboard.png")
2120
if err != nil {

clipboard_others.go renamed to clipboard_windows.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44
//
55
// Written by Changkun Ou <changkun.de>
66

7-
// +build !linux,!darwin
7+
//go:build windows
8+
// +build windows
89

910
package clipboard
1011

11-
func readAll() (buf []byte) {
12+
func read(t MIMEType) (buf []byte) {
1213
panic("unsupported")
1314
}
1415

15-
func writeAll(buf []byte) {
16+
// write writes the given data to clipboard and
17+
// returns true if success or false if failed.
18+
func write(t MIMEType, buf []byte) bool {
1619
panic("unsupported")
1720
}

0 commit comments

Comments
 (0)