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() (<-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 { cb, err := Get() if err != nil { continue } if atomic.LoadUint32(&isListening) == 1 { res <- cb continue } } } } } }() return res, nil }