Refactor some keyboard C code to go

This commit is contained in:
vcaesar 2022-01-31 23:12:24 -08:00
parent ed45411f5c
commit 99963bc6fc
7 changed files with 768 additions and 890 deletions

View File

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

View File

@ -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;
}

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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)
}
/*
____ __ ____ __ .__ __. _______ ______ ____ __ ____
\ \ / \ / / | | | \ | | | \ / __ \ \ \ / \ / /