Carbon Accessibility API - Getting windows information across spaces - windows

I have the following (minor) problem that I want to solve programmatically. Whenever I unplug my secondary monitor from my laptop, every windows get moved to be visible in the now smaller resolution. When I plug my external monitor back in, I need to manually replace the windows to their correct position. I have to do that every morning (sigh).
Now I decided to write a simple command-line program that could save the position of every open windows and reposition them when I want to restore their positions.
I have managed to do something that works just fine by using the Accessibility API, which allows me to control windows that aren't part of my process space. I have a problem though: the program can only see the windows that are in my current space (I'm talking about the OSX Spaces feature here).
In other words, when I run my program to save the windows positions, it will only be able to save the positions of the windows in the space I'm currently in.
Some more details about my program:
It loops through all the processes running and get their PIDs.
It creates application elements from these PIDs (AXUIElementCreateApplication)
It gets the windows associated with this application, and then their positions
When getting the windows elements from the application element, the AXUIElementCopyAttributeValues only returns me the windows of the current space.
Now, is there a way to control any windows (across different spaces)? If not, I wouldn't mind programmatically changing spaces to get every windows, but that doesn't seem possible.
Any help would be appreciated!

I'm not aware of a documented way to switch spaces.
You probably want CGSPrivate.h - CGSSetWorkspace et al. Just keep in mind those functions are SPI and can break without warning even in a 10.6.x release.

