I want to get the list of window titles of the currently running applications.
On windows I have EnumWndProc and GetWindowText.
On Linux I have XGetWindowProperty and XFetchName.
What is the Native Mac equivalent?
I want to get the list of window titles of the currently running applications.
On windows I have EnumWndProc and GetWindowText.
On Linux I have XGetWindowProperty and XFetchName.
What is the Native Mac equivalent?
A few potentially useful references:
NSWindowList()
-launchedApplications
and +runningApplications
CGWindowListCreate()
and CGWindowListCopyWindowInfo()
(requires 10.5)CGSGetWindowProperty()
CGSGetWindowProperty
is not officially documented, but I believe you can use it with the an item of NSWindowList()
as follows (completely untested):
OSErr err;
CGSValue titleValue;
char *title;
CGSConnection connection = _CGSDefaultConnection();
int windowCount, *windows, i;
NSCountWindows(&windowCount);
windows = malloc(windowCount * sizeof(*windows));
if (windows) {
NSWindowList(windowCount, windows);
for (i=0; i < windowCount; ++i) {
err = CGSGetWindowProperty(connection, windows[i],
CGSCreateCStringNoCopy("kCGSWindowTitle"),
&titleValue);
title = CGSCStringValue(titleValue);
}
free(windows);
}
In AppleScript, it's really easy:
tell application "System Events" to get the title of every window of every process
You can call applescript from within an application using NSAppleScript or use appscript as an ObjC-AppleScript bridge. With Leopard, you can use the Scripting Bridge (more untested code):
SystemEventsApplication *systemEvents = [SBApplication applicationWithBundleIdentifier:@"com.apple.systemevents"];
SBElementArray *processes = [systemEvents processes];
for (SystemEventsProcess* process in processes) {
NSArray *titles = [[process windows] arrayByApplyingSelector:@selector(title)];
}
You could even try it in one long call, if you don't care about readability.
SystemEventsApplication *systemEvents = [SBApplication applicationWithBundleIdentifier:@"com.apple.systemevents"];
NSArray *titles = [[[systemEvents processes]
arrayByApplyingSelector:@selector(windows)]
arrayByApplyingSelector:@selector(arrayByApplyingSelector:)
withObject:@selector(title)];
The compiler will complain that @selector(title)
is the wrong type, but it should work. Hand roll some delegation and you could turn the call into [[[systemEvents processes] windows] title]
.