CGWindowID from AXUIElement - cocoa

I'm trying to automate a foreign OSX application using the accessibility API. Some of
the state of the application isn't available through the API, so I acquire it through
screen scraping. To do this, I need to get CGWindowID for an accessibility object with
a 'Window Role'.
Is there any direct way of acquiring CGWindowID of a 'Window Role' accessibility object?
I can get it heuristically, by matching various attributes of the window, such as
the size, title and location, but this is really hacky, and I'd feel better if my
application would also support the corner cases, even if they are unlikely.

There is a function from at least Leopard and up (and still around as of 10.7.3):
extern "C" AXError _AXUIElementGetWindow(AXUIElementRef, CGWindowID* out);
Usual caveats about using something like this apply though. It may change as soon as the next OS update!

There’s no way to do that; the accessibility hierarchy is completely decoupled from the actual window/view hierarchy. I think your matching will work best.

The correct current declaration in a Swift Bridging Header is:
#import <AppKit/AppKit.h>
AXError _AXUIElementGetWindow(AXUIElementRef element, uint32_t *identifier);
As used here: https://github.com/rxhanson/Rectangle/blob/master/Rectangle/Rectangle-Bridging-Header.h

Related

Determine if a handle points to an element of the screen (and not a printer etc)

I'm looking for a way to identify if a handle references something on the/a screen (a screen, a window, a control, the entire virtual desktop, etc).
I'm trying to standardise the resolution of the interface so that I can consistently save it and do non-regression testing on it. So I've hooked a couple of system calls like GetDeviceCaps so that I can intercept the resolution and change it to a consistent 96DPI.
So far I've found GetObjectType that doesn't necessarily tell me if the object is part of the screen (comparing to OBJ_DC and OBJ_MemDC). Combining that with WindowFromDC I can get a slightly more indicative result, but it's still not perfect.
I thought maybe I could use EnumDisplayMonitors with null for the first two parameters, but it never seems to function.
Does anyone have a fool proof way of telling if a handle references a screen object or not?
Thank you in advance!
Loren
Turns out I could've used GetDeviceCaps with the parameter index set to TECHNOLOGY. An object related to rendering to a screen will be identified as DT_RASDISPLAY
See https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getdevicecaps

NSWindow keep in back of all windows/apps

So not really sure how to even google search this question... But, I'd like to make an NSWindow, reside in the back of all other windows/apps & I want it to be displayed on every Mission Control space (still in the back).
I've seen other applications that do this, so I know it's possible, just don't know how.
(I'm referring to Lion's function called Mission Control where you can switch through different spaces.)
Found the answer, there's a method/enum to make it so that the window will appear in all "spaces" (mission control).
[self.window setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
And a method to keep the window to the farthest back possible.
[self.window setLevel:kCGDesktopIconWindowLevelKey - 1];
All you have to do is use these two methods, and it'll do exactly what I requested. However, I wish there was a way to keep it from animating when coming down from Mission control (there is non to my knowledge).
You want to set the NSWindow's level and collectionBehavior properties.
The window level you'll want to use will depend on what behavior you're after from your window. You can find constants for the available window levels in CoreGraphics/CGWindowLevel.h. I'd suggest trying CGWindowLevelForKey(kCGDesktopIconWindowLevelKey) ± 1.
Which collection behavior you specify will also depend on what behavior you're after. The brief description in your question suggests that NSWindowCollectionBehaviorStationary | NSWindowCollectionBehaviorCanJoinAllSpaces may be a good starting point.

How to add a NSColorPicker to the application's main window?

I'm building an application to generate an array of colors based on a color chosen by the user.
The default on Mac OS X for color selection is to open a NSColorPanel containing multiple NSColorPickers. But, as the color selection process is the main interaction the user will have with the app, it'd be better to avoid the extra clicks and panel-popping in favor of a more straightforward way.
So, is there any way to add a NSColorPicker object to a window?
I know this is an older question, but check out NSColorWell. From the docs:
NSColorWell is an NSControl for selecting and displaying a single color value.
Interresting Question.
I strongly doubt it (but would love to be proven wrong). NSColorPickers are not NSControls (nor NSCells) so there's no clean wrapper to insert into a window.
Even if you were to instanciate an NSColorPanel and get a reference to its contentView and copy it (with all that defines the color picking controls) to your own window... there's no obvious way of obtaining the color value. NSColorPickers are plug-ins so you can't forsee the controls of a colorPicker.
The only other way I can see (and that's a stretch) would be to manually load the NSColorPickers plug-ins directly. I don't know how successfull this would be.
File a bug report and request the feature?

How to write an OS X application that can effect changes (custom cursor, draw an image) even when it is not active?

I previously asked a question about changing the cursor system-wide on OSX. I used NSCursor to change the cursor, but the effects are only as long as the application is active. When another application becomes active, the custom cursor is lost.
Here is a related, more general question. How can you write an application to have system-wife effects? For example drawing an image on-screen even when your application is not active, and something else is?
I understand I probably need to go at a lower level than the Cocoa APIs. I just cannot figure out where to start looking? Any specific Carbon APIs that I need to be looking at? Or even lower?
Any pointers would be appreciated! If you specifically know how to change the cursor system-wide or how to draw an image and move it around (no matter what application is active), that would solve my current problem as well! Can I write an application that can achieve this when its installed on the system?
Thanks!
You can achieve the effect you want, but not the way you're thinking about doing it.
You say,
I am writing a presentation aid application that shows the equivalent of the "laser pointer" on screen, programmatically. My first idea was to use the mouse cursor itself as the pointer, and change its appearance as a red circle.
Then fake that. Create an application, perhaps of type LSUIElement, perhaps not, depending on the behavior you want. Create a borderless window (type NSBorderlessWindowMask) and fill it with a clear color. Set its window level high enough so that it floats over everything (using -[NSWindow setLevel:], though I can't think of what the best level would be off-hand), and draw into it.
It's true that you cannot set the cursor when you are not the foremost app. It's true that you cannot just scribble on the screen. But you can get the same effects if you're clever.
This behaviour is not provided by any APIs on Mac OS X. You would have to modify the resource files in the OS, and that's a very dangerous operation that could brick the target computer. You have to know what you're doing.
Are you trying to implement a theming app or something like that? What's your goal? If you tell us what you are trying to do, we may be able to suggest alternate approaches.

What is the name of this Mac OS X control?

Does this control have a name? Or is it just a bunch of simple controls merged together? If so, what controls are they?
http://img8.imageshack.us/img8/3002/picture2xrb.png
It looks like an NSTableView with an a custom cell type and no column header. Have a look at the documentation for NSTableView's tableView:dataCellForTableColumn:row:. For columns which have the same type for all rows you may also set the cell class in interface builder.
I doubt the search box is part of the same control.
You could open the Application's Nib file to see what is in there. Look inside the application bundle. If the application is called Example then you should be able to find the Nib at Example.app/Contents/Resources/English.lproj/MainMenu.nib.
The best tool for investigating this is fscript, specifically FScriptAnywhere which will let you determine the class and much other information about any visual element of any Cocoa program (and do a lot of other interesting things with Cocoa programs).
In addition to what toholio said, an easy way to get the look and feel of the bottom button bar is with BWToolkit.

Resources