1
0
Fork 0

Init: Create & Init Project...

master
502647092 2018-08-30 20:36:03 +08:00
commit 3029507430
10 changed files with 588 additions and 0 deletions

29
.gitignore vendored Normal file
View 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
View 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
View 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

View 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

View 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()
}

View 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()
}

View 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
View 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
View 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
View 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)
}
}
}
}
}