mirror of
https://github.com/go-vgo/robotgo.git
synced 2025-06-01 14:43:55 +00:00
Compare commits
109 Commits
v1.0.0-rc1
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a8c387a070 | ||
![]() |
3eef3b5879 | ||
![]() |
b731094f61 | ||
![]() |
8d4679db07 | ||
![]() |
02c668a946 | ||
![]() |
5c2864485d | ||
![]() |
f101b10497 | ||
![]() |
73c07dc991 | ||
![]() |
fc47bc8216 | ||
![]() |
912ddcbfe4 | ||
![]() |
57b5e5bca2 | ||
![]() |
8031f7f526 | ||
![]() |
36bc85ad19 | ||
![]() |
5fc2bd4c73 | ||
![]() |
47abfac5ee | ||
![]() |
df0731c4df | ||
![]() |
03432155c1 | ||
![]() |
6a1f060a8c | ||
![]() |
e924f25fe1 | ||
![]() |
d300eedf54 | ||
![]() |
c07f3f0171 | ||
![]() |
0b18fa5058 | ||
![]() |
471f7ba05f | ||
![]() |
a84a195c4c | ||
![]() |
c8df366f89 | ||
![]() |
70f811ce53 | ||
![]() |
ecc260ea31 | ||
![]() |
78d01703b8 | ||
![]() |
47cde13dab | ||
![]() |
8db59aac2d | ||
![]() |
217d6cf1f1 | ||
![]() |
75fd24ea0a | ||
![]() |
bed6776ca2 | ||
![]() |
1923d7bb48 | ||
![]() |
ead43d062e | ||
![]() |
3258566802 | ||
![]() |
0de26ecee4 | ||
![]() |
c48e3d072c | ||
![]() |
b1ad7db6be | ||
![]() |
0110b85d40 | ||
![]() |
3e5b10f720 | ||
![]() |
cb51e2aa10 | ||
![]() |
85f2702683 | ||
![]() |
5b9871b063 | ||
![]() |
b201ab9f80 | ||
![]() |
d3e364fa26 | ||
![]() |
1f437d12e4 | ||
![]() |
c5110d0ac8 | ||
![]() |
f98b4c52bd | ||
![]() |
f1db2ede4a | ||
![]() |
d90493e63e | ||
![]() |
63eb594ea5 | ||
![]() |
8a990ac042 | ||
![]() |
bf1758b424 | ||
![]() |
9424b71a73 | ||
![]() |
6c137427db | ||
![]() |
ffbf4f875b | ||
![]() |
05c54c6f25 | ||
![]() |
3171c5bdff | ||
![]() |
b718cf4a8c | ||
![]() |
bfc28d12fa | ||
![]() |
e9421b58b6 | ||
![]() |
4d780b9908 | ||
![]() |
39818d41fa | ||
![]() |
eacf74f488 | ||
![]() |
61b77ce3e1 | ||
![]() |
01e4fffcb8 | ||
![]() |
e2f5f54804 | ||
![]() |
f22f063926 | ||
![]() |
722feb7ba3 | ||
![]() |
dbf0d84f12 | ||
![]() |
b8a6b1778e | ||
![]() |
a780825c09 | ||
![]() |
de675b4dd2 | ||
![]() |
ef191f2dfd | ||
![]() |
44b2715de0 | ||
![]() |
90f41269da | ||
![]() |
8a5ca54915 | ||
![]() |
5b0ac98ef3 | ||
![]() |
c2b5c864d2 | ||
![]() |
0c4055bfee | ||
![]() |
af32110521 | ||
![]() |
5c3cbd6e17 | ||
![]() |
3182fb9d73 | ||
![]() |
6fa2f418fa | ||
![]() |
8e7a413ec6 | ||
![]() |
8ce3a5dff0 | ||
![]() |
8ea126d35b | ||
![]() |
c62f7fd81e | ||
![]() |
92fd032685 | ||
![]() |
ffcf6b26cd | ||
![]() |
451bb91209 | ||
![]() |
cbca6d08c7 | ||
![]() |
d249cdcd9e | ||
![]() |
4140463ed1 | ||
![]() |
186bceb9d0 | ||
![]() |
01212c5684 | ||
![]() |
07dd53a897 | ||
![]() |
9afa311121 | ||
![]() |
94be6c56c1 | ||
![]() |
e0583e83ec | ||
![]() |
6a2ffab625 | ||
![]() |
679aef0f70 | ||
![]() |
cc6f1934f9 | ||
![]() |
4bdacf4187 | ||
![]() |
c8d35acd24 | ||
![]() |
e4848b4608 | ||
![]() |
f47571eaae | ||
![]() |
dd149367b3 |
@ -5,7 +5,7 @@ jobs:
|
||||
docker:
|
||||
# using custom image, see .circleci/images/primary/Dockerfile
|
||||
# - image: govgo/robotgoci:1.10.3
|
||||
- image: golang:1.19.4
|
||||
- image: golang:1.23.0
|
||||
working_directory: /gopath/src/github.com/go-vgo/robotgo
|
||||
steps:
|
||||
- checkout
|
||||
|
@ -1,5 +1,5 @@
|
||||
# FROM golang:1.10.1
|
||||
FROM golang:1.19.4-stretch AS build
|
||||
FROM golang:1.24.2-stretch AS build
|
||||
# FROM govgo/go:1.11.1
|
||||
|
||||
RUN apt update && apt install -y --no-install-recommends \
|
||||
|
4
.github/workflows/go.yml
vendored
4
.github/workflows/go.yml
vendored
@ -10,10 +10,10 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Set up Go 1.19
|
||||
- name: Set up Go 1.24.0
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: 1.24.0
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
|
@ -24,7 +24,7 @@ This process gives everyone a chance to validate the design, helps prevent dupli
|
||||
|
||||
## Testing redux
|
||||
|
||||
Before sending code out for review, run all the tests for the whole tree to make sure the changes don't break other usage and keep the compatibility on upgrade. You must be test on Mac, Windows, Linux and other. You should install the CLI for Circle CI, as we are using the server for continous testing.
|
||||
Before sending code out for review, run all the tests for the whole tree to make sure the changes don't break other usage and keep the compatibility on upgrade. You must be test on Mac, Windows, Linux and other. You should install the CLI for Circle CI, as we are using the server for continuous testing.
|
||||
|
||||
## Code review
|
||||
|
||||
|
115
README.md
115
README.md
@ -10,7 +10,7 @@
|
||||
[](https://travis-ci.org/go-vgo/robotgo)
|
||||

|
||||
[](https://goreportcard.com/report/github.com/go-vgo/robotgo)
|
||||
[](https://godoc.org/github.com/go-vgo/robotgo)
|
||||
[](https://pkg.go.dev/github.com/go-vgo/robotgo?tab=doc)
|
||||
[](https://github.com/go-vgo/robotgo/releases/latest)
|
||||
[](https://gitter.im/go-vgo/robotgo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
@ -29,7 +29,8 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x8
|
||||
- [Installation](#installation)
|
||||
- [Update](#update)
|
||||
- [Examples](#examples)
|
||||
- [Cross-Compiling](#crosscompiling)
|
||||
- [Type Conversion and keys](https://github.com/go-vgo/robotgo/blob/master/docs/keys.md)
|
||||
- [Cross-Compiling](https://github.com/go-vgo/robotgo/blob/master/docs/install.md#crosscompiling)
|
||||
- [Authors](#authors)
|
||||
- [Plans](#plans)
|
||||
- [Donate](#donate)
|
||||
@ -60,21 +61,31 @@ GCC
|
||||
```
|
||||
|
||||
#### For MacOS:
|
||||
```
|
||||
brew install go
|
||||
```
|
||||
|
||||
Xcode Command Line Tools (And Privacy setting: [#277](https://github.com/go-vgo/robotgo/issues/277) )
|
||||
Xcode Command Line Tools (And Privacy setting: [#277](https://github.com/go-vgo/robotgo/issues/277))
|
||||
|
||||
```
|
||||
xcode-select --install
|
||||
```
|
||||
|
||||
#### For Windows:
|
||||
```
|
||||
winget install Golang.go
|
||||
```
|
||||
|
||||
[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended)
|
||||
```
|
||||
winget install MartinStorsjo.LLVM-MinGW.UCRT
|
||||
```
|
||||
|
||||
Or [MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) or others Mingw [llvm-mingw](https://github.com/mstorsjo/llvm-mingw);
|
||||
|
||||
Download the Mingw, then set system environment variables `C:\mingw64\bin` to the Path.
|
||||
[Set environment variables to run GCC from command line](https://www.youtube.com/results?search_query=Set+environment+variables+to+run+GCC+from+command+line).
|
||||
|
||||
`Or the other GCC (But you should compile the "libpng" with yourself when use the bitmap.)`
|
||||
`Or the other GCC` (But you should compile the "libpng" with yourself when use the [bitmap](https://github.com/vcaesar/bitmap).)
|
||||
|
||||
#### For everything else:
|
||||
|
||||
@ -83,52 +94,55 @@ GCC
|
||||
|
||||
X11 with the XTest extension (the Xtst library)
|
||||
|
||||
"Clipboard": xsel xclip
|
||||
|
||||
"Bitmap":
|
||||
|
||||
libpng (Just used by bitmap)
|
||||
"Bitmap": libpng (Just used by the "bitmap".)
|
||||
|
||||
"Event":
|
||||
"Event-Gohook": xcb, xkb, libxkbcommon (Just used by the "hook".)
|
||||
|
||||
xcb, xkb, libxkbcommon
|
||||
|
||||
"Clipboard":
|
||||
|
||||
xsel xclip
|
||||
```
|
||||
|
||||
##### Ubuntu:
|
||||
|
||||
```yml
|
||||
# sudo apt install golang
|
||||
sudo snap install go --classic
|
||||
|
||||
# gcc
|
||||
sudo apt install gcc libc6-dev
|
||||
|
||||
# x11
|
||||
sudo apt install libx11-dev xorg-dev libxtst-dev
|
||||
|
||||
# Clipboard
|
||||
sudo apt install xsel xclip
|
||||
|
||||
#
|
||||
# Bitmap
|
||||
sudo apt install libpng++-dev
|
||||
|
||||
# Hook
|
||||
# GoHook
|
||||
sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev libxkbcommon-dev
|
||||
|
||||
# Clipboard
|
||||
sudo apt install xsel xclip
|
||||
```
|
||||
|
||||
##### Fedora:
|
||||
|
||||
```yml
|
||||
# x11
|
||||
sudo dnf install libXtst-devel
|
||||
|
||||
# Bitmap
|
||||
sudo dnf install libpng-devel
|
||||
|
||||
# Hook
|
||||
sudo dnf install libxkbcommon-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel
|
||||
|
||||
# Clipboard
|
||||
sudo dnf install xsel xclip
|
||||
|
||||
#
|
||||
# Bitmap
|
||||
sudo dnf install libpng-devel
|
||||
|
||||
# GoHook
|
||||
sudo dnf install libxkbcommon-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel
|
||||
|
||||
```
|
||||
|
||||
## Installation:
|
||||
@ -164,11 +178,18 @@ Note go1.10.x C file compilation cache problem, [golang #24355](https://github.c
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-vgo/robotgo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
robotgo.MouseSleep = 100
|
||||
robotgo.MouseSleep = 300
|
||||
|
||||
robotgo.Move(100, 100)
|
||||
fmt.Println(robotgo.Location())
|
||||
robotgo.Move(100, -200) // multi screen supported
|
||||
robotgo.MoveSmooth(120, -150)
|
||||
fmt.Println(robotgo.Location())
|
||||
|
||||
robotgo.ScrollDir(10, "up")
|
||||
robotgo.ScrollDir(20, "right")
|
||||
@ -243,6 +264,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-vgo/robotgo"
|
||||
"github.com/vcaesar/imgo"
|
||||
@ -267,13 +289,18 @@ func main() {
|
||||
num := robotgo.DisplaysNum()
|
||||
for i := 0; i < num; i++ {
|
||||
robotgo.DisplayID = i
|
||||
img1 := robotgo.CaptureImg()
|
||||
img1, _ := robotgo.CaptureImg()
|
||||
path1 := "save_" + strconv.Itoa(i)
|
||||
robotgo.Save(img1, path1+".png")
|
||||
robotgo.SaveJpeg(img1, path1+".jpeg", 50)
|
||||
|
||||
img2 := robotgo.CaptureImg(10, 10, 20, 20)
|
||||
img2, _ := robotgo.CaptureImg(10, 10, 20, 20)
|
||||
robotgo.Save(img2, "test_"+strconv.Itoa(i)+".png")
|
||||
|
||||
x, y, w, h := robotgo.GetDisplayBounds(i)
|
||||
img3, err := robotgo.CaptureImg(x, y, w, h)
|
||||
fmt.Println("Capture error: ", err)
|
||||
robotgo.Save(img3, path1+"_1.png")
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -353,8 +380,8 @@ func opencv() {
|
||||
// bit1 := robotgo.CaptureScreen(10, 10, 30, 30)
|
||||
// img1 := robotgo.ToImage(bit1)
|
||||
// defer robotgo.FreeBitmapArr(bit0, bit1)
|
||||
img := robotgo.CaptureImg()
|
||||
img1 := robotgo.CaptureImg(10, 10, 30, 30)
|
||||
img, _ := robotgo.CaptureImg()
|
||||
img1, _ := robotgo.CaptureImg(10, 10, 30, 30)
|
||||
|
||||
fmt.Print("gcv find image: ")
|
||||
fmt.Println(gcv.FindImg(img1, img))
|
||||
@ -487,40 +514,6 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
## CrossCompiling
|
||||
|
||||
##### Windows64 to windows32
|
||||
|
||||
```Go
|
||||
SET CGO_ENABLED=1
|
||||
SET GOARCH=386
|
||||
go build main.go
|
||||
```
|
||||
|
||||
#### Other to windows
|
||||
|
||||
Install Requirements (Ubuntu, Just used by bitmap.):
|
||||
|
||||
```bash
|
||||
sudo apt install gcc-multilib
|
||||
sudo apt install gcc-mingw-w64
|
||||
# fix err: zlib.h: No such file or directory
|
||||
sudo apt install libz-mingw-w64-dev
|
||||
```
|
||||
|
||||
Build the binary:
|
||||
|
||||
```Go
|
||||
GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -x ./
|
||||
```
|
||||
|
||||
```
|
||||
// CC=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\gcc.exe
|
||||
// CXX=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\g++.exe
|
||||
```
|
||||
|
||||
Some discussions and questions, please see [issues/228](https://github.com/go-vgo/robotgo/issues/228), [issues/143](https://github.com/go-vgo/robotgo/issues/143).
|
||||
|
||||
## Authors
|
||||
|
||||
- [The author is vz](https://github.com/vcaesar)
|
||||
|
@ -34,7 +34,7 @@ environment:
|
||||
PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH%
|
||||
# - COMPILER: MINGW_W64
|
||||
# ARCHITECTURE: x64
|
||||
GOVERSION: 1.19.4
|
||||
GOVERSION: 1.23.0
|
||||
# GOPATH: c:\gopath
|
||||
|
||||
# scripts that run after cloning repository
|
||||
|
@ -3,7 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
|
||||
Package clipboard read/write on clipboard
|
||||
*/
|
||||
package clipboard
|
||||
|
33
docs/install.md
Normal file
33
docs/install.md
Normal file
@ -0,0 +1,33 @@
|
||||
## CrossCompiling
|
||||
|
||||
##### Windows64 to windows32
|
||||
|
||||
```Go
|
||||
SET CGO_ENABLED=1
|
||||
SET GOARCH=386
|
||||
go build main.go
|
||||
```
|
||||
|
||||
#### Other to windows
|
||||
|
||||
Install Requirements (Ubuntu):
|
||||
|
||||
```bash
|
||||
sudo apt install gcc-multilib
|
||||
sudo apt install gcc-mingw-w64
|
||||
# fix err: zlib.h: No such file or directory, Just used by bitmap.
|
||||
sudo apt install libz-mingw-w64-dev
|
||||
```
|
||||
|
||||
Build the binary:
|
||||
|
||||
```Go
|
||||
GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -x ./
|
||||
```
|
||||
|
||||
```
|
||||
// CC=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\gcc.exe
|
||||
// CXX=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\g++.exe
|
||||
```
|
||||
|
||||
Some discussions and questions, please see [issues/228](https://github.com/go-vgo/robotgo/issues/228), [issues/143](https://github.com/go-vgo/robotgo/issues/143).
|
24
docs/keys.md
24
docs/keys.md
@ -1,3 +1,25 @@
|
||||
## Type Conversion
|
||||
|
||||
| | type conversion | func |
|
||||
| --- | --------------------------------- | ----------------------- |
|
||||
| \* | robotgo.Bitmap -> robotgo.CBitmap | robotgo.ToCBitmap() |
|
||||
| | robotgo.Bitmap -> \*image.RGBA | robotgo.ToRGBAGo() |
|
||||
| \* | robotgo.CBitmap -> C.MMBitmapRef | robotgo.ToMMBitmapRef() |
|
||||
| | robotgo.CBitmap -> robotgo.Bitmap | robotgo.ToBitmap() |
|
||||
| | robotgo.CBitmap -> image.Image | robotgo.ToImage() |
|
||||
| | robotgo.CBitmap -> \*image.RGBA | robotgo.ToRGBA() |
|
||||
| \* | C.MMBitmapRef -> robotgo.CBitmap | robotgo.CBitmap() |
|
||||
| \* | image.Image -> robotgo.Bitmap | robotgo.ImgToBitmap() |
|
||||
| | image.Image -> robotgo.CBitmap | robotgo.ImgToCBitmap() |
|
||||
| | image.Image -> []byte | robotgo.ToByteImg() |
|
||||
| | image.Image -> string | robotgo.ToStringImg() |
|
||||
| \* | \*image.RGBA -> robotgo.Bitmap | robotgo.RGBAToBitmap() |
|
||||
| \* | []byte -> image.Image | robotgo.ByteToImg() |
|
||||
| | []byte-> robotgo.CBitmap | robotgo.ByteToCBitmap() |
|
||||
| | []byte -> string | string() |
|
||||
| \* | string -> image.Image | robotgo.StrToImg() |
|
||||
| | string -> byte | []byte() |
|
||||
|
||||
# Keys
|
||||
|
||||
```Go
|
||||
@ -118,4 +140,4 @@
|
||||
"lights_kbd_toggle" Toggle keyboard backlight on/off No Windows support
|
||||
"lights_kbd_up" Turn up keyboard backlight brightness No Windows support
|
||||
"lights_kbd_down" Turn down keyboard backlight brightness No Windows support
|
||||
```
|
||||
```
|
||||
|
@ -7,16 +7,30 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
//
|
||||
// syscall.NewLazyDLL("user32.dll").NewProc("SetProcessDPIAware").Call()
|
||||
|
||||
width, height := robotgo.GetScaleSize()
|
||||
fmt.Println("get scale screen size: ", width, height)
|
||||
|
||||
bitmap := robotgo.CaptureScreen(0, 0, width, height)
|
||||
// robotgo.SaveBitmap(bitmap, "test.png")
|
||||
defer robotgo.FreeBitmap(bitmap)
|
||||
// bitmap.Save(bitmap, "test.png")
|
||||
robotgo.Save(robotgo.ToImage(bitmap), "test.png")
|
||||
|
||||
robotgo.Scale = true
|
||||
robotgo.Move(10, 10)
|
||||
robotgo.MoveSmooth(100, 100)
|
||||
|
||||
fmt.Println(robotgo.Location())
|
||||
|
||||
num := robotgo.DisplaysNum()
|
||||
for i := 0; i < num; i++ {
|
||||
rect := robotgo.GetScreenRect(i)
|
||||
fmt.Println("rect: ", rect)
|
||||
}
|
||||
}
|
||||
|
||||
func old() {
|
||||
sx := robotgo.ScaleX() // Deprecated
|
||||
s := robotgo.Scale1() // Deprecated, use the ScaleF() function
|
||||
robotx, roboty := 35*s/100, 25*s/100
|
||||
@ -28,7 +42,8 @@ func main() {
|
||||
rx, ry, rw, rh := sx, sy, robotx, roboty
|
||||
// bit1 := robotgo.CaptureScreen(10, 20, robotw, roboth)
|
||||
bit1 := robotgo.CaptureScreen(rx, ry, rw, rh)
|
||||
// robotgo.SaveBitmap(bit1, "test2.png")
|
||||
defer robotgo.FreeBitmap(bit1)
|
||||
// bitmap.Save(bit1, "test2.png")
|
||||
robotgo.Save(robotgo.ToImage(bit1), "test2.png")
|
||||
|
||||
clo := robotgo.GetPixelColor(robotx, roboty)
|
||||
|
@ -20,30 +20,38 @@ import (
|
||||
|
||||
func bitmap() {
|
||||
bit := robotgo.CaptureScreen()
|
||||
defer robotgo.FreeBitmap(bit)
|
||||
fmt.Println("abitMap...", bit)
|
||||
|
||||
gbit := robotgo.ToBitmap(bit)
|
||||
fmt.Println("bitmap...", gbit.Width)
|
||||
|
||||
gbitMap := robotgo.CaptureGo()
|
||||
fmt.Println("Go CaptureScreen...", gbitMap.Width)
|
||||
// fmt.Println("...", gbitmap.Width, gbitmap.BytesPerPixel)
|
||||
// robotgo.SaveCapture("saveCapture.png", 10, 20, 100, 100)
|
||||
robotgo.SaveCapture("saveCapture.png", 10, 20, 100, 100)
|
||||
|
||||
img := robotgo.CaptureImg()
|
||||
img, err := robotgo.CaptureImg()
|
||||
fmt.Println("error: ", err)
|
||||
robotgo.Save(img, "save.png")
|
||||
|
||||
num := robotgo.DisplaysNum()
|
||||
for i := 0; i < num; i++ {
|
||||
robotgo.DisplayID = i
|
||||
img1 := robotgo.CaptureImg()
|
||||
img1, _ := robotgo.CaptureImg()
|
||||
path1 := "save_" + strconv.Itoa(i)
|
||||
robotgo.Save(img1, path1+".png")
|
||||
robotgo.SaveJpeg(img1, path1+".jpeg", 50)
|
||||
|
||||
img2 := robotgo.CaptureImg(10, 10, 20, 20)
|
||||
img2, _ := robotgo.CaptureImg(10, 10, 20, 20)
|
||||
path2 := "test_" + strconv.Itoa(i)
|
||||
robotgo.Save(img2, path2+".png")
|
||||
robotgo.SaveJpeg(img2, path2+".jpeg", 50)
|
||||
|
||||
x, y, w, h := robotgo.GetDisplayBounds(i)
|
||||
img3, err := robotgo.CaptureImg(x, y, w, h)
|
||||
fmt.Println("Capture error: ", err)
|
||||
robotgo.Save(img3, path2+"_1.png")
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,7 +94,7 @@ func screen() {
|
||||
fmt.Println("ScaleF: ", s1)
|
||||
}
|
||||
sx, sy = robotgo.GetScaleSize()
|
||||
fmt.Println("get screen sclae size: ", sx, sy)
|
||||
fmt.Println("get screen scale size: ", sx, sy)
|
||||
|
||||
color()
|
||||
}
|
||||
|
49
go.mod
49
go.mod
@ -1,33 +1,38 @@
|
||||
module github.com/go-vgo/robotgo
|
||||
|
||||
go 1.17
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.6
|
||||
|
||||
require (
|
||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e
|
||||
github.com/otiai10/gosseract v2.2.1+incompatible
|
||||
github.com/otiai10/gosseract/v2 v2.4.1
|
||||
// github.com/robotn/gohook v0.31.3
|
||||
github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934
|
||||
github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770
|
||||
github.com/vcaesar/gops v0.30.0
|
||||
github.com/vcaesar/imgo v0.30.1
|
||||
github.com/vcaesar/keycode v0.10.0
|
||||
github.com/vcaesar/tt v0.20.0
|
||||
golang.org/x/image v0.1.0 // indirect
|
||||
github.com/robotn/xgb v0.10.0
|
||||
github.com/robotn/xgbutil v0.10.0
|
||||
github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35
|
||||
github.com/vcaesar/gops v0.41.0
|
||||
github.com/vcaesar/imgo v0.41.0
|
||||
github.com/vcaesar/keycode v0.10.1
|
||||
github.com/vcaesar/tt v0.20.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect
|
||||
github.com/otiai10/mint v1.3.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.22.10 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||
github.com/tklauser/numcpus v0.6.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/sys v0.2.0 // indirect
|
||||
github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e // indirect
|
||||
github.com/ebitengine/purego v0.8.3 // indirect
|
||||
github.com/gen2brain/shm v0.1.1 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/jezek/xgb v1.1.1 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.25.4 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
||||
github.com/tklauser/numcpus v0.10.0 // indirect
|
||||
github.com/vcaesar/screenshot v0.11.1
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect
|
||||
golang.org/x/image v0.27.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
)
|
||||
|
||||
// replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb
|
||||
|
147
go.sum
147
go.sum
@ -1,100 +1,71 @@
|
||||
github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ=
|
||||
github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 h1:Y5Q2mEwfzjMt5+3u70Gtw93ZOu2UuPeeeTBDntF7FoY=
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e h1:L+XrFvD0vBIBm+Wf9sFN6aU395t7JROoai0qXZraA4U=
|
||||
github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e/go.mod h1:SUxUaAK/0UG5lYyZR1L1nC4AaYYvSSYTWQSH3FPcxKU=
|
||||
github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc=
|
||||
github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/gen2brain/shm v0.1.1 h1:1cTVA5qcsUFixnDHl14TmRoxgfWEEZlTezpUj1vm5uQ=
|
||||
github.com/gen2brain/shm v0.1.1/go.mod h1:UgIcVtvmOu+aCJpqJX7GOtiN7X2ct+TKLg4RTxwPIUA=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 h1:dy+DS31tGEGCsZzB45HmJJNHjur8GDgtRNX9U7HnSX4=
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240/go.mod h1:3P4UH/k22rXyHIJD2w4h2XMqPX4Of/eySEZq9L6wqc4=
|
||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o=
|
||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c h1:VtwQ41oftZwlMnOEbMWQtSEUgU64U4s+GHk7hZK+jtY=
|
||||
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc=
|
||||
github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
||||
github.com/otiai10/gosseract v2.2.1+incompatible h1:Ry5ltVdpdp4LAa2bMjsSJH34XHVOV7XMi41HtzL8X2I=
|
||||
github.com/otiai10/gosseract v2.2.1+incompatible/go.mod h1:XrzWItCzCpFRZ35n3YtVTgq5bLAhFIkascoRo8G32QE=
|
||||
github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc=
|
||||
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4=
|
||||
github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc=
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/otiai10/gosseract/v2 v2.4.1 h1:G8AyBpXEeSlcq8TI85LH/pM5SXk8Djy2GEXisgyblRw=
|
||||
github.com/otiai10/gosseract/v2 v2.4.1/go.mod h1:1gNWP4Hgr2o7yqWfs6r5bZxAatjOIdqWxJLWsTsembk=
|
||||
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
|
||||
github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c h1:NRoLoZvkBTKvR5gQLgA3e0hqjkY9u1wm+iOL45VN/qI=
|
||||
github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ=
|
||||
github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk=
|
||||
github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU=
|
||||
github.com/shirou/gopsutil/v3 v3.22.10 h1:4KMHdfBRYXGF9skjDWiL4RA2N+E8dRdodU/bOZpPoVg=
|
||||
github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh4dQmV5xdFkQk=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
|
||||
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
|
||||
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
||||
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
|
||||
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
|
||||
github.com/vcaesar/gops v0.30.0 h1:970FznFxZP8ku0zckJRO+pI2fFhg3uJ0z+sQS0NHP4o=
|
||||
github.com/vcaesar/gops v0.30.0/go.mod h1:xV1wieUA4D9RaNQ8lf8AwPZ8bl+x/MM5w3SsMCr5KVs=
|
||||
github.com/vcaesar/imgo v0.30.1 h1:B7QMm2mZY+SGoEvvJwNi+eAv21ptvk2YT1IbP2OzyLE=
|
||||
github.com/vcaesar/imgo v0.30.1/go.mod h1:n4EluJIN/0UYYGPHBCY/BWlIjdRUdY5U6obtP2lrgdM=
|
||||
github.com/vcaesar/keycode v0.10.0 h1:Qx5QE8ZXHyRyjoA2QOxBp25OKMKB+zxMVqm0FWGV0d4=
|
||||
github.com/vcaesar/keycode v0.10.0/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ=
|
||||
github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA=
|
||||
github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk=
|
||||
golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
github.com/robotn/xgb v0.10.0 h1:O3kFbIwtwZ3pgLbp1h5slCQ4OpY8BdwugJLrUe6GPIM=
|
||||
github.com/robotn/xgb v0.10.0/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ=
|
||||
github.com/robotn/xgbutil v0.10.0 h1:gvf7mGQqCWQ68aHRtCxgdewRk+/KAJui6l3MJQQRCKw=
|
||||
github.com/robotn/xgbutil v0.10.0/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU=
|
||||
github.com/shirou/gopsutil/v4 v4.25.4 h1:cdtFO363VEOOFrUCjZRh4XVJkb548lyF0q0uTeMqYPw=
|
||||
github.com/shirou/gopsutil/v4 v4.25.4/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35 h1:wAZbkTZkqDzWsqxPh2qkBd3KvFU7tcxV0BP0Rnhkxog=
|
||||
github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35/go.mod h1:aMd4yDHLjbOuYP6fMxj1d9ACDQlSWwYztcpybGHCQc8=
|
||||
github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA=
|
||||
github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk=
|
||||
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
|
||||
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
|
||||
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
|
||||
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
|
||||
github.com/vcaesar/gops v0.41.0 h1:FG748Jyw3FOuZnbzSgB+CQSx2e5LbLCPWV2JU1brFdc=
|
||||
github.com/vcaesar/gops v0.41.0/go.mod h1:/3048L7Rj7QjQKTSB+kKc7hDm63YhTWy5QJ10TCP37A=
|
||||
github.com/vcaesar/imgo v0.41.0 h1:kNLYGrThXhB9Dd6IwFmfPnxq9P6yat2g7dpPjr7OWO8=
|
||||
github.com/vcaesar/imgo v0.41.0/go.mod h1:/LGOge8etlzaVu/7l+UfhJxR6QqaoX5yeuzGIMfWb4I=
|
||||
github.com/vcaesar/keycode v0.10.1 h1:0DesGmMAPWpYTCYddOFiCMKCDKgNnwiQa2QXindVUHw=
|
||||
github.com/vcaesar/keycode v0.10.1/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ=
|
||||
github.com/vcaesar/screenshot v0.11.1 h1:GgPuN89XC4Yh38dLx4quPlSo3YiWWhwIria/j3LtrqU=
|
||||
github.com/vcaesar/screenshot v0.11.1/go.mod h1:gJNwHBiP1v1v7i8TQ4yV1XJtcyn2I/OJL7OziVQkwjs=
|
||||
github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4=
|
||||
github.com/vcaesar/tt v0.20.1/go.mod h1:cH2+AwGAJm19Wa6xvEa+0r+sXDJBT0QgNQey6mwqLeU=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI=
|
||||
golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
|
||||
golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w=
|
||||
golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
2
img.go
2
img.go
@ -55,7 +55,7 @@ func SaveJpeg(img image.Image, path string, quality ...int) error {
|
||||
|
||||
// ToByteImg convert image.Image to []byte
|
||||
func ToByteImg(img image.Image, fm ...string) []byte {
|
||||
return imgo.ToByteImg(img, fm...)
|
||||
return imgo.ToByte(img, fm...)
|
||||
}
|
||||
|
||||
// ToStringImg convert image.Image to string
|
||||
|
14
key.go
14
key.go
@ -416,7 +416,7 @@ func keyTaps(k string, keyArr []string, pid int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func keyToggles(k string, keyArr []string, pid int, args ...interface{}) error {
|
||||
func keyToggles(k string, keyArr []string, pid int) error {
|
||||
if len(keyArr) <= 0 {
|
||||
keyArr = append(keyArr, "down")
|
||||
}
|
||||
@ -437,9 +437,7 @@ func keyToggles(k string, keyArr []string, pid int, args ...interface{}) error {
|
||||
}
|
||||
|
||||
C.toggleKeyCode(key, C.bool(down), flags, C.uintptr(pid))
|
||||
if len(args) > 0 {
|
||||
MilliSleep(KeySleep)
|
||||
}
|
||||
MilliSleep(KeySleep)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -482,9 +480,9 @@ func toErr(str *C.char) error {
|
||||
|
||||
// KeyTap taps the keyboard code;
|
||||
//
|
||||
// See keys:
|
||||
// See keys supported:
|
||||
//
|
||||
// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md
|
||||
// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md#keys
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
@ -532,7 +530,7 @@ func KeyTap(key string, args ...interface{}) error {
|
||||
//
|
||||
// See keys:
|
||||
//
|
||||
// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md
|
||||
// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md#keys
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
@ -613,7 +611,7 @@ func CharCodeAt(s string, n int) rune {
|
||||
return 0
|
||||
}
|
||||
|
||||
// UnicodeType tap uint32 unicode
|
||||
// UnicodeType tap the uint32 unicode
|
||||
func UnicodeType(str uint32, args ...int) {
|
||||
cstr := C.uint(str)
|
||||
pid := 0
|
||||
|
@ -179,7 +179,7 @@ enum _MMKeyCode {
|
||||
K_SHIFT = XK_Shift_L,
|
||||
K_LSHIFT = XK_Shift_L,
|
||||
K_RSHIFT = XK_Shift_R,
|
||||
K_CAPSLOCK = XK_Shift_Lock,
|
||||
K_CAPSLOCK = XK_Caps_Lock,
|
||||
K_SPACE = XK_space,
|
||||
K_INSERT = XK_Insert,
|
||||
K_PRINTSCREEN = XK_Print,
|
||||
|
@ -90,7 +90,8 @@ MMKeyCode keyCodeForChar(const char c) {
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
CFStringRef createStringForKey(CGKeyCode keyCode){
|
||||
TISInputSourceRef currentKeyboard = TISCopyCurrentASCIICapableKeyboardInputSource();
|
||||
// TISInputSourceRef currentKeyboard = TISCopyCurrentASCIICapableKeyboardInputSource();
|
||||
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardLayoutInputSource();
|
||||
CFDataRef layoutData = (CFDataRef) TISGetInputSourceProperty(
|
||||
currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
|
||||
|
||||
|
270
key/keypress_c.h
270
key/keypress_c.h
@ -58,107 +58,106 @@
|
||||
if (pid != 0) {
|
||||
CGEventPostToPid(pid, event);
|
||||
} else {
|
||||
CGEventPost(kCGSessionEventTap, event);
|
||||
CGEventPost(kCGHIDEventTap, event);
|
||||
}
|
||||
|
||||
CFRelease(event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static io_connect_t _getAuxiliaryKeyDriver(void) {
|
||||
static mach_port_t sEventDrvrRef = 0;
|
||||
mach_port_t masterPort, service, iter;
|
||||
kern_return_t kr;
|
||||
static io_connect_t _getAuxiliaryKeyDriver(void) {
|
||||
static mach_port_t sEventDrvrRef = 0;
|
||||
mach_port_t masterPort, service, iter;
|
||||
kern_return_t kr;
|
||||
|
||||
if (!sEventDrvrRef) {
|
||||
kr = IOMasterPort(bootstrap_port, &masterPort);
|
||||
assert(KERN_SUCCESS == kr);
|
||||
kr = IOServiceGetMatchingServices(masterPort, IOServiceMatching(kIOHIDSystemClass), &iter);
|
||||
assert(KERN_SUCCESS == kr);
|
||||
if (!sEventDrvrRef) {
|
||||
kr = IOMasterPort(bootstrap_port, &masterPort);
|
||||
assert(KERN_SUCCESS == kr);
|
||||
kr = IOServiceGetMatchingServices(masterPort, IOServiceMatching(kIOHIDSystemClass), &iter);
|
||||
assert(KERN_SUCCESS == kr);
|
||||
|
||||
service = IOIteratorNext(iter);
|
||||
assert(service);
|
||||
|
||||
kr = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &sEventDrvrRef);
|
||||
assert(KERN_SUCCESS == kr);
|
||||
service = IOIteratorNext(iter);
|
||||
assert(service);
|
||||
|
||||
IOObjectRelease(service);
|
||||
IOObjectRelease(iter);
|
||||
}
|
||||
return sEventDrvrRef;
|
||||
}
|
||||
#endif
|
||||
kr = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &sEventDrvrRef);
|
||||
assert(KERN_SUCCESS == kr);
|
||||
|
||||
#if defined(IS_WINDOWS)
|
||||
void win32KeyEvent(int key, MMKeyFlags flags, uintptr pid, int8_t isPid) {
|
||||
int scan = MapVirtualKey(key & 0xff, MAPVK_VK_TO_VSC);
|
||||
|
||||
/* Set the scan code for extended keys */
|
||||
switch (key){
|
||||
case VK_RCONTROL:
|
||||
case VK_SNAPSHOT: /* Print Screen */
|
||||
case VK_RMENU: /* Right Alt / Alt Gr */
|
||||
case VK_PAUSE: /* Pause / Break */
|
||||
case VK_HOME:
|
||||
case VK_UP:
|
||||
case VK_PRIOR: /* Page up */
|
||||
case VK_LEFT:
|
||||
case VK_RIGHT:
|
||||
case VK_END:
|
||||
case VK_DOWN:
|
||||
case VK_NEXT: /* 'Page Down' */
|
||||
case VK_INSERT:
|
||||
case VK_DELETE:
|
||||
case VK_LWIN:
|
||||
case VK_RWIN:
|
||||
case VK_APPS: /* Application */
|
||||
case VK_VOLUME_MUTE:
|
||||
case VK_VOLUME_DOWN:
|
||||
case VK_VOLUME_UP:
|
||||
case VK_MEDIA_NEXT_TRACK:
|
||||
case VK_MEDIA_PREV_TRACK:
|
||||
case VK_MEDIA_STOP:
|
||||
case VK_MEDIA_PLAY_PAUSE:
|
||||
case VK_BROWSER_BACK:
|
||||
case VK_BROWSER_FORWARD:
|
||||
case VK_BROWSER_REFRESH:
|
||||
case VK_BROWSER_STOP:
|
||||
case VK_BROWSER_SEARCH:
|
||||
case VK_BROWSER_FAVORITES:
|
||||
case VK_BROWSER_HOME:
|
||||
case VK_LAUNCH_MAIL:
|
||||
{
|
||||
flags |= KEYEVENTF_EXTENDEDKEY;
|
||||
break;
|
||||
IOObjectRelease(service);
|
||||
IOObjectRelease(iter);
|
||||
}
|
||||
return sEventDrvrRef;
|
||||
}
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
// todo: test this
|
||||
if (pid != 0) {
|
||||
HWND hwnd = getHwnd(pid, isPid);
|
||||
void win32KeyEvent(int key, MMKeyFlags flags, uintptr pid, int8_t isPid) {
|
||||
int scan = MapVirtualKey(key & 0xff, MAPVK_VK_TO_VSC);
|
||||
|
||||
int down = (flags == 0 ? WM_KEYDOWN : WM_KEYUP);
|
||||
// SendMessage(hwnd, down, key, 0);
|
||||
PostMessageW(hwnd, down, key, 0);
|
||||
return;
|
||||
/* Set the scan code for extended keys */
|
||||
switch (key){
|
||||
case VK_RCONTROL:
|
||||
case VK_SNAPSHOT: /* Print Screen */
|
||||
case VK_RMENU: /* Right Alt / Alt Gr */
|
||||
case VK_PAUSE: /* Pause / Break */
|
||||
case VK_HOME:
|
||||
case VK_UP:
|
||||
case VK_PRIOR: /* Page up */
|
||||
case VK_LEFT:
|
||||
case VK_RIGHT:
|
||||
case VK_END:
|
||||
case VK_DOWN:
|
||||
case VK_NEXT: /* 'Page Down' */
|
||||
case VK_INSERT:
|
||||
case VK_DELETE:
|
||||
case VK_LWIN:
|
||||
case VK_RWIN:
|
||||
case VK_APPS: /* Application */
|
||||
case VK_VOLUME_MUTE:
|
||||
case VK_VOLUME_DOWN:
|
||||
case VK_VOLUME_UP:
|
||||
case VK_MEDIA_NEXT_TRACK:
|
||||
case VK_MEDIA_PREV_TRACK:
|
||||
case VK_MEDIA_STOP:
|
||||
case VK_MEDIA_PLAY_PAUSE:
|
||||
case VK_BROWSER_BACK:
|
||||
case VK_BROWSER_FORWARD:
|
||||
case VK_BROWSER_REFRESH:
|
||||
case VK_BROWSER_STOP:
|
||||
case VK_BROWSER_SEARCH:
|
||||
case VK_BROWSER_FAVORITES:
|
||||
case VK_BROWSER_HOME:
|
||||
case VK_LAUNCH_MAIL:
|
||||
{
|
||||
flags |= KEYEVENTF_EXTENDEDKEY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// todo: test this
|
||||
if (pid != 0) {
|
||||
HWND hwnd = getHwnd(pid, isPid);
|
||||
|
||||
int down = (flags == 0 ? WM_KEYDOWN : WM_KEYUP);
|
||||
// SendMessage(hwnd, down, key, 0);
|
||||
PostMessageW(hwnd, down, key, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the scan code for keyup */
|
||||
// if ( flags & KEYEVENTF_KEYUP ) {
|
||||
// scan |= 0x80;
|
||||
// }
|
||||
// keybd_event(key, scan, flags, 0);
|
||||
|
||||
INPUT keyInput;
|
||||
|
||||
keyInput.type = INPUT_KEYBOARD;
|
||||
keyInput.ki.wVk = key;
|
||||
keyInput.ki.wScan = scan;
|
||||
keyInput.ki.dwFlags = flags;
|
||||
keyInput.ki.time = 0;
|
||||
keyInput.ki.dwExtraInfo = 0;
|
||||
SendInput(1, &keyInput, sizeof(keyInput));
|
||||
}
|
||||
|
||||
/* Set the scan code for keyup */
|
||||
// if ( flags & KEYEVENTF_KEYUP ) {
|
||||
// scan |= 0x80;
|
||||
// }
|
||||
// keybd_event(key, scan, flags, 0);
|
||||
|
||||
INPUT keyInput;
|
||||
|
||||
keyInput.type = INPUT_KEYBOARD;
|
||||
keyInput.ki.wVk = key;
|
||||
keyInput.ki.wScan = scan;
|
||||
keyInput.ki.dwFlags = flags;
|
||||
keyInput.ki.time = 0;
|
||||
keyInput.ki.dwExtraInfo = 0;
|
||||
SendInput(1, &keyInput, sizeof(keyInput));
|
||||
}
|
||||
#endif
|
||||
|
||||
void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, uintptr pid) {
|
||||
@ -180,7 +179,8 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, uintptr pi
|
||||
NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE);
|
||||
assert(KERN_SUCCESS == kr);
|
||||
} else {
|
||||
CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)code, down);
|
||||
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
CGEventRef keyEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode)code, down);
|
||||
assert(keyEvent != NULL);
|
||||
|
||||
CGEventSetType(keyEvent, down ? kCGEventKeyDown : kCGEventKeyUp);
|
||||
@ -189,6 +189,7 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, uintptr pi
|
||||
}
|
||||
|
||||
SendTo(pid, keyEvent);
|
||||
CFRelease(source);
|
||||
}
|
||||
#elif defined(IS_WINDOWS)
|
||||
const DWORD dwFlags = down ? 0 : KEYEVENTF_KEYUP;
|
||||
@ -269,57 +270,29 @@ void toggleKey(char c, const bool down, MMKeyFlags flags, uintptr pid) {
|
||||
// }
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
void toggleUnicode(UniChar ch, const bool down, uintptr pid) {
|
||||
/* This function relies on the convenient CGEventKeyboardSetUnicodeString(),
|
||||
convert characters to a keycode, but does not support adding modifier flags.
|
||||
It is only used in typeString().
|
||||
-- if you need modifier keys, use the above functions instead. */
|
||||
CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, 0, down);
|
||||
if (keyEvent == NULL) {
|
||||
fputs("Could not create keyboard event.\n", stderr);
|
||||
return;
|
||||
void toggleUnicode(UniChar ch, const bool down, uintptr pid) {
|
||||
/* This function relies on the convenient CGEventKeyboardSetUnicodeString(),
|
||||
convert characters to a keycode, but does not support adding modifier flags.
|
||||
It is only used in typeString().
|
||||
-- if you need modifier keys, use the above functions instead. */
|
||||
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
CGEventRef keyEvent = CGEventCreateKeyboardEvent(source, 0, down);
|
||||
if (keyEvent == NULL) {
|
||||
fputs("Could not create keyboard event.\n", stderr);
|
||||
return;
|
||||
}
|
||||
|
||||
CGEventKeyboardSetUnicodeString(keyEvent, 1, &ch);
|
||||
|
||||
SendTo(pid, keyEvent);
|
||||
CFRelease(source);
|
||||
}
|
||||
|
||||
CGEventKeyboardSetUnicodeString(keyEvent, 1, &ch);
|
||||
|
||||
SendTo(pid, keyEvent);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
#else
|
||||
#define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE, 0)
|
||||
|
||||
int input_utf(const char *utf) {
|
||||
Display *dpy = XOpenDisplay(NULL);
|
||||
KeySym sym = XStringToKeysym(utf);
|
||||
// KeySym sym = XKeycodeToKeysym(dpy, utf);
|
||||
|
||||
int min, max, numcodes;
|
||||
XDisplayKeycodes(dpy, &min, &max);
|
||||
KeySym *keysym;
|
||||
keysym = XGetKeyboardMapping(dpy, min, max-min+1, &numcodes);
|
||||
keysym[(max-min-1)*numcodes] = sym;
|
||||
XChangeKeyboardMapping(dpy, min, numcodes, keysym, (max-min));
|
||||
XFree(keysym);
|
||||
XFlush(dpy);
|
||||
|
||||
KeyCode code = XKeysymToKeycode(dpy, sym);
|
||||
XTestFakeKeyEvent(dpy, code, True, 1);
|
||||
XTestFakeKeyEvent(dpy, code, False, 1);
|
||||
|
||||
XFlush(dpy);
|
||||
XCloseDisplay(dpy);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#if !defined(USE_X11)
|
||||
int input_utf(const char *utf){
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// unicode type
|
||||
void unicodeType(const unsigned value, uintptr pid, int8_t isPid){
|
||||
void unicodeType(const unsigned value, uintptr pid, int8_t isPid) {
|
||||
#if defined(IS_MACOSX)
|
||||
UniChar ch = (UniChar)value; // Convert to unsigned char
|
||||
|
||||
@ -354,4 +327,33 @@ void unicodeType(const unsigned value, uintptr pid, int8_t isPid){
|
||||
microsleep(5.0);
|
||||
toggleUniKey(value, false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_X11)
|
||||
int input_utf(const char *utf) {
|
||||
Display *dpy = XOpenDisplay(NULL);
|
||||
KeySym sym = XStringToKeysym(utf);
|
||||
// KeySym sym = XKeycodeToKeysym(dpy, utf);
|
||||
|
||||
int min, max, numcodes;
|
||||
XDisplayKeycodes(dpy, &min, &max);
|
||||
KeySym *keysym;
|
||||
keysym = XGetKeyboardMapping(dpy, min, max-min+1, &numcodes);
|
||||
keysym[(max-min-1)*numcodes] = sym;
|
||||
XChangeKeyboardMapping(dpy, min, numcodes, keysym, (max-min));
|
||||
XFree(keysym);
|
||||
XFlush(dpy);
|
||||
|
||||
KeyCode code = XKeysymToKeycode(dpy, sym);
|
||||
XTestFakeKeyEvent(dpy, code, True, 1);
|
||||
XTestFakeKeyEvent(dpy, code, False, 1);
|
||||
|
||||
XFlush(dpy);
|
||||
XCloseDisplay(dpy);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int input_utf(const char *utf){
|
||||
return 0;
|
||||
}
|
||||
#endif
|
147
mouse/mouse_c.h
147
mouse/mouse_c.h
@ -15,119 +15,105 @@
|
||||
|
||||
/* Some convenience macros for converting our enums to the system API types. */
|
||||
#if defined(IS_MACOSX)
|
||||
CGEventType MMMouseDownToCGEventType(MMMouseButton button) {
|
||||
if (button == LEFT_BUTTON) {
|
||||
return kCGEventLeftMouseDown;
|
||||
CGEventType MMMouseDownToCGEventType(MMMouseButton button) {
|
||||
if (button == LEFT_BUTTON) {
|
||||
return kCGEventLeftMouseDown;
|
||||
}
|
||||
if (button == RIGHT_BUTTON) {
|
||||
return kCGEventRightMouseDown;
|
||||
}
|
||||
return kCGEventOtherMouseDown;
|
||||
}
|
||||
if (button == RIGHT_BUTTON) {
|
||||
return kCGEventRightMouseDown;
|
||||
}
|
||||
return kCGEventOtherMouseDown;
|
||||
}
|
||||
|
||||
CGEventType MMMouseUpToCGEventType(MMMouseButton button) {
|
||||
if (button == LEFT_BUTTON) { return kCGEventLeftMouseUp; }
|
||||
if (button == RIGHT_BUTTON) { return kCGEventRightMouseUp; }
|
||||
return kCGEventOtherMouseUp;
|
||||
}
|
||||
CGEventType MMMouseUpToCGEventType(MMMouseButton button) {
|
||||
if (button == LEFT_BUTTON) { return kCGEventLeftMouseUp; }
|
||||
if (button == RIGHT_BUTTON) { return kCGEventRightMouseUp; }
|
||||
return kCGEventOtherMouseUp;
|
||||
}
|
||||
|
||||
CGEventType MMMouseDragToCGEventType(MMMouseButton button) {
|
||||
if (button == LEFT_BUTTON) { return kCGEventLeftMouseDragged; }
|
||||
if (button == RIGHT_BUTTON) { return kCGEventRightMouseDragged; }
|
||||
return kCGEventOtherMouseDragged;
|
||||
}
|
||||
CGEventType MMMouseDragToCGEventType(MMMouseButton button) {
|
||||
if (button == LEFT_BUTTON) { return kCGEventLeftMouseDragged; }
|
||||
if (button == RIGHT_BUTTON) { return kCGEventRightMouseDragged; }
|
||||
return kCGEventOtherMouseDragged;
|
||||
}
|
||||
|
||||
CGEventType MMMouseToCGEventType(bool down, MMMouseButton button) {
|
||||
if (down) { return MMMouseDownToCGEventType(button); }
|
||||
return MMMouseUpToCGEventType(button);
|
||||
}
|
||||
CGEventType MMMouseToCGEventType(bool down, MMMouseButton button) {
|
||||
if (down) { return MMMouseDownToCGEventType(button); }
|
||||
return MMMouseUpToCGEventType(button);
|
||||
}
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
DWORD MMMouseUpToMEventF(MMMouseButton button) {
|
||||
if (button == LEFT_BUTTON) { return MOUSEEVENTF_LEFTUP; }
|
||||
if (button == RIGHT_BUTTON) { return MOUSEEVENTF_RIGHTUP; }
|
||||
return MOUSEEVENTF_MIDDLEUP;
|
||||
}
|
||||
DWORD MMMouseUpToMEventF(MMMouseButton button) {
|
||||
if (button == LEFT_BUTTON) { return MOUSEEVENTF_LEFTUP; }
|
||||
if (button == RIGHT_BUTTON) { return MOUSEEVENTF_RIGHTUP; }
|
||||
return MOUSEEVENTF_MIDDLEUP;
|
||||
}
|
||||
|
||||
DWORD MMMouseDownToMEventF(MMMouseButton button) {
|
||||
if (button == LEFT_BUTTON) { return MOUSEEVENTF_LEFTDOWN; }
|
||||
if (button == RIGHT_BUTTON) { return MOUSEEVENTF_RIGHTDOWN; }
|
||||
return MOUSEEVENTF_MIDDLEDOWN;
|
||||
}
|
||||
DWORD MMMouseDownToMEventF(MMMouseButton button) {
|
||||
if (button == LEFT_BUTTON) { return MOUSEEVENTF_LEFTDOWN; }
|
||||
if (button == RIGHT_BUTTON) { return MOUSEEVENTF_RIGHTDOWN; }
|
||||
return MOUSEEVENTF_MIDDLEDOWN;
|
||||
}
|
||||
|
||||
DWORD MMMouseToMEventF(bool down, MMMouseButton button) {
|
||||
if (down) { return MMMouseDownToMEventF(button); }
|
||||
return MMMouseUpToMEventF(button);
|
||||
}
|
||||
DWORD MMMouseToMEventF(bool down, MMMouseButton button) {
|
||||
if (down) { return MMMouseDownToMEventF(button); }
|
||||
return MMMouseUpToMEventF(button);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
/* Calculate the delta for a mouse move and add them to the event. */
|
||||
void calculateDeltas(CGEventRef *event, MMPointInt32 point){
|
||||
/* The next few lines are a workaround for games not detecting mouse moves. */
|
||||
CGEventRef get = CGEventCreate(NULL);
|
||||
CGPoint mouse = CGEventGetLocation(get);
|
||||
/* Calculate the delta for a mouse move and add them to the event. */
|
||||
void calculateDeltas(CGEventRef *event, MMPointInt32 point) {
|
||||
/* The next few lines are a workaround for games not detecting mouse moves. */
|
||||
CGEventRef get = CGEventCreate(NULL);
|
||||
CGPoint mouse = CGEventGetLocation(get);
|
||||
|
||||
// Calculate the deltas.
|
||||
int64_t deltaX = point.x - mouse.x;
|
||||
int64_t deltaY = point.y - mouse.y;
|
||||
// Calculate the deltas.
|
||||
int64_t deltaX = point.x - mouse.x;
|
||||
int64_t deltaY = point.y - mouse.y;
|
||||
|
||||
CGEventSetIntegerValueField(*event, kCGMouseEventDeltaX, deltaX);
|
||||
CGEventSetIntegerValueField(*event, kCGMouseEventDeltaY, deltaY);
|
||||
CGEventSetIntegerValueField(*event, kCGMouseEventDeltaX, deltaX);
|
||||
CGEventSetIntegerValueField(*event, kCGMouseEventDeltaY, deltaY);
|
||||
|
||||
CFRelease(get);
|
||||
}
|
||||
CFRelease(get);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Move the mouse to a specific point. */
|
||||
void moveMouse(MMPointInt32 point){
|
||||
#if defined(IS_MACOSX)
|
||||
CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved,
|
||||
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
CGEventRef move = CGEventCreateMouseEvent(source, kCGEventMouseMoved,
|
||||
CGPointFromMMPointInt32(point), kCGMouseButtonLeft);
|
||||
|
||||
calculateDeltas(&move, point);
|
||||
|
||||
CGEventPost(kCGSessionEventTap, move);
|
||||
CGEventPost(kCGHIDEventTap, move);
|
||||
CFRelease(move);
|
||||
CFRelease(source);
|
||||
#elif defined(USE_X11)
|
||||
Display *display = XGetMainDisplay();
|
||||
XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, point.x, point.y);
|
||||
|
||||
XSync(display, false);
|
||||
#elif defined(IS_WINDOWS)
|
||||
// Mouse motion is now done using SendInput with MOUSEINPUT.
|
||||
// We use Absolute mouse positioning
|
||||
#define MOUSE_COORD_TO_ABS(coord, width_or_height) ( \
|
||||
((65536 * coord) / width_or_height) + (coord < 0 ? -1 : 1))
|
||||
|
||||
MMRectInt32 rect = getScreenRect(1);
|
||||
int32_t x = MOUSE_COORD_TO_ABS(point.x - rect.origin.x, rect.size.w);
|
||||
int32_t y = MOUSE_COORD_TO_ABS(point.y - rect.origin.y, rect.size.h);
|
||||
|
||||
INPUT mouseInput;
|
||||
mouseInput.type = INPUT_MOUSE;
|
||||
mouseInput.mi.dx = x;
|
||||
mouseInput.mi.dy = y;
|
||||
mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_VIRTUALDESK;
|
||||
mouseInput.mi.time = 0; // System will provide the timestamp
|
||||
|
||||
mouseInput.mi.dwExtraInfo = 0;
|
||||
mouseInput.mi.mouseData = 0;
|
||||
SendInput(1, &mouseInput, sizeof(mouseInput));
|
||||
SetCursorPos(point.x, point.y);
|
||||
#endif
|
||||
}
|
||||
|
||||
void dragMouse(MMPointInt32 point, const MMMouseButton button){
|
||||
#if defined(IS_MACOSX)
|
||||
const CGEventType dragType = MMMouseDragToCGEventType(button);
|
||||
CGEventRef drag = CGEventCreateMouseEvent(NULL, dragType,
|
||||
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
CGEventRef drag = CGEventCreateMouseEvent(source, dragType,
|
||||
CGPointFromMMPointInt32(point), (CGMouseButton)button);
|
||||
|
||||
calculateDeltas(&drag, point);
|
||||
|
||||
CGEventPost(kCGSessionEventTap, drag);
|
||||
CGEventPost(kCGHIDEventTap, drag);
|
||||
CFRelease(drag);
|
||||
CFRelease(source);
|
||||
#else
|
||||
moveMouse(point);
|
||||
#endif
|
||||
@ -163,10 +149,12 @@ void toggleMouse(bool down, MMMouseButton button) {
|
||||
#if defined(IS_MACOSX)
|
||||
const CGPoint currentPos = CGPointFromMMPointInt32(location());
|
||||
const CGEventType mouseType = MMMouseToCGEventType(down, button);
|
||||
CGEventRef event = CGEventCreateMouseEvent(NULL, mouseType, currentPos, (CGMouseButton)button);
|
||||
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
CGEventRef event = CGEventCreateMouseEvent(source, mouseType, currentPos, (CGMouseButton)button);
|
||||
|
||||
CGEventPost(kCGSessionEventTap, event);
|
||||
CGEventPost(kCGHIDEventTap, event);
|
||||
CFRelease(event);
|
||||
CFRelease(source);
|
||||
#elif defined(USE_X11)
|
||||
Display *display = XGetMainDisplay();
|
||||
XTestFakeButtonEvent(display, button, down ? True : False, CurrentTime);
|
||||
@ -200,7 +188,8 @@ void doubleClick(MMMouseButton button){
|
||||
const CGEventType mouseTypeDown = MMMouseToCGEventType(true, button);
|
||||
const CGEventType mouseTypeUP = MMMouseToCGEventType(false, button);
|
||||
|
||||
CGEventRef event = CGEventCreateMouseEvent(NULL, mouseTypeDown, currentPos, kCGMouseButtonLeft);
|
||||
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
CGEventRef event = CGEventCreateMouseEvent(source, mouseTypeDown, currentPos, kCGMouseButtonLeft);
|
||||
|
||||
/* Set event to double click. */
|
||||
CGEventSetIntegerValueField(event, kCGMouseEventClickState, 2);
|
||||
@ -210,6 +199,7 @@ void doubleClick(MMMouseButton button){
|
||||
CGEventPost(kCGHIDEventTap, event);
|
||||
|
||||
CFRelease(event);
|
||||
CFRelease(source);
|
||||
#else
|
||||
/* Double click for everything else. */
|
||||
clickMouse(button);
|
||||
@ -226,14 +216,13 @@ void scrollMouseXY(int x, int y) {
|
||||
INPUT mouseScrollInputV;
|
||||
#endif
|
||||
|
||||
/* Direction should only be considered based on the scrollDirection. This Should not interfere. */
|
||||
/* Set up the OS specific solution */
|
||||
#if defined(__APPLE__)
|
||||
CGEventRef event;
|
||||
event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 2, y, x);
|
||||
#if defined(IS_MACOSX)
|
||||
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
CGEventRef event = CGEventCreateScrollWheelEvent(source, kCGScrollEventUnitPixel, 2, y, x);
|
||||
CGEventPost(kCGHIDEventTap, event);
|
||||
|
||||
CFRelease(event);
|
||||
CFRelease(source);
|
||||
#elif defined(USE_X11)
|
||||
int ydir = 4; /* Button 4 is up, 5 is down. */
|
||||
int xdir = 6;
|
||||
|
@ -43,5 +43,13 @@ func TestGetSysScale(t *testing.T) {
|
||||
log.Println("SysScale: ", s)
|
||||
|
||||
f := robotgo.ScaleF()
|
||||
log.Println("sclae: ", f)
|
||||
log.Println("scale: ", f)
|
||||
}
|
||||
|
||||
func TestGetTitle(t *testing.T) {
|
||||
// just exercise the function, it used to crash with a segfault + "Maximum
|
||||
// number of clients reached"
|
||||
for i := 0; i < 128; i++ {
|
||||
robotgo.GetTitle()
|
||||
}
|
||||
}
|
||||
|
87
robotgo.go
87
robotgo.go
@ -31,8 +31,12 @@ package robotgo
|
||||
|
||||
/*
|
||||
#cgo darwin CFLAGS: -x objective-c -Wno-deprecated-declarations
|
||||
#cgo darwin LDFLAGS: -framework Cocoa -framework OpenGL -framework IOKit
|
||||
#cgo darwin LDFLAGS: -framework Carbon -framework CoreFoundation
|
||||
#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
|
||||
@ -46,6 +50,7 @@ package robotgo
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"image"
|
||||
"runtime"
|
||||
"time"
|
||||
@ -68,7 +73,7 @@ var (
|
||||
// MouseSleep set the mouse default millisecond sleep time
|
||||
MouseSleep = 0
|
||||
// KeySleep set the key default millisecond sleep time
|
||||
KeySleep = 0
|
||||
KeySleep = 10
|
||||
|
||||
// DisplayID set the screen display id
|
||||
DisplayID = -1
|
||||
@ -86,9 +91,15 @@ type (
|
||||
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 is Bitmap struct
|
||||
// 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
|
||||
@ -266,6 +277,11 @@ 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()
|
||||
@ -328,6 +344,7 @@ func CaptureScreen(args ...int) CBitmap {
|
||||
x = C.int32_t(rect.X)
|
||||
y = C.int32_t(rect.Y)
|
||||
}
|
||||
|
||||
w = C.int32_t(rect.W)
|
||||
h = C.int32_t(rect.H)
|
||||
}
|
||||
@ -349,12 +366,15 @@ func CaptureGo(args ...int) Bitmap {
|
||||
return ToBitmap(bit)
|
||||
}
|
||||
|
||||
// CaptureImg capture the screen and return image.Image
|
||||
func CaptureImg(args ...int) image.Image {
|
||||
// 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)
|
||||
return ToImage(bit), nil
|
||||
}
|
||||
|
||||
// FreeBitmap free and dealloc the C bitmap
|
||||
@ -443,6 +463,11 @@ func GetXDisplayName() string {
|
||||
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
|
||||
@ -481,9 +506,9 @@ func CheckMouse(btn string) C.MMMouseButton {
|
||||
|
||||
// MoveScale calculate the os scale factor x, y
|
||||
func MoveScale(x, y int, displayId ...int) (int, int) {
|
||||
if Scale && runtime.GOOS == "windows" {
|
||||
if Scale || runtime.GOOS == "windows" {
|
||||
f := ScaleF()
|
||||
x, y = Scaled0(x, f), Scaled0(y, f)
|
||||
x, y = Scaled1(x, f), Scaled1(y, f)
|
||||
}
|
||||
|
||||
return x, y
|
||||
@ -530,8 +555,6 @@ func Drag(x, y int, args ...string) {
|
||||
//
|
||||
// robotgo.DragSmooth(10, 10)
|
||||
func DragSmooth(x, y int, args ...interface{}) {
|
||||
x, y = MoveScale(x, y)
|
||||
|
||||
Toggle("left")
|
||||
MilliSleep(50)
|
||||
MoveSmooth(x, y, args...)
|
||||
@ -607,6 +630,11 @@ func Location() (int, int) {
|
||||
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
|
||||
}
|
||||
|
||||
@ -853,12 +881,22 @@ func IsValid() bool {
|
||||
}
|
||||
|
||||
// SetActive set the window active
|
||||
func SetActive(win C.MData) {
|
||||
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() C.MData {
|
||||
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
|
||||
@ -932,8 +970,29 @@ func SetHandlePid(pid int, args ...int) {
|
||||
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) C.MData {
|
||||
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
|
||||
|
@ -179,7 +179,8 @@ func TestImage(t *testing.T) {
|
||||
err := SavePng(img, "robot_test.png")
|
||||
tt.Nil(t, err)
|
||||
|
||||
img1 := CaptureImg(10, 10, 20, 20)
|
||||
img1, err := CaptureImg(10, 10, 20, 20)
|
||||
tt.Nil(t, err)
|
||||
e := Save(img1, "robot_img.jpeg", 50)
|
||||
tt.Nil(t, e)
|
||||
|
||||
|
@ -17,7 +17,8 @@ import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/lxn/win"
|
||||
// "github.com/lxn/win"
|
||||
"github.com/tailscale/win"
|
||||
)
|
||||
|
||||
// FindWindow find window hwnd by name
|
||||
@ -57,7 +58,7 @@ func SetForeg(hwnd win.HWND) bool {
|
||||
return win.SetForegroundWindow(hwnd)
|
||||
}
|
||||
|
||||
// GetMian get the main display hwnd
|
||||
// GetMain get the main display hwnd
|
||||
func GetMain() win.HWND {
|
||||
return win.GetActiveWindow()
|
||||
}
|
||||
@ -67,20 +68,33 @@ func GetMainId() int {
|
||||
return int(GetMain())
|
||||
}
|
||||
|
||||
// ScaleF get the system scale val
|
||||
// ScaleF get the system scale value
|
||||
// if "displayId == -2" this function will get the desktop scale value
|
||||
func ScaleF(displayId ...int) (f float64) {
|
||||
if len(displayId) > 0 && displayId[0] != -1 {
|
||||
dpi := GetDPI(win.HWND(displayId[0]))
|
||||
f = float64(dpi) / 96.0
|
||||
if displayId[0] >= 0 {
|
||||
dpi := GetDPI(win.HWND(displayId[0]))
|
||||
f = float64(dpi) / 96.0
|
||||
}
|
||||
|
||||
if displayId[0] == -2 {
|
||||
f = float64(GetDPI(GetDesktopWindow())) / 96.0
|
||||
}
|
||||
} else {
|
||||
f = float64(GetMainDPI()) / 96.0
|
||||
}
|
||||
|
||||
if f == 0.0 {
|
||||
f = 1.0
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
// GetDesktopWindow get the desktop window hwnd id
|
||||
func GetDesktopWindow() win.HWND {
|
||||
return win.GetDesktopWindow()
|
||||
}
|
||||
|
||||
// GetMainDPI get the display dpi
|
||||
func GetMainDPI() int {
|
||||
return int(GetDPI(GetHWND()))
|
||||
|
@ -190,7 +190,7 @@ func DisplaysNum() int {
|
||||
return int(reply.Number)
|
||||
}
|
||||
|
||||
// GetMianId get the main display id
|
||||
// GetMainId get the main display id
|
||||
func GetMainId() int {
|
||||
conn, err := xgb.NewConn()
|
||||
if err != nil {
|
||||
|
19
screen.go
19
screen.go
@ -13,16 +13,17 @@ package robotgo
|
||||
import (
|
||||
"image"
|
||||
|
||||
"github.com/kbinani/screenshot"
|
||||
// "github.com/kbinani/screenshot"
|
||||
"github.com/vcaesar/screenshot"
|
||||
)
|
||||
|
||||
// GetScreenBound gets the display screen bounds
|
||||
// GetDisplayBounds gets the display screen bounds
|
||||
func GetDisplayBounds(i int) (x, y, w, h int) {
|
||||
bs := screenshot.GetDisplayBounds(i)
|
||||
return bs.Min.X, bs.Min.Y, bs.Dx(), bs.Dy()
|
||||
}
|
||||
|
||||
// GetDisplayBounds gets the display rect
|
||||
// GetDisplayRect gets the display rect
|
||||
func GetDisplayRect(i int) Rect {
|
||||
x, y, w, h := GetDisplayBounds(i)
|
||||
return Rect{
|
||||
@ -30,7 +31,7 @@ func GetDisplayRect(i int) Rect {
|
||||
Size{W: w, H: h}}
|
||||
}
|
||||
|
||||
// Capture capture the screenshot
|
||||
// Capture capture the screenshot, use the CaptureImg default
|
||||
func Capture(args ...int) (*image.RGBA, error) {
|
||||
displayId := 0
|
||||
if DisplayID != -1 {
|
||||
@ -50,3 +51,13 @@ func Capture(args ...int) (*image.RGBA, error) {
|
||||
|
||||
return screenshot.Capture(x, y, w, h)
|
||||
}
|
||||
|
||||
// SaveCapture capture screen and save the screenshot to image
|
||||
func SaveCapture(path string, args ...int) error {
|
||||
img, err := CaptureImg(args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return Save(img, path)
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "../base/pubs.h"
|
||||
#include "../base/rgb.h"
|
||||
#include "screengrab_c.h"
|
||||
#include "screen_c.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void padHex(MMRGBHex color, char* hex) {
|
||||
@ -79,6 +78,14 @@ char* get_XDisplay_name() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void close_main_display() {
|
||||
#if defined(USE_X11)
|
||||
XCloseMainDisplay();
|
||||
#else
|
||||
//
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t get_num_displays() {
|
||||
#if defined(IS_MACOSX)
|
||||
uint32_t count = 0;
|
||||
|
@ -4,9 +4,70 @@
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#elif defined(USE_X11)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xresource.h>
|
||||
// #include "../base/xdisplay_c.h"
|
||||
#endif
|
||||
|
||||
intptr scaleX();
|
||||
|
||||
double sys_scale(int32_t display_id) {
|
||||
#if defined(IS_MACOSX)
|
||||
CGDirectDisplayID displayID = (CGDirectDisplayID) display_id;
|
||||
if (displayID == -1) {
|
||||
displayID = CGMainDisplayID();
|
||||
}
|
||||
|
||||
CGDisplayModeRef modeRef = CGDisplayCopyDisplayMode(displayID);
|
||||
double pixelWidth = CGDisplayModeGetPixelWidth(modeRef);
|
||||
double targetWidth = CGDisplayModeGetWidth(modeRef);
|
||||
|
||||
return pixelWidth / targetWidth;
|
||||
#elif defined(USE_X11)
|
||||
Display *dpy = XOpenDisplay(NULL);
|
||||
|
||||
int scr = 0; /* Screen number */
|
||||
double xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) /
|
||||
((double) DisplayWidthMM(dpy, scr)));
|
||||
|
||||
char *rms = XResourceManagerString(dpy);
|
||||
if (rms) {
|
||||
XrmDatabase db = XrmGetStringDatabase(rms);
|
||||
if (db) {
|
||||
XrmValue value;
|
||||
char *type = NULL;
|
||||
|
||||
if (XrmGetResource(db, "Xft.dpi", "String", &type, &value)) {
|
||||
if (value.addr) {
|
||||
xres = atof(value.addr);
|
||||
}
|
||||
}
|
||||
|
||||
XrmDestroyDatabase(db);
|
||||
}
|
||||
}
|
||||
XCloseDisplay (dpy);
|
||||
|
||||
return xres / 96.0;
|
||||
#elif defined(IS_WINDOWS)
|
||||
double s = scaleX() / 96.0;
|
||||
return s;
|
||||
#endif
|
||||
}
|
||||
|
||||
intptr scaleX(){
|
||||
#if defined(IS_MACOSX)
|
||||
return 0;
|
||||
#elif defined(USE_X11)
|
||||
return 0;
|
||||
#elif defined(IS_WINDOWS)
|
||||
// Get desktop dc
|
||||
HDC desktopDc = GetDC(NULL);
|
||||
// Get native resolution
|
||||
intptr horizontalDPI = GetDeviceCaps(desktopDc, LOGPIXELSX);
|
||||
return horizontalDPI;
|
||||
#endif
|
||||
}
|
||||
|
||||
MMSizeInt32 getMainDisplaySize(void) {
|
||||
#if defined(IS_MACOSX)
|
||||
CGDirectDisplayID displayID = CGMainDisplayID();
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenGL/gl.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <ScreenCaptureKit/ScreenCaptureKit.h>
|
||||
#elif defined(USE_X11)
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
@ -12,6 +13,56 @@
|
||||
#elif defined(IS_WINDOWS)
|
||||
#include <string.h>
|
||||
#endif
|
||||
#include "screen_c.h"
|
||||
|
||||
#if defined(IS_MACOSX) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 140400
|
||||
static CGImageRef capture15(CGDirectDisplayID id, CGRect diIntersectDisplayLocal, CGColorSpaceRef colorSpace) {
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
__block CGImageRef image1 = nil;
|
||||
[SCShareableContent getShareableContentWithCompletionHandler:^(SCShareableContent* content, NSError* error) {
|
||||
@autoreleasepool {
|
||||
if (error) {
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
return;
|
||||
}
|
||||
|
||||
SCDisplay* target = nil;
|
||||
for (SCDisplay *display in content.displays) {
|
||||
if (display.displayID == id) {
|
||||
target = display;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!target) {
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
return;
|
||||
}
|
||||
|
||||
SCContentFilter* filter = [[SCContentFilter alloc] initWithDisplay:target excludingWindows:@[]];
|
||||
SCStreamConfiguration* config = [[SCStreamConfiguration alloc] init];
|
||||
config.queueDepth = 5;
|
||||
config.sourceRect = diIntersectDisplayLocal;
|
||||
config.width = diIntersectDisplayLocal.size.width * sys_scale(id);
|
||||
config.height = diIntersectDisplayLocal.size.height * sys_scale(id);
|
||||
config.scalesToFit = false;
|
||||
config.captureResolution = 1;
|
||||
|
||||
[SCScreenshotManager captureImageWithFilter:filter
|
||||
configuration:config
|
||||
completionHandler:^(CGImageRef img, NSError* error) {
|
||||
if (!error) {
|
||||
image1 = CGImageCreateCopyWithColorSpace(img, colorSpace);
|
||||
}
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
}];
|
||||
}
|
||||
}];
|
||||
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
dispatch_release(semaphore);
|
||||
return image1;
|
||||
}
|
||||
#endif
|
||||
|
||||
MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id, int8_t isPid) {
|
||||
#if defined(IS_MACOSX)
|
||||
@ -25,9 +76,16 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id,
|
||||
}
|
||||
|
||||
MMPointInt32 o = rect.origin; MMSizeInt32 s = rect.size;
|
||||
CGImageRef image = CGDisplayCreateImageForRect(displayID, CGRectMake(o.x, o.y, s.w, s.h));
|
||||
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 140400
|
||||
CGColorSpaceRef color = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
|
||||
CGImageRef image = capture15(displayID, CGRectMake(o.x, o.y, s.w, s.h), color);
|
||||
CGColorSpaceRelease(color);
|
||||
#else
|
||||
// This API is deprecated in macos 15, use ScreenCaptureKit's captureScreenshot
|
||||
CGImageRef image = CGDisplayCreateImageForRect(displayID, CGRectMake(o.x, o.y, s.w, s.h));
|
||||
#endif
|
||||
if (!image) { return NULL; }
|
||||
|
||||
|
||||
CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(image));
|
||||
if (!imageData) { return NULL; }
|
||||
|
||||
@ -54,7 +112,8 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id,
|
||||
|
||||
MMPointInt32 o = rect.origin; MMSizeInt32 s = rect.size;
|
||||
XImage *image = XGetImage(display, XDefaultRootWindow(display),
|
||||
(int)o.x, (int)o.y, (unsigned int)s.w, (unsigned int)s.h, AllPlanes, ZPixmap);
|
||||
(int)o.x, (int)o.y, (unsigned int)s.w, (unsigned int)s.h,
|
||||
AllPlanes, ZPixmap);
|
||||
XCloseDisplay(display);
|
||||
if (image == NULL) { return NULL; }
|
||||
|
||||
|
2
wayland_n.go
Normal file
2
wayland_n.go
Normal file
@ -0,0 +1,2 @@
|
||||
// +bulid linux,next
|
||||
package robotgo
|
@ -55,11 +55,11 @@ uintptr get_handle(){
|
||||
|
||||
uintptr b_get_handle() {
|
||||
#if defined(IS_MACOSX)
|
||||
return (uintptr)mData.CgID;
|
||||
return (uintptr)pub_mData.CgID;
|
||||
#elif defined(USE_X11)
|
||||
return (uintptr)mData.XWin;
|
||||
return (uintptr)pub_mData.XWin;
|
||||
#elif defined(IS_WINDOWS)
|
||||
return (uintptr)mData.HWnd;
|
||||
return (uintptr)pub_mData.HWnd;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ struct _MData{
|
||||
};
|
||||
|
||||
typedef struct _MData MData;
|
||||
MData mData;
|
||||
MData pub_mData;
|
||||
|
||||
struct _Bounds {
|
||||
int32_t X; // Top left X coordinate
|
||||
@ -191,6 +191,7 @@ typedef struct _Bounds Bounds;
|
||||
if (items != NULL) {
|
||||
*items = (uint32_t) nItems;
|
||||
}
|
||||
XCloseDisplay(rDisplay);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -8,70 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include <X11/Xresource.h>
|
||||
#endif
|
||||
// #if defined(USE_X11)
|
||||
// #include <X11/Xresource.h>
|
||||
// #endif
|
||||
|
||||
Bounds get_client(uintptr pid, int8_t isPid);
|
||||
intptr scaleX();
|
||||
|
||||
double sys_scale(int32_t display_id) {
|
||||
#if defined(IS_MACOSX)
|
||||
CGDirectDisplayID displayID = (CGDirectDisplayID) display_id;
|
||||
if (displayID == -1) {
|
||||
displayID = CGMainDisplayID();
|
||||
}
|
||||
|
||||
CGDisplayModeRef modeRef = CGDisplayCopyDisplayMode(displayID);
|
||||
double pixelWidth = CGDisplayModeGetPixelWidth(modeRef);
|
||||
double targetWidth = CGDisplayModeGetWidth(modeRef);
|
||||
|
||||
return pixelWidth / targetWidth;
|
||||
#elif defined(USE_X11)
|
||||
Display *dpy = XOpenDisplay(NULL);
|
||||
|
||||
int scr = 0; /* Screen number */
|
||||
double xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) /
|
||||
((double) DisplayWidthMM(dpy, scr)));
|
||||
|
||||
char *rms = XResourceManagerString(dpy);
|
||||
if (rms) {
|
||||
XrmDatabase db = XrmGetStringDatabase(rms);
|
||||
if (db) {
|
||||
XrmValue value;
|
||||
char *type = NULL;
|
||||
|
||||
if (XrmGetResource(db, "Xft.dpi", "String", &type, &value)) {
|
||||
if (value.addr) {
|
||||
xres = atof(value.addr);
|
||||
}
|
||||
}
|
||||
|
||||
XrmDestroyDatabase(db);
|
||||
}
|
||||
}
|
||||
XCloseDisplay (dpy);
|
||||
|
||||
return xres / 96.0;
|
||||
#elif defined(IS_WINDOWS)
|
||||
double s = scaleX() / 96.0;
|
||||
return s;
|
||||
#endif
|
||||
}
|
||||
|
||||
intptr scaleX(){
|
||||
#if defined(IS_MACOSX)
|
||||
return 0;
|
||||
#elif defined(USE_X11)
|
||||
return 0;
|
||||
#elif defined(IS_WINDOWS)
|
||||
// Get desktop dc
|
||||
HDC desktopDc = GetDC(NULL);
|
||||
// Get native resolution
|
||||
intptr horizontalDPI = GetDeviceCaps(desktopDc, LOGPIXELSX);
|
||||
return horizontalDPI;
|
||||
#endif
|
||||
}
|
||||
|
||||
Bounds get_bounds(uintptr pid, int8_t isPid){
|
||||
// Check if the window is valid
|
||||
|
@ -15,7 +15,7 @@ bool is_valid();
|
||||
bool IsAxEnabled(bool options);
|
||||
|
||||
MData get_active(void);
|
||||
void initWindow();
|
||||
void initWindow(uintptr handle);
|
||||
char* get_title_by_hand(MData m_data);
|
||||
void close_window_by_Id(MData m_data);
|
||||
|
||||
@ -24,8 +24,8 @@ uintptr initHandle = 0;
|
||||
|
||||
void initWindow(uintptr handle){
|
||||
#if defined(IS_MACOSX)
|
||||
mData.CgID = 0;
|
||||
mData.AxID = 0;
|
||||
pub_mData.CgID = 0;
|
||||
pub_mData.AxID = 0;
|
||||
#elif defined(USE_X11)
|
||||
Display *rDisplay = XOpenDisplay(NULL);
|
||||
// If atoms loaded
|
||||
@ -34,10 +34,10 @@ void initWindow(uintptr handle){
|
||||
if (rDisplay != NULL) {LoadAtoms();}
|
||||
}
|
||||
|
||||
mData.XWin = 0;
|
||||
pub_mData.XWin = 0;
|
||||
XCloseDisplay(rDisplay);
|
||||
#elif defined(IS_WINDOWS)
|
||||
mData.HWnd = 0;
|
||||
pub_mData.HWnd = 0;
|
||||
#endif
|
||||
setHandle(handle);
|
||||
}
|
||||
@ -67,33 +67,33 @@ MData set_handle_pid(uintptr pid, int8_t isPid){
|
||||
|
||||
void set_handle_pid_mData(uintptr pid, int8_t isPid){
|
||||
MData win = set_handle_pid(pid, isPid);
|
||||
mData = win;
|
||||
pub_mData = win;
|
||||
}
|
||||
|
||||
bool is_valid() {
|
||||
initWindow(initHandle);
|
||||
if (!IsAxEnabled(true)) {
|
||||
printf("%s\n", "Window: Accessibility API is disabled!\n"
|
||||
"Failed to enable access for assistive devices.");
|
||||
printf("%s\n", "Window: Accessibility API is disabled! "
|
||||
"Failed to enable access for assistive devices. \n");
|
||||
}
|
||||
MData actdata = get_active();
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
mData.CgID = actdata.CgID;
|
||||
mData.AxID = actdata.AxID;
|
||||
if (mData.CgID == 0 || mData.AxID == 0) { return false; }
|
||||
pub_mData.CgID = actdata.CgID;
|
||||
pub_mData.AxID = actdata.AxID;
|
||||
if (pub_mData.CgID == 0 || pub_mData.AxID == 0) { return false; }
|
||||
|
||||
CFTypeRef r = NULL;
|
||||
// Attempt to get the window role
|
||||
if (AXUIElementCopyAttributeValue(mData.AxID, kAXRoleAttribute, &r) == kAXErrorSuccess && r){
|
||||
if (AXUIElementCopyAttributeValue(pub_mData.AxID, kAXRoleAttribute, &r) == kAXErrorSuccess && r){
|
||||
CFRelease(r);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
#elif defined(USE_X11)
|
||||
mData.XWin = actdata.XWin;
|
||||
if (mData.XWin == 0) { return false; }
|
||||
pub_mData.XWin = actdata.XWin;
|
||||
if (pub_mData.XWin == 0) { return false; }
|
||||
|
||||
Display *rDisplay = XOpenDisplay(NULL);
|
||||
// Check for a valid X-Window display
|
||||
@ -103,8 +103,11 @@ bool is_valid() {
|
||||
XDismissErrors();
|
||||
|
||||
// Get the window PID property
|
||||
void* result = GetWindowProperty(mData, WM_PID,NULL);
|
||||
if (result == NULL) { return false; }
|
||||
void* result = GetWindowProperty(pub_mData, WM_PID,NULL);
|
||||
if (result == NULL) {
|
||||
XCloseDisplay(rDisplay);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Free result and return true
|
||||
XFree(result);
|
||||
@ -112,12 +115,12 @@ bool is_valid() {
|
||||
|
||||
return true;
|
||||
#elif defined(IS_WINDOWS)
|
||||
mData.HWnd = actdata.HWnd;
|
||||
if (mData.HWnd == 0) {
|
||||
pub_mData.HWnd = actdata.HWnd;
|
||||
if (pub_mData.HWnd == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsWindow(mData.HWnd) != 0;
|
||||
return IsWindow(pub_mData.HWnd) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -172,13 +175,13 @@ bool IsAxEnabled(bool options){
|
||||
bool setHandle(uintptr handle){
|
||||
#if defined(IS_MACOSX)
|
||||
// Release the AX element
|
||||
if (mData.AxID != NULL) {
|
||||
CFRelease(mData.AxID);
|
||||
if (pub_mData.AxID != NULL) {
|
||||
CFRelease(pub_mData.AxID);
|
||||
}
|
||||
|
||||
// Reset both values
|
||||
mData.CgID = 0;
|
||||
mData.AxID = 0;
|
||||
pub_mData.CgID = 0;
|
||||
pub_mData.AxID = 0;
|
||||
|
||||
if (handle == 0) {
|
||||
// return 0;
|
||||
@ -189,8 +192,8 @@ bool setHandle(uintptr handle){
|
||||
CGWindowID cgID = (CGWindowID)handle;
|
||||
AXUIElementRef axID = GetUIElement(cgID);
|
||||
if (axID != NULL){
|
||||
mData.CgID = cgID;
|
||||
mData.AxID = axID;
|
||||
pub_mData.CgID = cgID;
|
||||
pub_mData.AxID = axID;
|
||||
// return 0;
|
||||
return true;
|
||||
}
|
||||
@ -198,7 +201,7 @@ bool setHandle(uintptr handle){
|
||||
// return 1;
|
||||
return false;
|
||||
#elif defined(USE_X11)
|
||||
mData.XWin = (Window)handle;
|
||||
pub_mData.XWin = (Window)handle;
|
||||
if (handle == 0) {
|
||||
return true;
|
||||
}
|
||||
@ -207,10 +210,10 @@ bool setHandle(uintptr handle){
|
||||
return true;
|
||||
}
|
||||
|
||||
mData.XWin = 0;
|
||||
pub_mData.XWin = 0;
|
||||
return false;
|
||||
#elif defined(IS_WINDOWS)
|
||||
mData.HWnd = (HWND)handle;
|
||||
pub_mData.HWnd = (HWND)handle;
|
||||
if (handle == 0) {
|
||||
return true;
|
||||
}
|
||||
@ -219,7 +222,7 @@ bool setHandle(uintptr handle){
|
||||
return true;
|
||||
}
|
||||
|
||||
mData.HWnd = 0;
|
||||
pub_mData.HWnd = 0;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@ -234,7 +237,7 @@ bool IsTopMost(void){
|
||||
// XDismissErrors ();
|
||||
// return GetState (mData.XWin, STATE_TOPMOST);
|
||||
#elif defined(IS_WINDOWS)
|
||||
return (GetWindowLongPtr(mData.HWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
|
||||
return (GetWindowLongPtr(pub_mData.HWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -244,7 +247,7 @@ bool IsMinimized(void){
|
||||
#if defined(IS_MACOSX)
|
||||
CFBooleanRef data = NULL;
|
||||
// Determine whether the window is minimized
|
||||
if (AXUIElementCopyAttributeValue(mData.AxID, kAXMinimizedAttribute,
|
||||
if (AXUIElementCopyAttributeValue(pub_mData.AxID, kAXMinimizedAttribute,
|
||||
(CFTypeRef*) &data) == kAXErrorSuccess && data != NULL) {
|
||||
// Convert resulting data into a bool
|
||||
bool result = CFBooleanGetValue(data);
|
||||
@ -258,7 +261,7 @@ bool IsMinimized(void){
|
||||
// XDismissErrors();
|
||||
// return GetState(mData.XWin, STATE_MINIMIZE);
|
||||
#elif defined(IS_WINDOWS)
|
||||
return (GetWindowLongPtr(mData.HWnd, GWL_STYLE) & WS_MINIMIZE) != 0;
|
||||
return (GetWindowLongPtr(pub_mData.HWnd, GWL_STYLE) & WS_MINIMIZE) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -273,7 +276,7 @@ bool IsMaximized(void){
|
||||
// XDismissErrors();
|
||||
// return GetState(mData.XWin, STATE_MAXIMIZE);
|
||||
#elif defined(IS_WINDOWS)
|
||||
return (GetWindowLongPtr(mData.HWnd, GWL_STYLE) & WS_MAXIMIZE) != 0;
|
||||
return (GetWindowLongPtr(pub_mData.HWnd, GWL_STYLE) & WS_MAXIMIZE) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -364,11 +367,11 @@ MData get_active(void) {
|
||||
if (focused == NULL) { return result; } // Verify
|
||||
|
||||
AXUIElementRef element;
|
||||
CGWindowID win = 0;
|
||||
// Retrieve the currently focused window
|
||||
if (AXUIElementCopyAttributeValue(focused, kAXFocusedWindowAttribute, (CFTypeRef*) &element)
|
||||
== kAXErrorSuccess && element) {
|
||||
|
||||
CGWindowID win = 0;
|
||||
// Use undocumented API to get WID
|
||||
if (_AXUIElementGetWindow(element, &win) == kAXErrorSuccess && win) {
|
||||
// Manually set internals
|
||||
@ -377,6 +380,9 @@ MData get_active(void) {
|
||||
} else {
|
||||
CFRelease(element);
|
||||
}
|
||||
} else {
|
||||
result.CgID = win;
|
||||
result.AxID = element;
|
||||
}
|
||||
CFRelease(focused);
|
||||
|
||||
@ -405,6 +411,7 @@ MData get_active(void) {
|
||||
if (window != 0) {
|
||||
// Set and return the foreground window
|
||||
result.XWin = (Window)window;
|
||||
XCloseDisplay(rDisplay);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -446,9 +453,9 @@ void SetTopMost(bool state){
|
||||
#elif defined(USE_X11)
|
||||
// Ignore X errors
|
||||
// XDismissErrors();
|
||||
// SetState(mData.XWin, STATE_TOPMOST, state);
|
||||
// SetState(pub_mData.XWin, STATE_TOPMOST, state);
|
||||
#elif defined(IS_WINDOWS)
|
||||
SetWindowPos(mData.HWnd, state ? HWND_TOPMOST : HWND_NOTOPMOST,
|
||||
SetWindowPos(pub_mData.HWnd, state ? HWND_TOPMOST : HWND_NOTOPMOST,
|
||||
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
#endif
|
||||
}
|
||||
@ -457,7 +464,7 @@ void close_main_window () {
|
||||
// Check if the window is valid
|
||||
if (!is_valid()) { return; }
|
||||
|
||||
close_window_by_Id(mData);
|
||||
close_window_by_Id(pub_mData);
|
||||
}
|
||||
|
||||
void close_window_by_PId(uintptr pid, int8_t isPid){
|
||||
@ -494,13 +501,13 @@ void close_window_by_Id(MData m_data){
|
||||
char* get_main_title(){
|
||||
// Check if the window is valid
|
||||
if (!is_valid()) { return "is_valid failed."; }
|
||||
|
||||
return get_title_by_hand(mData);
|
||||
|
||||
return get_title_by_hand(pub_mData);
|
||||
}
|
||||
|
||||
char* get_title_by_pid(uintptr pid, int8_t isPid){
|
||||
MData win = set_handle_pid(pid, isPid);
|
||||
return get_title_by_hand(win);
|
||||
return get_title_by_hand(win);
|
||||
}
|
||||
|
||||
char* named(void *result) {
|
||||
@ -584,7 +591,7 @@ int32_t get_PID(void) {
|
||||
#if defined(IS_MACOSX)
|
||||
pid_t pid = 0;
|
||||
// Attempt to retrieve the window pid
|
||||
if (AXUIElementGetPid(mData.AxID, &pid)== kAXErrorSuccess) {
|
||||
if (AXUIElementGetPid(pub_mData.AxID, &pid)== kAXErrorSuccess) {
|
||||
return pid;
|
||||
}
|
||||
return 0;
|
||||
@ -593,7 +600,7 @@ int32_t get_PID(void) {
|
||||
XDismissErrors();
|
||||
|
||||
// Get the window PID
|
||||
long* result = (long*)GetWindowProperty(mData, WM_PID,NULL);
|
||||
long* result = (long*)GetWindowProperty(pub_mData, WM_PID,NULL);
|
||||
// Check result and convert it
|
||||
if (result == NULL) { return 0; }
|
||||
|
||||
@ -602,7 +609,7 @@ int32_t get_PID(void) {
|
||||
return pid;
|
||||
#elif defined(IS_WINDOWS)
|
||||
DWORD id = 0;
|
||||
GetWindowThreadProcessId(mData.HWnd, &id);
|
||||
GetWindowThreadProcessId(pub_mData.HWnd, &id);
|
||||
return id;
|
||||
#endif
|
||||
}
|
||||
|
2
windows_n.go
Normal file
2
windows_n.go
Normal file
@ -0,0 +1,2 @@
|
||||
// +bulid windows,next
|
||||
package robotgo
|
Loading…
Reference in New Issue
Block a user