Controlling level and focus of windows other apps with CGPrivate functions

自古美人都是妖i 提交于 2019-12-13 00:53:33

问题


Question

How to use these private functions on other windows? It would be nice to have this knowledge back in the wild. I am specifically trying to get CGSOrderWindow and CGSSetWindowLevel to work.

I was trying in the direction of:

temporarily register as the dock and then register the dock as the dock again immediately afterwards

or

code injection into the Dock process per this comment:

Also, the author of the above project seems determined to make all core functionality available as a framework. It seems to be implemented as code injection into the Dock process.

Reason I know this is possible

I have been doing work on trying to setLevel on window of another app, and focus window of another app if focused. I am posting this again with the info I learned because from my searching online, I know this was done in the past, its just the knowledge is not publicly out there anymore. The sourceforge pages are no longer there. So I was wondering if you could help me make this information public again.

This is the topic I read that gave me this information - http://cocoadev.com/HowtoControlOtherAppsWindows

Here you see comments like:

  • You cannot control an another app's windows from a user-level process, unfortunately.

    • SlavaKarpenko
  • You can, Slava, you just need to register as the Dock. It might be possible to temporarily register as the dock and then register the dock as the dock again immediately afterwards, not sure. I think the call you'd be wanting to investigate as CoreDockRegisterDockOwner in HIServices.framework.

    • FinlayDobbie
  • You could also use APE or similar to do control the windows, or (as mentioned above) register as the Dock (look for the private APIs with Universal Connection in their name). Has anyone found a polite way of getting the Dock to give up its universal connection? The only way I can find is to force quit the Dock and grab the universal connection when it's not looking (which prevents the dock reloading).

    • SamTaylor
  • There's an open source project up on sourceforge.net that looks much more like the window managers I've used on Unix boxes than Space.app (or Space.dock): http://wsmanager.sourceforge.net/

    • SteveCook

Verifying things work

This is what I learned, from the sources at bottom of this post, we see all these functions work with CGWindowIds, so how do I get that, this is how:

Get all windows with CGWindowListCopyWindowInfo. Then access each element from that array with CFArrayGetValueAtIndex and then get the CGWindowId with objectForKey:, kCGWindowNumber, and then integerValue.

Now if I try to focus or set level of a window that is OWNED by the app running the code, it works fantastic. For instance:

MY_TARGET_CGWINDOW_ID = 179;
rez_CGError = CGSOrderWindow(_CGSDefaultConnection, MY_TARGET_CGWINDOW_ID, kCGSOrderAbove, 0);

Will focus it, rez_CGError is 0. Even if the window is minimized, it is unminimized, without animation, and shown.

Now however, if I try this on a window of a different app we get some errors:

MY_TARGET_CGWINDOW_ID_of_other_app = 40;
rez_CGError = CGSOrderWindow(_CGSDefaultConnection, MY_TARGET_CGWINDOW_ID_of_other_app, kCGSOrderAbove, 0);

This fails and rez_CGError is 1000, which I suspect means "cid (CGSConnection) used does not have permission to modify target window". The same happens if I first do [app activateWithOptions: (NSApplicationActivateIgnoringOtherApps | NSApplicationActivateAllWindows)] before making the call above.

So I first get the cid of that owning window like this:

 var rez_CGError = CGSGetWindowOwner(_CGSDefaultConnection, MY_TARGET_CGWINDOW_ID_of_other_app, &ownerCid);

This works good and I get ownerCid is set to a value. Then I do the focus command with this new connection:

 rez_CGError = CGSOrderWindow(ownerCid, MY_TARGET_CGWINDOW_ID_of_other_app, kCGSOrderAbove, 0);

However this gives rez_CGError of 268435459, which I suspect means "current app does not have permission to use this ConnectionId (cid)". (Same happens if I call activateWithOptions first.

My Sources for the Private Functions

Here is the sources for some private functions I found - https://code.google.com/p/undocumented-goodness/source/browse/trunk/CoreGraphics/CGSPrivate.h

This one source here contains a function that is not in the above link - CGSGetConnectionIDForPSN - i test it and it exists - from - https://github.com/mnutt/libqxt/blob/767498816dfa1742a6f3aee787281745afec11b8/src/gui/qxtwindowsystem_mac.h#L80

来源:https://stackoverflow.com/questions/34738375/controlling-level-and-focus-of-windows-other-apps-with-cgprivate-functions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!