Merge pull request #454 from go-vgo/bitmap-pr

Refactor some keyboard C code to go
This commit is contained in:
Evans 2022-02-01 00:09:18 -08:00 committed by GitHub
commit 75cfe774b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 749 additions and 896 deletions

View File

@ -1,11 +1,12 @@
1. Please **speak English**, this is the language everybody of us can speak and write. 1. Please **speak English**, this is the language everybody of us can speak and write.
2. Please take a moment to **search** that an issue **doesn't already exist**. 2. Please take a moment to **search** that an issue **doesn't already exist**.
3. Please make sure `Golang, GCC` is installed correctly before installing RobotGo. 3. Please make sure `Golang, GCC` is installed correctly before installing RobotGo.
4. Please ask questions or config/deploy problems on our Gitter channel: https://gitter.im/go-vgo/robotgo <!-- 4. Please ask questions or config/deploy problems on our Gitter channel: https://gitter.im/go-vgo/robotgo -->
5. Please give all relevant information below for bug reports, incomplete details will be handled as an invalid report. 5. Please give all relevant information below for bug reports, incomplete details will be handled as an invalid report.
**You MUST delete the content above including this line before posting, otherwise your issue will be invalid.** **You MUST delete the content above including this line before posting, otherwise your issue will be invalid.**
- Robotgo version (or commit ref): - Robotgo version (or commit ref):
- Go version: - Go version:
- Gcc version: - Gcc version:

View File

@ -9,6 +9,7 @@ The pull request will be closed without any reasons if it does not satisfy any o
**You MUST delete the content above including this line before posting, otherwise your pull request will be invalid.** **You MUST delete the content above including this line before posting, otherwise your pull request will be invalid.**
**Please provide Issues links to:** **Please provide Issues links to:**
- Issues: #1 - Issues: #1

View File

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

647
key.go Normal file
View File

@ -0,0 +1,647 @@
// 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 {
val1 := C.CString(k)
defer C.free(unsafe.Pointer(val1))
key = C.keyCodeForChar(*val1)
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)
}

View File

@ -1,397 +1,8 @@
// 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 <stdlib.h>
#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;
}

View File

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

View File

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

View File

@ -1,5 +1,5 @@
#include "keypress.h" #include "keypress.h"
// #include "../base/deadbeef_rand_c.h" #include "../base/deadbeef_rand_c.h"
#include "../base/microsleep.h" #include "../base/microsleep.h"
#include <ctype.h> /* For isupper() */ #include <ctype.h> /* For isupper() */

View File

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

View File

@ -1,8 +1,5 @@
#include "mouse.h" #include "mouse.h"
// #include "../screen/screen.h" #include "../base/deadbeef_rand.h"
// #include "../screen/screen_c.h"
#include "../base/deadbeef_rand_c.h"
// #include "../deadbeef_rand.h"
#include "../base/microsleep.h" #include "../base/microsleep.h"
#include <math.h> /* For floor() */ #include <math.h> /* For floor() */

View File

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