mirror of
https://github.com/go-vgo/robotgo.git
synced 2025-05-28 21:13:55 +00:00
Refactor some keyboard C code to go
This commit is contained in:
parent
ed45411f5c
commit
99963bc6fc
@ -49,15 +49,15 @@ func keyTap() {
|
||||
fmt.Println("robotgo.KeyTap run error is: ", err)
|
||||
}
|
||||
|
||||
robotgo.KeyTap("h", "cmd", 12)
|
||||
robotgo.KeyTap("h", "cmd")
|
||||
|
||||
// press "i", "alt", "command" Key combination
|
||||
robotgo.KeyTap("i", "alt", "command")
|
||||
robotgo.KeyTap("i", "alt", "cmd", 11)
|
||||
robotgo.KeyTap("i", "alt", "cmd")
|
||||
|
||||
arr := []string{"alt", "cmd"}
|
||||
robotgo.KeyTap("i", arr)
|
||||
robotgo.KeyTap("i", arr, 12)
|
||||
robotgo.KeyTap("i", arr)
|
||||
|
||||
robotgo.KeyTap("i", "cmd", " alt", "shift")
|
||||
|
||||
|
672
key.go
Normal file
672
key.go
Normal file
@ -0,0 +1,672 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
package robotgo
|
||||
|
||||
/*
|
||||
// #include "key/keycode.h"
|
||||
#include "key/goKey.h"
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-vgo/robotgo/clipboard"
|
||||
"github.com/vcaesar/tt"
|
||||
)
|
||||
|
||||
const (
|
||||
// KeyA define key "a"
|
||||
KeyA = "a"
|
||||
KeyB = "b"
|
||||
KeyC = "c"
|
||||
KeyD = "d"
|
||||
KeyE = "e"
|
||||
KeyF = "f"
|
||||
KeyG = "g"
|
||||
KeyH = "h"
|
||||
KeyI = "i"
|
||||
KeyJ = "j"
|
||||
KeyK = "k"
|
||||
KeyL = "l"
|
||||
KeyM = "m"
|
||||
KeyN = "n"
|
||||
KeyO = "o"
|
||||
KeyP = "p"
|
||||
KeyQ = "q"
|
||||
KeyR = "r"
|
||||
KeyS = "s"
|
||||
KeyT = "t"
|
||||
KeyU = "u"
|
||||
KeyV = "v"
|
||||
KeyW = "w"
|
||||
KeyX = "x"
|
||||
KeyY = "y"
|
||||
KeyZ = "z"
|
||||
//
|
||||
Key0 = "0"
|
||||
Key1 = "1"
|
||||
Key2 = "2"
|
||||
Key3 = "3"
|
||||
Key4 = "4"
|
||||
Key5 = "5"
|
||||
Key6 = "6"
|
||||
Key7 = "7"
|
||||
Key8 = "8"
|
||||
Key9 = "9"
|
||||
|
||||
// Backspace backspace key string
|
||||
Backspace = "backspace"
|
||||
Delete = "delete"
|
||||
Enter = "enter"
|
||||
Tab = "tab"
|
||||
Esc = "esc"
|
||||
Escape = "escape"
|
||||
Up = "up" // Up arrow key
|
||||
Down = "down" // Down arrow key
|
||||
Right = "right" // Right arrow key
|
||||
Left = "left" // Left arrow key
|
||||
Home = "home"
|
||||
End = "end"
|
||||
Pageup = "pageup"
|
||||
Pagedown = "pagedown"
|
||||
|
||||
F1 = "f1"
|
||||
F2 = "f2"
|
||||
F3 = "f3"
|
||||
F4 = "f4"
|
||||
F5 = "f5"
|
||||
F6 = "f6"
|
||||
F7 = "f7"
|
||||
F8 = "f8"
|
||||
F9 = "f9"
|
||||
F10 = "f10"
|
||||
F11 = "f11"
|
||||
F12 = "f12"
|
||||
F13 = "f13"
|
||||
F14 = "f14"
|
||||
F15 = "f15"
|
||||
F16 = "f16"
|
||||
F17 = "f17"
|
||||
F18 = "f18"
|
||||
F19 = "f19"
|
||||
F20 = "f20"
|
||||
F21 = "f21"
|
||||
F22 = "f22"
|
||||
F23 = "f23"
|
||||
F24 = "f24"
|
||||
|
||||
Cmd = "cmd" // is the "win" key for windows
|
||||
Lcmd = "lcmd" // left command
|
||||
Rcmd = "rcmd" // right command
|
||||
// "command"
|
||||
Alt = "alt"
|
||||
Lalt = "lalt" // left alt
|
||||
Ralt = "ralt" // right alt
|
||||
Ctrl = "ctrl"
|
||||
Lctrl = "lctrl" // left ctrl
|
||||
Rctrl = "rctrl" // right ctrl
|
||||
Control = "control"
|
||||
Shift = "shift"
|
||||
Lshift = "lshift" // left shift
|
||||
Rshift = "rshift" // right shift
|
||||
// "right_shift"
|
||||
Capslock = "capslock"
|
||||
Space = "space"
|
||||
Print = "print"
|
||||
Printscreen = "printscreen" // No Mac support
|
||||
Insert = "insert"
|
||||
Menu = "menu" // Windows only
|
||||
|
||||
AudioMute = "audio_mute" // Mute the volume
|
||||
AudioVolDown = "audio_vol_down" // Lower the volume
|
||||
AudioVolUp = "audio_vol_up" // Increase the volume
|
||||
AudioPlay = "audio_play"
|
||||
AudioStop = "audio_stop"
|
||||
AudioPause = "audio_pause"
|
||||
AudioPrev = "audio_prev" // Previous Track
|
||||
AudioNext = "audio_next" // Next Track
|
||||
AudioRewind = "audio_rewind" // Linux only
|
||||
AudioForward = "audio_forward" // Linux only
|
||||
AudioRepeat = "audio_repeat" // Linux only
|
||||
AudioRandom = "audio_random" // Linux only
|
||||
|
||||
Num0 = "num0" // numpad 0
|
||||
Num1 = "num1"
|
||||
Num2 = "num2"
|
||||
Num3 = "num3"
|
||||
Num4 = "num4"
|
||||
Num5 = "num5"
|
||||
Num6 = "num6"
|
||||
Num7 = "num7"
|
||||
Num8 = "num8"
|
||||
Num9 = "num9"
|
||||
NumLock = "num_lock"
|
||||
|
||||
NumDecimal = "num."
|
||||
NumPlus = "num+"
|
||||
NumMinus = "num-"
|
||||
NumMul = "num*"
|
||||
NumDiv = "num/"
|
||||
NumClear = "num_clear"
|
||||
NumEnter = "num_enter"
|
||||
NumEqual = "num_equal"
|
||||
|
||||
LightsMonUp = "lights_mon_up" // Turn up monitor brightness No Windows support
|
||||
LightsMonDown = "lights_mon_down" // Turn down monitor brightness No Windows support
|
||||
LightsKbdToggle = "lights_kbd_toggle" // Toggle keyboard backlight on/off No Windows support
|
||||
LightsKbdUp = "lights_kbd_up" // Turn up keyboard backlight brightness No Windows support
|
||||
LightsKbdDown = "lights_kbd_down"
|
||||
)
|
||||
|
||||
// keyNames define MMKeyCode map
|
||||
var keyNames = map[string]C.MMKeyCode{
|
||||
"backspace": C.K_BACKSPACE,
|
||||
"delete": C.K_DELETE,
|
||||
"enter": C.K_RETURN,
|
||||
"tab": C.K_TAB,
|
||||
"esc": C.K_ESCAPE,
|
||||
"escape": C.K_ESCAPE,
|
||||
"up": C.K_UP,
|
||||
"down": C.K_DOWN,
|
||||
"right": C.K_RIGHT,
|
||||
"left": C.K_LEFT,
|
||||
"home": C.K_HOME,
|
||||
"end": C.K_END,
|
||||
"pageup": C.K_PAGEUP,
|
||||
"pagedown": C.K_PAGEDOWN,
|
||||
//
|
||||
"f1": C.K_F1,
|
||||
"f2": C.K_F2,
|
||||
"f3": C.K_F3,
|
||||
"f4": C.K_F4,
|
||||
"f5": C.K_F5,
|
||||
"f6": C.K_F6,
|
||||
"f7": C.K_F7,
|
||||
"f8": C.K_F8,
|
||||
"f9": C.K_F9,
|
||||
"f10": C.K_F10,
|
||||
"f11": C.K_F11,
|
||||
"f12": C.K_F12,
|
||||
"f13": C.K_F13,
|
||||
"f14": C.K_F14,
|
||||
"f15": C.K_F15,
|
||||
"f16": C.K_F16,
|
||||
"f17": C.K_F17,
|
||||
"f18": C.K_F18,
|
||||
"f19": C.K_F19,
|
||||
"f20": C.K_F20,
|
||||
"f21": C.K_F21,
|
||||
"f22": C.K_F22,
|
||||
"f23": C.K_F23,
|
||||
"f24": C.K_F24,
|
||||
//
|
||||
"cmd": C.K_META,
|
||||
"lcmd": C.K_LMETA,
|
||||
"rcmd": C.K_RMETA,
|
||||
"command": C.K_META,
|
||||
"alt": C.K_ALT,
|
||||
"lalt": C.K_LALT,
|
||||
"ralt": C.K_RALT,
|
||||
"ctrl": C.K_CONTROL,
|
||||
"lctrl": C.K_LCONTROL,
|
||||
"rctrl": C.K_RCONTROL,
|
||||
"control": C.K_CONTROL,
|
||||
"shift": C.K_SHIFT,
|
||||
"lshift": C.K_LSHIFT,
|
||||
"rshift": C.K_RSHIFT,
|
||||
"right_shift": C.K_RSHIFT,
|
||||
"capslock": C.K_CAPSLOCK,
|
||||
"space": C.K_SPACE,
|
||||
"print": C.K_PRINTSCREEN,
|
||||
"printscreen": C.K_PRINTSCREEN,
|
||||
"insert": C.K_INSERT,
|
||||
"menu": C.K_MENU,
|
||||
|
||||
"audio_mute": C.K_AUDIO_VOLUME_MUTE,
|
||||
"audio_vol_down": C.K_AUDIO_VOLUME_DOWN,
|
||||
"audio_vol_up": C.K_AUDIO_VOLUME_UP,
|
||||
"audio_play": C.K_AUDIO_PLAY,
|
||||
"audio_stop": C.K_AUDIO_STOP,
|
||||
"audio_pause": C.K_AUDIO_PAUSE,
|
||||
"audio_prev": C.K_AUDIO_PREV,
|
||||
"audio_next": C.K_AUDIO_NEXT,
|
||||
"audio_rewind": C.K_AUDIO_REWIND,
|
||||
"audio_forward": C.K_AUDIO_FORWARD,
|
||||
"audio_repeat": C.K_AUDIO_REPEAT,
|
||||
"audio_random": C.K_AUDIO_RANDOM,
|
||||
|
||||
"num0": C.K_NUMPAD_0,
|
||||
"num1": C.K_NUMPAD_1,
|
||||
"num2": C.K_NUMPAD_2,
|
||||
"num3": C.K_NUMPAD_3,
|
||||
"num4": C.K_NUMPAD_4,
|
||||
"num5": C.K_NUMPAD_5,
|
||||
"num6": C.K_NUMPAD_6,
|
||||
"num7": C.K_NUMPAD_7,
|
||||
"num8": C.K_NUMPAD_8,
|
||||
"num9": C.K_NUMPAD_9,
|
||||
"num_lock": C.K_NUMPAD_LOCK,
|
||||
|
||||
// todo: removed
|
||||
"numpad_0": C.K_NUMPAD_0,
|
||||
"numpad_1": C.K_NUMPAD_1,
|
||||
"numpad_2": C.K_NUMPAD_2,
|
||||
"numpad_3": C.K_NUMPAD_3,
|
||||
"numpad_4": C.K_NUMPAD_4,
|
||||
"numpad_5": C.K_NUMPAD_5,
|
||||
"numpad_6": C.K_NUMPAD_6,
|
||||
"numpad_7": C.K_NUMPAD_7,
|
||||
"numpad_8": C.K_NUMPAD_8,
|
||||
"numpad_9": C.K_NUMPAD_9,
|
||||
"numpad_lock": C.K_NUMPAD_LOCK,
|
||||
|
||||
"num.": C.K_NUMPAD_DECIMAL,
|
||||
"num+": C.K_NUMPAD_PLUS,
|
||||
"num-": C.K_NUMPAD_MINUS,
|
||||
"num*": C.K_NUMPAD_MUL,
|
||||
"num/": C.K_NUMPAD_DIV,
|
||||
"num_clear": C.K_NUMPAD_CLEAR,
|
||||
"num_enter": C.K_NUMPAD_ENTER,
|
||||
"num_equal": C.K_NUMPAD_EQUAL,
|
||||
|
||||
"lights_mon_up": C.K_LIGHTS_MON_UP,
|
||||
"lights_mon_down": C.K_LIGHTS_MON_DOWN,
|
||||
"lights_kbd_toggle": C.K_LIGHTS_KBD_TOGGLE,
|
||||
"lights_kbd_up": C.K_LIGHTS_KBD_UP,
|
||||
"lights_kbd_down": C.K_LIGHTS_KBD_DOWN,
|
||||
|
||||
// { NULL: C.K_NOT_A_KEY }
|
||||
}
|
||||
|
||||
func tapKeyCode(code C.MMKeyCode, flags C.MMKeyFlags) {
|
||||
C.toggleKeyCode(code, true, flags)
|
||||
MilliSleep(5)
|
||||
C.toggleKeyCode(code, false, flags)
|
||||
}
|
||||
|
||||
var keyErr = errors.New("Invalid key flag specified.")
|
||||
|
||||
func checkKeyCodes(k string) (key C.MMKeyCode, err error) {
|
||||
if k == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if len(k) == 1 {
|
||||
val := C.CString(k)
|
||||
key = C.keyCodeForChar(*val)
|
||||
C.free(unsafe.Pointer(val))
|
||||
if key == C.K_NOT_A_KEY {
|
||||
err = keyErr
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if v, ok := keyNames[k]; ok {
|
||||
key = v
|
||||
if key == C.K_NOT_A_KEY {
|
||||
err = keyErr
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func checkKeyFlags(f string) (flags C.MMKeyFlags) {
|
||||
m := map[string]C.MMKeyFlags{
|
||||
"alt": C.MOD_ALT,
|
||||
"ralt": C.MOD_ALT,
|
||||
"lalt": C.MOD_ALT,
|
||||
"cmd": C.MOD_META,
|
||||
"rcmd": C.MOD_META,
|
||||
"lcmd": C.MOD_META,
|
||||
"ctrl": C.MOD_CONTROL,
|
||||
"rctrl": C.MOD_CONTROL,
|
||||
"lctrl": C.MOD_CONTROL,
|
||||
"shift": C.MOD_SHIFT,
|
||||
"rshift": C.MOD_SHIFT,
|
||||
"lshift": C.MOD_SHIFT,
|
||||
"none": C.MOD_NONE,
|
||||
}
|
||||
|
||||
if v, ok := m[f]; ok {
|
||||
return v
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getFlagsFromValue(value []string) (flags C.MMKeyFlags) {
|
||||
if len(value) <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < len(value); i++ {
|
||||
var f C.MMKeyFlags = C.MOD_NONE
|
||||
|
||||
f = checkKeyFlags(value[i])
|
||||
flags = (C.MMKeyFlags)(flags | f)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func keyTaps(k string, keyArr []string) error {
|
||||
flags := getFlagsFromValue(keyArr)
|
||||
key, err := checkKeyCodes(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tapKeyCode(key, flags)
|
||||
MilliSleep(KeySleep)
|
||||
return nil
|
||||
}
|
||||
|
||||
func keyToggles(k string, keyArr []string) error {
|
||||
down := false
|
||||
if keyArr[0] == "down" {
|
||||
down = true
|
||||
}
|
||||
|
||||
flags := getFlagsFromValue(keyArr)
|
||||
key, err := checkKeyCodes(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
C.toggleKeyCode(key, C.bool(down), flags)
|
||||
MilliSleep(KeySleep)
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
__ ___ ___________ ____ .______ ______ ___ .______ _______
|
||||
| |/ / | ____\ \ / / | _ \ / __ \ / \ | _ \ | \
|
||||
| ' / | |__ \ \/ / | |_) | | | | | / ^ \ | |_) | | .--. |
|
||||
| < | __| \_ _/ | _ < | | | | / /_\ \ | / | | | |
|
||||
| . \ | |____ | | | |_) | | `--' | / _____ \ | |\ \----.| '--' |
|
||||
|__|\__\ |_______| |__| |______/ \______/ /__/ \__\ | _| `._____||_______/
|
||||
|
||||
*/
|
||||
|
||||
// ToInterfaces []string to []interface{}
|
||||
func ToInterfaces(fields []string) []interface{} {
|
||||
res := make([]interface{}, 0, len(fields))
|
||||
for _, s := range fields {
|
||||
res = append(res, s)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ToStrings []interface{} to []string
|
||||
func ToStrings(fields []interface{}) []string {
|
||||
res := make([]string, 0, len(fields))
|
||||
for _, s := range fields {
|
||||
res = append(res, s.(string))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func toErr(str *C.char) error {
|
||||
gstr := C.GoString(str)
|
||||
if gstr == "" {
|
||||
return nil
|
||||
}
|
||||
return errors.New(gstr)
|
||||
}
|
||||
|
||||
// KeyTap tap the keyboard code;
|
||||
//
|
||||
// See keys:
|
||||
// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md
|
||||
//
|
||||
// Examples:
|
||||
// robotgo.KeySleep = 100 // 100 millisecond
|
||||
// robotgo.KeyTap("a")
|
||||
// robotgo.KeyTap("i", "alt", "command")
|
||||
//
|
||||
// arr := []string{"alt", "command"}
|
||||
// robotgo.KeyTap("i", arr)
|
||||
//
|
||||
func KeyTap(tapKey string, args ...interface{}) error {
|
||||
var keyArr []string
|
||||
|
||||
tapKey = strings.ToLower(tapKey)
|
||||
if _, ok := Special[tapKey]; ok {
|
||||
tapKey = Special[tapKey]
|
||||
if len(args) <= 0 {
|
||||
args = append(args, "shift")
|
||||
}
|
||||
}
|
||||
|
||||
if len(args) > 0 {
|
||||
if reflect.TypeOf(args[0]) == reflect.TypeOf(keyArr) {
|
||||
keyArr = args[0].([]string)
|
||||
} else {
|
||||
keyArr = ToStrings(args)
|
||||
}
|
||||
}
|
||||
|
||||
return keyTaps(tapKey, keyArr)
|
||||
}
|
||||
|
||||
// KeyToggle toggle the keyboard, if there not have args default is "down"
|
||||
//
|
||||
// See keys:
|
||||
// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md
|
||||
//
|
||||
// Examples:
|
||||
// robotgo.KeyToggle("a")
|
||||
// robotgo.KeyToggle("a", "up")
|
||||
//
|
||||
// robotgo.KeyToggle("a", "up", "alt", "cmd")
|
||||
//
|
||||
func KeyToggle(key string, args ...string) error {
|
||||
if len(args) <= 0 {
|
||||
args = append(args, "down")
|
||||
}
|
||||
|
||||
key = strings.ToLower(key)
|
||||
if _, ok := Special[key]; ok {
|
||||
key = Special[key]
|
||||
if len(args) <= 1 {
|
||||
args = append(args, "shift")
|
||||
}
|
||||
}
|
||||
|
||||
return keyToggles(key, args)
|
||||
}
|
||||
|
||||
// KeyPress press key string
|
||||
func KeyPress(key string) error {
|
||||
err := KeyDown(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
MilliSleep(1 + rand.Intn(3))
|
||||
return KeyUp(key)
|
||||
}
|
||||
|
||||
// KeyDown press down a key
|
||||
func KeyDown(key string) error {
|
||||
return KeyToggle(key)
|
||||
}
|
||||
|
||||
// KeyUp press up a key
|
||||
func KeyUp(key string) error {
|
||||
return KeyToggle(key, "up")
|
||||
}
|
||||
|
||||
// ReadAll read string from clipboard
|
||||
func ReadAll() (string, error) {
|
||||
return clipboard.ReadAll()
|
||||
}
|
||||
|
||||
// WriteAll write string to clipboard
|
||||
func WriteAll(text string) error {
|
||||
return clipboard.WriteAll(text)
|
||||
}
|
||||
|
||||
// CharCodeAt char code at utf-8
|
||||
func CharCodeAt(s string, n int) rune {
|
||||
i := 0
|
||||
for _, r := range s {
|
||||
if i == n {
|
||||
return r
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// UnicodeType tap uint32 unicode
|
||||
func UnicodeType(str uint32) {
|
||||
cstr := C.uint(str)
|
||||
C.unicodeType(cstr)
|
||||
}
|
||||
|
||||
// ToUC trans string to unicode []string
|
||||
func ToUC(text string) []string {
|
||||
var uc []string
|
||||
|
||||
for _, r := range text {
|
||||
textQ := strconv.QuoteToASCII(string(r))
|
||||
textUnQ := textQ[1 : len(textQ)-1]
|
||||
|
||||
st := strings.Replace(textUnQ, "\\u", "U", -1)
|
||||
if st == "\\\\" {
|
||||
st = "\\"
|
||||
}
|
||||
if st == `\"` {
|
||||
st = `"`
|
||||
}
|
||||
uc = append(uc, st)
|
||||
}
|
||||
|
||||
return uc
|
||||
}
|
||||
|
||||
func inputUTF(str string) {
|
||||
cstr := C.CString(str)
|
||||
C.input_utf(cstr)
|
||||
|
||||
C.free(unsafe.Pointer(cstr))
|
||||
}
|
||||
|
||||
// TypeStr send a string, support UTF-8
|
||||
//
|
||||
// robotgo.TypeStr(string: The string to send, float64: microsleep time, x11 option)
|
||||
//
|
||||
// Examples:
|
||||
// robotgo.TypeStr("abc@123, hi, こんにちは")
|
||||
//
|
||||
func TypeStr(str string, args ...float64) {
|
||||
var tm, tm1 = 0.0, 7.0
|
||||
|
||||
if len(args) > 0 {
|
||||
tm = args[0]
|
||||
}
|
||||
if len(args) > 1 {
|
||||
tm1 = args[1]
|
||||
}
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
strUc := ToUC(str)
|
||||
for i := 0; i < len(strUc); i++ {
|
||||
ru := []rune(strUc[i])
|
||||
if len(ru) <= 1 {
|
||||
ustr := uint32(CharCodeAt(strUc[i], 0))
|
||||
UnicodeType(ustr)
|
||||
} else {
|
||||
inputUTF(strUc[i])
|
||||
MicroSleep(tm1)
|
||||
}
|
||||
|
||||
MicroSleep(tm)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < len([]rune(str)); i++ {
|
||||
ustr := uint32(CharCodeAt(str, i))
|
||||
UnicodeType(ustr)
|
||||
// if len(args) > 0 {
|
||||
MicroSleep(tm)
|
||||
// }
|
||||
}
|
||||
MilliSleep(KeySleep)
|
||||
}
|
||||
|
||||
// PasteStr paste a string, support UTF-8,
|
||||
// write the string to clipboard and tap `cmd + v`
|
||||
func PasteStr(str string) error {
|
||||
err := clipboard.WriteAll(str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
return KeyTap("v", "command")
|
||||
}
|
||||
|
||||
return KeyTap("v", "control")
|
||||
}
|
||||
|
||||
// TypeStrDelay type string delayed
|
||||
func TypeStrDelay(str string, delay int) {
|
||||
TypeStr(str)
|
||||
Sleep(delay)
|
||||
}
|
||||
|
||||
// Deprecated: use the TypeStr(),
|
||||
//
|
||||
// TypeStringDelayed type string delayed, Wno-deprecated
|
||||
//
|
||||
// This function will be removed in version v1.0.0
|
||||
func TypeStringDelayed(str string, delay int) {
|
||||
tt.Drop("TypeStringDelayed", "TypeStrDelay")
|
||||
TypeStrDelay(str, delay)
|
||||
}
|
||||
|
||||
// SetKeyDelay set keyboard delay
|
||||
func SetKeyDelay(delay int) {
|
||||
C.set_keyboard_delay(C.size_t(delay))
|
||||
}
|
||||
|
||||
// Deprecated: use the SetKeyDelay(),
|
||||
//
|
||||
// SetKeyboardDelay set keyboard delay, Wno-deprecated,
|
||||
//
|
||||
// This function will be removed in version v1.0.0
|
||||
func SetKeyboardDelay(delay int) {
|
||||
tt.Drop("SetKeyboardDelay", "SetKeyDelay")
|
||||
SetKeyDelay(delay)
|
||||
}
|
||||
|
||||
// SetDelay set the key and mouse delay
|
||||
func SetDelay(d ...int) {
|
||||
v := 10
|
||||
if len(d) > 0 {
|
||||
v = d[0]
|
||||
}
|
||||
|
||||
SetMouseDelay(v)
|
||||
SetKeyDelay(v)
|
||||
}
|
392
key/goKey.h
392
key/goKey.h
@ -1,397 +1,7 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
// Copyright 2016 The go-vgo Project Developers.
|
||||
|
||||
#include "../base/types.h"
|
||||
// #include "keycode.h"
|
||||
// #include "keypress.h"
|
||||
#include "keypress_c.h"
|
||||
#include "keycode_c.h"
|
||||
|
||||
|
||||
int keyboardDelay = 0;
|
||||
|
||||
struct KeyNames{
|
||||
const char* name;
|
||||
MMKeyCode key;
|
||||
}key_names[] = {
|
||||
{ "backspace", K_BACKSPACE },
|
||||
{ "delete", K_DELETE },
|
||||
{ "enter", K_RETURN },
|
||||
{ "tab", K_TAB },
|
||||
{ "esc", K_ESCAPE },
|
||||
{ "escape", K_ESCAPE },
|
||||
{ "up", K_UP },
|
||||
{ "down", K_DOWN },
|
||||
{ "right", K_RIGHT },
|
||||
{ "left", K_LEFT },
|
||||
{ "home", K_HOME },
|
||||
{ "end", K_END },
|
||||
{ "pageup", K_PAGEUP },
|
||||
{ "pagedown", K_PAGEDOWN },
|
||||
//
|
||||
{ "f1", K_F1 },
|
||||
{ "f2", K_F2 },
|
||||
{ "f3", K_F3 },
|
||||
{ "f4", K_F4 },
|
||||
{ "f5", K_F5 },
|
||||
{ "f6", K_F6 },
|
||||
{ "f7", K_F7 },
|
||||
{ "f8", K_F8 },
|
||||
{ "f9", K_F9 },
|
||||
{ "f10", K_F10 },
|
||||
{ "f11", K_F11 },
|
||||
{ "f12", K_F12 },
|
||||
{ "f13", K_F13 },
|
||||
{ "f14", K_F14 },
|
||||
{ "f15", K_F15 },
|
||||
{ "f16", K_F16 },
|
||||
{ "f17", K_F17 },
|
||||
{ "f18", K_F18 },
|
||||
{ "f19", K_F19 },
|
||||
{ "f20", K_F20 },
|
||||
{ "f21", K_F21 },
|
||||
{ "f22", K_F22 },
|
||||
{ "f23", K_F23 },
|
||||
{ "f24", K_F24 },
|
||||
//
|
||||
{ "cmd", K_META },
|
||||
{ "lcmd", K_LMETA },
|
||||
{ "rcmd", K_RMETA },
|
||||
{ "command", K_META },
|
||||
{ "alt", K_ALT },
|
||||
{ "lalt", K_LALT },
|
||||
{ "ralt", K_RALT },
|
||||
{ "ctrl", K_CONTROL },
|
||||
{ "lctrl", K_LCONTROL },
|
||||
{ "rctrl", K_RCONTROL },
|
||||
{ "control", K_CONTROL },
|
||||
{ "shift", K_SHIFT },
|
||||
{ "lshift", K_LSHIFT },
|
||||
{ "rshift", K_RSHIFT },
|
||||
{ "right_shift", K_RSHIFT },
|
||||
{ "capslock", K_CAPSLOCK },
|
||||
{ "space", K_SPACE },
|
||||
{ "print", K_PRINTSCREEN },
|
||||
{ "printscreen", K_PRINTSCREEN },
|
||||
{ "insert", K_INSERT },
|
||||
{ "menu", K_MENU },
|
||||
|
||||
{ "audio_mute", K_AUDIO_VOLUME_MUTE },
|
||||
{ "audio_vol_down", K_AUDIO_VOLUME_DOWN },
|
||||
{ "audio_vol_up", K_AUDIO_VOLUME_UP },
|
||||
{ "audio_play", K_AUDIO_PLAY },
|
||||
{ "audio_stop", K_AUDIO_STOP },
|
||||
{ "audio_pause", K_AUDIO_PAUSE },
|
||||
{ "audio_prev", K_AUDIO_PREV },
|
||||
{ "audio_next", K_AUDIO_NEXT },
|
||||
{ "audio_rewind", K_AUDIO_REWIND },
|
||||
{ "audio_forward", K_AUDIO_FORWARD },
|
||||
{ "audio_repeat", K_AUDIO_REPEAT },
|
||||
{ "audio_random", K_AUDIO_RANDOM },
|
||||
|
||||
{ "num0", K_NUMPAD_0 },
|
||||
{ "num1", K_NUMPAD_1 },
|
||||
{ "num2", K_NUMPAD_2 },
|
||||
{ "num3", K_NUMPAD_3 },
|
||||
{ "num4", K_NUMPAD_4 },
|
||||
{ "num5", K_NUMPAD_5 },
|
||||
{ "num6", K_NUMPAD_6 },
|
||||
{ "num7", K_NUMPAD_7 },
|
||||
{ "num8", K_NUMPAD_8 },
|
||||
{ "num9", K_NUMPAD_9 },
|
||||
{ "num_lock", K_NUMPAD_LOCK },
|
||||
|
||||
// todo: removed
|
||||
{ "numpad_0", K_NUMPAD_0 },
|
||||
{ "numpad_1", K_NUMPAD_1 },
|
||||
{ "numpad_2", K_NUMPAD_2 },
|
||||
{ "numpad_3", K_NUMPAD_3 },
|
||||
{ "numpad_4", K_NUMPAD_4 },
|
||||
{ "numpad_5", K_NUMPAD_5 },
|
||||
{ "numpad_6", K_NUMPAD_6 },
|
||||
{ "numpad_7", K_NUMPAD_7 },
|
||||
{ "numpad_8", K_NUMPAD_8 },
|
||||
{ "numpad_9", K_NUMPAD_9 },
|
||||
{ "numpad_lock", K_NUMPAD_LOCK },
|
||||
|
||||
{"num.", K_NUMPAD_DECIMAL },
|
||||
{"num+", K_NUMPAD_PLUS },
|
||||
{"num-", K_NUMPAD_MINUS },
|
||||
{"num*", K_NUMPAD_MUL },
|
||||
{"num/", K_NUMPAD_DIV },
|
||||
{"num_clear", K_NUMPAD_CLEAR },
|
||||
{"num_enter", K_NUMPAD_ENTER },
|
||||
{"num_equal", K_NUMPAD_EQUAL },
|
||||
|
||||
{ "lights_mon_up", K_LIGHTS_MON_UP },
|
||||
{ "lights_mon_down", K_LIGHTS_MON_DOWN },
|
||||
{ "lights_kbd_toggle",K_LIGHTS_KBD_TOGGLE },
|
||||
{ "lights_kbd_up", K_LIGHTS_KBD_UP },
|
||||
{ "lights_kbd_down", K_LIGHTS_KBD_DOWN },
|
||||
|
||||
{ NULL, K_NOT_A_KEY } /* end marker */
|
||||
};
|
||||
|
||||
int CheckKeyCodes(char* k, MMKeyCode *key){
|
||||
if (!key) { return -1; }
|
||||
|
||||
if (strlen(k) == 1) {
|
||||
*key = keyCodeForChar(*k);
|
||||
if (*key == K_NOT_A_KEY) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
*key = K_NOT_A_KEY;
|
||||
|
||||
struct KeyNames* kn = key_names;
|
||||
while (kn->name) {
|
||||
if (strcmp(k, kn->name) == 0){
|
||||
*key = kn->key;
|
||||
break;
|
||||
}
|
||||
kn++;
|
||||
}
|
||||
|
||||
if (*key == K_NOT_A_KEY) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CheckKeyFlags(char* f, MMKeyFlags* flags){
|
||||
if (!flags) { return -1; }
|
||||
|
||||
if (strcmp(f, "alt") == 0 || strcmp(f, "ralt") == 0 ||
|
||||
strcmp(f, "lalt") == 0 ) {
|
||||
*flags = MOD_ALT;
|
||||
}
|
||||
else if(strcmp(f, "command") == 0 || strcmp(f, "cmd") == 0 ||
|
||||
strcmp(f, "rcmd") == 0 || strcmp(f, "lcmd") == 0 ) {
|
||||
*flags = MOD_META;
|
||||
}
|
||||
else if(strcmp(f, "control") == 0 || strcmp(f, "ctrl") == 0 ||
|
||||
strcmp(f, "rctrl") == 0 || strcmp(f, "lctrl") == 0 ) {
|
||||
*flags = MOD_CONTROL;
|
||||
}
|
||||
else if(strcmp(f, "shift") == 0 || strcmp(f, "right_shift") == 0 ||
|
||||
strcmp(f, "rshift") == 0 || strcmp(f, "lshift") == 0 ) {
|
||||
*flags = MOD_SHIFT;
|
||||
}
|
||||
else if(strcmp(f, "none") == 0 ) {
|
||||
*flags = (MMKeyFlags) MOD_NONE;
|
||||
} else {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetFlagsFromValue(char* value[], MMKeyFlags* flags, int num){
|
||||
if (!flags) {return -1;}
|
||||
|
||||
int i;
|
||||
for ( i= 0; i <num; i++) {
|
||||
MMKeyFlags f = MOD_NONE;
|
||||
const int rv = CheckKeyFlags(value[i], &f);
|
||||
if (rv) { return rv; }
|
||||
|
||||
*flags = (MMKeyFlags)(*flags | f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
// return CheckKeyFlags(fstr, flags);
|
||||
}
|
||||
|
||||
// If it's not an array, it should be a single string value.
|
||||
char* key_Taps(char *k, char* keyArr[], int num, int keyDelay){
|
||||
MMKeyFlags flags = MOD_NONE;
|
||||
// MMKeyFlags flags = 0;
|
||||
MMKeyCode key;
|
||||
|
||||
switch(GetFlagsFromValue(keyArr, &flags, num)) {
|
||||
// switch (CheckKeyFlags(akey, &flags)){
|
||||
case -1:
|
||||
return "Null pointer in key flag.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key flag specified.";
|
||||
break;
|
||||
}
|
||||
|
||||
switch(CheckKeyCodes(k, &key)) {
|
||||
case -1:
|
||||
return "Null pointer in key code.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key code specified.";
|
||||
break;
|
||||
default:
|
||||
tapKeyCode(key, flags);
|
||||
microsleep(keyDelay);
|
||||
}
|
||||
|
||||
// return "0";
|
||||
return "";
|
||||
}
|
||||
|
||||
char* key_tap(char *k, char *akey, char *keyT, int keyDelay){
|
||||
MMKeyFlags flags = (MMKeyFlags) MOD_NONE;
|
||||
// MMKeyFlags flags = 0;
|
||||
MMKeyCode key;
|
||||
|
||||
// char *k;
|
||||
// k = *kstr;
|
||||
if (strcmp(akey, "null") != 0) {
|
||||
if (strcmp(keyT, "null") == 0) {
|
||||
switch (CheckKeyFlags(akey, &flags)) {
|
||||
case -1:
|
||||
return "Null pointer in key flag.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key flag specified.";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
char* akeyArr[2] = {akey, keyT};
|
||||
switch(GetFlagsFromValue(akeyArr, &flags, 2)) {
|
||||
case -1:
|
||||
return "Null pointer in key flag.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key flag specified.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(CheckKeyCodes(k, &key)) {
|
||||
case -1:
|
||||
return "Null pointer in key code.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key code specified.";
|
||||
break;
|
||||
default:
|
||||
tapKeyCode(key, flags);
|
||||
microsleep(keyDelay);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
char* key_Toggles(char* k, char* keyArr[], int num) {
|
||||
MMKeyFlags flags = (MMKeyFlags) MOD_NONE;
|
||||
MMKeyCode key;
|
||||
|
||||
bool down;
|
||||
char* d = keyArr[0];
|
||||
if (d != 0) {
|
||||
// char *d;
|
||||
// d = *dstr;
|
||||
if (strcmp(d, "down") == 0) {
|
||||
down = true;
|
||||
} else if (strcmp(d, "up") == 0) {
|
||||
down = false;
|
||||
} else {
|
||||
return "Invalid key state specified.";
|
||||
}
|
||||
}
|
||||
|
||||
switch (GetFlagsFromValue(keyArr, &flags, num)) {
|
||||
case -1:
|
||||
return "Null pointer in key flag.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key flag specified.";
|
||||
break;
|
||||
}
|
||||
|
||||
switch(CheckKeyCodes(k, &key)) {
|
||||
case -1:
|
||||
return "Null pointer in key code.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key code specified.";
|
||||
break;
|
||||
default:
|
||||
toggleKeyCode(key, down, flags);
|
||||
microsleep(keyboardDelay);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
// remove
|
||||
char* key_toggle(char* k, char* d, char* akey, char* keyT){
|
||||
MMKeyFlags flags = (MMKeyFlags) MOD_NONE;
|
||||
MMKeyCode key;
|
||||
|
||||
bool down;
|
||||
// char *k;
|
||||
// k = *kstr;
|
||||
|
||||
if (d != 0) {
|
||||
// char *d;
|
||||
// d = *dstr;
|
||||
if (strcmp(d, "down") == 0) {
|
||||
down = true;
|
||||
} else if (strcmp(d, "up") == 0) {
|
||||
down = false;
|
||||
} else {
|
||||
return "Invalid key state specified.";
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(akey, "null") != 0) {
|
||||
if (strcmp(keyT, "null") == 0) {
|
||||
switch (CheckKeyFlags(akey, &flags)) {
|
||||
case -1:
|
||||
return "Null pointer in key flag.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key flag specified.";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
char* akeyArr[2] = {akey, keyT};
|
||||
switch (GetFlagsFromValue(akeyArr, &flags, 2)) {
|
||||
case -1:
|
||||
return "Null pointer in key flag.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key flag specified.";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(CheckKeyCodes(k, &key)) {
|
||||
case -1:
|
||||
return "Null pointer in key code.";
|
||||
break;
|
||||
case -2:
|
||||
return "Invalid key code specified.";
|
||||
break;
|
||||
default:
|
||||
toggleKeyCode(key, down, flags);
|
||||
microsleep(keyboardDelay);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
void set_keyboard_delay(size_t val){
|
||||
keyboardDelay = val;
|
||||
}
|
@ -96,6 +96,13 @@ enum _MMKeyCode {
|
||||
K_NUMPAD_CLEAR = kVK_ANSI_KeypadClear,
|
||||
K_NUMPAD_ENTER = kVK_ANSI_KeypadEnter,
|
||||
K_NUMPAD_EQUAL = kVK_ANSI_KeypadEquals,
|
||||
K_NUMPAD_LB = kVK_ANSI_LeftBracket,
|
||||
K_NUMPAD_RB = kVK_ANSI_RightBracket,
|
||||
K_Backslash = kVK_ANSI_Backslash,
|
||||
K_Semicolon = kVK_ANSI_Semicolon,
|
||||
K_Quote = kVK_ANSI_Quote,
|
||||
K_Slash = kVK_ANSI_Slash,
|
||||
K_Grave = kVK_ANSI_Grave,
|
||||
|
||||
K_AUDIO_VOLUME_MUTE = 1007,
|
||||
K_AUDIO_VOLUME_DOWN = 1001,
|
||||
@ -204,6 +211,13 @@ enum _MMKeyCode {
|
||||
K_NUMPAD_CLEAR = K_NOT_A_KEY,
|
||||
K_NUMPAD_ENTER = 96, // XK_KP_Enter
|
||||
K_NUMPAD_EQUAL = XK_equal,
|
||||
K_NUMPAD_LB = XK_bracketleft,
|
||||
K_NUMPAD_RB = XK_bracketright,
|
||||
K_Backslash = XK_backslash,
|
||||
K_Semicolon = XK_semicolon,
|
||||
K_Quote = XK_apostrophe,
|
||||
K_Slash = XK_slash,
|
||||
K_Grave = XK_grave,
|
||||
|
||||
K_AUDIO_VOLUME_MUTE = XF86XK_AudioMute,
|
||||
K_AUDIO_VOLUME_DOWN = XF86XK_AudioLowerVolume,
|
||||
@ -227,6 +241,53 @@ enum _MMKeyCode {
|
||||
|
||||
typedef KeySym MMKeyCode;
|
||||
|
||||
/*
|
||||
* Structs to store key mappings not handled by XStringToKeysym() on some
|
||||
* Linux systems.
|
||||
*/
|
||||
struct XSpecialCharacterMapping {
|
||||
char name;
|
||||
MMKeyCode code;
|
||||
};
|
||||
|
||||
struct XSpecialCharacterMapping XSpecialCharacterTable[] = {
|
||||
{'~', XK_asciitilde},
|
||||
{'_', XK_underscore},
|
||||
{'[', XK_bracketleft},
|
||||
{']', XK_bracketright},
|
||||
{'!', XK_exclam},
|
||||
{'#', XK_numbersign},
|
||||
{'$', XK_dollar},
|
||||
{'%', XK_percent},
|
||||
{'&', XK_ampersand},
|
||||
{'*', XK_asterisk},
|
||||
{'+', XK_plus},
|
||||
{',', XK_comma},
|
||||
{'-', XK_minus},
|
||||
{'.', XK_period},
|
||||
{'?', XK_question},
|
||||
{'<', XK_less},
|
||||
{'>', XK_greater},
|
||||
{'=', XK_equal},
|
||||
{'@', XK_at},
|
||||
{':', XK_colon},
|
||||
{';', XK_semicolon},
|
||||
{'{', XK_braceleft},
|
||||
{'}', XK_braceright},
|
||||
{'|', XK_bar},
|
||||
{'^', XK_asciicircum},
|
||||
{'(', XK_parenleft},
|
||||
{')', XK_parenright},
|
||||
{' ', XK_space},
|
||||
{'/', XK_slash},
|
||||
{'\\', XK_backslash},
|
||||
{'`', XK_grave},
|
||||
{'"', XK_quoteright},
|
||||
{'\'', XK_quotedbl},
|
||||
{'\t', XK_Tab},
|
||||
{'\n', XK_Return}
|
||||
};
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
enum _MMKeyCode {
|
||||
@ -308,6 +369,13 @@ enum _MMKeyCode {
|
||||
K_NUMPAD_CLEAR = K_NOT_A_KEY,
|
||||
K_NUMPAD_ENTER = VK_RETURN,
|
||||
K_NUMPAD_EQUAL = VK_OEM_PLUS,
|
||||
K_NUMPAD_LB = VK_OEM_4,
|
||||
K_NUMPAD_RB = VK_OEM_6,
|
||||
K_Backslash = VK_OEM_5,
|
||||
K_Semicolon = VK_OEM_1,
|
||||
K_Quote = VK_OEM_7,
|
||||
K_Slash = VK_OEM_2,
|
||||
K_Grave = VK_OEM_3,
|
||||
|
||||
K_AUDIO_VOLUME_MUTE = VK_VOLUME_MUTE,
|
||||
K_AUDIO_VOLUME_DOWN = VK_VOLUME_DOWN,
|
||||
|
110
key/keycode_c.h
110
key/keycode_c.h
@ -8,61 +8,9 @@
|
||||
* Ownership follows the Create Rule; that is, it is the caller's
|
||||
* responsibility to release the returned object. */
|
||||
CFStringRef createStringForKey(CGKeyCode keyCode);
|
||||
|
||||
MMKeyCode keyCodeForCharFallBack(const char c);
|
||||
#elif defined(USE_X11)
|
||||
/*
|
||||
* Structs to store key mappings not handled by XStringToKeysym() on some
|
||||
* Linux systems.
|
||||
*/
|
||||
|
||||
struct XSpecialCharacterMapping {
|
||||
char name;
|
||||
MMKeyCode code;
|
||||
};
|
||||
|
||||
struct XSpecialCharacterMapping XSpecialCharacterTable[] = {
|
||||
{'~', XK_asciitilde},
|
||||
{'_', XK_underscore},
|
||||
{'[', XK_bracketleft},
|
||||
{']', XK_bracketright},
|
||||
{'!', XK_exclam},
|
||||
{'#', XK_numbersign},
|
||||
{'$', XK_dollar},
|
||||
{'%', XK_percent},
|
||||
{'&', XK_ampersand},
|
||||
{'*', XK_asterisk},
|
||||
{'+', XK_plus},
|
||||
{',', XK_comma},
|
||||
{'-', XK_minus},
|
||||
{'.', XK_period},
|
||||
{'?', XK_question},
|
||||
{'<', XK_less},
|
||||
{'>', XK_greater},
|
||||
{'=', XK_equal},
|
||||
{'@', XK_at},
|
||||
{':', XK_colon},
|
||||
{';', XK_semicolon},
|
||||
{'{', XK_braceleft},
|
||||
{'}', XK_braceright},
|
||||
{'|', XK_bar},
|
||||
{'^', XK_asciicircum},
|
||||
{'(', XK_parenleft},
|
||||
{')', XK_parenright},
|
||||
{' ', XK_space},
|
||||
{'/', XK_slash},
|
||||
{'\\', XK_backslash},
|
||||
{'`', XK_grave},
|
||||
{'"', XK_quoteright},
|
||||
{'\'', XK_quotedbl},
|
||||
// {'\'', XK_quoteright},
|
||||
{'\t', XK_Tab},
|
||||
{'\n', XK_Return}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
MMKeyCode keyCodeForChar(const char c){
|
||||
MMKeyCode keyCodeForChar(const char c) {
|
||||
#if defined(IS_MACOSX)
|
||||
/* OS X does not appear to have a built-in function for this, so instead we
|
||||
* have to write our own. */
|
||||
@ -89,20 +37,13 @@ MMKeyCode keyCodeForChar(const char c){
|
||||
}
|
||||
|
||||
charStr = CFStringCreateWithCharacters(kCFAllocatorDefault, &character, 1);
|
||||
|
||||
/* Our values may be NULL (0), so we need to use this function. */
|
||||
if (!CFDictionaryGetValueIfPresent(charToCodeDict, charStr,
|
||||
(const void **)&code)) {
|
||||
if (!CFDictionaryGetValueIfPresent(charToCodeDict, charStr, (const void **)&code)) {
|
||||
code = UINT16_MAX; /* Error */
|
||||
}
|
||||
|
||||
CFRelease(charStr);
|
||||
|
||||
// TISGetInputSourceProperty may return nil so we need fallback
|
||||
if (code == UINT16_MAX) {
|
||||
code = keyCodeForCharFallBack(c);
|
||||
}
|
||||
|
||||
if (code == UINT16_MAX) {
|
||||
return K_NOT_A_KEY;
|
||||
}
|
||||
@ -142,7 +83,6 @@ MMKeyCode keyCodeForChar(const char c){
|
||||
if (code == NoSymbol) {
|
||||
return K_NOT_A_KEY;
|
||||
}
|
||||
|
||||
return code;
|
||||
#endif
|
||||
}
|
||||
@ -167,50 +107,4 @@ CFStringRef createStringForKey(CGKeyCode keyCode){
|
||||
|
||||
return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1);
|
||||
}
|
||||
|
||||
MMKeyCode keyCodeForCharFallBack(const char c) {
|
||||
switch (c) {
|
||||
case 'A': return kVK_ANSI_A;
|
||||
case 'B': return kVK_ANSI_B;
|
||||
case 'C': return kVK_ANSI_C;
|
||||
case 'D': return kVK_ANSI_D;
|
||||
case 'E': return kVK_ANSI_E;
|
||||
case 'F': return kVK_ANSI_F;
|
||||
case 'G': return kVK_ANSI_G;
|
||||
case 'H': return kVK_ANSI_H;
|
||||
case 'I': return kVK_ANSI_I;
|
||||
case 'J': return kVK_ANSI_J;
|
||||
case 'K': return kVK_ANSI_K;
|
||||
case 'L': return kVK_ANSI_L;
|
||||
case 'M': return kVK_ANSI_M;
|
||||
case 'N': return kVK_ANSI_N;
|
||||
case 'O': return kVK_ANSI_O;
|
||||
case 'P': return kVK_ANSI_P;
|
||||
case 'Q': return kVK_ANSI_Q;
|
||||
case 'R': return kVK_ANSI_R;
|
||||
case 'S': return kVK_ANSI_S;
|
||||
case 'T': return kVK_ANSI_T;
|
||||
case 'U': return kVK_ANSI_U;
|
||||
case 'V': return kVK_ANSI_V;
|
||||
case 'W': return kVK_ANSI_W;
|
||||
case 'X': return kVK_ANSI_X;
|
||||
case 'Y': return kVK_ANSI_Y;
|
||||
case 'Z': return kVK_ANSI_Z;
|
||||
|
||||
|
||||
case '0': return kVK_ANSI_0;
|
||||
case '1': return kVK_ANSI_1;
|
||||
case '2': return kVK_ANSI_2;
|
||||
case '3': return kVK_ANSI_3;
|
||||
case '4': return kVK_ANSI_4;
|
||||
case '5': return kVK_ANSI_5;
|
||||
case '6': return kVK_ANSI_6;
|
||||
case '7': return kVK_ANSI_7;
|
||||
case '8': return kVK_ANSI_8;
|
||||
case '9': return kVK_ANSI_9;
|
||||
}
|
||||
|
||||
return K_NOT_A_KEY;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
11
keycode.go
11
keycode.go
@ -19,6 +19,17 @@ type uMap map[string]uint16
|
||||
// MouseMap robotgo hook mouse's code map
|
||||
var MouseMap = keycode.MouseMap
|
||||
|
||||
const (
|
||||
// Mleft mouse left button
|
||||
Mleft = "left"
|
||||
Mright = "right"
|
||||
Center = "center"
|
||||
WheelDown = "wheelDown"
|
||||
WheelUp = "wheelUp"
|
||||
WheelLeft = "wheelLeft"
|
||||
WheelRight = "wheelRight"
|
||||
)
|
||||
|
||||
// Keycode robotgo hook key's code map
|
||||
var Keycode = keycode.Keycode
|
||||
|
||||
|
399
robotgo.go
399
robotgo.go
@ -33,16 +33,12 @@ package robotgo
|
||||
#cgo darwin LDFLAGS: -framework Carbon -framework CoreFoundation
|
||||
|
||||
#cgo linux CFLAGS: -I/usr/src
|
||||
#cgo linux LDFLAGS: -L/usr/src -lX11 -lXtst -lm
|
||||
// #cgo linux LDFLAGS: -lX11-xcb -lxcb -lxcb-xkb -lxkbcommon -lxkbcommon-x11
|
||||
#cgo linux LDFLAGS: -L/usr/src -lm -lX11 -lXtst
|
||||
|
||||
// #cgo windows LDFLAGS: -lgdi32 -luser32 -lpng -lz
|
||||
#cgo windows LDFLAGS: -lgdi32 -luser32
|
||||
//
|
||||
// #include <AppKit/NSEvent.h>
|
||||
#include "screen/goScreen.h"
|
||||
#include "mouse/goMouse.h"
|
||||
#include "key/goKey.h"
|
||||
#include "window/goWindow.h"
|
||||
*/
|
||||
import "C"
|
||||
@ -50,19 +46,10 @@ import "C"
|
||||
import (
|
||||
"errors"
|
||||
"image"
|
||||
|
||||
// "os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
// "syscall"
|
||||
"math/rand"
|
||||
|
||||
"github.com/go-vgo/robotgo/clipboard"
|
||||
"github.com/vcaesar/tt"
|
||||
)
|
||||
|
||||
@ -142,7 +129,7 @@ func Sleep(tm int) {
|
||||
time.Sleep(time.Duration(tm) * time.Second)
|
||||
}
|
||||
|
||||
// MicroSleep time C.microsleep(tm)
|
||||
// MicroSleep time C.microsleep(tm), use the MilliSleep
|
||||
func MicroSleep(tm float64) {
|
||||
C.microsleep(C.double(tm))
|
||||
}
|
||||
@ -351,6 +338,13 @@ func FreeBitmap(bitmap CBitmap) {
|
||||
C.bitmap_dealloc(C.MMBitmapRef(bitmap))
|
||||
}
|
||||
|
||||
// FreeBitmapArr free and dealloc the C bitmap array
|
||||
func FreeBitmapArr(bit ...CBitmap) {
|
||||
for i := 0; i < len(bit); i++ {
|
||||
FreeBitmap(bit[i])
|
||||
}
|
||||
}
|
||||
|
||||
// ToMMBitmapRef trans CBitmap to C.MMBitmapRef
|
||||
func ToMMBitmapRef(bit CBitmap) C.MMBitmapRef {
|
||||
return C.MMBitmapRef(bit)
|
||||
@ -396,14 +390,12 @@ func ToRGBA(bit CBitmap) *image.RGBA {
|
||||
}
|
||||
|
||||
// SetXDisplayName set XDisplay name (Linux)
|
||||
func SetXDisplayName(name string) string {
|
||||
func SetXDisplayName(name string) error {
|
||||
cname := C.CString(name)
|
||||
str := C.set_XDisplay_name(cname)
|
||||
|
||||
gstr := C.GoString(str)
|
||||
C.free(unsafe.Pointer(cname))
|
||||
|
||||
return gstr
|
||||
return toErr(str)
|
||||
}
|
||||
|
||||
// GetXDisplayName get XDisplay name (Linux)
|
||||
@ -823,375 +815,6 @@ func SetMouseDelay(delay int) {
|
||||
C.set_mouse_delay(cdelay)
|
||||
}
|
||||
|
||||
/*
|
||||
__ ___ ___________ ____ .______ ______ ___ .______ _______
|
||||
| |/ / | ____\ \ / / | _ \ / __ \ / \ | _ \ | \
|
||||
| ' / | |__ \ \/ / | |_) | | | | | / ^ \ | |_) | | .--. |
|
||||
| < | __| \_ _/ | _ < | | | | / /_\ \ | / | | | |
|
||||
| . \ | |____ | | | |_) | | `--' | / _____ \ | |\ \----.| '--' |
|
||||
|__|\__\ |_______| |__| |______/ \______/ /__/ \__\ | _| `._____||_______/
|
||||
|
||||
*/
|
||||
|
||||
func toErr(str *C.char) error {
|
||||
gstr := C.GoString(str)
|
||||
if gstr == "" {
|
||||
return nil
|
||||
}
|
||||
return errors.New(gstr)
|
||||
}
|
||||
|
||||
// KeyTap tap the keyboard code;
|
||||
//
|
||||
// See keys:
|
||||
// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md
|
||||
//
|
||||
// Examples:
|
||||
// robotgo.KeySleep = 100 // 100 millisecond
|
||||
// robotgo.KeyTap("a")
|
||||
// robotgo.KeyTap("i", "alt", "command")
|
||||
//
|
||||
// arr := []string{"alt", "command"}
|
||||
// robotgo.KeyTap("i", arr)
|
||||
//
|
||||
func KeyTap(tapKey string, args ...interface{}) error {
|
||||
var (
|
||||
akey string
|
||||
keyT = "null"
|
||||
keyArr []string
|
||||
num int
|
||||
keyDelay int // This is legacy and drop option, use robotgo.KeySleep
|
||||
)
|
||||
|
||||
if _, ok := Special[tapKey]; ok {
|
||||
tapKey = Special[tapKey]
|
||||
if len(args) <= 0 {
|
||||
args = append(args, "shift")
|
||||
}
|
||||
}
|
||||
|
||||
// var ckeyArr []*C.char
|
||||
ckeyArr := make([](*C.char), 0)
|
||||
// zkey := C.CString(args[0])
|
||||
zkey := C.CString(tapKey)
|
||||
defer C.free(unsafe.Pointer(zkey))
|
||||
|
||||
// args not key delay
|
||||
if len(args) > 2 && (reflect.TypeOf(args[2]) != reflect.TypeOf(num)) {
|
||||
num = len(args)
|
||||
for i := 0; i < num; i++ {
|
||||
s := args[i].(string)
|
||||
ckeyArr = append(ckeyArr, (*C.char)(unsafe.Pointer(C.CString(s))))
|
||||
}
|
||||
|
||||
str := C.key_Taps(zkey,
|
||||
(**C.char)(unsafe.Pointer(&ckeyArr[0])), C.int(num), 0)
|
||||
MilliSleep(KeySleep)
|
||||
return toErr(str)
|
||||
}
|
||||
|
||||
// key delay
|
||||
if len(args) > 0 {
|
||||
if reflect.TypeOf(args[0]) == reflect.TypeOf(keyArr) {
|
||||
|
||||
keyArr = args[0].([]string)
|
||||
num = len(keyArr)
|
||||
for i := 0; i < num; i++ {
|
||||
ckeyArr = append(ckeyArr, (*C.char)(unsafe.Pointer(C.CString(keyArr[i]))))
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
keyDelay = args[1].(int)
|
||||
}
|
||||
} else {
|
||||
akey = args[0].(string)
|
||||
|
||||
if len(args) > 1 {
|
||||
if reflect.TypeOf(args[1]) == reflect.TypeOf(akey) {
|
||||
keyT = args[1].(string)
|
||||
if len(args) > 2 {
|
||||
keyDelay = args[2].(int)
|
||||
}
|
||||
} else {
|
||||
keyDelay = args[1].(int)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
akey = "null"
|
||||
keyArr = []string{"null"}
|
||||
}
|
||||
|
||||
if akey == "" && len(keyArr) != 0 {
|
||||
str := C.key_Taps(zkey, (**C.char)(unsafe.Pointer(&ckeyArr[0])),
|
||||
C.int(num), C.int(keyDelay))
|
||||
|
||||
MilliSleep(KeySleep)
|
||||
return toErr(str)
|
||||
}
|
||||
|
||||
amod := C.CString(akey)
|
||||
amodt := C.CString(keyT)
|
||||
str := C.key_tap(zkey, amod, amodt, C.int(keyDelay))
|
||||
|
||||
C.free(unsafe.Pointer(amod))
|
||||
C.free(unsafe.Pointer(amodt))
|
||||
|
||||
MilliSleep(KeySleep)
|
||||
return toErr(str)
|
||||
}
|
||||
|
||||
// KeyToggle toggle the keyboard, if there not have args default is "down"
|
||||
//
|
||||
// See keys:
|
||||
// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md
|
||||
//
|
||||
// Examples:
|
||||
// robotgo.KeyToggle("a")
|
||||
// robotgo.KeyToggle("a", "up")
|
||||
//
|
||||
// robotgo.KeyToggle("a", "up", "alt", "cmd")
|
||||
//
|
||||
func KeyToggle(key string, args ...string) error {
|
||||
if len(args) <= 0 {
|
||||
args = append(args, "down")
|
||||
}
|
||||
|
||||
if _, ok := Special[key]; ok {
|
||||
key = Special[key]
|
||||
if len(args) <= 1 {
|
||||
args = append(args, "shift")
|
||||
}
|
||||
}
|
||||
|
||||
ckey := C.CString(key)
|
||||
defer C.free(unsafe.Pointer(ckey))
|
||||
|
||||
ckeyArr := make([](*C.char), 0)
|
||||
if len(args) > 3 {
|
||||
num := len(args)
|
||||
for i := 0; i < num; i++ {
|
||||
ckeyArr = append(ckeyArr, (*C.char)(unsafe.Pointer(C.CString(args[i]))))
|
||||
}
|
||||
|
||||
str := C.key_Toggles(ckey, (**C.char)(unsafe.Pointer(&ckeyArr[0])), C.int(num))
|
||||
MilliSleep(KeySleep)
|
||||
return toErr(str)
|
||||
}
|
||||
|
||||
// use key_toggle()
|
||||
var (
|
||||
down, mKey, mKeyT = "null", "null", "null"
|
||||
// keyDelay = 10
|
||||
)
|
||||
|
||||
if len(args) > 0 {
|
||||
down = args[0]
|
||||
|
||||
if len(args) > 1 {
|
||||
mKey = args[1]
|
||||
if len(args) > 2 {
|
||||
mKeyT = args[2]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cdown := C.CString(down)
|
||||
cmKey := C.CString(mKey)
|
||||
cmKeyT := C.CString(mKeyT)
|
||||
|
||||
str := C.key_toggle(ckey, cdown, cmKey, cmKeyT)
|
||||
// str := C.key_Toggle(ckey, cdown, cmKey, cmKeyT, C.int(keyDelay))
|
||||
|
||||
C.free(unsafe.Pointer(cdown))
|
||||
C.free(unsafe.Pointer(cmKey))
|
||||
C.free(unsafe.Pointer(cmKeyT))
|
||||
|
||||
MilliSleep(KeySleep)
|
||||
return toErr(str)
|
||||
}
|
||||
|
||||
// KeyPress press key string
|
||||
func KeyPress(key string) error {
|
||||
err := KeyDown(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
MilliSleep(1 + rand.Intn(3))
|
||||
return KeyUp(key)
|
||||
}
|
||||
|
||||
// KeyDown press down a key
|
||||
func KeyDown(key string) error {
|
||||
return KeyToggle(key)
|
||||
}
|
||||
|
||||
// KeyUp press up a key
|
||||
func KeyUp(key string) error {
|
||||
return KeyToggle(key, "up")
|
||||
}
|
||||
|
||||
// ReadAll read string from clipboard
|
||||
func ReadAll() (string, error) {
|
||||
return clipboard.ReadAll()
|
||||
}
|
||||
|
||||
// WriteAll write string to clipboard
|
||||
func WriteAll(text string) error {
|
||||
return clipboard.WriteAll(text)
|
||||
}
|
||||
|
||||
// CharCodeAt char code at utf-8
|
||||
func CharCodeAt(s string, n int) rune {
|
||||
i := 0
|
||||
for _, r := range s {
|
||||
if i == n {
|
||||
return r
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// UnicodeType tap uint32 unicode
|
||||
func UnicodeType(str uint32) {
|
||||
cstr := C.uint(str)
|
||||
C.unicodeType(cstr)
|
||||
}
|
||||
|
||||
// ToUC trans string to unicode []string
|
||||
func ToUC(text string) []string {
|
||||
var uc []string
|
||||
|
||||
for _, r := range text {
|
||||
textQ := strconv.QuoteToASCII(string(r))
|
||||
textUnQ := textQ[1 : len(textQ)-1]
|
||||
|
||||
st := strings.Replace(textUnQ, "\\u", "U", -1)
|
||||
if st == "\\\\" {
|
||||
st = "\\"
|
||||
}
|
||||
if st == `\"` {
|
||||
st = `"`
|
||||
}
|
||||
uc = append(uc, st)
|
||||
}
|
||||
|
||||
return uc
|
||||
}
|
||||
|
||||
func inputUTF(str string) {
|
||||
cstr := C.CString(str)
|
||||
C.input_utf(cstr)
|
||||
|
||||
C.free(unsafe.Pointer(cstr))
|
||||
}
|
||||
|
||||
// TypeStr send a string, support UTF-8
|
||||
//
|
||||
// robotgo.TypeStr(string: The string to send, float64: microsleep time, x11 option)
|
||||
//
|
||||
// Examples:
|
||||
// robotgo.TypeStr("abc@123, hi, こんにちは")
|
||||
//
|
||||
func TypeStr(str string, args ...float64) {
|
||||
var tm, tm1 = 0.0, 7.0
|
||||
|
||||
if len(args) > 0 {
|
||||
tm = args[0]
|
||||
}
|
||||
if len(args) > 1 {
|
||||
tm1 = args[1]
|
||||
}
|
||||
|
||||
if runtime.GOOS == "linux" {
|
||||
strUc := ToUC(str)
|
||||
for i := 0; i < len(strUc); i++ {
|
||||
ru := []rune(strUc[i])
|
||||
if len(ru) <= 1 {
|
||||
ustr := uint32(CharCodeAt(strUc[i], 0))
|
||||
UnicodeType(ustr)
|
||||
} else {
|
||||
inputUTF(strUc[i])
|
||||
MicroSleep(tm1)
|
||||
}
|
||||
|
||||
MicroSleep(tm)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < len([]rune(str)); i++ {
|
||||
ustr := uint32(CharCodeAt(str, i))
|
||||
UnicodeType(ustr)
|
||||
|
||||
// if len(args) > 0 {
|
||||
MicroSleep(tm)
|
||||
// }
|
||||
}
|
||||
MilliSleep(KeySleep)
|
||||
}
|
||||
|
||||
// PasteStr paste a string, support UTF-8,
|
||||
// write the string to clipboard and tap `cmd + v`
|
||||
func PasteStr(str string) error {
|
||||
err := clipboard.WriteAll(str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
return KeyTap("v", "command")
|
||||
}
|
||||
|
||||
return KeyTap("v", "control")
|
||||
}
|
||||
|
||||
// TypeStrDelay type string delayed
|
||||
func TypeStrDelay(str string, delay int) {
|
||||
TypeStr(str)
|
||||
Sleep(delay)
|
||||
}
|
||||
|
||||
// Deprecated: use the TypeStr(),
|
||||
//
|
||||
// TypeStringDelayed type string delayed, Wno-deprecated
|
||||
//
|
||||
// This function will be removed in version v1.0.0
|
||||
func TypeStringDelayed(str string, delay int) {
|
||||
tt.Drop("TypeStringDelayed", "TypeStrDelay")
|
||||
TypeStrDelay(str, delay)
|
||||
}
|
||||
|
||||
// SetKeyDelay set keyboard delay
|
||||
func SetKeyDelay(delay int) {
|
||||
C.set_keyboard_delay(C.size_t(delay))
|
||||
}
|
||||
|
||||
// Deprecated: use the SetKeyDelay(),
|
||||
//
|
||||
// SetKeyboardDelay set keyboard delay, Wno-deprecated,
|
||||
//
|
||||
// This function will be removed in version v1.0.0
|
||||
func SetKeyboardDelay(delay int) {
|
||||
tt.Drop("SetKeyboardDelay", "SetKeyDelay")
|
||||
SetKeyDelay(delay)
|
||||
}
|
||||
|
||||
// SetDelay set the key and mouse delay
|
||||
func SetDelay(d ...int) {
|
||||
v := 10
|
||||
if len(d) > 0 {
|
||||
v = d[0]
|
||||
}
|
||||
|
||||
SetMouseDelay(v)
|
||||
SetKeyDelay(v)
|
||||
}
|
||||
|
||||
/*
|
||||
____ __ ____ __ .__ __. _______ ______ ____ __ ____
|
||||
\ \ / \ / / | | | \ | | | \ / __ \ \ \ / \ / /
|
||||
|
Loading…
Reference in New Issue
Block a user