mirror of
https://github.com/go-vgo/robotgo.git
synced 2025-05-31 06:13:55 +00:00
Merge pull request #442 from go-vgo/bitmap-pr
Add more multi screen support, update go mod, remove some code
This commit is contained in:
commit
897af2a0db
14
base/os.h
14
base/os.h
@ -46,4 +46,18 @@
|
||||
#define ADD_PADDING(width) (BYTE_ALIGN + (((width) - 1) & ~(BYTE_ALIGN - 1)))
|
||||
#endif
|
||||
|
||||
#if defined(IS_WINDOWS)
|
||||
#if defined (_WIN64)
|
||||
#define RobotGo_64
|
||||
#else
|
||||
#define RobotGo_32
|
||||
#endif
|
||||
#else
|
||||
#if defined (__x86_64__)
|
||||
#define RobotGo_64
|
||||
#else
|
||||
#define RobotGo_32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* OS_H */
|
||||
|
34
base/win32.h
Normal file
34
base/win32.h
Normal file
@ -0,0 +1,34 @@
|
||||
#if defined(IS_WINDOWS)
|
||||
BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
|
||||
uint32_t *count = (uint32_t*)dwData;
|
||||
(*count)++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct{
|
||||
HWND hWnd;
|
||||
DWORD dwPid;
|
||||
}WNDINFO;
|
||||
|
||||
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam){
|
||||
WNDINFO* pInfo = (WNDINFO*)lParam;
|
||||
DWORD dwProcessId = 0;
|
||||
GetWindowThreadProcessId(hWnd, &dwProcessId);
|
||||
|
||||
if (dwProcessId == pInfo->dwPid) {
|
||||
pInfo->hWnd = hWnd;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HWND GetHwndByPId(DWORD dwProcessId) {
|
||||
WNDINFO info = {0};
|
||||
info.hWnd = NULL;
|
||||
info.dwPid = dwProcessId;
|
||||
EnumWindows(EnumWindowsProc, (LPARAM)&info);
|
||||
// printf("%d\n", info.hWnd);
|
||||
return info.hWnd;
|
||||
}
|
||||
|
||||
#endif
|
@ -18,9 +18,9 @@ import (
|
||||
)
|
||||
|
||||
func bitmap() {
|
||||
abitMap := robotgo.CaptureScreen()
|
||||
fmt.Println("abitMap...", abitMap)
|
||||
gbit := robotgo.ToBitmap(abitMap)
|
||||
bit := robotgo.CaptureScreen()
|
||||
fmt.Println("abitMap...", bit)
|
||||
gbit := robotgo.ToBitmap(bit)
|
||||
fmt.Println("bitmap...", gbit.Width)
|
||||
|
||||
gbitMap := robotgo.CaptureGo()
|
||||
|
11
go.mod
11
go.mod
@ -8,7 +8,7 @@ require (
|
||||
// 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.21.3
|
||||
github.com/vcaesar/gops v0.22.0
|
||||
github.com/vcaesar/imgo v0.30.0
|
||||
github.com/vcaesar/keycode v0.10.0
|
||||
github.com/vcaesar/tt v0.20.0
|
||||
@ -17,15 +17,16 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/otiai10/mint v1.3.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/shirou/gopsutil v3.21.10+incompatible // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.21.12 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.9 // indirect
|
||||
github.com/tklauser/numcpus v0.3.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
)
|
||||
|
||||
|
31
go.sum
31
go.sum
@ -1,13 +1,14 @@
|
||||
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/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
|
||||
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
||||
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/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
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=
|
||||
@ -17,27 +18,31 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc=
|
||||
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
|
||||
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 h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY=
|
||||
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.21.10+incompatible h1:AL2kpVykjkqeN+MFe1WcwSBVUjGjvdU8/ubvCuXAjrU=
|
||||
github.com/shirou/gopsutil v3.21.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/gopsutil/v3 v3.21.12 h1:VoGxEW2hpmz0Vt3wUvHIl9fquzYLNpVpgNNB7pGJimA=
|
||||
github.com/shirou/gopsutil/v3 v3.21.12/go.mod h1:BToYZVTlSVlfazpDDYFnsVZLaoRG+g8ufT6fPQLdJzA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo=
|
||||
github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs=
|
||||
github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ=
|
||||
github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8=
|
||||
github.com/vcaesar/gops v0.21.3 h1:VR7amkxVv9CQfsotkXrmMyT19dVuNTa1PM/oopJeIc0=
|
||||
github.com/vcaesar/gops v0.21.3/go.mod h1:3e2EnlZTI9/44bqzRwkeZ3s0ZQwK2Cn4QPLx8Ii8Agk=
|
||||
github.com/vcaesar/gops v0.22.0 h1:aWHWxY3fvUuaJGph+LegYUSEU/874WJT7MInd8OUmP0=
|
||||
github.com/vcaesar/gops v0.22.0/go.mod h1:GFNGo9xpCfjcfd/Hovi9RSrpd4FdaQt8V92TzpU22w4=
|
||||
github.com/vcaesar/imgo v0.30.0 h1:ODQVX0EFJEh+WkKahCBtE0SqcDCIjl/kjiOplR0Ouh8=
|
||||
github.com/vcaesar/imgo v0.30.0/go.mod h1:8TGnt5hjaMgwDByvMFIzUDSh5uSea4n1tAbSvnhvA6U=
|
||||
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/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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
@ -51,13 +56,17 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw=
|
||||
golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
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=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
|
@ -10,18 +10,19 @@
|
||||
|
||||
#include "../base/types.h"
|
||||
#include "../base/rgb.h"
|
||||
#include "../base/win32.h"
|
||||
#include "screengrab_c.h"
|
||||
#include "screen_c.h"
|
||||
#include <stdio.h>
|
||||
// #include "../MMBitmap_c.h"
|
||||
|
||||
void padHex(MMRGBHex color, char* hex){
|
||||
void padHex(MMRGBHex color, char* hex) {
|
||||
// Length needs to be 7 because snprintf includes a terminating null.
|
||||
// Use %06x to pad hex value with leading 0s.
|
||||
snprintf(hex, 7, "%06x", color);
|
||||
}
|
||||
|
||||
char* pad_hex(MMRGBHex color){
|
||||
char* pad_hex(MMRGBHex color) {
|
||||
char hex[7];
|
||||
padHex(color, hex);
|
||||
// destroyMMBitmap(bitmap);
|
||||
@ -34,14 +35,14 @@ char* pad_hex(MMRGBHex color){
|
||||
|
||||
static uint8_t rgb[3];
|
||||
|
||||
uint8_t* color_hex_to_rgb(uint32_t h){
|
||||
uint8_t* color_hex_to_rgb(uint32_t h) {
|
||||
rgb[0] = RED_FROM_HEX(h);
|
||||
rgb[1] = GREEN_FROM_HEX(h);
|
||||
rgb[2] = BLUE_FROM_HEX(h);
|
||||
return rgb;
|
||||
}
|
||||
|
||||
uint32_t color_rgb_to_hex(uint8_t r, uint8_t g, uint8_t b){
|
||||
uint32_t color_rgb_to_hex(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return RGB_TO_HEX(r, g, b);
|
||||
}
|
||||
|
||||
@ -49,7 +50,7 @@ MMRGBHex get_px_color(int32_t x, int32_t y, int32_t display_id) {
|
||||
MMBitmapRef bitmap;
|
||||
MMRGBHex color;
|
||||
|
||||
if (!pointVisibleOnMainDisplay(MMPointInt32Make(x, y))){
|
||||
if (!pointVisibleOnMainDisplay(MMPointInt32Make(x, y))) {
|
||||
return color;
|
||||
}
|
||||
|
||||
@ -69,13 +70,13 @@ char* get_pixel_color(int32_t x, int32_t y, int32_t display_id) {
|
||||
return s;
|
||||
}
|
||||
|
||||
MMSizeInt32 get_screen_size(){
|
||||
MMSizeInt32 get_screen_size() {
|
||||
// Get display size.
|
||||
MMSizeInt32 displaySize = getMainDisplaySize();
|
||||
return displaySize;
|
||||
}
|
||||
|
||||
char* set_XDisplay_name(char* name){
|
||||
char* set_XDisplay_name(char* name) {
|
||||
#if defined(USE_X11)
|
||||
setXDisplay(name);
|
||||
return "success";
|
||||
@ -84,7 +85,7 @@ char* set_XDisplay_name(char* name){
|
||||
#endif
|
||||
}
|
||||
|
||||
char* get_XDisplay_name(){
|
||||
char* get_XDisplay_name() {
|
||||
#if defined(USE_X11)
|
||||
const char* display = getXDisplay();
|
||||
char* sd = (char*)calloc(100, sizeof(char*));
|
||||
@ -96,34 +97,26 @@ char* get_XDisplay_name(){
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(IS_WINDOWS)
|
||||
bool CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
|
||||
uint32_t *count = (uint32_t*)dwData;
|
||||
(*count)++;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t get_num_displays() {
|
||||
#if defined(IS_MACOSX)
|
||||
uint32_t count = 0;
|
||||
if (CGGetActiveDisplayList(0, nil, &count) == kCGErrorSuccess) {
|
||||
return count;
|
||||
}
|
||||
return 0;
|
||||
#elif defined(USE_X11)
|
||||
return 0;
|
||||
#elif defined(IS_WINDOWS)
|
||||
uint32_t count = 0;
|
||||
if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&count)) {
|
||||
return count;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
#if defined(IS_MACOSX)
|
||||
uint32_t count = 0;
|
||||
if (CGGetActiveDisplayList(0, nil, &count) == kCGErrorSuccess) {
|
||||
return count;
|
||||
}
|
||||
return 0;
|
||||
#elif defined(USE_X11)
|
||||
return 0;
|
||||
#elif defined(IS_WINDOWS)
|
||||
uint32_t count = 0;
|
||||
if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&count)) {
|
||||
return count;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void bitmap_dealloc(MMBitmapRef bitmap){
|
||||
void bitmap_dealloc(MMBitmapRef bitmap) {
|
||||
if (bitmap != NULL) {
|
||||
destroyMMBitmap(bitmap);
|
||||
bitmap = NULL;
|
||||
|
@ -17,15 +17,13 @@
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id){
|
||||
MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) {
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
MMBitmapRef bitmap = NULL;
|
||||
uint8_t *buffer = NULL;
|
||||
size_t bufferSize = 0;
|
||||
|
||||
CGDirectDisplayID displayID = (CGDirectDisplayID) display_id;
|
||||
|
||||
if (displayID == -1) {
|
||||
displayID = CGMainDisplayID();
|
||||
}
|
||||
@ -43,7 +41,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id){
|
||||
CFDataGetBytes(imageData, CFRangeMake(0, bufferSize), buffer);
|
||||
|
||||
bitmap = createMMBitmap_c(buffer,
|
||||
CGImageGetWidth(image),CGImageGetHeight(image),
|
||||
CGImageGetWidth(image), CGImageGetHeight(image),
|
||||
CGImageGetBytesPerRow(image), CGImageGetBitsPerPixel(image),
|
||||
CGImageGetBitsPerPixel(image) / 8);
|
||||
|
||||
@ -53,11 +51,16 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id){
|
||||
return bitmap;
|
||||
#elif defined(USE_X11)
|
||||
MMBitmapRef bitmap;
|
||||
Display *display;
|
||||
if (display_id == -1) {
|
||||
display = XOpenDisplay(NULL);
|
||||
} else {
|
||||
display = XGetMainDisplay();
|
||||
}
|
||||
|
||||
Display *display = XOpenDisplay(NULL);
|
||||
XImage *image = XGetImage(display, XDefaultRootWindow(display),
|
||||
(int)rect.origin.x, (int)rect.origin.y,
|
||||
(unsigned int)rect.size.w,(unsigned int)rect.size.h,
|
||||
(unsigned int)rect.size.w, (unsigned int)rect.size.h,
|
||||
AllPlanes, ZPixmap);
|
||||
XCloseDisplay(display);
|
||||
if (image == NULL) { return NULL; }
|
||||
@ -65,8 +68,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id){
|
||||
bitmap = createMMBitmap_c((uint8_t *)image->data,
|
||||
rect.size.w, rect.size.h, (size_t)image->bytes_per_line,
|
||||
(uint8_t)image->bits_per_pixel, (uint8_t)image->bits_per_pixel / 8);
|
||||
image->data = NULL; /* Steal ownership of bitmap data so we don't have to
|
||||
* copy it. */
|
||||
image->data = NULL; /* Steal ownership of bitmap data so we don't have to copy it. */
|
||||
XDestroyImage(image);
|
||||
|
||||
return bitmap;
|
||||
@ -90,7 +92,11 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id){
|
||||
bi.bmiHeader.biClrUsed = 0;
|
||||
bi.bmiHeader.biClrImportant = 0;
|
||||
|
||||
screen = GetDC(NULL); /* Get entire screen */
|
||||
if (display_id == -1) {
|
||||
screen = GetDC(NULL); /* Get entire screen */
|
||||
} else {
|
||||
screen = GetDC((HWND) display_id);
|
||||
}
|
||||
if (screen == NULL) { return NULL; }
|
||||
|
||||
/* Get screen data in display device context. */
|
||||
|
113
window/alert_c.h
113
window/alert_c.h
@ -14,7 +14,6 @@
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
|
||||
enum {
|
||||
TASK_SUCCESS = 0,
|
||||
FORK_FAILED = -1,
|
||||
@ -38,68 +37,67 @@ static int xmessage(char *argv[], int *exit_status);
|
||||
#endif
|
||||
|
||||
int showAlert(const char *title, const char *msg,
|
||||
const char *defaultButton, const char *cancelButton)
|
||||
{
|
||||
#if defined(IS_MACOSX)
|
||||
CFStringRef alertHeader = CFStringCreateWithUTF8String(title);
|
||||
CFStringRef alertMessage = CFStringCreateWithUTF8String(msg);
|
||||
CFStringRef defaultButtonTitle = CFStringCreateWithUTF8String(defaultButton);
|
||||
CFStringRef cancelButtonTitle = CFStringCreateWithUTF8String(cancelButton);
|
||||
CFOptionFlags responseFlags;
|
||||
SInt32 err = CFUserNotificationDisplayAlert(
|
||||
0.0, kCFUserNotificationNoteAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage,
|
||||
defaultButtonTitle, cancelButtonTitle, NULL, &responseFlags);
|
||||
const char *defaultButton, const char *cancelButton) {
|
||||
#if defined(IS_MACOSX)
|
||||
CFStringRef alertHeader = CFStringCreateWithUTF8String(title);
|
||||
CFStringRef alertMessage = CFStringCreateWithUTF8String(msg);
|
||||
CFStringRef defaultButtonTitle = CFStringCreateWithUTF8String(defaultButton);
|
||||
CFStringRef cancelButtonTitle = CFStringCreateWithUTF8String(cancelButton);
|
||||
CFOptionFlags responseFlags;
|
||||
SInt32 err = CFUserNotificationDisplayAlert(
|
||||
0.0, kCFUserNotificationNoteAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage,
|
||||
defaultButtonTitle, cancelButtonTitle, NULL, &responseFlags);
|
||||
|
||||
if (alertHeader != NULL) CFRelease(alertHeader);
|
||||
if (alertMessage != NULL) CFRelease(alertMessage);
|
||||
if (defaultButtonTitle != NULL) CFRelease(defaultButtonTitle);
|
||||
if (cancelButtonTitle != NULL) CFRelease(cancelButtonTitle);
|
||||
if (alertHeader != NULL) CFRelease(alertHeader);
|
||||
if (alertMessage != NULL) CFRelease(alertMessage);
|
||||
if (defaultButtonTitle != NULL) CFRelease(defaultButtonTitle);
|
||||
if (cancelButtonTitle != NULL) CFRelease(cancelButtonTitle);
|
||||
|
||||
if (err != 0) { return -1; }
|
||||
return (responseFlags == kCFUserNotificationDefaultResponse) ? 0 : 1;
|
||||
#elif defined(USE_X11)
|
||||
/* Note that args[0] is set by the xmessage() function. */
|
||||
const char *args[10] = {NULL, msg, "-title", title, "-center"};
|
||||
int response, ret;
|
||||
char *buttonList = NULL; /* To be free()'d. */
|
||||
if (err != 0) { return -1; }
|
||||
return (responseFlags == kCFUserNotificationDefaultResponse) ? 0 : 1;
|
||||
#elif defined(USE_X11)
|
||||
/* Note that args[0] is set by the xmessage() function. */
|
||||
const char *args[10] = {NULL, msg, "-title", title, "-center"};
|
||||
int response, ret;
|
||||
char *buttonList = NULL; /* To be free()'d. */
|
||||
|
||||
if (defaultButton == NULL) defaultButton = "OK";
|
||||
if (defaultButton == NULL) defaultButton = "OK";
|
||||
|
||||
// snprintf.h
|
||||
if (cancelButton == NULL) {
|
||||
asprintf(&buttonList, "%s:2", defaultButton);
|
||||
} else {
|
||||
asprintf(&buttonList, "%s:2,%s:3", defaultButton, cancelButton);
|
||||
}
|
||||
|
||||
if (buttonList == NULL) { return -1; /* asprintf() failed. */ }
|
||||
args[5] = "-buttons";
|
||||
args[6] = buttonList;
|
||||
args[7] = "-default";
|
||||
args[8] = defaultButton;
|
||||
args[9] = NULL;
|
||||
|
||||
ret = xmessage((char **)args, &response);
|
||||
if (buttonList != NULL) {
|
||||
free(buttonList);
|
||||
buttonList = NULL;
|
||||
}
|
||||
|
||||
if (ret != TASK_SUCCESS) {
|
||||
if (ret == EXEC_FAILED) {
|
||||
fputs("xmessage or equivalent not found.\n", stderr);
|
||||
// snprintf.h
|
||||
if (cancelButton == NULL) {
|
||||
asprintf(&buttonList, "%s:2", defaultButton);
|
||||
} else {
|
||||
asprintf(&buttonList, "%s:2,%s:3", defaultButton, cancelButton);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (response == 2) ? 0 : 1;
|
||||
#else
|
||||
/* TODO: Display custom buttons instead of the pre-defined "OK"
|
||||
* and "Cancel". */
|
||||
int response = MessageBox(NULL, msg, title,
|
||||
(cancelButton == NULL) ? MB_OK : MB_OKCANCEL);
|
||||
return (response == IDOK) ? 0 : 1;
|
||||
#endif
|
||||
if (buttonList == NULL) { return -1; /* asprintf() failed. */ }
|
||||
args[5] = "-buttons";
|
||||
args[6] = buttonList;
|
||||
args[7] = "-default";
|
||||
args[8] = defaultButton;
|
||||
args[9] = NULL;
|
||||
|
||||
ret = xmessage((char **)args, &response);
|
||||
if (buttonList != NULL) {
|
||||
free(buttonList);
|
||||
buttonList = NULL;
|
||||
}
|
||||
|
||||
if (ret != TASK_SUCCESS) {
|
||||
if (ret == EXEC_FAILED) {
|
||||
fputs("xmessage or equivalent not found.\n", stderr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (response == 2) ? 0 : 1;
|
||||
#else
|
||||
/* TODO: Display custom buttons instead of the pre-defined "OK"
|
||||
* and "Cancel". */
|
||||
int response = MessageBox(NULL, msg, title,
|
||||
(cancelButton == NULL) ? MB_OK : MB_OKCANCEL);
|
||||
return (response == IDOK) ? 0 : 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(USE_X11)
|
||||
@ -171,5 +169,4 @@ static int runTask(const char *taskname, char * const argv[], int *exit_status)
|
||||
return TASK_SUCCESS; /* Success! */
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
26
window/arr.h
26
window/arr.h
@ -1,26 +0,0 @@
|
||||
// #include <stdio.h>
|
||||
// #include <stdlib.h>
|
||||
// #include <stdbool.h>
|
||||
|
||||
struct Arr{
|
||||
int len;
|
||||
int cnu;
|
||||
char** pName;
|
||||
int *pId;
|
||||
};
|
||||
|
||||
// int init_Arr(struct Arr *pArray, int len){
|
||||
// pArray->pName = (char**)malloc(sizeof(char*)*len);
|
||||
// pArray->pId = (int*)malloc(sizeof(int)*len);
|
||||
// if(NULL == pArray->pName){
|
||||
// printf("false \n");
|
||||
// return 1;
|
||||
// }else{
|
||||
// pArray->len = len;
|
||||
// pArray->cnu = 0;
|
||||
// printf("true %d \n", pArray->len);
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// return 0;
|
||||
// }
|
@ -121,7 +121,7 @@ char* get_title(uintptr pid, uintptr isHwnd){
|
||||
return title;
|
||||
}
|
||||
|
||||
int32 get_PID(void){
|
||||
int32_t get_PID(void){
|
||||
int pid = WGetPID();
|
||||
return pid;
|
||||
}
|
||||
|
133
window/process.h
133
window/process.h
@ -1,133 +0,0 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// #include <regex.h>
|
||||
#include <string.h>
|
||||
#if defined(IS_MACOSX)
|
||||
#if defined (__x86_64__)
|
||||
#define RobotGo_64
|
||||
#else
|
||||
#define RobotGo_32
|
||||
#endif
|
||||
// #include <sys/utsname.h>
|
||||
// #include <mach/task.h>
|
||||
// #include <mach/mach_vm.h>
|
||||
|
||||
// Apple process API
|
||||
#include <libproc.h>
|
||||
#include <dlfcn.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
|
||||
#ifdef MAC_OS_X_VERSION_10_11
|
||||
#define kAXValueCGPointType kAXValueTypeCGPoint
|
||||
#define kAXValueCGSizeType kAXValueTypeCGSize
|
||||
#endif
|
||||
|
||||
#ifndef EXC_MASK_GUARD
|
||||
#define EXC_MASK_GUARD 0
|
||||
#endif
|
||||
#elif defined(USE_X11)
|
||||
#if defined (__x86_64__)
|
||||
#define RobotGo_64
|
||||
#else
|
||||
#define RobotGo_32
|
||||
#endif
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#ifndef X_HAVE_UTF8_STRING
|
||||
#error It appears that X_HAVE_UTF8_STRING is not defined - \
|
||||
please verify that your version of XLib is supported
|
||||
#endif
|
||||
#elif defined(IS_WINDOWS)
|
||||
#if defined (_WIN64)
|
||||
#define RobotGo_64
|
||||
#else
|
||||
#define RobotGo_32
|
||||
#endif
|
||||
|
||||
#include <winuser.h>
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
typedef signed char int8; // Signed 8-Bit integer
|
||||
typedef signed short int16; // Signed 16-Bit integer
|
||||
typedef signed int int32; // Signed 32-Bit integer
|
||||
typedef signed long long int64; // Signed 64-Bit integer
|
||||
|
||||
typedef unsigned char uint8; // Unsigned 8-Bit integer
|
||||
typedef unsigned short uint16; // Unsigned 16-Bit integer
|
||||
typedef unsigned int uint32; // Unsigned 32-Bit integer
|
||||
typedef unsigned long long uint64; // Unsigned 64-Bit integer
|
||||
|
||||
typedef float real32; // 32-Bit float value
|
||||
typedef double real64; // 64-Bit float value
|
||||
|
||||
#ifdef RobotGo_64
|
||||
|
||||
typedef int64 intptr; // Signed pointer integer
|
||||
typedef uint64 uintptr; // Unsigned pointer integer
|
||||
|
||||
#else
|
||||
|
||||
typedef int32 intptr; // Signed pointer integer
|
||||
typedef uint32 uintptr; // Unsigned pointer integer
|
||||
|
||||
#endif
|
||||
//
|
||||
|
||||
struct _PData{
|
||||
int32 ProcID; // The process ID
|
||||
|
||||
char* Name; // Name of process
|
||||
char* Path; // Path of process
|
||||
|
||||
bool Is64Bit; // Process is 64-Bit
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
task_t Handle; // The mach task
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
uint32 Handle; // Unused handle
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
HANDLE Handle; // Process handle
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _PPData{
|
||||
int32 ProcID; // The process ID
|
||||
|
||||
char** Name; // Name of process
|
||||
char** Path; // Path of process
|
||||
|
||||
bool Is64Bit; // Process is 64-Bit
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
task_t Handle; // The mach task
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
uint32 Handle; // Unused handle
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
HANDLE Handle; // Process handle
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct _PData PData;
|
112
window/pub.h
112
window/pub.h
@ -9,6 +9,19 @@
|
||||
// except according to those terms.
|
||||
|
||||
// #include "../base/os.h"
|
||||
#if defined(IS_MACOSX)
|
||||
#include <dlfcn.h>
|
||||
#elif defined(USE_X11)
|
||||
#include <X11/Xatom.h>
|
||||
#endif
|
||||
|
||||
#ifdef RobotGo_64
|
||||
typedef int64_t intptr;
|
||||
typedef uint64_t uintptr;
|
||||
#else
|
||||
typedef int32_t intptr;
|
||||
typedef uint32_t uintptr; // Unsigned pointer integer
|
||||
#endif
|
||||
|
||||
struct _MData{
|
||||
#if defined(IS_MACOSX)
|
||||
@ -23,49 +36,41 @@ struct _MData{
|
||||
};
|
||||
|
||||
typedef struct _MData MData;
|
||||
|
||||
MData mData;
|
||||
|
||||
struct _Bounds{
|
||||
int32 X; // Top left X coordinate
|
||||
int32 Y; // Top left Y coordinate
|
||||
int32 W; // Total bounds width
|
||||
int32 H; // Total bounds height
|
||||
struct _Bounds {
|
||||
int32_t X; // Top left X coordinate
|
||||
int32_t Y; // Top left Y coordinate
|
||||
int32_t W; // bounds width
|
||||
int32_t H; // bounds height
|
||||
};
|
||||
|
||||
typedef struct _Bounds Bounds;
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
static Boolean(*gAXIsProcessTrustedWithOptions) (CFDictionaryRef);
|
||||
|
||||
static CFStringRef* gkAXTrustedCheckOptionPrompt;
|
||||
|
||||
AXError _AXUIElementGetWindow(AXUIElementRef, CGWindowID* out);
|
||||
|
||||
static AXUIElementRef GetUIElement(CGWindowID win){
|
||||
intptr pid = 0;
|
||||
// double_t pid = 0;
|
||||
|
||||
// Create array storing window
|
||||
CGWindowID window[1] = { win };
|
||||
CFArrayRef wlist = CFArrayCreate(NULL,
|
||||
(const void**)window, 1, NULL);
|
||||
CFArrayRef wlist = CFArrayCreate(NULL, (const void**)window, 1, NULL);
|
||||
|
||||
// Get window info
|
||||
CFArrayRef info = CGWindowListCreateDescriptionFromArray(wlist);
|
||||
CFRelease(wlist);
|
||||
|
||||
// Check whether the resulting array is populated
|
||||
if (info != NULL && CFArrayGetCount(info) > 0){
|
||||
if (info != NULL && CFArrayGetCount(info) > 0) {
|
||||
// Retrieve description from info array
|
||||
CFDictionaryRef desc = (CFDictionaryRef)CFArrayGetValueAtIndex(info, 0);
|
||||
|
||||
// Get window PID
|
||||
CFNumberRef data =(CFNumberRef)
|
||||
CFDictionaryGetValue(desc, kCGWindowOwnerPID);
|
||||
|
||||
if (data != NULL){
|
||||
CFNumberRef data = (CFNumberRef) CFDictionaryGetValue(desc, kCGWindowOwnerPID);
|
||||
if (data != NULL) {
|
||||
CFNumberGetValue(data, kCFNumberIntType, &pid);
|
||||
}
|
||||
|
||||
@ -74,17 +79,15 @@ typedef struct _Bounds Bounds;
|
||||
}
|
||||
|
||||
// Check if PID was retrieved
|
||||
if (pid <= 0) {return NULL;}
|
||||
if (pid <= 0) { return NULL; }
|
||||
|
||||
// Create an accessibility object using retrieved PID
|
||||
AXUIElementRef application = AXUIElementCreateApplication(pid);
|
||||
|
||||
if (application == 0) {return NULL;}
|
||||
|
||||
CFArrayRef windows = NULL;
|
||||
// Get all windows associated with the app
|
||||
AXUIElementCopyAttributeValues(application,
|
||||
kAXWindowsAttribute, 0, 1024, &windows);
|
||||
AXUIElementCopyAttributeValues(application, kAXWindowsAttribute, 0, 1024, &windows);
|
||||
|
||||
// Reference to resulting value
|
||||
AXUIElementRef result = NULL;
|
||||
@ -94,14 +97,11 @@ typedef struct _Bounds Bounds;
|
||||
// Loop all windows in the process
|
||||
for (CFIndex i = 0; i < count; ++i){
|
||||
// Get the element at the index
|
||||
AXUIElementRef element = (AXUIElementRef)
|
||||
CFArrayGetValueAtIndex(windows, i);
|
||||
|
||||
AXUIElementRef element = (AXUIElementRef) CFArrayGetValueAtIndex(windows, i);
|
||||
CGWindowID temp = 0;
|
||||
// Use undocumented API to get WindowID
|
||||
_AXUIElementGetWindow(element, &temp);
|
||||
|
||||
// Check results
|
||||
if (temp == win) {
|
||||
// Retain element
|
||||
CFRetain(element);
|
||||
@ -117,15 +117,11 @@ typedef struct _Bounds Bounds;
|
||||
return result;
|
||||
}
|
||||
#elif defined(USE_X11)
|
||||
|
||||
// Error Handling
|
||||
|
||||
typedef int (*XErrorHandler) (Display*, XErrorEvent*);
|
||||
|
||||
static int XHandleError(Display* dp, XErrorEvent* e) { return 0; }
|
||||
|
||||
XErrorHandler mOld;
|
||||
|
||||
void XDismissErrors (void) {
|
||||
Display *rDisplay = XOpenDisplay(NULL);
|
||||
// Save old handler and dismiss errors
|
||||
@ -139,12 +135,11 @@ typedef struct _Bounds Bounds;
|
||||
}
|
||||
|
||||
// Definitions
|
||||
|
||||
struct Hints{
|
||||
unsigned long Flags;
|
||||
unsigned long Funcs;
|
||||
unsigned long Decorations;
|
||||
signed long Mode;
|
||||
signed long Mode;
|
||||
unsigned long Stat;
|
||||
};
|
||||
|
||||
@ -186,10 +181,8 @@ typedef struct _Bounds Bounds;
|
||||
XCloseDisplay(rDisplay);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Functions
|
||||
static void* GetWindowProperty(MData win, Atom atom, uint32* items){
|
||||
static void* GetWindowProperty(MData win, Atom atom, uint32_t* items) {
|
||||
// Property variables
|
||||
Atom type; int format;
|
||||
unsigned long nItems;
|
||||
@ -200,25 +193,22 @@ typedef struct _Bounds Bounds;
|
||||
// Check the atom
|
||||
if (atom != None) {
|
||||
// Retrieve and validate the specified property
|
||||
if (!XGetWindowProperty(rDisplay, win.XWin, atom, 0,
|
||||
BUFSIZ, False, AnyPropertyType, &type, &format,
|
||||
&nItems, &bAfter, &result) && result && nItems) {
|
||||
if (!XGetWindowProperty(rDisplay, win.XWin, atom, 0,
|
||||
BUFSIZ, False, AnyPropertyType, &type, &format, &nItems, &bAfter, &result)
|
||||
&& result && nItems) {
|
||||
|
||||
// Copy items result
|
||||
if (items != NULL) {
|
||||
*items = (uint32) nItems;
|
||||
*items = (uint32_t) nItems;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the items result if valid
|
||||
if (items != NULL) {*items = 0;}
|
||||
|
||||
// Free the result if it got allocated
|
||||
if (items != NULL) { *items = 0; }
|
||||
if (result != NULL) {
|
||||
XFree (result);
|
||||
XFree(result);
|
||||
}
|
||||
|
||||
XCloseDisplay(rDisplay);
|
||||
@ -226,12 +216,10 @@ typedef struct _Bounds Bounds;
|
||||
}
|
||||
|
||||
//////
|
||||
|
||||
#define STATE_TOPMOST 0
|
||||
#define STATE_MINIMIZE 1
|
||||
#define STATE_MAXIMIZE 2
|
||||
|
||||
|
||||
//////
|
||||
static void SetDesktopForWindow(MData win){
|
||||
Display *rDisplay = XOpenDisplay(NULL);
|
||||
@ -239,7 +227,6 @@ typedef struct _Bounds Bounds;
|
||||
if (WM_DESKTOP != None && WM_CURDESK != None) {
|
||||
// Get desktop property
|
||||
long* desktop = (long*)GetWindowProperty(win, WM_DESKTOP,NULL);
|
||||
|
||||
// Check result value
|
||||
if (desktop != NULL) {
|
||||
// Retrieve the screen number
|
||||
@ -258,9 +245,8 @@ typedef struct _Bounds Bounds;
|
||||
e.data.l[1] = CurrentTime;
|
||||
|
||||
// Send the message
|
||||
XSendEvent(rDisplay,
|
||||
root, False, SubstructureNotifyMask |
|
||||
SubstructureRedirectMask, (XEvent*) &e);
|
||||
XSendEvent(rDisplay, root, False, SubstructureNotifyMask | SubstructureRedirectMask,
|
||||
(XEvent*) &e);
|
||||
|
||||
XFree(desktop);
|
||||
}
|
||||
@ -272,27 +258,39 @@ typedef struct _Bounds Bounds;
|
||||
Bounds frame;
|
||||
// Retrieve frame bounds
|
||||
if (WM_EXTENTS != None) {
|
||||
long* result; uint32 nItems = 0;
|
||||
long* result; uint32_t nItems = 0;
|
||||
// Get the window extents property
|
||||
result = (long*) GetWindowProperty(win, WM_EXTENTS, &nItems);
|
||||
|
||||
// Verify the results
|
||||
if (result != NULL) {
|
||||
if (nItems == 4) {
|
||||
frame.X = (int32) result[0];
|
||||
frame.Y = (int32) result[2];
|
||||
frame.W = (int32) result[0] + (int32) result[1];
|
||||
frame.H = (int32) result[2] + (int32) result[3];
|
||||
frame.X = (int32_t) result[0];
|
||||
frame.Y = (int32_t) result[2];
|
||||
frame.W = (int32_t) result[0] + (int32_t) result[1];
|
||||
frame.H = (int32_t) result[2] + (int32_t) result[3];
|
||||
}
|
||||
|
||||
XFree(result);
|
||||
}
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
//
|
||||
void win_min(HWND hwnd, bool state){
|
||||
if (state) {
|
||||
ShowWindow(hwnd, SW_MINIMIZE);
|
||||
} else {
|
||||
ShowWindow(hwnd, SW_RESTORE);
|
||||
}
|
||||
}
|
||||
|
||||
void win_max(HWND hwnd, bool state){
|
||||
if (state) {
|
||||
ShowWindow(hwnd, SW_MAXIMIZE);
|
||||
} else {
|
||||
ShowWindow(hwnd, SW_RESTORE);
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,56 +0,0 @@
|
||||
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// #include "../base/os.h"
|
||||
|
||||
#if defined(IS_WINDOWS)
|
||||
typedef struct{
|
||||
HWND hWnd;
|
||||
DWORD dwPid;
|
||||
}WNDINFO;
|
||||
|
||||
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam){
|
||||
WNDINFO* pInfo = (WNDINFO*)lParam;
|
||||
DWORD dwProcessId = 0;
|
||||
GetWindowThreadProcessId(hWnd, &dwProcessId);
|
||||
|
||||
if (dwProcessId == pInfo->dwPid) {
|
||||
pInfo->hWnd = hWnd;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HWND GetHwndByPId(DWORD dwProcessId){
|
||||
WNDINFO info = {0};
|
||||
info.hWnd = NULL;
|
||||
info.dwPid = dwProcessId;
|
||||
EnumWindows(EnumWindowsProc, (LPARAM)&info);
|
||||
// printf("%d\n", info.hWnd);
|
||||
return info.hWnd;
|
||||
}
|
||||
|
||||
// window
|
||||
void win_min(HWND hwnd, bool state){
|
||||
if (state) {
|
||||
ShowWindow(hwnd, SW_MINIMIZE);
|
||||
} else {
|
||||
ShowWindow(hwnd, SW_RESTORE);
|
||||
}
|
||||
}
|
||||
|
||||
void win_max(HWND hwnd, bool state){
|
||||
if (state) {
|
||||
ShowWindow(hwnd, SW_MAXIMIZE);
|
||||
} else {
|
||||
ShowWindow(hwnd, SW_RESTORE);
|
||||
}
|
||||
}
|
||||
#endif
|
@ -20,26 +20,23 @@ 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)
|
||||
char *displayname = NULL;
|
||||
Display *dpy = XOpenDisplay(displayname);
|
||||
|
||||
Display *dpy = XOpenDisplay(NULL);
|
||||
|
||||
int scr = 0; /* Screen number */
|
||||
double xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) /
|
||||
((double) DisplayWidthMM(dpy, scr)));
|
||||
|
||||
// https://github.com/glfw/glfw/issues/1019#issuecomment-302772498
|
||||
char *rms = XResourceManagerString(dpy);
|
||||
if (rms) {
|
||||
XrmDatabase db = XrmGetStringDatabase(rms);
|
||||
@ -75,7 +72,6 @@ intptr scaleX(){
|
||||
HDC desktopDc = GetDC(NULL);
|
||||
// Get native resolution
|
||||
intptr horizontalDPI = GetDeviceCaps(desktopDc, LOGPIXELSX);
|
||||
// intptr verticalDPI = GetDeviceCaps(desktopDc, LOGPIXELSY);
|
||||
return horizontalDPI;
|
||||
#endif
|
||||
}
|
||||
@ -86,9 +82,7 @@ intptr scaleY(){
|
||||
#elif defined(USE_X11)
|
||||
return 0;
|
||||
#elif defined(IS_WINDOWS)
|
||||
// Get desktop dc
|
||||
HDC desktopDc = GetDC(NULL);
|
||||
// Get native resolution
|
||||
intptr verticalDPI = GetDeviceCaps(desktopDc, LOGPIXELSY);
|
||||
return verticalDPI;
|
||||
#endif
|
||||
@ -100,7 +94,6 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){
|
||||
if (!IsValid()) { return bounds; }
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
// Bounds bounds;
|
||||
AXValueRef axp = NULL;
|
||||
AXValueRef axs = NULL;
|
||||
@ -136,9 +129,7 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){
|
||||
if (axs != NULL) { CFRelease(axs); }
|
||||
|
||||
return bounds;
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
// Ignore X errors
|
||||
XDismissErrors();
|
||||
MData win;
|
||||
@ -153,7 +144,6 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){
|
||||
bounds.H = client.H + frame.H;
|
||||
|
||||
return bounds;
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
HWND hwnd;
|
||||
if (isHwnd == 0) {
|
||||
@ -171,21 +161,17 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){
|
||||
bounds.H = rect.bottom - rect.top;
|
||||
|
||||
return bounds;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
Bounds get_client(uintptr pid, uintptr isHwnd){
|
||||
Bounds get_client(uintptr pid, uintptr isHwnd) {
|
||||
// Check if the window is valid
|
||||
Bounds bounds;
|
||||
if (!IsValid()) { return bounds; }
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
return get_bounds(pid, isHwnd);
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
Display *rDisplay = XOpenDisplay(NULL);
|
||||
|
||||
// Ignore X errors
|
||||
@ -197,7 +183,7 @@ Bounds get_client(uintptr pid, uintptr isHwnd){
|
||||
Window root, parent;
|
||||
Window* children;
|
||||
unsigned int count;
|
||||
int32 x = 0, y = 0;
|
||||
int32_t x = 0, y = 0;
|
||||
|
||||
// Check if the window is the root
|
||||
XQueryTree(rDisplay, win.XWin,
|
||||
@ -227,7 +213,6 @@ Bounds get_client(uintptr pid, uintptr isHwnd){
|
||||
XCloseDisplay(rDisplay);
|
||||
|
||||
return bounds;
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
HWND hwnd;
|
||||
if (isHwnd == 0) {
|
||||
@ -253,6 +238,5 @@ Bounds get_client(uintptr pid, uintptr isHwnd){
|
||||
bounds.H = rect.bottom - rect.top;
|
||||
|
||||
return bounds;
|
||||
|
||||
#endif
|
||||
}
|
213
window/window.h
213
window/window.h
@ -9,10 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
// #include "../base/os.h"
|
||||
// #include <stdlib.h>
|
||||
#include "process.h"
|
||||
#include "pub.h"
|
||||
#include "win32.h"
|
||||
|
||||
bool setHandle(uintptr handle);
|
||||
bool IsValid();
|
||||
@ -22,16 +19,13 @@ void initWindow();
|
||||
char* get_title_by_hand(MData m_data);
|
||||
void close_window_by_Id(MData m_data);
|
||||
|
||||
//int findwindow()
|
||||
|
||||
// int findwindow()
|
||||
uintptr initHandle = 0;
|
||||
|
||||
void initWindow(uintptr handle){
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
mData.CgID = 0;
|
||||
mData.AxID = 0;
|
||||
|
||||
#elif defined(USE_X11)
|
||||
Display *rDisplay = XOpenDisplay(NULL);
|
||||
// If atoms loaded
|
||||
@ -45,7 +39,6 @@ void initWindow(uintptr handle){
|
||||
#elif defined(IS_WINDOWS)
|
||||
mData.HWnd = 0;
|
||||
#endif
|
||||
|
||||
setHandle(handle);
|
||||
}
|
||||
|
||||
@ -59,7 +52,6 @@ bool Is64Bit() {
|
||||
|
||||
MData set_handle_pid(uintptr pid, uintptr isHwnd){
|
||||
MData win;
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
// Handle to a AXUIElementRef
|
||||
win.AxID = AXUIElementCreateApplication(pid);
|
||||
@ -91,58 +83,50 @@ bool IsValid(){
|
||||
MData actdata = GetActive();
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
mData.CgID = actdata.CgID;
|
||||
mData.AxID = actdata.AxID;
|
||||
|
||||
if (mData.CgID == 0 || mData.AxID == 0)return false;
|
||||
if (mData.CgID == 0 || mData.AxID == 0){ return false; }
|
||||
|
||||
CFTypeRef r = NULL;
|
||||
|
||||
// Attempt to get the window role
|
||||
if (AXUIElementCopyAttributeValue(mData.AxID,
|
||||
kAXRoleAttribute,&r) == kAXErrorSuccess && r){
|
||||
CFRelease (r);
|
||||
if (AXUIElementCopyAttributeValue(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;}
|
||||
if (mData.XWin == 0) { return false; }
|
||||
|
||||
Display *rDisplay = XOpenDisplay(NULL);
|
||||
// Check for a valid X-Window display
|
||||
if (rDisplay == NULL) {return false;}
|
||||
if (rDisplay == NULL) { return false; }
|
||||
|
||||
// Ignore X errors
|
||||
XDismissErrors();
|
||||
|
||||
// Get the window PID property
|
||||
void* result = GetWindowProperty(mData, WM_PID,NULL);
|
||||
if (result == NULL) {return false;}
|
||||
if (result == NULL) { return false; }
|
||||
|
||||
// Free result and return true
|
||||
XFree(result);
|
||||
XCloseDisplay(rDisplay);
|
||||
return true;
|
||||
|
||||
return true;
|
||||
#elif defined(IS_WINDOWS)
|
||||
mData.HWnd = actdata.HWnd;
|
||||
|
||||
if (mData.HWnd == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsWindow(mData.HWnd) != 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsAxEnabled(bool options){
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
// Statically load all required functions one time
|
||||
static dispatch_once_t once; dispatch_once (&once,
|
||||
^{
|
||||
@ -152,19 +136,18 @@ bool IsAxEnabled(bool options){
|
||||
|
||||
// Validate the handle
|
||||
if (handle != NULL) {
|
||||
*(void**) (&gAXIsProcessTrustedWithOptions) =
|
||||
*(void**) (&gAXIsProcessTrustedWithOptions) =
|
||||
dlsym (handle, "AXIsProcessTrustedWithOptions");
|
||||
|
||||
gkAXTrustedCheckOptionPrompt = (CFStringRef*)
|
||||
dlsym (handle, "kAXTrustedCheckOptionPrompt");
|
||||
gkAXTrustedCheckOptionPrompt =
|
||||
(CFStringRef*) dlsym (handle, "kAXTrustedCheckOptionPrompt");
|
||||
}
|
||||
});
|
||||
|
||||
// Check for new OSX 10.9 function
|
||||
if (gAXIsProcessTrustedWithOptions) {
|
||||
// Check whether to show prompt
|
||||
CFBooleanRef displayPrompt = options ?
|
||||
kCFBooleanTrue : kCFBooleanFalse;
|
||||
CFBooleanRef displayPrompt = options ? kCFBooleanTrue : kCFBooleanFalse;
|
||||
|
||||
// Convert display prompt value into a dictionary
|
||||
const void* k[] = { *gkAXTrustedCheckOptionPrompt };
|
||||
@ -186,7 +169,6 @@ bool IsAxEnabled(bool options){
|
||||
return AXAPIEnabled() || AXIsProcessTrusted();
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
#elif defined(USE_X11)
|
||||
return true;
|
||||
#elif defined(IS_WINDOWS)
|
||||
@ -198,7 +180,7 @@ bool IsAxEnabled(bool options){
|
||||
bool setHandle(uintptr handle){
|
||||
#if defined(IS_MACOSX)
|
||||
// Release the AX element
|
||||
if (mData.AxID != NULL){
|
||||
if (mData.AxID != NULL) {
|
||||
CFRelease(mData.AxID);
|
||||
}
|
||||
|
||||
@ -206,7 +188,7 @@ bool setHandle(uintptr handle){
|
||||
mData.CgID = 0;
|
||||
mData.AxID = 0;
|
||||
|
||||
if (handle == 0){
|
||||
if (handle == 0) {
|
||||
// return 0;
|
||||
return true;
|
||||
}
|
||||
@ -214,7 +196,6 @@ bool setHandle(uintptr handle){
|
||||
// Retrieve the window element
|
||||
CGWindowID cgID = (CGWindowID)handle;
|
||||
AXUIElementRef axID = GetUIElement(cgID);
|
||||
|
||||
if (axID != NULL){
|
||||
mData.CgID = cgID;
|
||||
mData.AxID = axID;
|
||||
@ -224,11 +205,8 @@ bool setHandle(uintptr handle){
|
||||
|
||||
// return 1;
|
||||
return false;
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
mData.XWin = (Window)handle;
|
||||
|
||||
if (handle == 0){
|
||||
return true;
|
||||
}
|
||||
@ -240,9 +218,7 @@ bool setHandle(uintptr handle){
|
||||
mData.XWin = 0;
|
||||
return false;
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
mData.HWnd = (HWND)handle;
|
||||
|
||||
if (handle == 0) {
|
||||
return true;
|
||||
}
|
||||
@ -253,7 +229,6 @@ bool setHandle(uintptr handle){
|
||||
|
||||
mData.HWnd = 0;
|
||||
return false;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -272,20 +247,13 @@ bool IsTopMost(void){
|
||||
// Check the window validity
|
||||
if (!IsValid()) {return false;}
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
return false; // WARNING: Unavailable
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
// Ignore X errors
|
||||
// XDismissErrors ();
|
||||
// return GetState (mData.XWin, STATE_TOPMOST);
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
return (GetWindowLongPtr(mData.HWnd, GWL_EXSTYLE)
|
||||
& WS_EX_TOPMOST) != 0;
|
||||
|
||||
return (GetWindowLongPtr(mData.HWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -293,13 +261,10 @@ bool IsMinimized(void){
|
||||
// Check the window validity
|
||||
if (!IsValid()) {return false;}
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
CFBooleanRef data = NULL;
|
||||
|
||||
// Determine whether the window is minimized
|
||||
if (AXUIElementCopyAttributeValue(mData.AxID,
|
||||
kAXMinimizedAttribute, (CFTypeRef*) &data)
|
||||
== kAXErrorSuccess && data != NULL) {
|
||||
if (AXUIElementCopyAttributeValue(mData.AxID, kAXMinimizedAttribute,
|
||||
(CFTypeRef*) &data) == kAXErrorSuccess && data != NULL) {
|
||||
// Convert resulting data into a bool
|
||||
bool result = CFBooleanGetValue(data);
|
||||
CFRelease(data);
|
||||
@ -307,52 +272,36 @@ bool IsMinimized(void){
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
// Ignore X errors
|
||||
// XDismissErrors();
|
||||
// return GetState(mData.XWin, STATE_MINIMIZE);
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
return (GetWindowLongPtr(mData.HWnd, GWL_STYLE)
|
||||
& WS_MINIMIZE) != 0;
|
||||
|
||||
return (GetWindowLongPtr(mData.HWnd, GWL_STYLE) & WS_MINIMIZE) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//////
|
||||
|
||||
bool IsMaximized(void){
|
||||
// Check the window validity
|
||||
if (!IsValid()) {return false;}
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
return false; // WARNING: Unavailable
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
// Ignore X errors
|
||||
// XDismissErrors();
|
||||
// return GetState(mData.XWin, STATE_MAXIMIZE);
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
return (GetWindowLongPtr(mData.HWnd, GWL_STYLE)
|
||||
& WS_MAXIMIZE) != 0;
|
||||
|
||||
return (GetWindowLongPtr(mData.HWnd, GWL_STYLE) & WS_MAXIMIZE) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetActive(const MData win){
|
||||
void SetActive(const MData win) {
|
||||
// Check if the window is valid
|
||||
if (!IsValid()) { return; }
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
// Attempt to raise the specified window object
|
||||
if (AXUIElementPerformAction(win.AxID, kAXRaiseAction)
|
||||
!= kAXErrorSuccess) {
|
||||
if (AXUIElementPerformAction(win.AxID, kAXRaiseAction) != kAXErrorSuccess) {
|
||||
pid_t pid = 0;
|
||||
// Attempt to retrieve the PID of the window
|
||||
if (AXUIElementGetPid(win.AxID, &pid)
|
||||
@ -362,10 +311,6 @@ void SetActive(const MData win){
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
// NOTE: Until Apple actually removes
|
||||
// these functions, there's no real
|
||||
// reason to switch to the NS* flavor
|
||||
|
||||
ProcessSerialNumber psn;
|
||||
// Attempt to retrieve the process psn
|
||||
if (GetProcessForPID(pid, &psn) == 0) {
|
||||
@ -377,7 +322,6 @@ void SetActive(const MData win){
|
||||
}
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
// Ignore X errors
|
||||
XDismissErrors();
|
||||
|
||||
@ -410,24 +354,20 @@ void SetActive(const MData win){
|
||||
XRaiseWindow(rDisplay, win.XWin);
|
||||
|
||||
// Set the specified window's input focus
|
||||
XSetInputFocus(rDisplay, win.XWin,
|
||||
RevertToParent, CurrentTime);
|
||||
XSetInputFocus(rDisplay, win.XWin, RevertToParent, CurrentTime);
|
||||
}
|
||||
XCloseDisplay(rDisplay);
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
if (IsMinimized()) {
|
||||
ShowWindow(win.HWnd, SW_RESTORE);
|
||||
}
|
||||
|
||||
SetForegroundWindow(win.HWnd);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
MData GetActive(void){
|
||||
MData GetActive(void) {
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
MData result;
|
||||
// Ignore deprecated warnings
|
||||
#pragma clang diagnostic push
|
||||
@ -435,8 +375,7 @@ MData GetActive(void){
|
||||
|
||||
ProcessSerialNumber psn; pid_t pid;
|
||||
// Attempt to retrieve the front process
|
||||
if (GetFrontProcess(&psn) != 0 ||
|
||||
GetProcessPID(&psn, &pid) != 0) {
|
||||
if (GetFrontProcess(&psn) != 0 || GetProcessPID(&psn, &pid) != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -448,30 +387,23 @@ MData GetActive(void){
|
||||
|
||||
AXUIElementRef element;
|
||||
// Retrieve the currently focused window
|
||||
if (AXUIElementCopyAttributeValue(focused,
|
||||
kAXFocusedWindowAttribute, (CFTypeRef*)
|
||||
&element) == kAXErrorSuccess && element) {
|
||||
if (AXUIElementCopyAttributeValue(focused, kAXFocusedWindowAttribute, (CFTypeRef*) &element)
|
||||
== kAXErrorSuccess && element) {
|
||||
|
||||
CGWindowID win = 0;
|
||||
// Use undocumented API to get WID
|
||||
if (_AXUIElementGetWindow(element, &win)
|
||||
== kAXErrorSuccess && win) {
|
||||
if (_AXUIElementGetWindow(element, &win) == kAXErrorSuccess && win) {
|
||||
// Manually set internals
|
||||
result.CgID = win;
|
||||
result.AxID = element;
|
||||
}
|
||||
// Something went wrong
|
||||
else {
|
||||
} else {
|
||||
CFRelease(element);
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(focused);
|
||||
|
||||
return result;
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
MData result;
|
||||
Display *rDisplay = XOpenDisplay(NULL);
|
||||
// Check X-Window display
|
||||
@ -508,13 +440,11 @@ MData GetActive(void){
|
||||
// Return foreground window
|
||||
result.XWin = window;
|
||||
return result;
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
// Attempt to get the foreground window multiple times in case
|
||||
MData result;
|
||||
|
||||
uint8 times = 0;
|
||||
uint8_t times = 0;
|
||||
while (++times < 20) {
|
||||
HWND handle;
|
||||
handle = GetForegroundWindow();
|
||||
@ -523,11 +453,10 @@ MData GetActive(void){
|
||||
result.HWnd = (HWND)handle;
|
||||
return result;
|
||||
}
|
||||
Sleep (20);
|
||||
Sleep(20);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -536,21 +465,14 @@ void SetTopMost(bool state){
|
||||
// Check window validity
|
||||
if (!IsValid()) {return;}
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
// WARNING: Unavailable
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
// Ignore X errors
|
||||
// XDismissErrors();
|
||||
// SetState(mData.XWin, STATE_TOPMOST, state);
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
SetWindowPos(mData.HWnd,
|
||||
state ? HWND_TOPMOST : HWND_NOTOPMOST,
|
||||
SetWindowPos(mData.HWnd, state ? HWND_TOPMOST : HWND_NOTOPMOST,
|
||||
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -573,20 +495,15 @@ void close_window_by_Id(MData m_data){
|
||||
if (!IsValid()) { return; }
|
||||
#if defined(IS_MACOSX)
|
||||
AXUIElementRef b = NULL;
|
||||
|
||||
// Retrieve the close button of this window
|
||||
if (AXUIElementCopyAttributeValue(m_data.AxID,
|
||||
kAXCloseButtonAttribute, (CFTypeRef*) &b)
|
||||
if (AXUIElementCopyAttributeValue(m_data.AxID, kAXCloseButtonAttribute, (CFTypeRef*) &b)
|
||||
== kAXErrorSuccess && b != NULL) {
|
||||
// Simulate button press on the close button
|
||||
AXUIElementPerformAction(b, kAXPressAction);
|
||||
CFRelease(b);
|
||||
}
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
Display *rDisplay = XOpenDisplay(NULL);
|
||||
|
||||
// Ignore X errors
|
||||
XDismissErrors();
|
||||
|
||||
@ -594,7 +511,6 @@ void close_window_by_Id(MData m_data){
|
||||
XDestroyWindow(rDisplay, m_data.XWin);
|
||||
XCloseDisplay(rDisplay);
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
PostMessage(m_data.HWnd, WM_CLOSE, 0, 0);
|
||||
#endif
|
||||
}
|
||||
@ -611,18 +527,29 @@ char* get_title_by_pid(uintptr pid, uintptr isHwnd){
|
||||
return get_title_by_hand(win);
|
||||
}
|
||||
|
||||
char* named(void *result) {
|
||||
char *name = (char*)calloc(strlen(result)+1, sizeof(char*));
|
||||
char *rptr = (char*)result;
|
||||
char *nptr = name;
|
||||
while (*rptr) {
|
||||
*nptr = *rptr;
|
||||
nptr++;
|
||||
rptr++;
|
||||
}
|
||||
*nptr = '\0';
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
char* get_title_by_hand(MData m_data){
|
||||
// Check if the window is valid
|
||||
if (!IsValid()) {return "IsValid failed.";}
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
CFStringRef data = NULL;
|
||||
|
||||
// Determine the current title of the window
|
||||
if (AXUIElementCopyAttributeValue(m_data.AxID,
|
||||
kAXTitleAttribute, (CFTypeRef*) &data)
|
||||
== kAXErrorSuccess && data != NULL) {
|
||||
kAXTitleAttribute, (CFTypeRef*) &data) == kAXErrorSuccess && data != NULL) {
|
||||
char conv[512];
|
||||
// Convert result to a C-String
|
||||
CFStringGetCString(data, conv, 512, kCFStringEncodingUTF8);
|
||||
@ -635,28 +562,17 @@ char* get_title_by_hand(MData m_data){
|
||||
}
|
||||
|
||||
return "";
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
void* result;
|
||||
// Ignore X errors
|
||||
XDismissErrors();
|
||||
|
||||
// Get window title (UTF-8)
|
||||
result = GetWindowProperty(m_data, WM_NAME, NULL);
|
||||
|
||||
// Check result value
|
||||
if (result != NULL) {
|
||||
// Convert result to a string
|
||||
char *name = (char*)calloc(strlen(result)+1, sizeof(char*));
|
||||
char *rptr = (char*)result;
|
||||
char *nptr = name;
|
||||
while (*rptr) {
|
||||
*nptr = *rptr;
|
||||
nptr++;
|
||||
rptr++;
|
||||
}
|
||||
*nptr = '\0';
|
||||
char* name = named(result);
|
||||
XFree(result);
|
||||
|
||||
if (name != NULL) { return name; }
|
||||
@ -664,28 +580,17 @@ char* get_title_by_hand(MData m_data){
|
||||
|
||||
// Get window title (ASCII)
|
||||
result = GetWindowProperty(m_data, XA_WM_NAME, NULL);
|
||||
|
||||
// Check result value
|
||||
if (result != NULL) {
|
||||
// Convert result to a string
|
||||
char *name = (char*)calloc(strlen(result)+1, sizeof(char*));
|
||||
char *rptr = (char*)result;
|
||||
char *nptr = name;
|
||||
while (*rptr) {
|
||||
*nptr = *rptr;
|
||||
nptr++;
|
||||
rptr++;
|
||||
}
|
||||
*nptr = '\0';
|
||||
char* name = named(result);
|
||||
XFree(result);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
return "";
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
if (GetWindowText(m_data.HWnd, m_data.Title, 512) > 0){
|
||||
char* name = m_data.Title;
|
||||
|
||||
@ -695,44 +600,36 @@ char* get_title_by_hand(MData m_data){
|
||||
}
|
||||
|
||||
return "";
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
int32 WGetPID(void){
|
||||
int32_t WGetPID(void) {
|
||||
// Check window validity
|
||||
if (!IsValid()) { return 0; }
|
||||
|
||||
#if defined(IS_MACOSX)
|
||||
|
||||
pid_t pid = 0;
|
||||
// Attempt to retrieve the window pid
|
||||
if (AXUIElementGetPid(mData.AxID, &pid)== kAXErrorSuccess) {
|
||||
return pid;
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
#elif defined(USE_X11)
|
||||
|
||||
// Ignore X errors
|
||||
XDismissErrors();
|
||||
|
||||
// Get the window PID
|
||||
long* result = (long*)GetWindowProperty(mData, WM_PID,NULL);
|
||||
|
||||
// Check result and convert it
|
||||
if (result == NULL) { return 0; }
|
||||
int32 pid = (int32) *result;
|
||||
|
||||
int32_t pid = (int32_t) *result;
|
||||
XFree(result);
|
||||
return pid;
|
||||
|
||||
#elif defined(IS_WINDOWS)
|
||||
|
||||
DWORD id = 0;
|
||||
DWORD id = 0;
|
||||
GetWindowThreadProcessId(mData.HWnd, &id);
|
||||
return id;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user