Import upstream version 0.1.4+git20210312.1.1438b32
Debian Janitor
1 year, 6 months ago
0 | 0 | language: go |
1 | 1 | |
2 | os: | |
3 | - linux | |
4 | - osx | |
5 | - windows | |
6 | ||
2 | 7 | go: |
3 | - go1.4.3 | |
4 | - go1.5.4 | |
5 | - go1.6.4 | |
6 | - go1.7.6 | |
7 | - go1.8.7 | |
8 | - go1.9.4 | |
9 | - go1.10 | |
8 | - go1.13.x | |
9 | - go1.x | |
10 | ||
11 | services: | |
12 | - xvfb | |
10 | 13 | |
11 | 14 | before_install: |
12 | 15 | - export DISPLAY=:99.0 |
13 | - sh -e /etc/init.d/xvfb start | |
14 | 16 | |
15 | 17 | script: |
16 | - sudo apt-get install xsel | |
18 | - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install xsel; fi | |
17 | 19 | - go test -v . |
18 | - sudo apt-get install xclip | |
20 | - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install xclip; fi | |
19 | 21 | - go test -v . |
0 | [![Build Status](https://travis-ci.org/atotto/clipboard.svg?branch=master)](https://travis-ci.org/atotto/clipboard) | |
0 | [![Build Status](https://travis-ci.com/atotto/clipboard.svg?branch=master)](https://travis-ci.com/atotto/clipboard) | |
1 | 1 | |
2 | 2 | [![GoDoc](https://godoc.org/github.com/atotto/clipboard?status.svg)](http://godoc.org/github.com/atotto/clipboard) |
3 | 3 |
0 | // Copyright 2013 @atotto. All rights reserved. | |
1 | // Use of this source code is governed by a BSD-style | |
2 | // license that can be found in the LICENSE file. | |
3 | ||
4 | // +build plan9 | |
5 | ||
6 | package clipboard | |
7 | ||
8 | import ( | |
9 | "os" | |
10 | "io/ioutil" | |
11 | ) | |
12 | ||
13 | func readAll() (string, error) { | |
14 | f, err := os.Open("/dev/snarf") | |
15 | if err != nil { | |
16 | return "", err | |
17 | } | |
18 | defer f.Close() | |
19 | ||
20 | str, err := ioutil.ReadAll(f) | |
21 | if err != nil { | |
22 | return "", err | |
23 | } | |
24 | ||
25 | return string(str), nil | |
26 | } | |
27 | ||
28 | func writeAll(text string) error { | |
29 | f, err := os.OpenFile("/dev/snarf", os.O_WRONLY, 0666) | |
30 | if err != nil { | |
31 | return err | |
32 | } | |
33 | defer f.Close() | |
34 | ||
35 | _, err = f.Write([]byte(text)) | |
36 | if err != nil { | |
37 | return err | |
38 | } | |
39 | ||
40 | return nil | |
41 | } |
14 | 14 | const ( |
15 | 15 | xsel = "xsel" |
16 | 16 | xclip = "xclip" |
17 | wlcopy = "wl-copy" | |
18 | wlpaste = "wl-paste" | |
17 | powershellExe = "powershell.exe" | |
18 | clipExe = "clip.exe" | |
19 | wlcopy = "wl-copy" | |
20 | wlpaste = "wl-paste" | |
19 | 21 | termuxClipboardGet = "termux-clipboard-get" |
20 | 22 | termuxClipboardSet = "termux-clipboard-set" |
21 | 23 | ) |
22 | 24 | |
23 | 25 | var ( |
24 | 26 | Primary bool |
27 | trimDos bool | |
25 | 28 | |
26 | 29 | pasteCmdArgs []string |
27 | 30 | copyCmdArgs []string |
32 | 35 | xclipPasteArgs = []string{xclip, "-out", "-selection", "clipboard"} |
33 | 36 | xclipCopyArgs = []string{xclip, "-in", "-selection", "clipboard"} |
34 | 37 | |
38 | powershellExePasteArgs = []string{powershellExe, "Get-Clipboard"} | |
39 | clipExeCopyArgs = []string{clipExe} | |
40 | ||
35 | 41 | wlpasteArgs = []string{wlpaste, "--no-newline"} |
36 | wlcopyArgs = []string{wlcopy} | |
42 | wlcopyArgs = []string{wlcopy} | |
37 | 43 | |
38 | 44 | termuxPasteArgs = []string{termuxClipboardGet} |
39 | 45 | termuxCopyArgs = []string{termuxClipboardSet} |
43 | 49 | |
44 | 50 | func init() { |
45 | 51 | if os.Getenv("WAYLAND_DISPLAY") != "" { |
46 | pasteCmdArgs = wlpasteArgs; | |
47 | copyCmdArgs = wlcopyArgs; | |
52 | pasteCmdArgs = wlpasteArgs | |
53 | copyCmdArgs = wlcopyArgs | |
48 | 54 | |
49 | 55 | if _, err := exec.LookPath(wlcopy); err == nil { |
50 | 56 | if _, err := exec.LookPath(wlpaste); err == nil { |
76 | 82 | } |
77 | 83 | } |
78 | 84 | |
85 | pasteCmdArgs = powershellExePasteArgs | |
86 | copyCmdArgs = clipExeCopyArgs | |
87 | trimDos = true | |
88 | ||
89 | if _, err := exec.LookPath(clipExe); err == nil { | |
90 | if _, err := exec.LookPath(powershellExe); err == nil { | |
91 | return | |
92 | } | |
93 | } | |
94 | ||
79 | 95 | Unsupported = true |
80 | 96 | } |
81 | 97 | |
102 | 118 | if err != nil { |
103 | 119 | return "", err |
104 | 120 | } |
105 | return string(out), nil | |
121 | result := string(out) | |
122 | if trimDos && len(result) > 1 { | |
123 | result = result[:len(result)-2] | |
124 | } | |
125 | return result, nil | |
106 | 126 | } |
107 | 127 | |
108 | 128 | func writeAll(text string) error { |
6 | 6 | package clipboard |
7 | 7 | |
8 | 8 | import ( |
9 | "runtime" | |
9 | 10 | "syscall" |
10 | 11 | "time" |
11 | 12 | "unsafe" |
17 | 18 | ) |
18 | 19 | |
19 | 20 | var ( |
20 | user32 = syscall.MustLoadDLL("user32") | |
21 | openClipboard = user32.MustFindProc("OpenClipboard") | |
22 | closeClipboard = user32.MustFindProc("CloseClipboard") | |
23 | emptyClipboard = user32.MustFindProc("EmptyClipboard") | |
24 | getClipboardData = user32.MustFindProc("GetClipboardData") | |
25 | setClipboardData = user32.MustFindProc("SetClipboardData") | |
21 | user32 = syscall.MustLoadDLL("user32") | |
22 | isClipboardFormatAvailable = user32.MustFindProc("IsClipboardFormatAvailable") | |
23 | openClipboard = user32.MustFindProc("OpenClipboard") | |
24 | closeClipboard = user32.MustFindProc("CloseClipboard") | |
25 | emptyClipboard = user32.MustFindProc("EmptyClipboard") | |
26 | getClipboardData = user32.MustFindProc("GetClipboardData") | |
27 | setClipboardData = user32.MustFindProc("SetClipboardData") | |
26 | 28 | |
27 | 29 | kernel32 = syscall.NewLazyDLL("kernel32") |
28 | 30 | globalAlloc = kernel32.NewProc("GlobalAlloc") |
49 | 51 | } |
50 | 52 | |
51 | 53 | func readAll() (string, error) { |
54 | // LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution). | |
55 | // Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock. | |
56 | runtime.LockOSThread() | |
57 | defer runtime.UnlockOSThread() | |
58 | if formatAvailable, _, err := isClipboardFormatAvailable.Call(cfUnicodetext); formatAvailable == 0 { | |
59 | return "", err | |
60 | } | |
52 | 61 | err := waitOpenClipboard() |
53 | 62 | if err != nil { |
54 | 63 | return "", err |
55 | 64 | } |
56 | defer closeClipboard.Call() | |
57 | 65 | |
58 | 66 | h, _, err := getClipboardData.Call(cfUnicodetext) |
59 | 67 | if h == 0 { |
68 | _, _, _ = closeClipboard.Call() | |
60 | 69 | return "", err |
61 | 70 | } |
62 | 71 | |
63 | 72 | l, _, err := globalLock.Call(h) |
64 | 73 | if l == 0 { |
74 | _, _, _ = closeClipboard.Call() | |
65 | 75 | return "", err |
66 | 76 | } |
67 | 77 | |
69 | 79 | |
70 | 80 | r, _, err := globalUnlock.Call(h) |
71 | 81 | if r == 0 { |
82 | _, _, _ = closeClipboard.Call() | |
72 | 83 | return "", err |
73 | 84 | } |
74 | 85 | |
86 | closed, _, err := closeClipboard.Call() | |
87 | if closed == 0 { | |
88 | return "", err | |
89 | } | |
75 | 90 | return text, nil |
76 | 91 | } |
77 | 92 | |
78 | 93 | func writeAll(text string) error { |
94 | // LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution). | |
95 | // Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock. | |
96 | runtime.LockOSThread() | |
97 | defer runtime.UnlockOSThread() | |
98 | ||
79 | 99 | err := waitOpenClipboard() |
80 | 100 | if err != nil { |
81 | 101 | return err |
82 | 102 | } |
83 | defer closeClipboard.Call() | |
84 | 103 | |
85 | 104 | r, _, err := emptyClipboard.Call(0) |
86 | 105 | if r == 0 { |
106 | _, _, _ = closeClipboard.Call() | |
87 | 107 | return err |
88 | 108 | } |
89 | 109 | |
93 | 113 | // been allocated using the function with the GMEM_MOVEABLE flag." |
94 | 114 | h, _, err := globalAlloc.Call(gmemMoveable, uintptr(len(data)*int(unsafe.Sizeof(data[0])))) |
95 | 115 | if h == 0 { |
116 | _, _, _ = closeClipboard.Call() | |
96 | 117 | return err |
97 | 118 | } |
98 | 119 | defer func() { |
103 | 124 | |
104 | 125 | l, _, err := globalLock.Call(h) |
105 | 126 | if l == 0 { |
127 | _, _, _ = closeClipboard.Call() | |
106 | 128 | return err |
107 | 129 | } |
108 | 130 | |
109 | 131 | r, _, err = lstrcpy.Call(l, uintptr(unsafe.Pointer(&data[0]))) |
110 | 132 | if r == 0 { |
133 | _, _, _ = closeClipboard.Call() | |
111 | 134 | return err |
112 | 135 | } |
113 | 136 | |
114 | 137 | r, _, err = globalUnlock.Call(h) |
115 | 138 | if r == 0 { |
116 | 139 | if err.(syscall.Errno) != 0 { |
140 | _, _, _ = closeClipboard.Call() | |
117 | 141 | return err |
118 | 142 | } |
119 | 143 | } |
120 | 144 | |
121 | 145 | r, _, err = setClipboardData.Call(cfUnicodetext, h) |
122 | 146 | if r == 0 { |
147 | _, _, _ = closeClipboard.Call() | |
123 | 148 | return err |
124 | 149 | } |
125 | 150 | h = 0 // suppress deferred cleanup |
151 | closed, _, err := closeClipboard.Call() | |
152 | if closed == 0 { | |
153 | return err | |
154 | } | |
126 | 155 | return nil |
127 | 156 | } |