Applications’ “windows” property does not include panels

Basically, I am wanting users to be able to do things like:

tell application “Keyboard Maestro Engine”
set bounds of window 1 to {600, 167, 1911, 1141}
end tell

But pretty much all the windows in Keyboard Maestro Engine are palettes, so they do not appear in the “windows” property, and there is no equivalent for “panels” that I can find.

Any suggestions for a solution? By thoughts so far (other than “this is all too hard and I’m going to go implement something else”) are:

  • Find a way to have NSPanels included in the “windows” property.
  • Sigh and implement another property “panels” and return an array of the same sort of window objects. But ideally I don’t want to have to implement the window objects myself.
  • Deeply sigh and implement a “panels” property, and have it return a new class with the same sort of behaviours as the built in window class.

I’d really prefer the first approach as for this purpose, all windows are going to be panels anyway, and the “windows” property will otherwise be useless.

Any suggestions?

The windows property is implemented by NSApplication’s orderedWindows property, so you can override -orderedWindows to return what windows you want.

2 Likes

Perfect! Just what I needed. Code in my delegate is attached in case it is of any use. Unfortunately it is not easy to get an ordered list of windows including palettes pre-10.12, so folks on earlier OS versions will have to take their chances with it. Also, detecting the NSStatusBarWindow icon pseudo-windows is a nuisance, but should be safe enough.

Much appreciated. I know scripters will make good use of this.

static bool IsStatusBarIconWindow( NSWindow* window )
{
	if ( [window.className isEqualToString:@"NSStatusBarWindow"] ) return true;
	if ( window.frame.size.height < 25 ) return true;
	return false;
}

- (NSArray<NSWindow *>*) orderedWindows;
{
	__block NSMutableArray<NSWindow *>* windows = [NSMutableArray new];
	if (@available(macOS 10.12.0, *)) {
		[NSApp enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack usingBlock:^(NSWindow * _Nonnull window, BOOL * _Nonnull stop) {
			[windows addObject:window];
		}];
	} else {
		[windows addObjectsFromArray:[NSApp windows]];
	}
	[windows kbm_removeObjectsMatchedByBlock:^bool(NSWindow* obj) {
		return_from_block !obj.visible or IsStatusBarIconWindow( obj );
	}];
	return windows;
}

- (BOOL) application:(NSApplication *)sender delegateHandlesKey:(NSString *)key;
{
	return [key isEqualToString:@"orderedWindows"];
}

1 Like