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:
Evans 2022-01-22 11:39:24 -04:00 committed by GitHub
commit 897af2a0db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 289 additions and 571 deletions

View File

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

View File

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

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

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

View File

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

View File

@ -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. */

View File

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

View File

@ -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;
// }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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