mirror of https://github.com/Wox-launcher/Wox
117 lines
2.7 KiB
Go
117 lines
2.7 KiB
Go
package util
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
"wox/util/clipboard"
|
|
"wox/util/keyboard"
|
|
)
|
|
|
|
var noSelection = errors.New("no selection")
|
|
var lastClipboardChangeTimestamp int64 = 0
|
|
|
|
type SelectionType string
|
|
|
|
const (
|
|
SelectionTypeText SelectionType = "text"
|
|
SelectionTypeFile SelectionType = "file"
|
|
)
|
|
|
|
type Selection struct {
|
|
Type SelectionType
|
|
// Only available when Type is SelectionTypeText
|
|
Text string
|
|
// Only available when Type is SelectionTypeFile
|
|
FilePaths []string
|
|
}
|
|
|
|
func InitSelection() {
|
|
clipboard.Watch(func(data clipboard.Data) {
|
|
lastClipboardChangeTimestamp = GetSystemTimestamp()
|
|
})
|
|
}
|
|
|
|
func (s *Selection) String() string {
|
|
switch s.Type {
|
|
case SelectionTypeText:
|
|
return s.Text
|
|
case SelectionTypeFile:
|
|
return strings.Join(s.FilePaths, ";")
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func (s *Selection) IsEmpty() bool {
|
|
switch s.Type {
|
|
case SelectionTypeText:
|
|
return s.Text == ""
|
|
case SelectionTypeFile:
|
|
return s.FilePaths == nil || len(s.FilePaths) == 0
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func GetSelected() (Selection, error) {
|
|
simulateStartTimestamp := GetSystemTimestamp()
|
|
if keyboard.SimulateCopy() != nil {
|
|
return Selection{}, errors.New("error simulate ctrl c")
|
|
}
|
|
|
|
// loop to wait for clipboard data to be updated, so that we can get the clipboard data as soon as possible if the clipboard data is updated
|
|
// because sometimes clipboard data is not updated immediately after simulated ctrl c, small text data is updated immediately, but large file data is not
|
|
var clipboardDataAfter clipboard.Data
|
|
loopTimes := 10
|
|
for i := 0; i < loopTimes; i++ {
|
|
isLastLoop := loopTimes-1 == i
|
|
|
|
// wait for clipboard data to be updated
|
|
time.Sleep(50 * time.Millisecond)
|
|
|
|
clipboardData, err := clipboard.ReadFilesAndText()
|
|
if err != nil {
|
|
if isLastLoop {
|
|
return Selection{}, err
|
|
} else {
|
|
continue
|
|
}
|
|
}
|
|
|
|
// clipboard data must be updated between simulateStartTimestamp and simulateEndTimestamp
|
|
// otherwise, it means that the clipboard data is not updated by the simulated ctrl c
|
|
if lastClipboardChangeTimestamp < simulateStartTimestamp {
|
|
if isLastLoop {
|
|
return Selection{}, noSelection
|
|
} else {
|
|
continue
|
|
}
|
|
}
|
|
|
|
clipboardDataAfter = clipboardData
|
|
break
|
|
}
|
|
|
|
if clipboardDataAfter == nil {
|
|
return Selection{}, noSelection
|
|
}
|
|
|
|
switch clipboardDataAfter.GetType() {
|
|
case clipboard.ClipboardTypeText:
|
|
textData := clipboardDataAfter.(*clipboard.TextData)
|
|
return Selection{
|
|
Type: SelectionTypeText,
|
|
Text: textData.Text,
|
|
}, nil
|
|
case clipboard.ClipboardTypeFile:
|
|
fileData := clipboardDataAfter.(*clipboard.FilePathData)
|
|
return Selection{
|
|
Type: SelectionTypeFile,
|
|
FilePaths: fileData.FilePaths,
|
|
}, nil
|
|
}
|
|
|
|
return Selection{}, errors.New("unknown clipboard type")
|
|
}
|