123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- // 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_MACOSX)
- #include <dlfcn.h>
- #elif defined(USE_X11)
- #include <X11/Xatom.h>
- #endif
- struct _MData{
- #if defined(IS_MACOSX)
- CGWindowID CgID; // Handle to a CGWindowID
- AXUIElementRef AxID; // Handle to a AXUIElementRef
- #elif defined(USE_X11)
- Window XWin; // Handle to an X11 window
- #elif defined(IS_WINDOWS)
- HWND HWnd; // Handle to a window HWND
- TCHAR Title[512];
- #endif
- };
- typedef struct _MData MData;
- MData pub_mData;
- 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);
- // Get window info
- CFArrayRef info = CGWindowListCreateDescriptionFromArray(wlist);
- CFRelease(wlist);
- // Check whether the resulting array is populated
- 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) {
- CFNumberGetValue(data, kCFNumberIntType, &pid);
- }
- // Return result
- CFRelease(info);
- }
- // Check if PID was retrieved
- 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);
- // Reference to resulting value
- AXUIElementRef result = NULL;
- if (windows != NULL) {
- int count = CFArrayGetCount(windows);
- // 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);
- CGWindowID temp = 0;
- // Use undocumented API to get WindowID
- _AXUIElementGetWindow(element, &temp);
- if (temp == win) {
- // Retain element
- CFRetain(element);
- result = element;
- break;
- }
- }
- CFRelease(windows);
- }
- CFRelease(application);
- 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
- mOld = XSetErrorHandler(XHandleError);
- // Flush output buffer
- XSync(rDisplay, False);
- // Reinstate old handler
- XSetErrorHandler(mOld);
- XCloseDisplay(rDisplay);
- }
- // Definitions
- struct Hints{
- unsigned long Flags;
- unsigned long Funcs;
- unsigned long Decorations;
- signed long Mode;
- unsigned long Stat;
- };
- static Atom WM_STATE = None;
- static Atom WM_ABOVE = None;
- static Atom WM_HIDDEN = None;
- static Atom WM_HMAX = None;
- static Atom WM_VMAX = None;
- static Atom WM_DESKTOP = None;
- static Atom WM_CURDESK = None;
- static Atom WM_NAME = None;
- static Atom WM_UTF8 = None;
- static Atom WM_PID = None;
- static Atom WM_ACTIVE = None;
- static Atom WM_HINTS = None;
- static Atom WM_EXTENTS = None;
- ////////////////////////////////////////////////////////////////////////////////
- static void LoadAtoms (void){
- Display *rDisplay = XOpenDisplay(NULL);
- WM_STATE = XInternAtom(rDisplay, "_NET_WM_STATE", True);
- WM_ABOVE = XInternAtom(rDisplay, "_NET_WM_STATE_ABOVE", True);
- WM_HIDDEN = XInternAtom(rDisplay, "_NET_WM_STATE_HIDDEN", True);
- WM_HMAX = XInternAtom(rDisplay, "_NET_WM_STATE_MAXIMIZED_HORZ", True);
- WM_VMAX = XInternAtom(rDisplay, "_NET_WM_STATE_MAXIMIZED_VERT", True);
- WM_DESKTOP = XInternAtom(rDisplay, "_NET_WM_DESKTOP", True);
- WM_CURDESK = XInternAtom(rDisplay, "_NET_CURRENT_DESKTOP", True);
- WM_NAME = XInternAtom(rDisplay, "_NET_WM_NAME", True);
- WM_UTF8 = XInternAtom(rDisplay, "UTF8_STRING", True);
- WM_PID = XInternAtom(rDisplay, "_NET_WM_PID", True);
- WM_ACTIVE = XInternAtom(rDisplay, "_NET_ACTIVE_WINDOW", True);
- WM_HINTS = XInternAtom(rDisplay, "_MOTIF_WM_HINTS", True);
- WM_EXTENTS = XInternAtom(rDisplay, "_NET_FRAME_EXTENTS", True);
- XCloseDisplay(rDisplay);
- }
- // Functions
- static void* GetWindowProperty(MData win, Atom atom, uint32_t* items) {
- // Property variables
- Atom type; int format;
- unsigned long nItems;
- unsigned long bAfter;
- unsigned char* result = NULL;
- Display *rDisplay = XOpenDisplay(NULL);
- // 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) {
- // Copy items result
- if (items != NULL) {
- *items = (uint32_t) nItems;
- }
- XCloseDisplay(rDisplay);
- return result;
- }
- }
- // Reset the items result if valid
- if (items != NULL) { *items = 0; }
- if (result != NULL) {
- XFree(result);
- }
- XCloseDisplay(rDisplay);
- return NULL;
- }
- //////
- #define STATE_TOPMOST 0
- #define STATE_MINIMIZE 1
- #define STATE_MAXIMIZE 2
- //////
- static void SetDesktopForWindow(MData win){
- Display *rDisplay = XOpenDisplay(NULL);
- // Validate every atom that we want to use
- 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
- XWindowAttributes attr = { 0 };
- XGetWindowAttributes(rDisplay, win.XWin, &attr);
- int s = XScreenNumberOfScreen(attr.screen);
- Window root = XRootWindow(rDisplay, s);
- // Prepare an event
- XClientMessageEvent e = { 0 };
- e.window = root; e.format = 32;
- e.message_type = WM_CURDESK;
- e.display = rDisplay;
- e.type = ClientMessage;
- e.data.l[0] = *desktop;
- e.data.l[1] = CurrentTime;
- // Send the message
- XSendEvent(rDisplay, root, False, SubstructureNotifyMask | SubstructureRedirectMask,
- (XEvent*) &e);
- XFree(desktop);
- }
- }
- XCloseDisplay(rDisplay);
- }
- static Bounds GetFrame(MData win){
- Bounds frame;
- // Retrieve frame bounds
- if (WM_EXTENTS != None) {
- long* result; uint32_t nItems = 0;
- // Get the window extents property
- result = (long*) GetWindowProperty(win, WM_EXTENTS, &nItems);
- if (result != NULL) {
- if (nItems == 4) {
- 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)
- HWND getHwnd(uintptr pid, int8_t isPid);
-
- 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
|