You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
3.2 KiB
Go

package clipboard
import (
"b612.me/win32api"
"errors"
"fmt"
"sync/atomic"
"time"
)
var stopSign chan struct{}
var isListening uint32
/*
func listenMethod2() (<-chan Clipboard, error) {
if atomic.LoadUint32(&isListening) == 1 {
return nil, errors.New("Already listening")
}
atomic.StoreUint32(&isListening, 1)
res := make(chan Clipboard, 3)
stopSign = make(chan struct{})
hWnd, err := win32api.CreateWindowEx(0,
"Message",
"B612 Clipboard Listener",
0,
0, 0, 500, 500,
0, 0, 0, nil)
if hWnd == 0 || err != nil {
return nil, fmt.Errorf("Failed to create window: %v,hWnd:%v", err, hWnd)
}
set, err := win32api.AddClipboardFormatListener(hWnd)
if !set || err != nil {
return nil, fmt.Errorf("Failed to set clipboard listener: %v", err)
}
fetcher := make(chan struct{}, 8)
go fetchListener(hWnd, fetcher)
go func() {
for {
select {
case <-stopSign:
fmt.Println("stopped")
atomic.StoreUint32(&isListening, 0)
close(res)
close(stopSign)
win32api.RemoveClipboardFormatListener(win32api.HWND(hWnd))
win32api.DestoryWindow(hWnd)
return
case <-fetcher:
cb, err := Get()
if err != nil {
fmt.Println(err)
}
if atomic.LoadUint32(&isListening) == 1 {
res <- cb
continue
}
}
}
}()
return res, nil
}
func fetchListener(hWnd win32api.HWND, res chan struct{}) {
for {
var msg win32api.MSG
_, err := win32api.GetMessage(&msg, hWnd, 0, 0)
if msg.Message == 0x0012 {
return
}
if err == nil && win32api.DWORD(msg.Message) == win32api.WM_CLIPBOARDUPDATE {
res <- struct{}{}
}
}
}
*/
func PauseListen() error {
if atomic.LoadUint32(&isListening) == 0 {
return errors.New("Not listening")
}
atomic.StoreUint32(&isListening, 2)
return nil
}
func RecoverListen() error {
if atomic.LoadUint32(&isListening) == 0 {
return errors.New("Not Listening")
}
atomic.StoreUint32(&isListening, 1)
return nil
}
func StopListen() error {
defer func() {
if r := recover(); r != nil {
fmt.Println("StopListen panic:", r)
}
}()
if atomic.LoadUint32(&isListening) == 0 {
return nil
}
stopSign <- struct{}{}
return nil
}
func Listen(onlyMeta bool) (<-chan Clipboard, error) {
if atomic.LoadUint32(&isListening) != 0 {
return nil, errors.New("Already listening")
}
atomic.StoreUint32(&isListening, 1)
res := make(chan Clipboard, 3)
stopSign = make(chan struct{})
go func() {
var storeSeq win32api.DWORD
for {
select {
case <-stopSign:
atomic.StoreUint32(&isListening, 0)
close(res)
close(stopSign)
return
case <-time.After(time.Millisecond * 900):
seq, err := win32api.GetClipboardSequenceNumber()
if err != nil {
continue
}
if seq != storeSeq {
storeSeq = seq
//fmt.Println("Clipboard updated", seq, storeSeq)
if atomic.LoadUint32(&isListening) == 1 {
if !onlyMeta {
cb, err := Get()
if err != nil {
continue
}
if atomic.LoadUint32(&isListening) == 1 {
res <- cb
continue
}
} else {
cb, err := GetMeta()
if err != nil {
continue
}
if atomic.LoadUint32(&isListening) == 1 {
res <- cb
continue
}
}
}
}
}
}
}()
return res, nil
}