From 481fbb72a5e6b6ba48d7bfea721ef22d7422c590 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 21 Jan 2022 15:58:02 -0400 Subject: [PATCH] Add more multi screen support, update go mod, remove some code --- base/os.h | 14 +++ base/win32.h | 34 +++++++ examples/screen/main.go | 6 +- go.mod | 11 ++- go.sum | 31 +++--- screen/goScreen.h | 57 +++++------ screen/screengrab_c.h | 24 +++-- window/alert_c.h | 113 +++++++++++---------- window/arr.h | 26 ----- window/goWindow.h | 2 +- window/process.h | 133 ------------------------- window/pub.h | 95 +++++++++--------- window/win32.h | 56 ----------- window/win_sys.h | 24 +---- window/window.h | 212 +++++++++++----------------------------- 15 files changed, 277 insertions(+), 561 deletions(-) create mode 100644 base/win32.h delete mode 100644 window/arr.h delete mode 100644 window/process.h delete mode 100644 window/win32.h diff --git a/base/os.h b/base/os.h index ab46989..5d08c4f 100644 --- a/base/os.h +++ b/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 */ diff --git a/base/win32.h b/base/win32.h new file mode 100644 index 0000000..d5b458e --- /dev/null +++ b/base/win32.h @@ -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 \ No newline at end of file diff --git a/examples/screen/main.go b/examples/screen/main.go index d6d7ff3..118a8b9 100644 --- a/examples/screen/main.go +++ b/examples/screen/main.go @@ -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() diff --git a/go.mod b/go.mod index d2f60ef..0d96a29 100644 --- a/go.mod +++ b/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 ) diff --git a/go.sum b/go.sum index 4bed75b..16a189a 100644 --- a/go.sum +++ b/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= diff --git a/screen/goScreen.h b/screen/goScreen.h index ab6cf70..3a38f87 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -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 // #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; diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index ebc9b68..32367b5 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -17,15 +17,13 @@ #include #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. */ diff --git a/window/alert_c.h b/window/alert_c.h index 12f7143..db7455e 100644 --- a/window/alert_c.h +++ b/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 diff --git a/window/arr.h b/window/arr.h deleted file mode 100644 index 26bc835..0000000 --- a/window/arr.h +++ /dev/null @@ -1,26 +0,0 @@ -// #include -// #include -// #include - -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; -// } \ No newline at end of file diff --git a/window/goWindow.h b/window/goWindow.h index ea56f6f..fd8a794 100644 --- a/window/goWindow.h +++ b/window/goWindow.h @@ -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; } diff --git a/window/process.h b/window/process.h deleted file mode 100644 index 0324967..0000000 --- a/window/process.h +++ /dev/null @@ -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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// #include -#include -#if defined(IS_MACOSX) - #if defined (__x86_64__) - #define RobotGo_64 - #else - #define RobotGo_32 - #endif - // #include - // #include - // #include - - // Apple process API - #include - #include - #include - - #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 - #include - - #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 - #include -#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; diff --git a/window/pub.h b/window/pub.h index a781491..a30d52f 100644 --- a/window/pub.h +++ b/window/pub.h @@ -10,6 +10,14 @@ // #include "../base/os.h" +#ifdef RobotGo_64 + typedef int64 intptr; + typedef uint64 uintptr; +#else + typedef int32_t intptr; + typedef uint32_t uintptr; // Unsigned pointer integer +#endif + struct _MData{ #if defined(IS_MACOSX) CGWindowID CgID; // Handle to a CGWindowID @@ -23,49 +31,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 +74,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 +92,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 +112,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 +130,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 +176,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* items) { // Property variables Atom type; int format; unsigned long nItems; @@ -200,25 +188,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; } - 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 +211,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 +222,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 +240,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); } @@ -275,8 +256,6 @@ typedef struct _Bounds Bounds; long* result; uint32 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]; @@ -288,11 +267,25 @@ typedef struct _Bounds Bounds; 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 \ No newline at end of file diff --git a/window/win32.h b/window/win32.h deleted file mode 100644 index 8935aef..0000000 --- a/window/win32.h +++ /dev/null @@ -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 or the MIT license -// , 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 \ No newline at end of file diff --git a/window/win_sys.h b/window/win_sys.h index 0a7cbe6..3710eb9 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -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,7 +161,6 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){ bounds.H = rect.bottom - rect.top; return bounds; - #endif } @@ -181,11 +170,8 @@ Bounds get_client(uintptr pid, uintptr isHwnd){ if (!IsValid()) { return bounds; } #if defined(IS_MACOSX) - return get_bounds(pid, isHwnd); - #elif defined(USE_X11) - Display *rDisplay = XOpenDisplay(NULL); // Ignore X errors @@ -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 } \ No newline at end of file diff --git a/window/window.h b/window/window.h index a8cba40..83bd7b7 100644 --- a/window/window.h +++ b/window/window.h @@ -9,10 +9,10 @@ // except according to those terms. // #include "../base/os.h" -// #include -#include "process.h" #include "pub.h" -#include "win32.h" +#if defined(IS_MACOSX) + #include +#endif bool setHandle(uintptr handle); bool IsValid(); @@ -22,16 +22,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 +42,6 @@ void initWindow(uintptr handle){ #elif defined(IS_WINDOWS) mData.HWnd = 0; #endif - setHandle(handle); } @@ -59,7 +55,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 +86,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 +139,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 +172,6 @@ bool IsAxEnabled(bool options){ return AXAPIEnabled() || AXIsProcessTrusted(); #pragma clang diagnostic pop } - #elif defined(USE_X11) return true; #elif defined(IS_WINDOWS) @@ -198,7 +183,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 +191,7 @@ bool setHandle(uintptr handle){ mData.CgID = 0; mData.AxID = 0; - if (handle == 0){ + if (handle == 0) { // return 0; return true; } @@ -214,7 +199,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 +208,8 @@ bool setHandle(uintptr handle){ // return 1; return false; - #elif defined(USE_X11) - mData.XWin = (Window)handle; - if (handle == 0){ return true; } @@ -240,9 +221,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 +232,6 @@ bool setHandle(uintptr handle){ mData.HWnd = 0; return false; - #endif } @@ -272,20 +250,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 +264,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 +275,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 +314,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 +325,6 @@ void SetActive(const MData win){ } #elif defined(USE_X11) - // Ignore X errors XDismissErrors(); @@ -410,24 +357,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 +378,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 +390,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,9 +443,7 @@ 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; @@ -523,11 +456,10 @@ MData GetActive(void){ result.HWnd = (HWND)handle; return result; } - Sleep (20); + Sleep(20); } return result; - #endif } @@ -536,21 +468,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 +498,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 +514,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 +530,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 +565,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 +583,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 +603,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; XFree(result); return pid; - #elif defined(IS_WINDOWS) - - DWORD id = 0; + DWORD id = 0; GetWindowThreadProcessId(mData.HWnd, &id); return id; - #endif }