If you want to avoid using private APIs you can take advantage of the fact Mission Control has keyboard shortcuts for moving to various spaces, and you can programmatically send the key codes to activate them. I wrote a blog post about it (http://ianyh.com/blog/2013/06/05/accessibility/) for a tiling window manager I've been working on called Amethyst, which has some example code you can check out in -[AMWindow moveToSpace:].
The short version is moving to a space looks something like using the default ctrl + arrow key to move to adjacent spaces:
CGEventRef keyboardDownEvent = CGEventCreateKeyboardEvent(NULL, kVK_RightArrow, true);
CGEventRef keyboardUpEvent = CGEventCreateKeyboardEvent(NULL, kVK_RightArrow, false);
CGEventSetFlags(keyboardDownEvent, kCGEventFlagMaskControl);
CGEventSetFlags(keyboardUpEvent, 0);
CGEventPost(kCGHIDEventTap, keyboardDownEvent);
CGEventPost(kCGHIDEventTap, keyboardUpEvent);
CFRelease(keyboardEvent);
CFRelease(keyboardEventUp);
You could combine this with NSWorkspaceActiveSpaceDidChangeNotification to traverse all spaces and gather window data.
Also, as a potentially interesting note the accessibility APIs can actually give you windows across all spaces at the same time, but it will only give you windows in spaces that you have traversed to since the process utilizing the APIs launched. I have no idea why this is the case, but it does seem to be.

Related

How to stop Explorer starting my application maximized?

Explorer seems to always start my application with SW_MAXIMIZE (STARTF_USESHOWWINDOW is set in STARTUPINFO.dwFlags). I know that ShowWindow will use this value the first time you/Windows needs to display a window but it has the unfortunate consequence of maximizing a window that should never be maximized.
My window is created with CreateDialogIndirectParam and has the following styles: WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_CLIPCHILDREN|DS_MODALFRAME|DS_CENTER|WS_VISIBLE. Why does ShowWindow not check if WS_MAXIMIZEBOX is set before allowing STARTF_USESHOWWINDOW to force SW_MAXIMIZE? Is this a bug in Windows?
This happens on a HP Stream 7 with Windows 8.1. I'm not sure if Explorer does this because it is touch enabled or because of the small screen.
Is this Explorer behavior documented anywhere and is there a way to turn it off? What is the best way to stop Explorer (or any other parent process) from affecting my initial window mode? (I don't want to block people starting me with SW_*MINIMIZE*)
WinVer.exe in system32 has the same problem:
My first thought was to turn off STARTF_USESHOWWINDOW in the PEB if the parent wanted me to start maximized but that is too nasty and undocumented so I have not tried that yet.
Preventing any kind of size change (which is OK for my application since it is just a "modal" dialog) sort of works:
case WM_WINDOWPOSCHANGING:
((WINDOWPOS*)lp)->flags |= SWP_NOSIZE;
return true;
The problem is that the window position is still set to 0 x 0 like a maximized window.
A better solution seems to be to detect and correct the problem after WM_INITDIALOG:
case WM_INITDIALOG:
PostMessage(hDlg, WM_APP, 0, 0);
break;
case WM_APP:
if (IsZoomed(hDlg)) ShowWindow(hDlg, SW_SHOWNOACTIVATE);
break;
I am the proud owner of several HP Stream 7 tablets and I would like to add my 2 cents here. Microsoft has made an arbitrary decision that devices with screen sizes smaller than 8 inches will behave differently than the norm. A lot of users are somewhat aware of this, but unaware that this is where your problem originates.
Windows determines a screen's size by reading the EDID information from the screen, which contains sizing information in it, in centimeters.
If no sizing information is present in the EDID, or the sizing information is below Microsoft's arbitrarily chosen 8 inch threshold, you get this apparent misbehavior which is at the very least, aggrivating to those who notice it and don't want it.
The solution is to override the default driver for the monitor in Device Manager with one that informs Windows that the screen is in fact, 8 inches or larger.
To do so, you need to first read the EDID information from the registry with a tool such as Deltacast's E-EDID Editor (free, last time I checked), and modify the size values and save the modified file someplace you can find it.
After you have modified your EDID file and saved it, download Monitor Asset Manager from EnTech (also free) and use it to create an INF file.
Once the INF file has been created, you need to restart Windows with the Advanced settings menu and choose to Disable Driver Signing Enforcement, since the INF file you created won't be digitally signed. Once disabled, open Device Manager in Windows and update the driver for the monitor using the INF file you created. You will need to confirm that you do in fact want to install the unsigned driver file.
Reboot and Windows will now behave normally with the one catch that, the onscreen keyboard will now appear a different size and will have more options available.
Sadly, Microsoft can change this behavior in the future, so there is no guarantee that through the same flawed decision making process they used to implement this in the first place, they won't force it down our throats again, using a much more difficult to counteract method.

Create a program that alters the execution of a windows application

I have a windows application which has several sub-forms. i have to navigate through 5 or 6 forms to reach the form i need. this is time consuming since i have to open it several times through the day and i do it daily.
my need: i dont have the source project for this application, i got it as an executable program, but i need to create some application that does these steps for me automatically. In other words i need to find a way to automatically click the buttons that navigate through the forms and opens the form i need from step one.
is there any way i can do this ?
There is indeed, though generic solutions already exist to perform just this kind of function to arbitrary programs.
You can use Spy++ or a resource-editor, like ResHack or ResEdit to look at the program and get the control ids of the navigation buttons.
Once done, you can get a handle to the program itself and then send messages to it's WindowProcedure that would be generated if the user clicked the controls with a mouse,
Another alternative, is to get the position of the running target application, after you've got it's HWND, by using the GetWindowRect function. You could then use this position along with vert/horiz distances to generate mouse events.
The two have more-or-less the same result, though some applications won't work with approach #1.
In one instance, you need to use Spy++ to get the control IDs.
In the other instance, you need to use an image editor to get the pixel offsets of the controls.
In both instances, you'll need to use FindWindow, along with the window's title-text in order to get a HWND handle.
You could use a combination of the two - asking the program itself with GetDlgItem for the handle of the controls you need to click. You could then query the control for its position, before using mouse_event to position the mouse above it and again to click it.
Quite a few ways to skin this cat, actually.
Pre-existing solutions like AutoIt are said to be very easy to use and will be much easier than coding a new program for each target.

Detecting SetCursorPos()?

You can probably figure out why I am asking this question. Even if not, it's very simple.
My question is whether it is possible to detect the use of SetCursorPos() on one's own application, without scanning other running applications for any calls to this API.
For example, if I have my cursor in a window and I call SetCursorPos(), can this window in anyway know that the cursor placement is not directly from the mouse (raw input)?
I am not oblivious to the fact that you can 'know' whether a mouse input is raw simply by checking how the position alters; for example, if the position changes from 100(X) & 100(Y) to 500(X) and 500(Y), without moving through each individual location between these two, then with certainty, something has altered the mouse position.
If anyone of you know of a way to produce 'raw mouse input', without any application being able to tell the difference between the output from a function, and that from a mouse--if there is such a difference--then that'd suffice, too.
Of course, whenever I move my mouse, the operating system I am using detects this and then appropriately moves the cursor accordingly. In practice, I should be able to alter this low level functionality as to my will?
There is no way for a window to directly determine how the mouse was moved. External applications could be using SetCursorPos(), but they could also be using lower level functions like mouse_event() or SendInput() instead. By the time the notification reach the target window, the OS has already normalized the data and any source information is lost If you really needed to detect use of SetCursorPos() or other functions, you would have to directly hook into those functions in every running process. Alternatively, you might try registering for "Raw Input" via RegisterRawInputDevices() and see if you get a corresponding notification from the mouse hardware directy, assumine those simulating functions do not trigger Raw notifications as well.

How Imitate a [Ctrl+Left mouse click] on the center of the form or open another program and type in a word?

Babylon dictionary and a couple of other dictionaries allow to click on any word in any windows program
and automatically recognize the word under the cursor, and at once open the dictionary window while searching for that word in installed dictionaries.
You can on the other hand open your dictionary, type in your word and press Enter, the result will be the same.
There's a Delphi form, containing a text label, for example with the word "Automaton".
My question is:
How to send a word from my Delphi application right into the dictionary window, as if you typed it manually and pressed Enter?
The best solution is to send some message through the Windows mechanism, but if it is too complicated, there's another solution, and so the second answer: as I described, we need to model a [Ctrl+left mouse] click on a form where this word is displayed on a form [ a visual label on the screen of my Delphi application], to be exact, on some central pixel of this label.
Could you kindly give an advice how to do one thing or another in Delphi ?
** edit:
The problem with AppActivate is this: Babylon dict has a daemon part that seats in the tray.
In the task manager a real window where the text should be input also is named 'Babylon'.
So AppActivate('Babylon') tries to bring to front the non-visual part of the application.
Do you have any suggestion how to determine the windows handle or something of a real visual part of the application? In the task manager, I repeat both visual and non-visual parts are named 'Babylon'.
I cannot offer an answer so much as some insight and advice...
There are certain applications which "intercept" keyboard and mouse instructions, and essentially "nullify" them if they are being immitated by software. Generally-speaking, you'd only see this in proper AntiVirus software such as Kaspersky by design... however:
The way some (not many, but some) programs hook keyboard and mouse inputs, as a side-effect, behave the same way. If you have attempted all of the advice given as comments above, and cannot get Babylon to trigger an action as a result, it is likely Babylon behaves as I have described.
If what I suspect is true, then the method you are attempting is simply not possible (at least, not using any simple Pascal code on its own... ASM might be able to do it but that's beyond my knowledge).
A better solution may be to do a little research to see if any of the following options are available to you:
1) Does Babylon have a Pipeline or API you can use to interface your application(s) with it?
2) Is the particular functionality you require of Babylon accessible through one (or more) DLL files distributed as part of Babylon?
3) Is there an alternative to using Babylon for your needs?
I know it's not an answer as such (certainly not one you'd want to hear), but it may point you in a better direction.

