-
Notifications
You must be signed in to change notification settings - Fork 2
/
clipboard.go
140 lines (108 loc) · 2.78 KB
/
clipboard.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright 2013 The Walk Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package walk
import (
"syscall"
"unsafe"
)
import (
"github.com/lxn/win"
)
const clipboardWindowClass = `\o/ Walk_Clipboard_Class \o/`
func init() {
MustRegisterWindowClass(clipboardWindowClass)
hwnd := win.CreateWindowEx(
0,
syscall.StringToUTF16Ptr(clipboardWindowClass),
nil,
0,
0,
0,
0,
0,
win.HWND_MESSAGE,
0,
0,
nil)
if hwnd == 0 {
panic("failed to create clipboard window")
}
clipboard.hwnd = hwnd
}
var clipboard ClipboardService
// Clipboard returns an object that provides access to the system clipboard.
func Clipboard() *ClipboardService {
return &clipboard
}
// ClipboardService provides access to the system clipboard.
type ClipboardService struct {
hwnd win.HWND
}
// Clear clears the contents of the clipboard.
func (c *ClipboardService) Clear() error {
return c.withOpenClipboard(func() error {
if !win.EmptyClipboard() {
return lastError("EmptyClipboard")
}
return nil
})
}
// ContainsText returns whether the clipboard currently contains text data.
func (c *ClipboardService) ContainsText() (available bool, err error) {
err = c.withOpenClipboard(func() error {
available = win.IsClipboardFormatAvailable(win.CF_UNICODETEXT)
return nil
})
return
}
// Text returns the current text data of the clipboard.
func (c *ClipboardService) Text() (text string, err error) {
err = c.withOpenClipboard(func() error {
hMem := win.HGLOBAL(win.GetClipboardData(win.CF_UNICODETEXT))
if hMem == 0 {
return lastError("GetClipboardData")
}
p := win.GlobalLock(hMem)
if p == nil {
return lastError("GlobalLock()")
}
defer win.GlobalUnlock(hMem)
text = win.UTF16PtrToString((*uint16)(p))
return nil
})
return
}
// SetText sets the current text data of the clipboard.
func (c *ClipboardService) SetText(s string) error {
return c.withOpenClipboard(func() error {
utf16, err := syscall.UTF16FromString(s)
if err != nil {
return err
}
hMem := win.GlobalAlloc(win.GMEM_MOVEABLE, uintptr(len(utf16)*2))
if hMem == 0 {
return lastError("GlobalAlloc")
}
p := win.GlobalLock(hMem)
if p == nil {
return lastError("GlobalLock()")
}
win.MoveMemory(p, unsafe.Pointer(&utf16[0]), uintptr(len(utf16)*2))
win.GlobalUnlock(hMem)
if 0 == win.SetClipboardData(win.CF_UNICODETEXT, win.HANDLE(hMem)) {
// We need to free hMem.
defer win.GlobalFree(hMem)
return lastError("SetClipboardData")
}
// The system now owns the memory referred to by hMem.
return nil
})
}
func (c *ClipboardService) withOpenClipboard(f func() error) error {
if !win.OpenClipboard(c.hwnd) {
return lastError("OpenClipboard")
}
defer win.CloseClipboard()
return f()
}