9

I have accomplished listing all the windows (in z order from front to back I think/hope) using CGWindowListCopyWindowInfo but I am having an issue getting the NSWindow* from it so I can use with orderFront: etc.

It seems I don't even get CGWindowID from it.

This is my code, it is js-ctypes.

var cfarr_win = ostypes.API('CGWindowListCopyWindowInfo')(ostypes.CONST.kCGWindowListOptionAll | ostypes.CONST.kCGWindowListExcludeDesktopElements, ostypes.CONST.kCGNullWindowID);

var cnt_win = ostypes.API('CFArrayGetCount')(cfarr_win);

for (var i = 0; i < cnt_win; i++) {
    var thisWin = {};
    // trying to get NSWindow* to the window here, so i can use with orderFront: etc

    // example on how i get pid:
    var rez_pid = ostypes.API('objc_msgSend')(c_win, ostypes.HELPER.sel('objectForKey:'), myNSStrings.get('kCGWindowOwnerPID'));
    var int_pid = ostypes.API('objc_msgSend')(rez_pid, ostypes.HELPER.sel('integerValue'));
    thisWin.pid = int_pid;

    // How can I get NSWindow*

}

PS: Even though I am using the exclude desktop elements flag I am still get desktop elements like cursor and dock, by any chance if answerer can shed some light on how to fix that too that would be awesome!

halfer
  • 19,824
  • 17
  • 99
  • 186
Noitidart
  • 35,443
  • 37
  • 154
  • 323
  • 1
    First, you can only have `NSWindow`s for the windows of the app in which the code is running. What are you actually trying to do? Which windows are you trying to order front and why? If you're working with the app's own windows, you can use `[NSWindow windowNumbersWithOptions:0]` to get Cocoa window numbers and `[NSApp windowWithWindowNumber:someWindowNumber]` to get an `NSWindow*`. – Ken Thomases Aug 08 '15 at 06:30
  • Aw drats @KenThomases thanks for always looking out. I have two needs in two different addons. (1) I created a thing which lists all windows for Windows, Linux/Unix, and OSX. Then people can pick which one they want to stay "Always on Top". (2) And then in another app I am trying to focus the most recent window of a PID, so I traverse the windows in z order, and the first one that comes up with that PID I want to focus it. For this second case is my only option to get the window number with this method then use apple script? I have no backup ideas for first need :( – Noitidart Aug 08 '15 at 08:47
  • (3) My third need, which was for my screenshot addon, was to get bounds of all windows, for the "Window Wand" feature of the thing, using that then clicking a window in the screenshot selects it, I was able to handle that awesomely. – Noitidart Aug 08 '15 at 08:50
  • 2
    For (2), you can activate the app which owns the window and that will give its frontmost window (or, more accurately, its key window) focus. You can use `NSRunningApplication` and its `-activateWithOptions:` method to do that. For a (deprecated) C approach, you could use `SetFrontProcessWithOptions(..., kSetFrontProcessFrontWindowOnly)`. – Ken Thomases Aug 08 '15 at 10:58
  • Thanks @KenThomases yep Im doing `[[NSApplication sharedApplication] activeateIgnoringOtherApps]` and then that key window focus will have to work for now. Its much better then nothing: https://github.com/Noitidart/NativeShot/blob/master/modules/workers/MainWorker.js#L815 any ideas on that always on top thing? Im stuck there :( I knocked out windows and linux but stranded on osx :( – Noitidart Aug 08 '15 at 11:21
  • 1
    That's not what I was recommending. What you wrote is for activating your own app. I was making a suggestion for activating another app, which is what your point 2 was about. You find create an instance of `NSRunningApplication` for the target PID using `[NSRunningApplication runningApplicationWithProcessIdentifier:pid]` and then activate that. – Ken Thomases Aug 08 '15 at 11:38
  • Ahhh crap @KenThomases I just realized I cant get NSAppSharedApp for another app, thanks man for that I'll use that technique. Do you think if I post on apple dev place the 100$ a year thing, they'll help me solve the always on top for another app so i match other platforms like windows and linux.? – Noitidart Aug 08 '15 at 17:42
  • Hey @KenThomases I found something real interesting `CGSWindowOrder(cid, wid, kCGSOrderAbove, nil)` would this work from my process to order a window of another pid? I also saw something super interesting called `CGSGetWindowLevel` maybe this one work from other process? I found it here: https://code.google.com/p/undocumented-goodness/source/browse/trunk/CoreGraphics/CGSPrivate.h – Noitidart Aug 10 '15 at 03:59
  • Hey @KenThomases I tried the `SetFrontProcess` and `activateWithOptions` however if all windows are minimized it is not unminimizing them all - may you please take a look - http://stackoverflow.com/questions/34721737/focusing-app-with-activatewithoptions-only-works-if-non-miniaturized – Noitidart Jan 12 '16 at 00:51

1 Answers1

7

The key you should be using to get window ID's is kCGWindowNumber.

And to get a NSWindow from a window number, you could use [NSApp windowWithWindowNumber:windowNumber].

Unfortunately this will only work for windows that your app owns and not for other applications windows.

Furthermore, if you really wanted to use NSWindow once you get the window ID for other app's windows, it's a bad assumption: not all CGWindows are NSWindows. And outside of that above call, Apple doesn't provide a way to get from CGWindow to NSWindow. To work with other app's windows (provided the other app is cooperative), you'll have to stick with working with the CGWindow objects.

Community
  • 1
  • 1
Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
  • Aw drats thanks @Michael. Do you know of any way to make a window "always on top" with CGWindowID? :( By chance do you know how come desktop elements are being included even though I flagged them out? – Noitidart Aug 08 '15 at 08:49
  • a window your app/process owns or some other app's window? – Michael Dautermann Aug 08 '15 at 08:53
  • For the always on top its not just my own app, its any app. I made an addon for Firefox which lists all (not just my app/ which is firefox)windows for Windows, Linux/Unix, and OSX. In Windows and Linux/Unix they can check mark a window and it will set it to be always on top perfectly, but OSX was driving me nuts as only way I know how to make on top is get NSWindow then setLevel to floating type. – Noitidart Aug 08 '15 at 08:54
  • 1
    I'm pretty certain you can't change the window level of other app's windows (it'd be a likely security issue, not to mention that more and more apps are operating in sandbox mode). – Michael Dautermann Aug 08 '15 at 09:20
  • Aww drats lol, ok thanks man Ill keep digging and let you know if I ever find anything, windows and linuxs are done and i cant release unless i give mac users same experience :( – Noitidart Aug 08 '15 at 09:30
  • Hey Michael I found something real interesting `CGSWindowOrder(cid, wid, kCGSOrderAbove, nil)` would this work from my process to order a window of another pid? I also saw something super interesting called `CGSGetWindowLevel` maybe this one work from other process? I found it here: https://code.google.com/p/undocumented-goodness/source/browse/trunk/CoreGraphics/CGSPrivate.h – Noitidart Aug 10 '15 at 03:59
  • Hi @Michael is it possible for the reverse? I have a `NSWindow` and am trying to get the `CGWindowID` is this possible? I thought to use [`[NSWindow windowNumber]`](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSWindow_Class/index.html#//apple_ref/occ/instp/NSWindow/windowNumber) but the docs warn its not the same number. – Noitidart Mar 18 '16 at 05:11