Is there anything like Winsplit Revolution for Mac OS X?

Is there anything like Winsplit Revolution for Mac OS X?
Try these:
Zooom/2 ($15) has been my favorite since I installed it. Fast, flexible, and minimizes the number of key combinations I need to remember
Divvy ($15) might soon replace Zoom/2 for me. It's closer to Winsplit. You can arrange windows on a grid, define your own grid arrangements, and define your own shortcuts. It also minimizes the number of keystroke combinations you need to remember. BONUS: There are Mac and Windows versions, which means if you use both platforms you can use the same window management method across all your machines.
Breeze ($8) makes it easy to make windows fullscreen, split left, or split right. It also lets you save screen states (generic) and for specific apps.
Moom ($5) is a more recent entry. It supports both keyboard shortcuts and mouse shortcuts. For the mouse shortcuts, moving the cursor over the greeen zoom button displays a popup list of different layout options: full screen, left/right half, top/bottom half, or any of the corners.
SizeUp ($10) mimics various aspects of WinSplit functionality, but it relies on many keystroke combinations that take time to learn. The advantage is quickly moving windows. The drawback is that it uses up a lot of global keyboard shortcuts, and there are so many I couldn't remember them all.
Cinch ($7) is a mouse-driven app by the makers of SizeUp. Drag your window to various hot zones on the screen edges and the window will "cinch" to that edge and resize to fill half the screen. Similar to the built-in resizing feature in Windows 7.
MercuryMover ($20) is quite powerful and offers fine-grained control. However, there are a lot of different key combinations and, overall, I didn't find it as easy to learn or as elegant as WinSplit. I uninstalled it almost immediately. It struck me as powerful, but inefficient and unwieldy.
The DIY approach (free) mentioned in another post is to combine some applescripts and bind them to quicksilver triggers. I haven't tried this. But it is a free solution.
I found the weak window management one of the hardest things to cope with when I started using a Mac.
Why go beyond spaces and expose?
Winsplit significantly adds to what spaces and expose can do. I didn't understand the appeal until I actually used it. Before that, I thought virtual desktops (ie, like spaces) was enough. Now I consider it must-have functionality, especially on large monitors and multi-mon setups.
On my Windows machine running 3 monitors, I would rank the importance of these different apps in the following order:
Winsplit-like window rearranging
Spaces-like virtual desktops
Expose-like application switching
On my MacBook, I've learned to approach it the other way.
Expose-like application switching
Winsplit-like window rearranging
Spaces-like virtual desktops
From the Winsplit website I understand more or less the functionality; in the past I actually used to have my window manager (Waimea) configured to do exactly that in linux.
You may try using Quicksilver to trigger one of a custom set of applescripts; each applescript would resize and move the currently focused window to a predefined location.
See this macosxhints post for inspiration...
ShiftIt is a free option. Assignable hotkeys to resize to different portions of the screen (Left, Right, Top, Bottom, Top Left, Top Right, Bottom Left, Bottom Right, Full Screen and Center with current size)
Link to ShiftIt on github
Just click on the big download button towards the right of the screen.
Spectacle is a good option, its free and open source. And easy to use with keyboard shortcut :
Windows can be moved to a number of predefined regions of the screen:
Move to the left half ⌥⌘←
Move to the right half ⌥⌘→
Move to the top half ⌥⌘↑
Move to the bottom half ⌥⌘↓
Move to the upper left ⌃⌘←
Move to the lower left ⌃⇧⌘←
Move to the upper right ⌃⌘→
Move to the lower right — ⌃⇧⌘→
Another question on StackOverflow adresses the same issue
https://stackoverflow.com/questions/276760/tiling-window-manager-for-os-x
One answer provided links to an app called TwoUP. It's free, and does the job on OSX!
Thanks to Dong Hoon's answer, I have developed a hybrid solution. Using the AppleScript Editor, you can create scripts to resize the current window, like this:
tell application "System Events"
set _everyProcess to every process
repeat with n from 1 to count of _everyProcess
set _frontMost to frontmost of item n of _everyProcess
if _frontMost is true then set _frontMostApp to process n
end repeat
set _windowOne to window 1 of _frontMostApp
set position of _windowOne to {5, 0}
set size of _windowOne to {1150, 735}
end tell
such a script will work on a 13" MacBook. Using subtle variations of this script saved to /Users/[YourUserNameHere]/Library/Scripts, you can have configure the AppleScript Editor to show itself in the menu bar, where it will allow you to select a script to run.
Using several different scripts, I'm able to resize and reposition any window with only two clicks.
Hope this helps.
It looks like TwoUp is dead, but here are some other options:
Cinch ($7) is like Aero Snap for Mac.
Breeze ($8) allows you to save window states and restore them like a template to another window.
Divvy ($14) shows a grid on the screen where you can select boxes to indicate how you want the window to fill your screen.
I haven't used Winsplit, so I don't know how it compares, but an app I developed, Optimal Layout, offers very flexible window tiling, as well as moving and resizing from the keyboard:
http://most-advantageous.com/optimal-layout/
You can also try Arrange application which features resize and reposition with keyboard shortcuts, on screen menu and by dragging window.
You should also try out secondbar. gives you an extra menubar at the second display + re-arrange options. See this link.
You can even try SplitScreenapp.com. It allows you to resize Mac Windows in many ways including full split, half split, drag and snap, etc.
I doubt it. Between Spaces and Expose, there's not much need for a third-party app to help manage multiple windows.

Resources