// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. /* Package robotgo Go native cross-platform system automation. Please make sure Golang, GCC is installed correctly before installing RobotGo; See Requirements: https://github.com/go-vgo/robotgo#requirements Installation: With Go module support (Go 1.11+), just import: import "github.com/go-vgo/robotgo" Otherwise, to install the robotgo package, run the command: go get -u github.com/go-vgo/robotgo */ package robotgo /* #cgo darwin CFLAGS: -x objective-c -Wno-deprecated-declarations #cgo darwin LDFLAGS: -framework Cocoa -framework CoreFoundation -framework IOKit #cgo darwin LDFLAGS: -framework Carbon -framework OpenGL // #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 140400 #cgo darwin LDFLAGS: -framework ScreenCaptureKit #endif #cgo linux CFLAGS: -I/usr/src #cgo linux LDFLAGS: -L/usr/src -lm -lX11 -lXtst #cgo windows LDFLAGS: -lgdi32 -luser32 // #include "screen/goScreen.h" #include "mouse/mouse_c.h" #include "window/goWindow.h" */ import "C" import ( "errors" "image" "runtime" "time" "unsafe" "github.com/vcaesar/tt" ) const ( // Version get the robotgo version Version = "v1.00.0.1189, MT. Baker!" ) // GetVersion get the robotgo version func GetVersion() string { return Version } var ( // MouseSleep set the mouse default millisecond sleep time MouseSleep = 0 // KeySleep set the key default millisecond sleep time KeySleep = 10 // DisplayID set the screen display id DisplayID = -1 // NotPid used the hwnd not pid in windows NotPid bool // Scale option the os screen scale Scale bool ) type ( // Map a map[string]interface{} Map map[string]interface{} // CHex define CHex as c rgb Hex type (C.MMRGBHex) CHex C.MMRGBHex // CBitmap define CBitmap as C.MMBitmapRef type CBitmap C.MMBitmapRef // Handle define window Handle as C.MData type Handle C.MData ) // Bitmap define the go Bitmap struct // // The common type conversion of bitmap: // // https://github.com/go-vgo/robotgo/blob/master/docs/keys.md#type-conversion type Bitmap struct { ImgBuf *uint8 Width, Height int Bytewidth int BitsPixel uint8 BytesPerPixel uint8 } // Point is point struct type Point struct { X int Y int } // Size is size structure type Size struct { W, H int } // Rect is rect structure type Rect struct { Point Size } // Try handler(err) func Try(fun func(), handler func(interface{})) { defer func() { if err := recover(); err != nil { handler(err) } }() fun() } // MilliSleep sleep tm milli second func MilliSleep(tm int) { time.Sleep(time.Duration(tm) * time.Millisecond) } // Sleep time.Sleep tm second func Sleep(tm int) { time.Sleep(time.Duration(tm) * time.Second) } // Deprecated: use the MilliSleep(), // // MicroSleep time C.microsleep(tm) func MicroSleep(tm float64) { C.microsleep(C.double(tm)) } // GoString trans C.char to string func GoString(char *C.char) string { return C.GoString(char) } /* _______. ______ .______ _______ _______ .__ __. / | / || _ \ | ____|| ____|| \ | | | (----`| ,----'| |_) | | |__ | |__ | \| | \ \ | | | / | __| | __| | . ` | .----) | | `----.| |\ \----.| |____ | |____ | |\ | |_______/ \______|| _| `._____||_______||_______||__| \__| */ // ToMMRGBHex trans CHex to C.MMRGBHex func ToMMRGBHex(hex CHex) C.MMRGBHex { return C.MMRGBHex(hex) } // UintToHex trans uint32 to robotgo.CHex func UintToHex(u uint32) CHex { hex := U32ToHex(C.uint32_t(u)) return CHex(hex) } // U32ToHex trans C.uint32_t to C.MMRGBHex func U32ToHex(hex C.uint32_t) C.MMRGBHex { return C.MMRGBHex(hex) } // U8ToHex trans *C.uint8_t to C.MMRGBHex func U8ToHex(hex *C.uint8_t) C.MMRGBHex { return C.MMRGBHex(*hex) } // PadHex trans C.MMRGBHex to string func PadHex(hex C.MMRGBHex) string { color := C.pad_hex(hex) gcolor := C.GoString(color) C.free(unsafe.Pointer(color)) return gcolor } // PadHexs trans CHex to string func PadHexs(hex CHex) string { return PadHex(C.MMRGBHex(hex)) } // HexToRgb trans hex to rgb func HexToRgb(hex uint32) *C.uint8_t { return C.color_hex_to_rgb(C.uint32_t(hex)) } // RgbToHex trans rgb to hex func RgbToHex(r, g, b uint8) C.uint32_t { return C.color_rgb_to_hex(C.uint8_t(r), C.uint8_t(g), C.uint8_t(b)) } // GetPxColor get the pixel color return C.MMRGBHex func GetPxColor(x, y int, displayId ...int) C.MMRGBHex { cx := C.int32_t(x) cy := C.int32_t(y) display := displayIdx(displayId...) color := C.get_px_color(cx, cy, C.int32_t(display)) return color } // GetPixelColor get the pixel color return string func GetPixelColor(x, y int, displayId ...int) string { return PadHex(GetPxColor(x, y, displayId...)) } // GetLocationColor get the location pos's color func GetLocationColor(displayId ...int) string { x, y := Location() return GetPixelColor(x, y, displayId...) } // IsMain is main display func IsMain(displayId int) bool { return displayId == GetMainId() } func displayIdx(id ...int) int { display := -1 if DisplayID != -1 { display = DisplayID } if len(id) > 0 { display = id[0] } return display } func getNumDisplays() int { return int(C.get_num_displays()) } // GetHWNDByPid get the hwnd by pid func GetHWNDByPid(pid int) int { return int(C.get_hwnd_by_pid(C.uintptr(pid))) } // SysScale get the sys scale func SysScale(displayId ...int) float64 { display := displayIdx(displayId...) s := C.sys_scale(C.int32_t(display)) return float64(s) } // Scaled get the screen scaled return scale size func Scaled(x int, displayId ...int) int { f := ScaleF(displayId...) return Scaled0(x, f) } // Scaled0 return int(x * f) func Scaled0(x int, f float64) int { return int(float64(x) * f) } // Scaled1 return int(x / f) func Scaled1(x int, f float64) int { return int(float64(x) / f) } // GetScreenSize get the screen size func GetScreenSize() (int, int) { size := C.getMainDisplaySize() return int(size.w), int(size.h) } // GetScreenRect get the screen rect (x, y, w, h) func GetScreenRect(displayId ...int) Rect { display := -1 if len(displayId) > 0 { display = displayId[0] } rect := C.getScreenRect(C.int32_t(display)) x, y, w, h := int(rect.origin.x), int(rect.origin.y), int(rect.size.w), int(rect.size.h) if runtime.GOOS == "windows" { // f := ScaleF(displayId...) f := ScaleF() x, y, w, h = Scaled0(x, f), Scaled0(y, f), Scaled0(w, f), Scaled0(h, f) } return Rect{ Point{X: x, Y: y}, Size{W: w, H: h}, } } // GetScaleSize get the screen scale size func GetScaleSize(displayId ...int) (int, int) { x, y := GetScreenSize() f := ScaleF(displayId...) return int(float64(x) * f), int(float64(y) * f) } // CaptureScreen capture the screen return bitmap(c struct), // use `defer robotgo.FreeBitmap(bitmap)` to free the bitmap // // robotgo.CaptureScreen(x, y, w, h int) func CaptureScreen(args ...int) CBitmap { var x, y, w, h C.int32_t displayId := -1 if DisplayID != -1 { displayId = DisplayID } if len(args) > 4 { displayId = args[4] } if len(args) > 3 { x = C.int32_t(args[0]) y = C.int32_t(args[1]) w = C.int32_t(args[2]) h = C.int32_t(args[3]) } else { // Get the main screen rect. rect := GetScreenRect(displayId) if runtime.GOOS == "windows" { x = C.int32_t(rect.X) y = C.int32_t(rect.Y) } w = C.int32_t(rect.W) h = C.int32_t(rect.H) } isPid := 0 if NotPid || len(args) > 5 { isPid = 1 } bit := C.capture_screen(x, y, w, h, C.int32_t(displayId), C.int8_t(isPid)) return CBitmap(bit) } // CaptureGo capture the screen and return bitmap(go struct) func CaptureGo(args ...int) Bitmap { bit := CaptureScreen(args...) defer FreeBitmap(bit) return ToBitmap(bit) } // CaptureImg capture the screen and return image.Image, error func CaptureImg(args ...int) (image.Image, error) { bit := CaptureScreen(args...) if bit == nil { return nil, errors.New("Capture image not found.") } defer FreeBitmap(bit) return ToImage(bit), nil } // FreeBitmap free and dealloc the C bitmap func FreeBitmap(bitmap CBitmap) { // C.destroyMMBitmap(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 func ToMMBitmapRef(bit CBitmap) C.MMBitmapRef { return C.MMBitmapRef(bit) } // ToBitmap trans C.MMBitmapRef to Bitmap func ToBitmap(bit CBitmap) Bitmap { bitmap := Bitmap{ ImgBuf: (*uint8)(bit.imageBuffer), Width: int(bit.width), Height: int(bit.height), Bytewidth: int(bit.bytewidth), BitsPixel: uint8(bit.bitsPerPixel), BytesPerPixel: uint8(bit.bytesPerPixel), } return bitmap } // ToCBitmap trans Bitmap to C.MMBitmapRef func ToCBitmap(bit Bitmap) CBitmap { cbitmap := C.createMMBitmap_c( (*C.uint8_t)(bit.ImgBuf), C.int32_t(bit.Width), C.int32_t(bit.Height), C.int32_t(bit.Bytewidth), C.uint8_t(bit.BitsPixel), C.uint8_t(bit.BytesPerPixel), ) return CBitmap(cbitmap) } // ToImage convert C.MMBitmapRef to standard image.Image func ToImage(bit CBitmap) image.Image { return ToRGBA(bit) } // ToRGBA convert C.MMBitmapRef to standard image.RGBA func ToRGBA(bit CBitmap) *image.RGBA { bmp1 := ToBitmap(bit) return ToRGBAGo(bmp1) } // ImgToCBitmap trans image.Image to CBitmap func ImgToCBitmap(img image.Image) CBitmap { return ToCBitmap(ImgToBitmap(img)) } // ByteToCBitmap trans []byte to CBitmap func ByteToCBitmap(by []byte) CBitmap { img, _ := ByteToImg(by) return ImgToCBitmap(img) } // SetXDisplayName set XDisplay name (Linux) func SetXDisplayName(name string) error { cname := C.CString(name) str := C.set_XDisplay_name(cname) C.free(unsafe.Pointer(cname)) return toErr(str) } // GetXDisplayName get XDisplay name (Linux) func GetXDisplayName() string { name := C.get_XDisplay_name() gname := C.GoString(name) C.free(unsafe.Pointer(name)) return gname } // CloseMainDisplay close the main X11 display func CloseMainDisplay() { C.close_main_display() } // Deprecated: use the ScaledF(), // // ScaleX get the primary display horizontal DPI scale factor, drop func ScaleX() int { return int(C.scaleX()) } /* .___ ___. ______ __ __ _______. _______ | \/ | / __ \ | | | | / || ____| | \ / | | | | | | | | | | (----`| |__ | |\/| | | | | | | | | | \ \ | __| | | | | | `--' | | `--' | .----) | | |____ |__| |__| \______/ \______/ |_______/ |_______| */ // CheckMouse check the mouse button func CheckMouse(btn string) C.MMMouseButton { // button = args[0].(C.MMMouseButton) m1 := map[string]C.MMMouseButton{ "left": C.LEFT_BUTTON, "center": C.CENTER_BUTTON, "right": C.RIGHT_BUTTON, "wheelDown": C.WheelDown, "wheelUp": C.WheelUp, "wheelLeft": C.WheelLeft, "wheelRight": C.WheelRight, } if v, ok := m1[btn]; ok { return v } return C.LEFT_BUTTON } // MoveScale calculate the os scale factor x, y func MoveScale(x, y int, displayId ...int) (int, int) { if Scale || runtime.GOOS == "windows" { f := ScaleF() x, y = Scaled1(x, f), Scaled1(y, f) } return x, y } // Move move the mouse to (x, y) // // Examples: // // robotgo.MouseSleep = 100 // 100 millisecond // robotgo.Move(10, 10) func Move(x, y int, displayId ...int) { x, y = MoveScale(x, y, displayId...) cx := C.int32_t(x) cy := C.int32_t(y) C.moveMouse(C.MMPointInt32Make(cx, cy)) MilliSleep(MouseSleep) } // Deprecated: use the DragSmooth(), // // Drag drag the mouse to (x, y), // It's not valid now, use the DragSmooth() func Drag(x, y int, args ...string) { x, y = MoveScale(x, y) var button C.MMMouseButton = C.LEFT_BUTTON cx := C.int32_t(x) cy := C.int32_t(y) if len(args) > 0 { button = CheckMouse(args[0]) } C.dragMouse(C.MMPointInt32Make(cx, cy), button) MilliSleep(MouseSleep) } // DragSmooth drag the mouse like smooth to (x, y) // // Examples: // // robotgo.DragSmooth(10, 10) func DragSmooth(x, y int, args ...interface{}) { Toggle("left") MilliSleep(50) MoveSmooth(x, y, args...) Toggle("left", "up") } // MoveSmooth move the mouse smooth, // moves mouse to x, y human like, with the mouse button up. // // robotgo.MoveSmooth(x, y int, low, high float64, mouseDelay int) // // Examples: // // robotgo.MoveSmooth(10, 10) // robotgo.MoveSmooth(10, 10, 1.0, 2.0) func MoveSmooth(x, y int, args ...interface{}) bool { // if runtime.GOOS == "windows" { // f := ScaleF() // x, y = Scaled0(x, f), Scaled0(y, f) // } x, y = MoveScale(x, y) cx := C.int32_t(x) cy := C.int32_t(y) var ( mouseDelay = 1 low C.double high C.double ) if len(args) > 2 { mouseDelay = args[2].(int) } if len(args) > 1 { low = C.double(args[0].(float64)) high = C.double(args[1].(float64)) } else { low = 1.0 high = 3.0 } cbool := C.smoothlyMoveMouse(C.MMPointInt32Make(cx, cy), low, high) MilliSleep(MouseSleep + mouseDelay) return bool(cbool) } // MoveArgs get the mouse relative args func MoveArgs(x, y int) (int, int) { mx, my := Location() mx = mx + x my = my + y return mx, my } // MoveRelative move mouse with relative func MoveRelative(x, y int) { Move(MoveArgs(x, y)) } // MoveSmoothRelative move mouse smooth with relative func MoveSmoothRelative(x, y int, args ...interface{}) { mx, my := MoveArgs(x, y) MoveSmooth(mx, my, args...) } // Location get the mouse location position return x, y func Location() (int, int) { pos := C.location() x := int(pos.x) y := int(pos.y) if Scale || runtime.GOOS == "windows" { f := ScaleF() x, y = Scaled0(x, f), Scaled0(y, f) } return x, y } // Click click the mouse button // // robotgo.Click(button string, double bool) // // Examples: // // robotgo.Click() // default is left button // robotgo.Click("right") // robotgo.Click("wheelLeft") func Click(args ...interface{}) { var ( button C.MMMouseButton = C.LEFT_BUTTON double bool ) if len(args) > 0 { button = CheckMouse(args[0].(string)) } if len(args) > 1 { double = args[1].(bool) } if !double { C.clickMouse(button) } else { C.doubleClick(button) } MilliSleep(MouseSleep) } // MoveClick move and click the mouse // // robotgo.MoveClick(x, y int, button string, double bool) // // Examples: // // robotgo.MouseSleep = 100 // robotgo.MoveClick(10, 10) func MoveClick(x, y int, args ...interface{}) { Move(x, y) MilliSleep(50) Click(args...) } // MovesClick move smooth and click the mouse // // use the `robotgo.MouseSleep = 100` func MovesClick(x, y int, args ...interface{}) { MoveSmooth(x, y) MilliSleep(50) Click(args...) } // Toggle toggle the mouse, support button: // // "left", "center", "right", // "wheelDown", "wheelUp", "wheelLeft", "wheelRight" // // Examples: // // robotgo.Toggle("left") // default is down // robotgo.Toggle("left", "up") func Toggle(key ...interface{}) error { var button C.MMMouseButton = C.LEFT_BUTTON if len(key) > 0 { button = CheckMouse(key[0].(string)) } down := true if len(key) > 1 && key[1].(string) == "up" { down = false } C.toggleMouse(C.bool(down), button) if len(key) > 2 { MilliSleep(MouseSleep) } return nil } // MouseDown send mouse down event func MouseDown(key ...interface{}) error { return Toggle(key...) } // MouseUp send mouse up event func MouseUp(key ...interface{}) error { if len(key) <= 0 { key = append(key, "left") } return Toggle(append(key, "up")...) } // Scroll scroll the mouse to (x, y) // // robotgo.Scroll(x, y, msDelay int) // // Examples: // // robotgo.Scroll(10, 10) func Scroll(x, y int, args ...int) { var msDelay = 10 if len(args) > 0 { msDelay = args[0] } cx := C.int(x) cy := C.int(y) C.scrollMouseXY(cx, cy) MilliSleep(MouseSleep + msDelay) } // ScrollDir scroll the mouse with direction to (x, "up") // supported: "up", "down", "left", "right" // // Examples: // // robotgo.ScrollDir(10, "down") // robotgo.ScrollDir(10, "up") func ScrollDir(x int, direction ...interface{}) { d := "down" if len(direction) > 0 { d = direction[0].(string) } if d == "down" { Scroll(0, -x) } if d == "up" { Scroll(0, x) } if d == "left" { Scroll(x, 0) } if d == "right" { Scroll(-x, 0) } // MilliSleep(MouseSleep) } // ScrollSmooth scroll the mouse smooth, // default scroll 5 times and sleep 100 millisecond // // robotgo.ScrollSmooth(toy, num, sleep, tox) // // Examples: // // robotgo.ScrollSmooth(-10) // robotgo.ScrollSmooth(-10, 6, 200, -10) func ScrollSmooth(to int, args ...int) { i := 0 num := 5 if len(args) > 0 { num = args[0] } tm := 100 if len(args) > 1 { tm = args[1] } tox := 0 if len(args) > 2 { tox = args[2] } for { Scroll(tox, to) MilliSleep(tm) i++ if i == num { break } } MilliSleep(MouseSleep) } // ScrollRelative scroll mouse with relative // // Examples: // // robotgo.ScrollRelative(10, 10) func ScrollRelative(x, y int, args ...int) { mx, my := MoveArgs(x, y) Scroll(mx, my, args...) } /* ____ __ ____ __ .__ __. _______ ______ ____ __ ____ \ \ / \ / / | | | \ | | | \ / __ \ \ \ / \ / / \ \/ \/ / | | | \| | | .--. | | | | \ \/ \/ / \ / | | | . ` | | | | | | | | \ / \ /\ / | | | |\ | | '--' | `--' | \ /\ / \__/ \__/ |__| |__| \__| |_______/ \______/ \__/ \__/ */ func alertArgs(args ...string) (string, string) { var ( defaultBtn = "Ok" cancelBtn = "Cancel" ) if len(args) > 0 { defaultBtn = args[0] } if len(args) > 1 { cancelBtn = args[1] } return defaultBtn, cancelBtn } func showAlert(title, msg string, args ...string) bool { defaultBtn, cancelBtn := alertArgs(args...) cTitle := C.CString(title) cMsg := C.CString(msg) defaultButton := C.CString(defaultBtn) cancelButton := C.CString(cancelBtn) cbool := C.showAlert(cTitle, cMsg, defaultButton, cancelButton) ibool := int(cbool) C.free(unsafe.Pointer(cTitle)) C.free(unsafe.Pointer(cMsg)) C.free(unsafe.Pointer(defaultButton)) C.free(unsafe.Pointer(cancelButton)) return ibool == 0 } // IsValid valid the window func IsValid() bool { abool := C.is_valid() gbool := bool(abool) return gbool } // SetActive set the window active func SetActive(win Handle) { SetActiveC(C.MData(win)) } // SetActiveC set the window active func SetActiveC(win C.MData) { C.set_active(win) } // GetActive get the active window func GetActive() Handle { return Handle(GetActiveC()) } // GetActiveC get the active window func GetActiveC() C.MData { mdata := C.get_active() // fmt.Println("active----", mdata) return mdata } // MinWindow set the window min func MinWindow(pid int, args ...interface{}) { var ( state = true isPid int ) if len(args) > 0 { state = args[0].(bool) } if len(args) > 1 || NotPid { isPid = 1 } C.min_window(C.uintptr(pid), C.bool(state), C.int8_t(isPid)) } // MaxWindow set the window max func MaxWindow(pid int, args ...interface{}) { var ( state = true isPid int ) if len(args) > 0 { state = args[0].(bool) } if len(args) > 1 || NotPid { isPid = 1 } C.max_window(C.uintptr(pid), C.bool(state), C.int8_t(isPid)) } // CloseWindow close the window func CloseWindow(args ...int) { if len(args) <= 0 { C.close_main_window() return } var pid, isPid int if len(args) > 0 { pid = args[0] } if len(args) > 1 || NotPid { isPid = 1 } C.close_window_by_PId(C.uintptr(pid), C.int8_t(isPid)) } // SetHandle set the window handle func SetHandle(hwnd int) { chwnd := C.uintptr(hwnd) C.setHandle(chwnd) } // SetHandlePid set the window handle by pid func SetHandlePid(pid int, args ...int) { var isPid int if len(args) > 0 || NotPid { isPid = 1 } C.set_handle_pid_mData(C.uintptr(pid), C.int8_t(isPid)) } // GetHandById get handle mdata by id func GetHandById(id int, args ...int) Handle { isPid := 1 if len(args) > 0 { isPid = args[0] } return GetHandByPid(id, isPid) } // GetHandByPid get handle mdata by pid func GetHandByPid(pid int, args ...int) Handle { return Handle(GetHandByPidC(pid, args...)) } // Deprecated: use the GetHandByPid(), // // GetHandPid get handle mdata by pid func GetHandPid(pid int, args ...int) Handle { return GetHandByPid(pid, args...) } // GetHandByPidC get handle mdata by pid func GetHandByPidC(pid int, args ...int) C.MData { var isPid int if len(args) > 0 || NotPid { isPid = 1 } return C.set_handle_pid(C.uintptr(pid), C.int8_t(isPid)) } // GetHandle get the window handle func GetHandle() int { hwnd := C.get_handle() ghwnd := int(hwnd) // fmt.Println("gethwnd---", ghwnd) return ghwnd } // Deprecated: use the GetHandle(), // // # GetBHandle get the window handle, Wno-deprecated // // This function will be removed in version v1.0.0 func GetBHandle() int { tt.Drop("GetBHandle", "GetHandle") hwnd := C.b_get_handle() ghwnd := int(hwnd) //fmt.Println("gethwnd---", ghwnd) return ghwnd } func cgetTitle(pid, isPid int) string { title := C.get_title_by_pid(C.uintptr(pid), C.int8_t(isPid)) gtitle := C.GoString(title) return gtitle } // GetTitle get the window title return string // // Examples: // // fmt.Println(robotgo.GetTitle()) // // ids, _ := robotgo.FindIds() // robotgo.GetTitle(ids[0]) func GetTitle(args ...int) string { if len(args) <= 0 { title := C.get_main_title() gtitle := C.GoString(title) return gtitle } if len(args) > 1 { return internalGetTitle(args[0], args[1]) } return internalGetTitle(args[0]) } // GetPid get the process id return int32 func GetPid() int { pid := C.get_PID() return int(pid) } // internalGetBounds get the window bounds func internalGetBounds(pid, isPid int) (int, int, int, int) { bounds := C.get_bounds(C.uintptr(pid), C.int8_t(isPid)) return int(bounds.X), int(bounds.Y), int(bounds.W), int(bounds.H) } // internalGetClient get the window client bounds func internalGetClient(pid, isPid int) (int, int, int, int) { bounds := C.get_client(C.uintptr(pid), C.int8_t(isPid)) return int(bounds.X), int(bounds.Y), int(bounds.W), int(bounds.H) } // Is64Bit determine whether the sys is 64bit func Is64Bit() bool { b := C.Is64Bit() return bool(b) } func internalActive(pid, isPid int) { C.active_PID(C.uintptr(pid), C.int8_t(isPid)) } // ActivePid active the window by Pid, // If args[0] > 0 on the Windows platform via a window handle to active // func ActivePid(pid int32, args ...int) { // var isPid int // if len(args) > 0 { // isPid = args[0] // } // C.active_PID(C.uintptr(pid), C.uintptr(isPid)) // } // ActiveName active the window by name // // Examples: // // robotgo.ActiveName("chrome") func ActiveName(name string) error { pids, err := FindIds(name) if err == nil && len(pids) > 0 { return ActivePid(pids[0]) } return err }