window.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  1. // Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT
  2. // file at the top-level directory of this distribution and at
  3. // https://github.com/go-vgo/robotgo/blob/master/LICENSE
  4. //
  5. // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  6. // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  7. // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  8. // option. This file may not be copied, modified, or distributed
  9. // except according to those terms.
  10. // #include "../base/os.h"
  11. // #include <stdlib.h>
  12. #include "process.h"
  13. struct _MData{
  14. #if defined(IS_MACOSX)
  15. CGWindowID CgID; // Handle to a CGWindowID
  16. AXUIElementRef AxID; // Handle to a AXUIElementRef
  17. #elif defined(USE_X11)
  18. Window XWin; // Handle to an X11 window
  19. #elif defined(IS_WINDOWS)
  20. HWND HWnd; // Handle to a window HWND
  21. #endif
  22. };
  23. typedef struct _MData MData;
  24. MData mData;
  25. bool setHandle(uintptr handle);
  26. bool IsValid();
  27. bool IsAxEnabled(bool options);
  28. MData GetActive (void);
  29. void aWindow();
  30. #if defined(IS_MACOSX)
  31. static Boolean (*gAXIsProcessTrustedWithOptions) (CFDictionaryRef);
  32. static CFStringRef* gkAXTrustedCheckOptionPrompt;
  33. AXError _AXUIElementGetWindow (AXUIElementRef, CGWindowID* out);
  34. static AXUIElementRef GetUIElement (CGWindowID win){
  35. intptr pid = 0;
  36. // double_t pid=0;
  37. // Create array storing window
  38. CGWindowID window[1] = { win };
  39. CFArrayRef wlist = CFArrayCreate (NULL,
  40. (const void**) window, 1, NULL);
  41. // Get window info
  42. CFArrayRef info =CGWindowListCreateDescriptionFromArray (wlist);
  43. CFRelease (wlist);
  44. // Check whether the resulting array is populated
  45. if (info != NULL && CFArrayGetCount (info) > 0){
  46. // Retrieve description from info array
  47. CFDictionaryRef desc = (CFDictionaryRef) CFArrayGetValueAtIndex (info, 0);
  48. // Get window PID
  49. CFNumberRef data =(CFNumberRef)
  50. CFDictionaryGetValue (desc, kCGWindowOwnerPID);
  51. if (data != NULL)
  52. CFNumberGetValue (data, kCFNumberIntType, &pid);
  53. // Return result
  54. CFRelease (info);
  55. }
  56. // Check if PID was retrieved
  57. if (pid <= 0) return NULL;
  58. // Create an accessibility object using retrieved PID
  59. AXUIElementRef application = AXUIElementCreateApplication (pid);
  60. if (application == 0) return NULL;
  61. CFArrayRef windows = NULL;
  62. // Get all windows associated with the app
  63. AXUIElementCopyAttributeValues (application,
  64. kAXWindowsAttribute, 0, 1024, &windows);
  65. // Reference to resulting value
  66. AXUIElementRef result = NULL;
  67. if (windows != NULL){
  68. int count = CFArrayGetCount (windows);
  69. // Loop all windows in the process
  70. for (CFIndex i = 0; i < count; ++i){
  71. // Get the element at the index
  72. AXUIElementRef element = (AXUIElementRef)
  73. CFArrayGetValueAtIndex (windows, i);
  74. CGWindowID temp = 0;
  75. // Use undocumented API to get WindowID
  76. _AXUIElementGetWindow (element, &temp);
  77. // Check results
  78. if (temp == win){
  79. // Retain element
  80. CFRetain (element);
  81. result = element;
  82. break;
  83. }
  84. }
  85. CFRelease (windows);
  86. }
  87. CFRelease (application);
  88. return result;
  89. }
  90. #elif defined(USE_X11)
  91. // Error Handling
  92. typedef int (*XErrorHandler) (Display*, XErrorEvent*);
  93. static int XHandleError (Display* dp, XErrorEvent* e) { return 0; }
  94. XErrorHandler mOld;
  95. void XDismissErrors (void){
  96. Display *rDisplay = XOpenDisplay(NULL);
  97. // Save old handler and dismiss errors
  98. mOld = XSetErrorHandler (XHandleError);
  99. // Flush output buffer
  100. XSync (rDisplay, False);
  101. // Reinstate old handler
  102. XSetErrorHandler (mOld);
  103. }
  104. // Definitions
  105. struct Hints
  106. {
  107. unsigned long Flags;
  108. unsigned long Funcs;
  109. unsigned long Decorations;
  110. signed long Mode;
  111. unsigned long Stat;
  112. };
  113. static Atom WM_STATE = None;
  114. static Atom WM_ABOVE = None;
  115. static Atom WM_HIDDEN = None;
  116. static Atom WM_HMAX = None;
  117. static Atom WM_VMAX = None;
  118. static Atom WM_DESKTOP = None;
  119. static Atom WM_CURDESK = None;
  120. static Atom WM_NAME = None;
  121. static Atom WM_UTF8 = None;
  122. static Atom WM_PID = None;
  123. static Atom WM_ACTIVE = None;
  124. static Atom WM_HINTS = None;
  125. static Atom WM_EXTENTS = None;
  126. ////////////////////////////////////////////////////////////////////////////////
  127. static void LoadAtoms (void)
  128. {
  129. Display *rDisplay = XOpenDisplay(NULL);
  130. WM_STATE = XInternAtom (rDisplay, "_NET_WM_STATE", True);
  131. WM_ABOVE = XInternAtom (rDisplay, "_NET_WM_STATE_ABOVE", True);
  132. WM_HIDDEN = XInternAtom (rDisplay, "_NET_WM_STATE_HIDDEN", True);
  133. WM_HMAX = XInternAtom (rDisplay, "_NET_WM_STATE_MAXIMIZED_HORZ", True);
  134. WM_VMAX = XInternAtom (rDisplay, "_NET_WM_STATE_MAXIMIZED_VERT", True);
  135. WM_DESKTOP = XInternAtom (rDisplay, "_NET_WM_DESKTOP", True);
  136. WM_CURDESK = XInternAtom (rDisplay, "_NET_CURRENT_DESKTOP", True);
  137. WM_NAME = XInternAtom (rDisplay, "_NET_WM_NAME", True);
  138. WM_UTF8 = XInternAtom (rDisplay, "UTF8_STRING", True);
  139. WM_PID = XInternAtom (rDisplay, "_NET_WM_PID", True);
  140. WM_ACTIVE = XInternAtom (rDisplay, "_NET_ACTIVE_WINDOW", True);
  141. WM_HINTS = XInternAtom (rDisplay, "_MOTIF_WM_HINTS", True);
  142. WM_EXTENTS = XInternAtom (rDisplay, "_NET_FRAME_EXTENTS", True);
  143. }
  144. // Functions
  145. static void* GetWindowProperty (MData win, Atom atom, uint32* items)
  146. {
  147. // Property variables
  148. Atom type; int format;
  149. unsigned long nItems;
  150. unsigned long bAfter;
  151. unsigned char* result = NULL;
  152. Display *rDisplay = XOpenDisplay(NULL);
  153. // Check the atom
  154. if (atom != None)
  155. {
  156. // Retrieve and validate the specified property
  157. if (!XGetWindowProperty (rDisplay, win.XWin, atom, 0,
  158. BUFSIZ, False, AnyPropertyType, &type, &format,
  159. &nItems, &bAfter, &result) && result && nItems)
  160. {
  161. // Copy items result
  162. if (items != NULL)
  163. *items = (uint32) nItems;
  164. return result;
  165. }
  166. }
  167. // Reset the items result if valid
  168. if (items != NULL) *items = 0;
  169. // Free the result if it got allocated
  170. if (result != NULL) XFree (result);
  171. return NULL;
  172. }
  173. //////
  174. #define STATE_TOPMOST 0
  175. #define STATE_MINIMIZE 1
  176. #define STATE_MAXIMIZE 2
  177. //////
  178. static void SetDesktopForWindow (MData win){
  179. Display *rDisplay = XOpenDisplay(NULL);
  180. // Validate every atom that we want to use
  181. if (WM_DESKTOP != None && WM_CURDESK != None){
  182. // Get desktop property
  183. long* desktop = (long*)
  184. GetWindowProperty (win, WM_DESKTOP,NULL);
  185. // Check result value
  186. if (desktop != NULL){
  187. // Retrieve the screen number
  188. XWindowAttributes attr = { 0 };
  189. XGetWindowAttributes (rDisplay, win.XWin, &attr);
  190. int s = XScreenNumberOfScreen (attr.screen);
  191. Window root = XRootWindow(rDisplay, s);
  192. // Prepare an event
  193. XClientMessageEvent e = { 0 };
  194. e.window = root; e.format = 32;
  195. e.message_type = WM_CURDESK;
  196. e.display = rDisplay;
  197. e.type = ClientMessage;
  198. e.data.l[0] = *desktop;
  199. e.data.l[1] = CurrentTime;
  200. // Send the message
  201. XSendEvent(rDisplay,
  202. root, False, SubstructureNotifyMask |
  203. SubstructureRedirectMask, (XEvent*) &e);
  204. XFree(desktop);
  205. }
  206. }
  207. }
  208. #elif defined(IS_WINDOWS)
  209. //
  210. #endif
  211. //int findwindow()
  212. uintptr ahandle = 0;
  213. void aWindow(uintptr handle){
  214. #if defined(IS_MACOSX)
  215. mData.CgID = 0;
  216. mData.AxID = 0;
  217. #elif defined(USE_X11)
  218. Display *rDisplay = XOpenDisplay(NULL);
  219. // If atoms loaded
  220. if (WM_PID == None){
  221. // Load all necessary atom properties
  222. if (rDisplay != NULL) LoadAtoms();
  223. }
  224. mData.XWin = 0;
  225. #elif defined(IS_WINDOWS)
  226. mData.HWnd = 0;
  227. #endif
  228. setHandle(handle);
  229. }
  230. bool IsValid (){
  231. aWindow(ahandle);
  232. if(!IsAxEnabled(true))printf("%s\n", "Window:Accessibility API is disabled!\nFailed to enable access for assistive devices.");
  233. MData actdata=GetActive();
  234. #if defined(IS_MACOSX)
  235. mData.CgID=actdata.CgID;
  236. mData.AxID=actdata.AxID;
  237. if (mData.CgID == 0 || mData.AxID == 0)return false;
  238. CFTypeRef r = NULL;
  239. // Attempt to get the window role
  240. if (AXUIElementCopyAttributeValue(mData.AxID,
  241. kAXRoleAttribute,&r) == kAXErrorSuccess && r){
  242. CFRelease (r);
  243. return true;
  244. }
  245. return false;
  246. #elif defined(USE_X11)
  247. mData.XWin=actdata.XWin;
  248. if (mData.XWin == 0)return false;
  249. Display *rDisplay = XOpenDisplay(NULL);
  250. // Check for a valid X-Window display
  251. if (rDisplay == NULL) return false;
  252. // Ignore X errors
  253. XDismissErrors();
  254. // Get the window PID property
  255. void* result = GetWindowProperty(mData, WM_PID,NULL);
  256. if (result == NULL) return false;
  257. // Free result and return true
  258. XFree (result); return true;
  259. #elif defined(IS_WINDOWS)
  260. mData.HWnd=actdata.HWnd;
  261. if (mData.HWnd == 0)
  262. return false;
  263. return IsWindow (mData.HWnd) != 0;
  264. #endif
  265. }
  266. bool IsAxEnabled (bool options){
  267. #if defined(IS_MACOSX)
  268. // Statically load all required functions one time
  269. static dispatch_once_t once; dispatch_once (&once,
  270. ^{
  271. // Open the framework
  272. void* handle = dlopen
  273. ("/System/Library/Frameworks/Application"
  274. "Services.framework/ApplicationServices", RTLD_LAZY);
  275. // Validate the handle
  276. if (handle != NULL){
  277. *(void**) (&gAXIsProcessTrustedWithOptions) =
  278. dlsym (handle, "AXIsProcessTrustedWithOptions");
  279. gkAXTrustedCheckOptionPrompt = (CFStringRef*)
  280. dlsym (handle, "kAXTrustedCheckOptionPrompt");
  281. }
  282. });
  283. // Check for new OSX 10.9 function
  284. if (gAXIsProcessTrustedWithOptions){
  285. // Check whether to show prompt
  286. CFBooleanRef displayPrompt = options ?
  287. kCFBooleanTrue : kCFBooleanFalse;
  288. // Convert display prompt value into a dictionary
  289. const void* k[] = { *gkAXTrustedCheckOptionPrompt };
  290. const void* v[] = { displayPrompt };
  291. CFDictionaryRef o = CFDictionaryCreate
  292. (NULL, k, v, 1, NULL, NULL);
  293. // Determine whether the process is actually trusted
  294. bool result = (*gAXIsProcessTrustedWithOptions) (o);
  295. // Free memory
  296. CFRelease (o);
  297. return result;
  298. }else{
  299. // Ignore deprecated warnings
  300. #pragma clang diagnostic push
  301. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  302. // Check whether we have accessibility access
  303. return AXAPIEnabled() || AXIsProcessTrusted();
  304. #pragma clang diagnostic pop
  305. }
  306. #elif defined(USE_X11)
  307. return true;
  308. #elif defined(IS_WINDOWS)
  309. return true;
  310. #endif
  311. }
  312. // int
  313. bool setHandle (uintptr handle){
  314. #if defined(IS_MACOSX)
  315. // Release the AX element
  316. if (mData.AxID != NULL)CFRelease (mData.AxID);
  317. // Reset both values
  318. mData.CgID = 0;
  319. mData.AxID = 0;
  320. if (handle == 0)return 0;
  321. // return true;
  322. // Retrieve the window element
  323. CGWindowID cgID = (CGWindowID) handle;
  324. AXUIElementRef axID = GetUIElement (cgID);
  325. if (axID != NULL){
  326. mData.CgID = cgID;
  327. mData.AxID = axID;
  328. // return 0;
  329. return true;
  330. }
  331. // return 1;
  332. return false;
  333. #elif defined(USE_X11)
  334. mData.XWin = (Window) handle;
  335. if (handle == 0)
  336. return true;
  337. if (IsValid())
  338. return true;
  339. mData.XWin = 0;
  340. return false;
  341. #elif defined(IS_WINDOWS)
  342. mData.HWnd = (HWND) handle;
  343. if (handle == 0)
  344. return true;
  345. if (IsValid())
  346. return true;
  347. mData.HWnd = 0;
  348. return false;
  349. #endif
  350. }
  351. //uint32 uintptr
  352. uintptr getHandle(){
  353. #if defined(IS_MACOSX)
  354. return (uintptr) mData.CgID;
  355. #elif defined(USE_X11)
  356. return (uintptr) mData.XWin;
  357. #elif defined(IS_WINDOWS)
  358. return (uintptr) mData.HWnd;
  359. #endif
  360. }
  361. bool IsTopMost (void){
  362. // Check the window validity
  363. if (!IsValid()) return false;
  364. #if defined(IS_MACOSX)
  365. return false; // WARNING: Unavailable
  366. #elif defined(USE_X11)
  367. // Ignore X errors
  368. // XDismissErrors ();
  369. // return GetState (mData.XWin, STATE_TOPMOST);
  370. #elif defined(IS_WINDOWS)
  371. return (GetWindowLongPtr (mData.HWnd,
  372. GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
  373. #endif
  374. }
  375. bool IsMinimized(void){
  376. // Check the window validity
  377. if (!IsValid()) return false;
  378. #if defined(IS_MACOSX)
  379. CFBooleanRef data = NULL;
  380. // Determine whether the window is minimized
  381. if (AXUIElementCopyAttributeValue (mData.AxID,
  382. kAXMinimizedAttribute, (CFTypeRef*) &data)
  383. == kAXErrorSuccess && data != NULL)
  384. {
  385. // Convert resulting data into a bool
  386. bool result = CFBooleanGetValue(data);
  387. CFRelease (data); return result;
  388. }
  389. return false;
  390. #elif defined(USE_X11)
  391. // Ignore X errors
  392. // XDismissErrors();
  393. // return GetState (mData.XWin, STATE_MINIMIZE);
  394. #elif defined(IS_WINDOWS)
  395. return (GetWindowLongPtr (mData.HWnd,
  396. GWL_STYLE) & WS_MINIMIZE) != 0;
  397. #endif
  398. }
  399. //////
  400. bool IsMaximized(void){
  401. // Check the window validity
  402. if (!IsValid()) return false;
  403. #if defined(IS_MACOSX)
  404. return false; // WARNING: Unavailable
  405. #elif defined(USE_X11)
  406. // Ignore X errors
  407. // XDismissErrors();
  408. // return GetState (mData.XWin, STATE_MAXIMIZE);
  409. #elif defined(IS_WINDOWS)
  410. return (GetWindowLongPtr (mData.HWnd,
  411. GWL_STYLE) & WS_MAXIMIZE) != 0;
  412. #endif
  413. }
  414. void SetActive(const MData win){
  415. // Check if the window is valid
  416. if (!IsValid()) return;
  417. #if defined(IS_MACOSX)
  418. // Attempt to raise the specified window object
  419. if (AXUIElementPerformAction (win.AxID,
  420. kAXRaiseAction) == kAXErrorSuccess)
  421. {
  422. pid_t pid = 0;
  423. // Attempt to retrieve the PID of the window
  424. if (AXUIElementGetPid (win.AxID, &pid)
  425. != kAXErrorSuccess || !pid) return;
  426. // Ignore deprecated warnings
  427. #pragma clang diagnostic push
  428. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  429. // NOTE: Until Apple actually removes
  430. // these functions, there's no real
  431. // reason to switch to the NS* flavor
  432. ProcessSerialNumber psn;
  433. // Attempt to retrieve the process psn
  434. if (GetProcessForPID (pid, &psn) == 0){
  435. // Gracefully activate process
  436. SetFrontProcessWithOptions (&psn,
  437. kSetFrontProcessFrontWindowOnly);
  438. }
  439. #pragma clang diagnostic pop
  440. }
  441. #elif defined(USE_X11)
  442. // Ignore X errors
  443. XDismissErrors();
  444. // Go to the specified window's desktop
  445. SetDesktopForWindow(win);
  446. Display *rDisplay = XOpenDisplay(NULL);
  447. // Check the atom value
  448. if (WM_ACTIVE != None){
  449. // Retrieve the screen number
  450. XWindowAttributes attr = { 0 };
  451. XGetWindowAttributes (rDisplay,
  452. win.XWin, &attr);
  453. int s = XScreenNumberOfScreen(attr.screen);
  454. // Prepare an event
  455. XClientMessageEvent e = { 0 };
  456. e.window = win.XWin;
  457. e.format = 32;
  458. e.message_type = WM_ACTIVE;
  459. e.display = rDisplay;
  460. e.type = ClientMessage;
  461. e.data.l[0] = 2;
  462. e.data.l[1] = CurrentTime;
  463. // Send the message
  464. XSendEvent(rDisplay, XRootWindow (rDisplay, s), False,
  465. SubstructureNotifyMask | SubstructureRedirectMask,
  466. (XEvent*) &e);
  467. }else{
  468. // Attempt to raise the specified window
  469. XRaiseWindow(rDisplay, win.XWin);
  470. // Set the specified window's input focus
  471. XSetInputFocus(rDisplay, win.XWin,
  472. RevertToParent, CurrentTime);
  473. }
  474. #elif defined(IS_WINDOWS)
  475. if (IsMinimized())
  476. ShowWindow(win.HWnd, SW_RESTORE);
  477. SetForegroundWindow (win.HWnd);
  478. #endif
  479. }
  480. MData GetActive (void){
  481. #if defined(IS_MACOSX)
  482. MData result;
  483. // Ignore deprecated warnings
  484. #pragma clang diagnostic push
  485. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  486. ProcessSerialNumber psn; pid_t pid;
  487. // Attempt to retrieve the front process
  488. if (GetFrontProcess (&psn ) != 0 ||
  489. GetProcessPID (&psn, &pid) != 0)
  490. return result;
  491. #pragma clang diagnostic pop
  492. // Create accessibility object using focused PID
  493. AXUIElementRef focused = AXUIElementCreateApplication (pid);
  494. if (focused == NULL) return result; // Verify
  495. AXUIElementRef element;
  496. // Retrieve the currently focused window
  497. if (AXUIElementCopyAttributeValue (focused,
  498. kAXFocusedWindowAttribute, (CFTypeRef*)
  499. &element) == kAXErrorSuccess && element)
  500. {
  501. CGWindowID win = 0;
  502. // Use undocumented API to get WID
  503. if (_AXUIElementGetWindow (element,
  504. &win) == kAXErrorSuccess && win)
  505. {
  506. // Manually set internals
  507. result.CgID = win;
  508. result.AxID = element;
  509. }
  510. // Something went wrong
  511. else CFRelease (element);
  512. }
  513. CFRelease (focused);
  514. return result;
  515. #elif defined(USE_X11)
  516. MData result;
  517. Display *rDisplay = XOpenDisplay(NULL);
  518. // Check X-Window display
  519. if (WM_ACTIVE == None ||
  520. rDisplay == NULL)
  521. return result;
  522. // Ignore X errors
  523. XDismissErrors();
  524. // Get the current active window
  525. result.XWin=XDefaultRootWindow (rDisplay);
  526. void* active = GetWindowProperty(result,WM_ACTIVE,NULL);
  527. // Check result value
  528. if (active != NULL)
  529. {
  530. // Extract window from the result
  531. long window = *((long*) active);
  532. XFree (active); if (window != 0)
  533. {
  534. // Set and return the foreground window
  535. result.XWin = (Window) window;
  536. return result;
  537. }
  538. }
  539. // Use input focus instead
  540. Window window = None;
  541. int revert = RevertToNone;
  542. XGetInputFocus (rDisplay,
  543. &window, &revert);
  544. // Return foreground window
  545. result.XWin = window;
  546. return result;
  547. #elif defined(IS_WINDOWS)
  548. // Attempt to get the foreground window multiple times in case
  549. MData result;
  550. uint8 times = 0;
  551. while (++times < 20)
  552. {
  553. HWND handle;
  554. handle = GetForegroundWindow();
  555. if (handle != NULL){
  556. // mData.HWnd=(uintptr) handle;
  557. result.HWnd= (HWND)handle;
  558. return result;
  559. }
  560. Sleep (20);
  561. }
  562. return result;
  563. #endif
  564. }
  565. void SetTopMost (bool state){
  566. // Check window validity
  567. if (!IsValid()) return;
  568. #if defined(IS_MACOSX)
  569. // WARNING: Unavailable
  570. #elif defined(USE_X11)
  571. // Ignore X errors
  572. // XDismissErrors ();
  573. // SetState (mData.XWin, STATE_TOPMOST, state);
  574. #elif defined(IS_WINDOWS)
  575. SetWindowPos (mData.HWnd, state ?
  576. HWND_TOPMOST : HWND_NOTOPMOST, 0,
  577. 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  578. #endif
  579. }
  580. //CloseWindow
  581. void CloseWin(void){
  582. // Check window validity
  583. if (!IsValid()) return;
  584. #if defined(IS_MACOSX)
  585. AXUIElementRef b = NULL;
  586. // Retrieve the close button of this window
  587. if (AXUIElementCopyAttributeValue (mData.AxID,
  588. kAXCloseButtonAttribute, (CFTypeRef*) &b)
  589. == kAXErrorSuccess && b != NULL)
  590. {
  591. // Simulate button press on the close button
  592. AXUIElementPerformAction (b, kAXPressAction);
  593. CFRelease (b);
  594. }
  595. #elif defined(USE_X11)
  596. Display *rDisplay = XOpenDisplay(NULL);
  597. // Ignore X errors
  598. XDismissErrors();
  599. // Close the window
  600. XDestroyWindow (rDisplay, mData.XWin);
  601. #elif defined(IS_WINDOWS)
  602. PostMessage (mData.HWnd, WM_CLOSE, 0, 0);
  603. #endif
  604. }
  605. char *GetTitle(){
  606. // Check if the window is valid
  607. if (!IsValid()) return "IsValid failed.";
  608. #if defined(IS_MACOSX)
  609. CFStringRef data = NULL;
  610. // Determine the current title of the window
  611. if (AXUIElementCopyAttributeValue (mData.AxID,
  612. kAXTitleAttribute, (CFTypeRef*) &data)
  613. == kAXErrorSuccess && data != NULL)
  614. {
  615. char conv[512];
  616. // Convert result to a C-String
  617. CFStringGetCString (data, conv,
  618. 512, kCFStringEncodingUTF8);
  619. CFRelease (data);
  620. char* s=(char*)calloc(100,sizeof(char*));
  621. if(s)strcpy(s,conv);
  622. // return (char *)&conv;
  623. return s;
  624. }
  625. return "null";
  626. #elif defined(USE_X11)
  627. void* result;
  628. // Ignore X errors
  629. XDismissErrors();
  630. // Get window title (UTF-8)
  631. result = GetWindowProperty(mData, WM_NAME,NULL);
  632. // Check result value
  633. if (result != NULL){
  634. // Convert result to a string
  635. char *name=(char*) result;
  636. XFree (result);
  637. if (name!=NULL)return name;
  638. }
  639. // Get window title (ASCII)
  640. result = GetWindowProperty(mData, XA_WM_NAME,NULL);
  641. // Check result value
  642. if (result != NULL){
  643. // Convert result to a string
  644. char *name =(char*) result;
  645. XFree (result); return name;
  646. }
  647. return "null";
  648. #elif defined(IS_WINDOWS)
  649. TCHAR name[512];
  650. return GetWindowText
  651. (mData.HWnd, name, 512) > 0 ? name : "null";
  652. // return GetWindowText
  653. // (mData.HWnd, name, 512) > 0 ?
  654. // _UTF8Encode (name) : "null";
  655. #endif
  656. }
  657. int32 WGetPID(void){
  658. // Check window validity
  659. if (!IsValid()) return 0;
  660. #if defined(IS_MACOSX)
  661. pid_t pid = 0;
  662. // Attempt to retrieve the window pid
  663. if (AXUIElementGetPid(mData.AxID, &pid)
  664. == kAXErrorSuccess) return pid;
  665. return 0;
  666. #elif defined(USE_X11)
  667. // Ignore X errors
  668. XDismissErrors();
  669. // Get the window PID
  670. long* result = (long*)
  671. GetWindowProperty(mData, WM_PID,NULL);
  672. // Check result and convert it
  673. if (result == NULL) return 0;
  674. int32 pid = (int32) *result;
  675. XFree (result); return pid;
  676. #elif defined(IS_WINDOWS)
  677. DWORD id = 0;
  678. GetWindowThreadProcessId (mData.HWnd, &id);
  679. return id;
  680. #endif
  681. }