Init: Create & Init Project...
This commit is contained in:
commit
3029507430
29
.gitignore
vendored
Normal file
29
.gitignore
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
# ---> Go
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
|
||||
/vendor
|
||||
debug
|
||||
*.exe
|
17
Gopkg.lock
generated
Normal file
17
Gopkg.lock
generated
Normal file
@ -0,0 +1,17 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:256554af8321e28c57fab65ec53c3497d6e5d03c8b9eab1530875530030b68ef"
|
||||
name = "github.com/lxn/win"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "785c4956069227e430929ac27bfa26af2ff25dfb"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = ["github.com/lxn/win"]
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
34
Gopkg.toml
Normal file
34
Gopkg.toml
Normal file
@ -0,0 +1,34 @@
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/lxn/win"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
22
lib/clipboard/clipboard.go
Normal file
22
lib/clipboard/clipboard.go
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2013 @atotto. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package clipboard read/write on clipboard
|
||||
package clipboard
|
||||
|
||||
// import ()
|
||||
|
||||
// ReadAll read string from clipboard
|
||||
func ReadAll() (string, error) {
|
||||
return readAll()
|
||||
}
|
||||
|
||||
// WriteAll write string to clipboard
|
||||
func WriteAll(text string) error {
|
||||
return writeAll(text)
|
||||
}
|
||||
|
||||
// Unsupported might be set true during clipboard init, to help callers decide
|
||||
// whether or not to offer clipboard options.
|
||||
var Unsupported bool
|
52
lib/clipboard/clipboard_darwin.go
Normal file
52
lib/clipboard/clipboard_darwin.go
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2013 @atotto. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin
|
||||
|
||||
package clipboard
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
var (
|
||||
pasteCmdArgs = "pbpaste"
|
||||
copyCmdArgs = "pbcopy"
|
||||
)
|
||||
|
||||
func getPasteCommand() *exec.Cmd {
|
||||
return exec.Command(pasteCmdArgs)
|
||||
}
|
||||
|
||||
func getCopyCommand() *exec.Cmd {
|
||||
return exec.Command(copyCmdArgs)
|
||||
}
|
||||
|
||||
func readAll() (string, error) {
|
||||
pasteCmd := getPasteCommand()
|
||||
out, err := pasteCmd.Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
func writeAll(text string) error {
|
||||
copyCmd := getCopyCommand()
|
||||
in, err := copyCmd.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := copyCmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := in.Write([]byte(text)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := in.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return copyCmd.Wait()
|
||||
}
|
98
lib/clipboard/clipboard_unix.go
Normal file
98
lib/clipboard/clipboard_unix.go
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright 2013 @atotto. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build freebsd linux netbsd openbsd solaris dragonfly
|
||||
|
||||
package clipboard
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
const (
|
||||
xsel = "xsel"
|
||||
xclip = "xclip"
|
||||
)
|
||||
|
||||
var (
|
||||
// Primary choose primary mode on unix
|
||||
Primary bool
|
||||
|
||||
pasteCmdArgs, copyCmdArgs []string
|
||||
|
||||
xselPasteArgs = []string{xsel, "--output", "--clipboard"}
|
||||
xselCopyArgs = []string{xsel, "--input", "--clipboard"}
|
||||
|
||||
xclipPasteArgs = []string{xclip, "-out", "-selection", "clipboard"}
|
||||
xclipCopyArgs = []string{xclip, "-in", "-selection", "clipboard"}
|
||||
|
||||
errMissingCommands = errors.New("No clipboard utilities available. Please install xsel or xclip")
|
||||
)
|
||||
|
||||
func init() {
|
||||
pasteCmdArgs = xclipPasteArgs
|
||||
copyCmdArgs = xclipCopyArgs
|
||||
|
||||
if _, err := exec.LookPath(xclip); err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
pasteCmdArgs = xselPasteArgs
|
||||
copyCmdArgs = xselCopyArgs
|
||||
|
||||
if _, err := exec.LookPath(xsel); err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
Unsupported = true
|
||||
}
|
||||
|
||||
func getPasteCommand() *exec.Cmd {
|
||||
if Primary {
|
||||
pasteCmdArgs = pasteCmdArgs[:1]
|
||||
}
|
||||
return exec.Command(pasteCmdArgs[0], pasteCmdArgs[1:]...)
|
||||
}
|
||||
|
||||
func getCopyCommand() *exec.Cmd {
|
||||
if Primary {
|
||||
copyCmdArgs = copyCmdArgs[:1]
|
||||
}
|
||||
return exec.Command(copyCmdArgs[0], copyCmdArgs[1:]...)
|
||||
}
|
||||
|
||||
func readAll() (string, error) {
|
||||
if Unsupported {
|
||||
return "", errMissingCommands
|
||||
}
|
||||
pasteCmd := getPasteCommand()
|
||||
out, err := pasteCmd.Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
func writeAll(text string) error {
|
||||
if Unsupported {
|
||||
return errMissingCommands
|
||||
}
|
||||
copyCmd := getCopyCommand()
|
||||
in, err := copyCmd.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := copyCmd.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := in.Write([]byte(text)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := in.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return copyCmd.Wait()
|
||||
}
|
132
lib/clipboard/clipboard_windows.go
Normal file
132
lib/clipboard/clipboard_windows.go
Normal file
@ -0,0 +1,132 @@
|
||||
// Copyright 2013 @atotto. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows
|
||||
|
||||
package clipboard
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
cfUnicodetext = 13
|
||||
// gmemFixed = 0x0000
|
||||
gmemMoveable = 0x0002
|
||||
)
|
||||
|
||||
var (
|
||||
user32 = syscall.MustLoadDLL("user32")
|
||||
openClipboard = user32.MustFindProc("OpenClipboard")
|
||||
closeClipboard = user32.MustFindProc("CloseClipboard")
|
||||
emptyClipboard = user32.MustFindProc("EmptyClipboard")
|
||||
getClipboardData = user32.MustFindProc("GetClipboardData")
|
||||
setClipboardData = user32.MustFindProc("SetClipboardData")
|
||||
|
||||
kernel32 = syscall.NewLazyDLL("kernel32")
|
||||
globalAlloc = kernel32.NewProc("GlobalAlloc")
|
||||
globalFree = kernel32.NewProc("GlobalFree")
|
||||
globalLock = kernel32.NewProc("GlobalLock")
|
||||
globalUnlock = kernel32.NewProc("GlobalUnlock")
|
||||
lstrcpy = kernel32.NewProc("lstrcpyW")
|
||||
)
|
||||
|
||||
// waitOpenClipboard opens the clipboard, waiting for up to a second to do so.
|
||||
func waitOpenClipboard() error {
|
||||
started := time.Now()
|
||||
limit := started.Add(time.Second)
|
||||
var r uintptr
|
||||
var err error
|
||||
for time.Now().Before(limit) {
|
||||
r, _, err = openClipboard.Call(0)
|
||||
if r != 0 {
|
||||
return nil
|
||||
}
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func readAll() (string, error) {
|
||||
// r, _, err := openClipboard.Call(0)
|
||||
err := waitOpenClipboard()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer closeClipboard.Call()
|
||||
|
||||
h, _, err := getClipboardData.Call(cfUnicodetext)
|
||||
if h == 0 {
|
||||
return "", err
|
||||
}
|
||||
|
||||
l, _, err := globalLock.Call(h)
|
||||
if l == 0 {
|
||||
return "", err
|
||||
}
|
||||
|
||||
text := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(l))[:])
|
||||
|
||||
r, _, err := globalUnlock.Call(h)
|
||||
if r == 0 {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return text, nil
|
||||
}
|
||||
|
||||
func writeAll(text string) error {
|
||||
err := waitOpenClipboard()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closeClipboard.Call()
|
||||
|
||||
r, _, err := emptyClipboard.Call(0)
|
||||
if r == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
data := syscall.StringToUTF16(text)
|
||||
|
||||
// "If the hMem parameter identifies a memory object, the object must have
|
||||
// been allocated using the function with the GMEM_MOVEABLE flag."
|
||||
h, _, err := globalAlloc.Call(gmemMoveable,
|
||||
uintptr(len(data)*int(unsafe.Sizeof(data[0]))))
|
||||
if h == 0 {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if h != 0 {
|
||||
globalFree.Call(h)
|
||||
}
|
||||
}()
|
||||
|
||||
l, _, err := globalLock.Call(h)
|
||||
if l == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
r, _, err = lstrcpy.Call(l, uintptr(unsafe.Pointer(&data[0])))
|
||||
if r == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
r, _, err = globalUnlock.Call(h)
|
||||
if r == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
r, _, err = setClipboardData.Call(cfUnicodetext, h)
|
||||
if r == 0 {
|
||||
if err.(syscall.Errno) != 0 {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
h = 0 // suppress deferred cleanup
|
||||
return nil
|
||||
}
|
45
lib/event.go
Normal file
45
lib/event.go
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2011 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.
|
||||
|
||||
// +build windows
|
||||
|
||||
package lib
|
||||
|
||||
type EventHandler func()
|
||||
|
||||
type Event struct {
|
||||
handlers []EventHandler
|
||||
}
|
||||
|
||||
func (e *Event) Attach(handler EventHandler) int {
|
||||
for i, h := range e.handlers {
|
||||
if h == nil {
|
||||
e.handlers[i] = handler
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
e.handlers = append(e.handlers, handler)
|
||||
return len(e.handlers) - 1
|
||||
}
|
||||
|
||||
func (e *Event) Detach(handle int) {
|
||||
e.handlers[handle] = nil
|
||||
}
|
||||
|
||||
type EventPublisher struct {
|
||||
event Event
|
||||
}
|
||||
|
||||
func (p *EventPublisher) Event() *Event {
|
||||
return &p.event
|
||||
}
|
||||
|
||||
func (p *EventPublisher) Publish() {
|
||||
for _, handler := range p.event.handlers {
|
||||
if handler != nil {
|
||||
handler()
|
||||
}
|
||||
}
|
||||
}
|
80
lib/windows.go
Normal file
80
lib/windows.go
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright 2010 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.
|
||||
|
||||
// +build windows
|
||||
|
||||
package lib
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/lxn/win"
|
||||
)
|
||||
|
||||
var (
|
||||
registeredWindowClasses = make(map[string]bool)
|
||||
defaultWndProcPtr = syscall.NewCallback(defaultWndProc)
|
||||
)
|
||||
|
||||
// MustRegisterWindowClass registers the specified window class.
|
||||
//
|
||||
// MustRegisterWindowClass must be called once for every window type that is not
|
||||
// based on any system provided control, before calling InitChildWidget or
|
||||
// InitWidget. Calling MustRegisterWindowClass twice with the same className
|
||||
// results in a panic.
|
||||
func MustRegisterWindowClass(className string) {
|
||||
MustRegisterWindowClassWithWndProcPtr(className, defaultWndProcPtr)
|
||||
}
|
||||
|
||||
func MustRegisterWindowClassWithStyle(className string, style uint32) {
|
||||
MustRegisterWindowClassWithWndProcPtrAndStyle(className, defaultWndProcPtr, style)
|
||||
}
|
||||
|
||||
func MustRegisterWindowClassWithWndProcPtr(className string, wndProcPtr uintptr) {
|
||||
MustRegisterWindowClassWithWndProcPtrAndStyle(className, wndProcPtr, 0)
|
||||
}
|
||||
|
||||
func MustRegisterWindowClassWithWndProcPtrAndStyle(className string, wndProcPtr uintptr, style uint32) {
|
||||
if registeredWindowClasses[className] {
|
||||
panic("window class already registered")
|
||||
}
|
||||
|
||||
hInst := win.GetModuleHandle(nil)
|
||||
if hInst == 0 {
|
||||
panic("GetModuleHandle")
|
||||
}
|
||||
|
||||
hIcon := win.LoadIcon(hInst, win.MAKEINTRESOURCE(7)) // rsrc uses 7 for app icon
|
||||
if hIcon == 0 {
|
||||
hIcon = win.LoadIcon(0, win.MAKEINTRESOURCE(win.IDI_APPLICATION))
|
||||
}
|
||||
if hIcon == 0 {
|
||||
panic("LoadIcon")
|
||||
}
|
||||
|
||||
hCursor := win.LoadCursor(0, win.MAKEINTRESOURCE(win.IDC_ARROW))
|
||||
if hCursor == 0 {
|
||||
panic("LoadCursor")
|
||||
}
|
||||
|
||||
var wc win.WNDCLASSEX
|
||||
wc.CbSize = uint32(unsafe.Sizeof(wc))
|
||||
wc.LpfnWndProc = wndProcPtr
|
||||
wc.HInstance = hInst
|
||||
wc.HIcon = hIcon
|
||||
wc.HCursor = hCursor
|
||||
wc.HbrBackground = win.COLOR_BTNFACE + 1
|
||||
wc.LpszClassName = syscall.StringToUTF16Ptr(className)
|
||||
wc.Style = style
|
||||
|
||||
if atom := win.RegisterClassEx(&wc); atom == 0 {
|
||||
panic("RegisterClassEx")
|
||||
}
|
||||
registeredWindowClasses[className] = true
|
||||
}
|
||||
|
||||
func defaultWndProc(hwnd win.HWND, msg uint32, wParam, lParam uintptr) (result uintptr) {
|
||||
return win.DefWindowProc(hwnd, msg, wParam, lParam)
|
||||
}
|
79
main.go
Normal file
79
main.go
Normal file
@ -0,0 +1,79 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"yumc.pw/cloud/clipboard-sync/lib/clipboard"
|
||||
)
|
||||
|
||||
func main() {
|
||||
t := flag.String("t", "c", "Type c(client) or s(server)")
|
||||
a := flag.String("a", "http://127.0.0.1:8080", "Server Address")
|
||||
b := flag.String("b", ":8080", "Server Listen Port")
|
||||
flag.Parse()
|
||||
if *t == "c" {
|
||||
if clipboard.Unsupported {
|
||||
panic("Unsupported On This Machine")
|
||||
}
|
||||
readClipboard(*a)
|
||||
} else {
|
||||
startServer(*b)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
TextHeader = "Go-Clipboard-Text"
|
||||
TimeHeader = "Go-Clipboard-Time"
|
||||
)
|
||||
|
||||
func startServer(b string) {
|
||||
text := ""
|
||||
time := time.Now().Unix()
|
||||
var err error
|
||||
g := gin.Default()
|
||||
g.GET("/", func(c *gin.Context) {
|
||||
c.Header(TextHeader, text)
|
||||
c.Header(TimeHeader, strconv.FormatInt(time, 10))
|
||||
})
|
||||
g.POST("/", func(c *gin.Context) {
|
||||
text = c.Query("text")
|
||||
time, err = strconv.ParseInt(c.Query("time"), 10, 64)
|
||||
})
|
||||
g.Run(b)
|
||||
}
|
||||
|
||||
func readClipboard(a string) {
|
||||
old, _ := clipboard.ReadAll()
|
||||
updateTime := time.Now().Unix()
|
||||
client := &http.Client{}
|
||||
address := a + "?text=%s&time=%s"
|
||||
for {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
text, _ := clipboard.ReadAll()
|
||||
if old != text {
|
||||
old = text
|
||||
updateTime = time.Now().Unix()
|
||||
request, _ := http.NewRequest("POST",
|
||||
fmt.Sprintf(address, text, strconv.FormatInt(updateTime, 10)), nil)
|
||||
client.Do(request)
|
||||
} else {
|
||||
response, _ := http.Get(a)
|
||||
texts, ok := response.Header[TextHeader]
|
||||
if ok {
|
||||
sText := texts[0]
|
||||
sTime, _ := strconv.ParseInt(response.Header[TimeHeader][0], 10, 64)
|
||||
if sTime > updateTime {
|
||||
old = sText
|
||||
updateTime = time.Now().Unix()
|
||||
clipboard.WriteAll(sText)
|
||||
fmt.Printf("Update Clipboard: %s\n", sText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user