robotgo/window/window.h

720 lines
14 KiB
C
Raw Permalink Normal View History

2016-11-10 06:34:13 +00:00
// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
2016-12-11 09:14:14 +00:00
// https://github.com/go-vgo/robotgo/blob/master/LICENSE
2016-11-10 06:34:13 +00:00
//
// 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.
2016-11-10 10:59:37 +00:00
// #include "../base/os.h"
// #include <stdlib.h>
2016-11-21 09:08:11 +00:00
#include "process.h"
#include "pub.h"
2018-08-21 17:04:23 +00:00
#include "win32.h"
2016-11-10 10:59:37 +00:00
bool setHandle(uintptr handle);
bool IsValid();
bool IsAxEnabled(bool options);
2018-01-21 14:21:16 +00:00
MData GetActive(void);
2018-07-09 11:55:37 +00:00
void initWindow();
2018-08-21 16:47:31 +00:00
char* get_title_by_hand(MData m_data);
void close_window_by_Id(MData m_data);
2016-11-10 10:59:37 +00:00
//int findwindow()
2018-07-09 11:55:37 +00:00
uintptr initHandle = 0;
2016-11-10 10:59:37 +00:00
2018-07-09 11:55:37 +00:00
void initWindow(uintptr handle){
2016-11-10 10:59:37 +00:00
#if defined(IS_MACOSX)
mData.CgID = 0;
mData.AxID = 0;
#elif defined(USE_X11)
Display *rDisplay = XOpenDisplay(NULL);
// If atoms loaded
2018-07-09 11:55:37 +00:00
if (WM_PID == None) {
2016-11-10 10:59:37 +00:00
// Load all necessary atom properties
2018-01-21 13:56:33 +00:00
if (rDisplay != NULL) {LoadAtoms();}
2016-11-10 10:59:37 +00:00
}
mData.XWin = 0;
#elif defined(IS_WINDOWS)
mData.HWnd = 0;
#endif
setHandle(handle);
}
2019-05-06 14:33:10 +00:00
bool Is64Bit() {
#ifdef RobotGo_64
return true;
#endif
return false;
}
MData set_handle_pid(uintptr pid, uintptr isHwnd){
2018-08-21 17:04:23 +00:00
MData win;
#if defined(IS_MACOSX)
// Handle to a AXUIElementRef
win.AxID = AXUIElementCreateApplication(pid);
#elif defined(USE_X11)
win.XWin = (Window)pid; // Handle to an X11 window
#elif defined(IS_WINDOWS)
// win.HWnd = (HWND)pid; // Handle to a window HWND
if (isHwnd == 0) {
win.HWnd = GetHwndByPId(pid);
} else {
win.HWnd = (HWND)pid;
}
#endif
return win;
}
void set_handle_pid_mData(uintptr pid, uintptr isHwnd){
MData win = set_handle_pid(pid, isHwnd);
mData = win;
}
2018-01-21 14:21:16 +00:00
bool IsValid(){
2018-07-09 11:55:37 +00:00
initWindow(initHandle);
2018-07-09 12:10:22 +00:00
if (!IsAxEnabled(true)) {
printf("%s\n", "Window:Accessibility API is disabled!\n"
"Failed to enable access for assistive devices.");
2018-01-21 13:56:33 +00:00
}
2017-11-20 14:03:30 +00:00
MData actdata = GetActive();
2016-11-10 10:59:37 +00:00
#if defined(IS_MACOSX)
2017-11-20 14:03:30 +00:00
mData.CgID = actdata.CgID;
mData.AxID = actdata.AxID;
2016-11-10 10:59:37 +00:00
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);
return true;
}
return false;
#elif defined(USE_X11)
2017-11-23 15:44:41 +00:00
mData.XWin = actdata.XWin;
2018-01-21 13:56:33 +00:00
if (mData.XWin == 0) {return false;}
2016-11-10 10:59:37 +00:00
Display *rDisplay = XOpenDisplay(NULL);
// Check for a valid X-Window display
2018-01-21 13:56:33 +00:00
if (rDisplay == NULL) {return false;}
2016-11-10 10:59:37 +00:00
// Ignore X errors
XDismissErrors();
// Get the window PID property
void* result = GetWindowProperty(mData, WM_PID,NULL);
2018-01-21 13:56:33 +00:00
if (result == NULL) {return false;}
2016-11-10 10:59:37 +00:00
// Free result and return true
2018-02-11 11:03:35 +00:00
XFree(result);
2018-01-21 13:56:33 +00:00
return true;
2016-11-10 10:59:37 +00:00
#elif defined(IS_WINDOWS)
2017-11-20 14:03:30 +00:00
mData.HWnd = actdata.HWnd;
2016-11-10 10:59:37 +00:00
2018-07-09 11:55:37 +00:00
if (mData.HWnd == 0) {
2016-11-10 10:59:37 +00:00
return false;
2018-01-21 13:56:33 +00:00
}
2016-11-10 10:59:37 +00:00
2018-01-21 13:56:33 +00:00
return IsWindow(mData.HWnd) != 0;
2016-11-10 10:59:37 +00:00
#endif
}
2018-01-21 14:21:16 +00:00
bool IsAxEnabled(bool options){
2016-11-10 10:59:37 +00:00
#if defined(IS_MACOSX)
// Statically load all required functions one time
static dispatch_once_t once; dispatch_once (&once,
^{
// Open the framework
2018-01-21 13:56:33 +00:00
void* handle = dlopen("/System/Library/Frameworks/Application"
2016-11-10 10:59:37 +00:00
"Services.framework/ApplicationServices", RTLD_LAZY);
// Validate the handle
2018-07-09 11:55:37 +00:00
if (handle != NULL) {
2016-11-10 10:59:37 +00:00
*(void**) (&gAXIsProcessTrustedWithOptions) =
dlsym (handle, "AXIsProcessTrustedWithOptions");
gkAXTrustedCheckOptionPrompt = (CFStringRef*)
dlsym (handle, "kAXTrustedCheckOptionPrompt");
}
});
// Check for new OSX 10.9 function
2018-07-09 11:55:37 +00:00
if (gAXIsProcessTrustedWithOptions) {
2016-11-10 10:59:37 +00:00
// Check whether to show prompt
CFBooleanRef displayPrompt = options ?
kCFBooleanTrue : kCFBooleanFalse;
// Convert display prompt value into a dictionary
const void* k[] = { *gkAXTrustedCheckOptionPrompt };
const void* v[] = { displayPrompt };
2018-01-21 14:21:16 +00:00
CFDictionaryRef o = CFDictionaryCreate(NULL, k, v, 1, NULL, NULL);
2016-11-10 10:59:37 +00:00
// Determine whether the process is actually trusted
2018-01-21 13:56:33 +00:00
bool result = (*gAXIsProcessTrustedWithOptions)(o);
2016-11-10 10:59:37 +00:00
// Free memory
2018-01-21 13:56:33 +00:00
CFRelease(o);
2016-11-10 10:59:37 +00:00
return result;
2018-07-09 11:55:37 +00:00
} else {
2016-11-10 10:59:37 +00:00
// Ignore deprecated warnings
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// Check whether we have accessibility access
return AXAPIEnabled() || AXIsProcessTrusted();
#pragma clang diagnostic pop
}
#elif defined(USE_X11)
return true;
#elif defined(IS_WINDOWS)
return true;
#endif
}
// int
2018-01-21 14:21:16 +00:00
bool setHandle(uintptr handle){
2016-11-10 10:59:37 +00:00
#if defined(IS_MACOSX)
// Release the AX element
2018-01-21 13:56:33 +00:00
if (mData.AxID != NULL){
CFRelease(mData.AxID);
2018-02-11 11:03:35 +00:00
}
2016-11-10 10:59:37 +00:00
// Reset both values
mData.CgID = 0;
mData.AxID = 0;
2018-01-21 14:21:16 +00:00
if (handle == 0){
// return 0;
return true;
2018-01-21 14:21:16 +00:00
}
2016-11-10 10:59:37 +00:00
// Retrieve the window element
2018-01-21 13:56:33 +00:00
CGWindowID cgID = (CGWindowID)handle;
AXUIElementRef axID = GetUIElement(cgID);
2016-11-10 10:59:37 +00:00
if (axID != NULL){
mData.CgID = cgID;
mData.AxID = axID;
// return 0;
return true;
}
// return 1;
return false;
#elif defined(USE_X11)
2018-01-21 13:56:33 +00:00
mData.XWin = (Window)handle;
2016-11-10 10:59:37 +00:00
2018-01-21 13:56:33 +00:00
if (handle == 0){
2016-11-10 10:59:37 +00:00
return true;
2018-01-21 13:56:33 +00:00
}
2016-11-10 10:59:37 +00:00
2018-01-21 13:56:33 +00:00
if (IsValid()){
2016-11-10 10:59:37 +00:00
return true;
2018-01-21 13:56:33 +00:00
}
2016-11-10 10:59:37 +00:00
mData.XWin = 0;
return false;
#elif defined(IS_WINDOWS)
2018-01-21 13:56:33 +00:00
mData.HWnd = (HWND)handle;
2016-11-10 10:59:37 +00:00
2018-07-09 11:55:37 +00:00
if (handle == 0) {
2016-11-10 10:59:37 +00:00
return true;
2018-01-21 13:56:33 +00:00
}
2016-11-10 10:59:37 +00:00
2018-07-09 11:55:37 +00:00
if (IsValid()) {
2016-11-10 10:59:37 +00:00
return true;
2018-01-21 13:56:33 +00:00
}
2016-11-10 10:59:37 +00:00
mData.HWnd = 0;
return false;
#endif
}
2018-04-11 13:14:57 +00:00
// uint32 uintptr
2018-07-09 11:55:37 +00:00
uintptr getHandle() {
#if defined(IS_MACOSX)
return (uintptr)mData.CgID;
#elif defined(USE_X11)
return (uintptr)mData.XWin;
#elif defined(IS_WINDOWS)
return (uintptr)mData.HWnd;
#endif
2016-11-10 10:59:37 +00:00
}
2018-01-21 14:21:16 +00:00
bool IsTopMost(void){
2016-11-10 10:59:37 +00:00
// Check the window validity
2018-01-21 13:56:33 +00:00
if (!IsValid()) {return false;}
2016-11-10 10:59:37 +00:00
#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)
2018-02-11 11:03:35 +00:00
return (GetWindowLongPtr(mData.HWnd, GWL_EXSTYLE)
& WS_EX_TOPMOST) != 0;
2016-11-10 10:59:37 +00:00
#endif
}
2016-11-23 12:40:28 +00:00
bool IsMinimized(void){
// Check the window validity
2018-01-21 13:56:33 +00:00
if (!IsValid()) {return false;}
2016-11-23 12:40:28 +00:00
#if defined(IS_MACOSX)
CFBooleanRef data = NULL;
// Determine whether the window is minimized
2018-01-21 14:21:16 +00:00
if (AXUIElementCopyAttributeValue(mData.AxID,
2016-11-23 12:40:28 +00:00
kAXMinimizedAttribute, (CFTypeRef*) &data)
2018-07-09 11:55:37 +00:00
== kAXErrorSuccess && data != NULL) {
2016-11-23 12:40:28 +00:00
// Convert resulting data into a bool
bool result = CFBooleanGetValue(data);
2018-02-11 11:03:35 +00:00
CFRelease(data);
2018-01-21 14:21:16 +00:00
return result;
2016-11-23 12:40:28 +00:00
}
return false;
#elif defined(USE_X11)
// Ignore X errors
// XDismissErrors();
2018-08-13 12:53:49 +00:00
// return GetState(mData.XWin, STATE_MINIMIZE);
2016-11-23 12:40:28 +00:00
#elif defined(IS_WINDOWS)
2018-02-11 11:03:35 +00:00
return (GetWindowLongPtr(mData.HWnd, GWL_STYLE)
& WS_MINIMIZE) != 0;
2016-11-23 12:40:28 +00:00
#endif
}
//////
bool IsMaximized(void){
// Check the window validity
2018-01-21 13:56:33 +00:00
if (!IsValid()) {return false;}
2016-11-23 12:40:28 +00:00
#if defined(IS_MACOSX)
return false; // WARNING: Unavailable
#elif defined(USE_X11)
// Ignore X errors
// XDismissErrors();
2018-08-13 12:53:49 +00:00
// return GetState(mData.XWin, STATE_MAXIMIZE);
2016-11-23 12:40:28 +00:00
#elif defined(IS_WINDOWS)
2018-02-11 11:03:35 +00:00
return (GetWindowLongPtr(mData.HWnd, GWL_STYLE)
& WS_MAXIMIZE) != 0;
2016-11-23 12:40:28 +00:00
#endif
}
void SetActive(const MData win){
// Check if the window is valid
if (!IsValid()) { return; }
2016-11-23 12:40:28 +00:00
#if defined(IS_MACOSX)
// Attempt to raise the specified window object
2018-02-11 11:03:35 +00:00
if (AXUIElementPerformAction(win.AxID, kAXRaiseAction)
2018-07-09 11:55:37 +00:00
!= kAXErrorSuccess) {
2016-11-23 12:40:28 +00:00
pid_t pid = 0;
// Attempt to retrieve the PID of the window
2018-02-11 11:03:35 +00:00
if (AXUIElementGetPid(win.AxID, &pid)
2018-01-21 13:56:33 +00:00
!= kAXErrorSuccess || !pid) {return;}
2016-11-23 12:40:28 +00:00
// Ignore deprecated warnings
#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
2018-07-09 11:55:37 +00:00
if (GetProcessForPID(pid, &psn) == 0) {
2016-11-23 12:40:28 +00:00
// Gracefully activate process
2018-01-21 13:56:33 +00:00
SetFrontProcessWithOptions(&psn, kSetFrontProcessFrontWindowOnly);
2016-11-23 12:40:28 +00:00
}
#pragma clang diagnostic pop
}
#elif defined(USE_X11)
// Ignore X errors
XDismissErrors();
// Go to the specified window's desktop
SetDesktopForWindow(win);
Display *rDisplay = XOpenDisplay(NULL);
// Check the atom value
2018-07-09 11:55:37 +00:00
if (WM_ACTIVE != None) {
2016-11-23 12:40:28 +00:00
// Retrieve the screen number
XWindowAttributes attr = { 0 };
2018-02-11 11:03:35 +00:00
XGetWindowAttributes(rDisplay, win.XWin, &attr);
2016-11-23 12:40:28 +00:00
int s = XScreenNumberOfScreen(attr.screen);
// Prepare an event
XClientMessageEvent e = { 0 };
e.window = win.XWin;
e.format = 32;
e.message_type = WM_ACTIVE;
e.display = rDisplay;
e.type = ClientMessage;
e.data.l[0] = 2;
e.data.l[1] = CurrentTime;
// Send the message
2018-01-21 14:21:16 +00:00
XSendEvent(rDisplay, XRootWindow(rDisplay, s), False,
2016-11-23 12:40:28 +00:00
SubstructureNotifyMask | SubstructureRedirectMask,
(XEvent*) &e);
2018-07-09 11:55:37 +00:00
} else {
2016-11-23 12:40:28 +00:00
// Attempt to raise the specified window
XRaiseWindow(rDisplay, win.XWin);
// Set the specified window's input focus
XSetInputFocus(rDisplay, win.XWin,
RevertToParent, CurrentTime);
}
#elif defined(IS_WINDOWS)
2018-07-09 11:55:37 +00:00
if (IsMinimized()) {
2016-11-23 12:40:28 +00:00
ShowWindow(win.HWnd, SW_RESTORE);
2018-01-21 13:56:33 +00:00
}
2016-11-23 12:40:28 +00:00
2018-01-21 13:56:33 +00:00
SetForegroundWindow(win.HWnd);
2016-11-23 12:40:28 +00:00
#endif
}
2018-01-21 14:21:16 +00:00
MData GetActive(void){
2016-11-10 10:59:37 +00:00
#if defined(IS_MACOSX)
MData result;
// Ignore deprecated warnings
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
ProcessSerialNumber psn; pid_t pid;
// Attempt to retrieve the front process
2018-01-21 14:21:16 +00:00
if (GetFrontProcess(&psn) != 0 ||
2018-07-09 11:55:37 +00:00
GetProcessPID(&psn, &pid) != 0) {
2016-11-10 10:59:37 +00:00
return result;
2018-01-21 13:56:33 +00:00
}
2016-11-10 10:59:37 +00:00
#pragma clang diagnostic pop
// Create accessibility object using focused PID
2018-01-21 13:56:33 +00:00
AXUIElementRef focused = AXUIElementCreateApplication(pid);
if (focused == NULL) {return result; }// Verify
2016-11-10 10:59:37 +00:00
AXUIElementRef element;
// Retrieve the currently focused window
2018-01-21 14:21:16 +00:00
if (AXUIElementCopyAttributeValue(focused,
2016-11-10 10:59:37 +00:00
kAXFocusedWindowAttribute, (CFTypeRef*)
2018-07-09 11:55:37 +00:00
&element) == kAXErrorSuccess && element) {
2018-01-21 13:56:33 +00:00
2016-11-10 10:59:37 +00:00
CGWindowID win = 0;
// Use undocumented API to get WID
2018-02-11 11:03:35 +00:00
if (_AXUIElementGetWindow(element, &win)
2018-07-09 11:55:37 +00:00
== kAXErrorSuccess && win) {
2016-11-10 10:59:37 +00:00
// Manually set internals
result.CgID = win;
result.AxID = element;
}
// Something went wrong
2018-01-21 13:56:33 +00:00
else {
CFRelease(element);
}
2016-11-10 10:59:37 +00:00
}
2018-01-21 13:56:33 +00:00
CFRelease(focused);
2018-02-11 11:03:35 +00:00
2016-11-10 10:59:37 +00:00
return result;
#elif defined(USE_X11)
MData result;
Display *rDisplay = XOpenDisplay(NULL);
// Check X-Window display
2018-07-09 11:55:37 +00:00
if (WM_ACTIVE == None || rDisplay == NULL) {
2016-11-10 10:59:37 +00:00
return result;
2018-01-21 13:56:33 +00:00
}
2016-11-10 10:59:37 +00:00
// Ignore X errors
XDismissErrors();
// Get the current active window
2018-01-21 13:56:33 +00:00
result.XWin = XDefaultRootWindow(rDisplay);
2018-08-13 12:53:49 +00:00
void* active = GetWindowProperty(result, WM_ACTIVE, NULL);
2016-11-10 10:59:37 +00:00
// Check result value
2018-07-09 11:55:37 +00:00
if (active != NULL) {
2016-11-10 10:59:37 +00:00
// Extract window from the result
2018-01-21 14:21:16 +00:00
long window = *((long*)active);
2018-02-11 11:03:35 +00:00
XFree(active);
2018-01-21 13:56:33 +00:00
2018-07-09 11:55:37 +00:00
if (window != 0) {
2016-11-10 10:59:37 +00:00
// Set and return the foreground window
2018-01-21 14:21:16 +00:00
result.XWin = (Window)window;
2016-11-10 10:59:37 +00:00
return result;
}
}
// Use input focus instead
Window window = None;
int revert = RevertToNone;
XGetInputFocus(rDisplay, &window, &revert);
2016-11-10 10:59:37 +00:00
// 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;
2018-07-09 11:55:37 +00:00
while (++times < 20) {
2016-11-10 10:59:37 +00:00
HWND handle;
handle = GetForegroundWindow();
2018-07-09 11:55:37 +00:00
if (handle != NULL) {
2017-11-23 15:44:41 +00:00
// mData.HWnd = (uintptr) handle;
result.HWnd = (HWND)handle;
2016-11-10 10:59:37 +00:00
return result;
}
Sleep (20);
}
return result;
#endif
}
2018-01-21 14:21:16 +00:00
void SetTopMost(bool state){
2016-11-10 10:59:37 +00:00
// Check window validity
2018-01-21 13:56:33 +00:00
if (!IsValid()) {return;}
2016-11-10 10:59:37 +00:00
#if defined(IS_MACOSX)
// WARNING: Unavailable
#elif defined(USE_X11)
// Ignore X errors
2018-02-11 11:03:35 +00:00
// XDismissErrors();
// SetState(mData.XWin, STATE_TOPMOST, state);
2016-11-10 10:59:37 +00:00
#elif defined(IS_WINDOWS)
2018-02-11 11:03:35 +00:00
SetWindowPos(mData.HWnd,
state ? HWND_TOPMOST : HWND_NOTOPMOST,
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
2016-11-10 10:59:37 +00:00
#endif
}
void close_main_window (){
// Check if the window is valid
if (!IsValid()) { return; }
close_window_by_Id(mData);
}
void close_window_by_PId(uintptr pid, uintptr isHwnd){
MData win = set_handle_pid(pid, isHwnd);
close_window_by_Id(win);
}
2017-11-23 15:44:41 +00:00
// CloseWindow
void close_window_by_Id(MData m_data){
2016-11-10 10:59:37 +00:00
// Check window validity
2019-03-19 15:15:33 +00:00
if (!IsValid()) { return; }
2016-11-10 10:59:37 +00:00
#if defined(IS_MACOSX)
AXUIElementRef b = NULL;
// Retrieve the close button of this window
if (AXUIElementCopyAttributeValue(m_data.AxID,
2016-11-10 10:59:37 +00:00
kAXCloseButtonAttribute, (CFTypeRef*) &b)
2018-07-09 11:55:37 +00:00
== kAXErrorSuccess && b != NULL) {
2016-11-10 10:59:37 +00:00
// Simulate button press on the close button
2018-01-21 13:56:33 +00:00
AXUIElementPerformAction(b, kAXPressAction);
CFRelease(b);
2016-11-10 10:59:37 +00:00
}
#elif defined(USE_X11)
Display *rDisplay = XOpenDisplay(NULL);
// Ignore X errors
XDismissErrors();
// Close the window
XDestroyWindow(rDisplay, m_data.XWin);
2016-11-10 10:59:37 +00:00
#elif defined(IS_WINDOWS)
PostMessage(m_data.HWnd, WM_CLOSE, 0, 0);
2016-11-10 10:59:37 +00:00
#endif
}
char* get_main_title(){
2018-08-23 14:42:23 +00:00
// Check if the window is valid
2019-03-19 15:15:33 +00:00
if (!IsValid()) { return "IsValid failed."; }
2018-08-23 14:42:23 +00:00
2018-08-21 17:04:23 +00:00
return get_title_by_hand(mData);
}
char* get_title_by_pid(uintptr pid, uintptr isHwnd){
MData win = set_handle_pid(pid, isHwnd);
2018-08-21 17:04:23 +00:00
return get_title_by_hand(win);
}
char* get_title_by_hand(MData m_data){
2016-11-10 10:59:37 +00:00
// Check if the window is valid
2018-01-21 13:56:33 +00:00
if (!IsValid()) {return "IsValid failed.";}
2018-08-21 17:04:23 +00:00
2016-11-10 10:59:37 +00:00
#if defined(IS_MACOSX)
CFStringRef data = NULL;
2018-02-11 11:03:35 +00:00
2016-11-10 10:59:37 +00:00
// Determine the current title of the window
if (AXUIElementCopyAttributeValue(m_data.AxID,
2016-11-10 10:59:37 +00:00
kAXTitleAttribute, (CFTypeRef*) &data)
2018-07-09 11:55:37 +00:00
== kAXErrorSuccess && data != NULL) {
2016-11-10 10:59:37 +00:00
char conv[512];
// Convert result to a C-String
2018-10-21 17:39:07 +00:00
CFStringGetCString(data, conv, 512, kCFStringEncodingUTF8);
2018-01-21 13:56:33 +00:00
CFRelease(data);
2018-10-21 17:39:07 +00:00
2018-01-21 13:56:33 +00:00
char* s = (char*)calloc(100, sizeof(char*));
2018-10-21 17:39:07 +00:00
if (s) { strcpy(s, conv); }
2016-11-10 10:59:37 +00:00
// return (char *)&conv;
return s;
}
2017-11-20 14:03:30 +00:00
return "";
2016-11-10 10:59:37 +00:00
#elif defined(USE_X11)
void* result;
// Ignore X errors
XDismissErrors();
// Get window title (UTF-8)
2019-03-19 15:05:32 +00:00
result = GetWindowProperty(m_data, WM_NAME, NULL);
2016-11-10 10:59:37 +00:00
// Check result value
2018-07-09 11:55:37 +00:00
if (result != NULL) {
2016-11-10 10:59:37 +00:00
// Convert result to a string
2018-01-21 14:21:16 +00:00
char *name = (char*)result;
2018-01-21 13:56:33 +00:00
XFree(result);
2016-11-10 10:59:37 +00:00
2019-03-19 15:05:32 +00:00
if (name != NULL) { return name; }
2016-11-10 10:59:37 +00:00
}
// Get window title (ASCII)
2019-03-19 15:05:32 +00:00
result = GetWindowProperty(m_data, XA_WM_NAME, NULL);
2016-11-10 10:59:37 +00:00
// Check result value
2018-07-09 11:55:37 +00:00
if (result != NULL) {
2016-11-10 10:59:37 +00:00
// Convert result to a string
2018-01-21 14:21:16 +00:00
char *name = (char*)result;
2018-02-11 11:03:35 +00:00
XFree(result);
2018-01-21 13:56:33 +00:00
return name;
2016-11-10 10:59:37 +00:00
}
2017-11-20 14:03:30 +00:00
return "";
2016-11-10 10:59:37 +00:00
#elif defined(IS_WINDOWS)
if (GetWindowText(m_data.HWnd, m_data.Title, 512) > 0){
char* name = m_data.Title;
char* str = (char*)calloc(100, sizeof(char*));
2019-03-19 15:05:32 +00:00
if (str) { strcpy(str, name); }
return str;
}
return "";
2016-11-10 10:59:37 +00:00
#endif
}
2017-01-18 12:34:35 +00:00
int32 WGetPID(void){
// Check window validity
2019-03-19 15:05:32 +00:00
if (!IsValid()) { return 0; }
2017-01-18 12:34:35 +00:00
#if defined(IS_MACOSX)
pid_t pid = 0;
// Attempt to retrieve the window pid
2018-08-13 12:53:49 +00:00
if (AXUIElementGetPid(mData.AxID, &pid)== kAXErrorSuccess) {
return pid;
}
2017-01-18 12:34:35 +00:00
return 0;
#elif defined(USE_X11)
// Ignore X errors
XDismissErrors();
// Get the window PID
2018-01-21 13:56:33 +00:00
long* result = (long*)GetWindowProperty(mData, WM_PID,NULL);
2017-01-18 12:34:35 +00:00
// Check result and convert it
2019-03-19 15:05:32 +00:00
if (result == NULL) { return 0; }
2017-01-18 12:34:35 +00:00
int32 pid = (int32) *result;
2018-02-11 11:03:35 +00:00
XFree(result);
2018-01-21 13:56:33 +00:00
return pid;
2017-01-18 12:34:35 +00:00
#elif defined(IS_WINDOWS)
DWORD id = 0;
2018-01-21 13:56:33 +00:00
GetWindowThreadProcessId(mData.HWnd, &id);
2017-01-18 12:34:35 +00:00
return id;
#endif
}