mirror of
https://github.com/go-vgo/robotgo.git
synced 2025-05-29 21:43: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)
|
fmt.Println("robotgo.KeyTap run error is: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
robotgo.KeyTap("h", "cmd", 12)
|
robotgo.KeyTap("h", "cmd")
|
||||||
|
|
||||||
// press "i", "alt", "command" Key combination
|
// press "i", "alt", "command" Key combination
|
||||||
robotgo.KeyTap("i", "alt", "command")
|
robotgo.KeyTap("i", "alt", "command")
|
||||||
robotgo.KeyTap("i", "alt", "cmd", 11)
|
robotgo.KeyTap("i", "alt", "cmd")
|
||||||
|
|
||||||
arr := []string{"alt", "cmd"}
|
arr := []string{"alt", "cmd"}
|
||||||
robotgo.KeyTap("i", arr)
|
robotgo.KeyTap("i", arr)
|
||||||
robotgo.KeyTap("i", arr, 12)
|
robotgo.KeyTap("i", arr)
|
||||||
|
|
||||||
robotgo.KeyTap("i", "cmd", " alt", "shift")
|
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
|
// Copyright 2016 The go-vgo Project Developers.
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "../base/types.h"
|
#include "../base/types.h"
|
||||||
// #include "keycode.h"
|
// #include "keycode.h"
|
||||||
// #include "keypress.h"
|
// #include "keypress.h"
|
||||||
#include "keypress_c.h"
|
#include "keypress_c.h"
|
||||||
#include "keycode_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_CLEAR = kVK_ANSI_KeypadClear,
|
||||||
K_NUMPAD_ENTER = kVK_ANSI_KeypadEnter,
|
K_NUMPAD_ENTER = kVK_ANSI_KeypadEnter,
|
||||||
K_NUMPAD_EQUAL = kVK_ANSI_KeypadEquals,
|
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_MUTE = 1007,
|
||||||
K_AUDIO_VOLUME_DOWN = 1001,
|
K_AUDIO_VOLUME_DOWN = 1001,
|
||||||
@ -204,6 +211,13 @@ enum _MMKeyCode {
|
|||||||
K_NUMPAD_CLEAR = K_NOT_A_KEY,
|
K_NUMPAD_CLEAR = K_NOT_A_KEY,
|
||||||
K_NUMPAD_ENTER = 96, // XK_KP_Enter
|
K_NUMPAD_ENTER = 96, // XK_KP_Enter
|
||||||
K_NUMPAD_EQUAL = XK_equal,
|
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_MUTE = XF86XK_AudioMute,
|
||||||
K_AUDIO_VOLUME_DOWN = XF86XK_AudioLowerVolume,
|
K_AUDIO_VOLUME_DOWN = XF86XK_AudioLowerVolume,
|
||||||
@ -227,6 +241,53 @@ enum _MMKeyCode {
|
|||||||
|
|
||||||
typedef KeySym 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)
|
#elif defined(IS_WINDOWS)
|
||||||
|
|
||||||
enum _MMKeyCode {
|
enum _MMKeyCode {
|
||||||
@ -308,6 +369,13 @@ enum _MMKeyCode {
|
|||||||
K_NUMPAD_CLEAR = K_NOT_A_KEY,
|
K_NUMPAD_CLEAR = K_NOT_A_KEY,
|
||||||
K_NUMPAD_ENTER = VK_RETURN,
|
K_NUMPAD_ENTER = VK_RETURN,
|
||||||
K_NUMPAD_EQUAL = VK_OEM_PLUS,
|
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_MUTE = VK_VOLUME_MUTE,
|
||||||
K_AUDIO_VOLUME_DOWN = VK_VOLUME_DOWN,
|
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
|
* Ownership follows the Create Rule; that is, it is the caller's
|
||||||
* responsibility to release the returned object. */
|
* responsibility to release the returned object. */
|
||||||
CFStringRef createStringForKey(CGKeyCode keyCode);
|
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
|
#endif
|
||||||
|
|
||||||
MMKeyCode keyCodeForChar(const char c){
|
MMKeyCode keyCodeForChar(const char c) {
|
||||||
#if defined(IS_MACOSX)
|
#if defined(IS_MACOSX)
|
||||||
/* OS X does not appear to have a built-in function for this, so instead we
|
/* OS X does not appear to have a built-in function for this, so instead we
|
||||||
* have to write our own. */
|
* have to write our own. */
|
||||||
@ -89,20 +37,13 @@ MMKeyCode keyCodeForChar(const char c){
|
|||||||
}
|
}
|
||||||
|
|
||||||
charStr = CFStringCreateWithCharacters(kCFAllocatorDefault, &character, 1);
|
charStr = CFStringCreateWithCharacters(kCFAllocatorDefault, &character, 1);
|
||||||
|
|
||||||
/* Our values may be NULL (0), so we need to use this function. */
|
/* Our values may be NULL (0), so we need to use this function. */
|
||||||
if (!CFDictionaryGetValueIfPresent(charToCodeDict, charStr,
|
if (!CFDictionaryGetValueIfPresent(charToCodeDict, charStr, (const void **)&code)) {
|
||||||
(const void **)&code)) {
|
|
||||||
code = UINT16_MAX; /* Error */
|
code = UINT16_MAX; /* Error */
|
||||||
}
|
}
|
||||||
|
|
||||||
CFRelease(charStr);
|
CFRelease(charStr);
|
||||||
|
|
||||||
// TISGetInputSourceProperty may return nil so we need fallback
|
// TISGetInputSourceProperty may return nil so we need fallback
|
||||||
if (code == UINT16_MAX) {
|
|
||||||
code = keyCodeForCharFallBack(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (code == UINT16_MAX) {
|
if (code == UINT16_MAX) {
|
||||||
return K_NOT_A_KEY;
|
return K_NOT_A_KEY;
|
||||||
}
|
}
|
||||||
@ -142,7 +83,6 @@ MMKeyCode keyCodeForChar(const char c){
|
|||||||
if (code == NoSymbol) {
|
if (code == NoSymbol) {
|
||||||
return K_NOT_A_KEY;
|
return K_NOT_A_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
return code;
|
return code;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -167,50 +107,4 @@ CFStringRef createStringForKey(CGKeyCode keyCode){
|
|||||||
|
|
||||||
return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1);
|
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
|
#endif
|
||||||
|
11
keycode.go
11
keycode.go
@ -19,6 +19,17 @@ type uMap map[string]uint16
|
|||||||
// MouseMap robotgo hook mouse's code map
|
// MouseMap robotgo hook mouse's code map
|
||||||
var MouseMap = keycode.MouseMap
|
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
|
// Keycode robotgo hook key's code map
|
||||||
var Keycode = keycode.Keycode
|
var Keycode = keycode.Keycode
|
||||||
|
|
||||||
|
399
robotgo.go
399
robotgo.go
@ -33,16 +33,12 @@ package robotgo
|
|||||||
#cgo darwin LDFLAGS: -framework Carbon -framework CoreFoundation
|
#cgo darwin LDFLAGS: -framework Carbon -framework CoreFoundation
|
||||||
|
|
||||||
#cgo linux CFLAGS: -I/usr/src
|
#cgo linux CFLAGS: -I/usr/src
|
||||||
#cgo linux LDFLAGS: -L/usr/src -lX11 -lXtst -lm
|
#cgo linux LDFLAGS: -L/usr/src -lm -lX11 -lXtst
|
||||||
// #cgo linux LDFLAGS: -lX11-xcb -lxcb -lxcb-xkb -lxkbcommon -lxkbcommon-x11
|
|
||||||
|
|
||||||
// #cgo windows LDFLAGS: -lgdi32 -luser32 -lpng -lz
|
|
||||||
#cgo windows LDFLAGS: -lgdi32 -luser32
|
#cgo windows LDFLAGS: -lgdi32 -luser32
|
||||||
//
|
//
|
||||||
// #include <AppKit/NSEvent.h>
|
|
||||||
#include "screen/goScreen.h"
|
#include "screen/goScreen.h"
|
||||||
#include "mouse/goMouse.h"
|
#include "mouse/goMouse.h"
|
||||||
#include "key/goKey.h"
|
|
||||||
#include "window/goWindow.h"
|
#include "window/goWindow.h"
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
@ -50,19 +46,10 @@ import "C"
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"image"
|
"image"
|
||||||
|
|
||||||
// "os"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
// "syscall"
|
|
||||||
"math/rand"
|
|
||||||
|
|
||||||
"github.com/go-vgo/robotgo/clipboard"
|
|
||||||
"github.com/vcaesar/tt"
|
"github.com/vcaesar/tt"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -142,7 +129,7 @@ func Sleep(tm int) {
|
|||||||
time.Sleep(time.Duration(tm) * time.Second)
|
time.Sleep(time.Duration(tm) * time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MicroSleep time C.microsleep(tm)
|
// MicroSleep time C.microsleep(tm), use the MilliSleep
|
||||||
func MicroSleep(tm float64) {
|
func MicroSleep(tm float64) {
|
||||||
C.microsleep(C.double(tm))
|
C.microsleep(C.double(tm))
|
||||||
}
|
}
|
||||||
@ -351,6 +338,13 @@ func FreeBitmap(bitmap CBitmap) {
|
|||||||
C.bitmap_dealloc(C.MMBitmapRef(bitmap))
|
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
|
// ToMMBitmapRef trans CBitmap to C.MMBitmapRef
|
||||||
func ToMMBitmapRef(bit CBitmap) C.MMBitmapRef {
|
func ToMMBitmapRef(bit CBitmap) C.MMBitmapRef {
|
||||||
return C.MMBitmapRef(bit)
|
return C.MMBitmapRef(bit)
|
||||||
@ -396,14 +390,12 @@ func ToRGBA(bit CBitmap) *image.RGBA {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetXDisplayName set XDisplay name (Linux)
|
// SetXDisplayName set XDisplay name (Linux)
|
||||||
func SetXDisplayName(name string) string {
|
func SetXDisplayName(name string) error {
|
||||||
cname := C.CString(name)
|
cname := C.CString(name)
|
||||||
str := C.set_XDisplay_name(cname)
|
str := C.set_XDisplay_name(cname)
|
||||||
|
|
||||||
gstr := C.GoString(str)
|
|
||||||
C.free(unsafe.Pointer(cname))
|
C.free(unsafe.Pointer(cname))
|
||||||
|
|
||||||
return gstr
|
return toErr(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetXDisplayName get XDisplay name (Linux)
|
// GetXDisplayName get XDisplay name (Linux)
|
||||||
@ -823,375 +815,6 @@ func SetMouseDelay(delay int) {
|
|||||||
C.set_mouse_delay(cdelay)
|
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