I want to detect when a window is being moved in real time and figured that CGDisplayStreamCreate etc. should provide just that. But I'm having difficulty deciding which window is being moved when my CGDisplayStreamFrameAvailableHandler is called. Is there a direct way to match the updated rects with with an app and its windows?
CGDisplayStream cannot tell you which applications/windows are responsible for a given screen update. You might be able to use another API like Accessibility to determine window locations and then guess which of the kCGDisplayStreamUpdateMovedRects corresponds to each window, but that will not be very reliable. If you're going to go the route of Accessibility, you may as well use Accessibility notifications for window move events: How can my app detect a change to another app's window?.
If you also need the pixel contents of the windows when they are moving, then you'll need to do some unfortunate time alignment between CGDisplayStream and Accessibility callbacks.
Related
I am running a game that has buttons on both sides of the screen, which gives you an easy control on a tablet. But on ARC it makes it difficult to use because you need to move your mouse across the screen a bunch of times. Does ARC Welder have an option to make a key on the keyboard "tap" a certain place on the screen?
If you are comfortable with the concept of scripting, you could use AutoHotKey to use keyboard events to click specific areas of the screen. This would be through your OS, not the ARC, but I think the script can be linked to a specific application so it will only run with that app.
See specifically Click
Imagine I save my window's position in my preferences file. Now, the user moves the window to a second monitor, then quits my app. Then he disconnects the second monitor and launches my app again.
Now my app wants to restore the window's saved location. But if it blindly restores the old window coordinates, the window will be off-screen.
I used to use ConstrainWindowToScreen for my Carbon app, but now that I'm porting it to Cocoa, I can not find an equivalent for this.
The docs suggest that, somehow, Cocoa would automatically prevent this from happening. While that might be the case when the monitors change while the window is open, in my case where I've stored the window location myself and restore them when I re-open the window at launch, this isn't going to work. I need to invoke Cocoa's magic functionality on demand, but how?
(Note: I am aware that I could iterate over all available screens, but that's quite a pain to write myself if I want to get this foolproof. Still, if you can present a complete C or ObjC function that solve it this way, that'd be appreciated, too.)
See the "Managing Window Frames in User Defaults" section in the NSWindow Class Reference. Those methods ensure that a window will be placed entirely on screen.
If you want to save and restore the window location yourself (as a string), use -stringWithSavedFrame and -setFrameFromString:.
Use -saveFrameUsingName: and -setFrameUsingName to have NSWindow save and restore its frame in the user defaults, given a window name.
I agree with Darren's suggestion to use the built-in mechanism for restoring window positions. Really, it's as easy as setting a window's frame autosave name in IB (or with -setFrameAutosaveName:).
That said, if a window has a title bar, then all of the methods which order it onto the screen (e.g. -orderFront: or -makeKeyAndOrderFront:) will automatically reposition it to make sure at least the title bar and a significant chunk of the window is on the screen. It's honestly difficult to get a titled window to be theoretically visible but actually off-screen.
I need to host my window upon a window of another application.
How to enumerate windows of another Cocoa application? Is it possible to control
them?
If no: how can I draw upon a window of another application?
Thanks!
How to enumerate windows of another Cocoa application?
You can enumerate the windows of another application using the Accessibility API. It doesn't matter whether that application is Cocoa or not.
Is it possible to control them?
Here, it does matter, indirectly, whether the application is Cocoa (or Carbon using standard controls). More precisely, it matters whether the application is accessible.
It usually is possible to move another window, resize it, or do simple things with controls in it (such as press buttons).
It is not possible to tape one of your windows to a window in another application. You will have to observe its location and move your window when the other moves. Following a live drag this way is not possible.
If no: how can I draw upon a window of another application?
You can't. You can only draw in your own windows.
You can make a transparent overlay window and draw on that, but that gets you back to the problem of taping one of your windows to a window in another application.
You should probably ask a broader question about whatever it is you hope to achieve by taping one of your windows to a window in another application or by drawing into a window in another application.
Checkout CGWindow.h
CGWindowListCreateDescriptionFromArray() is probably what you're looking for.
Cocoa does not support reparenting of another application window, or drawing on it.
But, there're two ways to get windows attributes for all the applications, like position, size, z-order, etc.
Accessibility API (also allows to control a foreign application window: move, resize, press buttons on it, etc.). If a foreign application does not support Accessibility API, then...
Quartz Window Services and a sample code for them, called "Son of Grab".
I've been searching forever for a solution to this, so I thought I'd seek out the brainpower of greater minds than mine. I'm developing a Cocoa app that uses the Accessibility API to manipulate another program (it's a hotkey app). The app I'm controlling typically has multiple windows open, with some hidden behind others. What I would like to do, if it's possible, is to send mouse events to windows using the Accessibility API in a way that presses a button in the window without bringing it to the foreground (interact with the window but don't activate it). The reason I'm trying to do this is that sending the mouse event to this other window will force it to the foreground and disrupt the user's interaction with the foremost window.
This is possible on Windows - apparently, because apps similar to mine do it there - but I'm getting the feeling that this isn't possible with Cocoa, given the way the window manager works. Am I mistaken?
Accessibility is higher-level than that. You send, for example, AXPress actions to AXButton objects, but “press” is not necessarily a click—pressing the space bar while a view is focused, for example, is also a “press”. AXPress is a high-level action that means “do your thing”, which obviously has meaning for some views (such as buttons) and not others (such as fields).
Accessibility activating the application does make sense when you look at it from its intended purpose: Assistive devices for disabled users. If the user “presses” something by whatever means, they probably intend to activate the application and work in it.
Quartz Event Services will get you almost there: You can create an event tap for the process you want to control, and you can forge events and send them to a tap. The catch is that you can only send events to a tap when the tap fires—i.e., when the application already has an event to deal with. When it doesn't, you're stuck.
In a fairly graphics intsensive application the requirements state that it should default to full screen mode even though the application is running under Windows. I know many games do this but I find it annoying. The default IMO should be to open in a window rather than full screen mode. I am proposing the first time the user runs the application they should select the default behavior. Am I wrong?
I think the annoyance-factor depends a lot on what the application tries to do.
If it is some utility that I might start while working in 5 different applications and it forces its fullscreen-ness on my, then I'd get highly annoyed.
If it is a specialized application that helps me with the entire workflow of a given task (so that I never or rarely need any other apps open at the same time), then fullscreen might actually be a valid default.
Whatever you do, just make sure that toggling the startup behaviour is very discoverable. Because no matter which way you'll go, some of your users will disagree with your decision. And for them it should be very easy to change to their prefered way.
I would follow the requirement the first time the application is launched. I would also provide a simple way to switch from full screen to windowed, for instance by pressing ESC (and another way to go back to full screen). Then I would store the mode when quitting the application and restore this mode at next launch.
Before doing the opposite of what your requirements say, I'd have the requirements changed.
However, what about giving the user the choice at install time?
The window at first-start-up should default to the optimal size for the largest proportion of users. For a graphics-intensive full-featured app, that may very well be full screen.
As for individual user preferences for window size, it seems to me most users won’t know if they want full screen or not until after they’ve started to use the app and see how much screen space they need and how much they use the window in conjunction with other windows. Asking them which size they want at install or first-start-up could thus be annoying and even confusing. It’s better to put such a setting under Options/Preferences.
Perhaps the best thing to do is save the window status on exit. Users who like it non-maximized thus only have to non-maximize it (and size it) once and then forget about it. The only consideration is to have some way to reset the window to the default (e.g., Window > Standard Size menu item) for novice users who accidentally resize or reposition the window to something bizarre and don’t know how to get it back. Alternatively, you could have a Window > Keep Sizes and Positions menu item for users to explicitly save the window status across sessions.
Go back to the requirements writers and ask them if they have considered non-traditional monitor setups, such as:
30" or larger monitor. Do you really want your app hogging up all the screen real-estate?
Multiple monitors. Which monitor will you run on? Can the user move your app from one monitor to another? Can your app span more than one monitor?
Virtual desktops. Can the user move your app from one desktop to another? Can they switch desktops while your app is running? Can your app span more than one desktop?
Such setups are increasingly common, especially large monitors. IMO, full-screen mode (the default for many older Windows apps) is becoming less and less useful.
The problem with presenting the user with the option of initially selecting fullscreen / vs windows is that they haven't used the software yet. How can they make a decision on which is better for them, without experience?
I would run the app in whichever mode provided the best user experience and then offer an option to change it both in the Preferences and though a hint while starting up the application for the 2nd time.