Force Qt Window on top of XPlane Window - c++

I am writing a flight simulator application. For that my Qt Application window should stay on top of the flight simulator application window.
The flight simulators (P3D, FSX, XPlane) offer 2 different window modes, i.e. "windowed" and "full screen". The windowed modes are no problem, I can just set Qt::WindowStaysOnTopHint for my window and it works. However, it does not work for the XPlane fullscreen mode (but does for P3D/FSX).
I have no idea what XPlane fullscreen mode really does, only that it uses OpenGL. Obviously my window looses focus when I click into the XPlane Window. On Windows I can get it back on top with ALT+TAB
I have tried (triggered by timer) widget->activateWindow(); with no result. Are there any more "tricks" I could try.

In general, an application can't force itself to the front. It can request being brought to the front, but whether that request is granted is up to the window manager.
Applications (on some platforms) can tell the window manager that they will allow certain other applications to be brought to the front instead of themselves (which allows those applications to forcefully bring themselves to the front over the granting applications, but not over other uncooperative applications). Generally this is all a cooperative thing and no one application can force its will on all the others (which IMHO is a good thing).

Related

Fullscreen mode on monitor A in dual-monitor setup breaks when moving windows from monitor B onto it

I am building a Win7/8/10 x64 Direct3D11 desktop application that allows the user to switch between windowed and fullscreen mode (proper dedicated fullscreen mode, not just a maximized window*). On a dual-monitor setup I am encountering some issues.
The switch itself is performed manually using IDXGISwapChain::SetFullscreenState and works as intended: The monitor that houses the lion's share of the window area (let's call it monitor A) goes into dedicated fullscreen mode while leaving the other (monitor B) as it was, allowing the user to interact normally with windows on B as well as the fullscreen application on A.
However, if a window on B is dragged or resized so that it crosses over to A, the application's fullscreen state gets disturbed: Sometimes it just reverts back to windowed mode (leaving the application's internal tracking variable out of sync), sometimes it stays in a quasi fullscreen mode where it seemingly refuses further mode switches, and so on. The same thing happens if a window that overlapped both A and B before the application went into fullscreen mode gets focus.
Is there any way to prevent this?
I wish the OS would honor my application's dedicated fullscreen mode and keep it in a robust state even if other windows are dragged onto that monitor. I'd want the behavior to be similar to having an "always-on-top, maximized borderless window" in its stead, i.e. have other windows just "disappear behind it" and not affect the state of my fullscreen window at all.
I have tried some workarounds, like responding to WM_KILLFOCUS and temporarily switching my application into a "maximixed borderless window" until it receives WM_SETFOCUS again, but the WM_KILLFOCUS message has a lag during which there is time for a user to drag another window into the area that is then still in fullscreen mode, thereby setting me back to square one.
*The reason I want this feature rather than simply using a maximized borderless window (which is also a supported mode, btw) has to do with it allowing for much lower mouse-movement-to-rendering latency, vsync control (ON/OFF) etc.. all of which are - in short - important to the nature of this application (which is not a game).
Although not ideal (ideal would be that there was a way to have the OS itself handle this properly), I have found a reasonable workaround that I suppose I can live with for now. It is a variation of the concept mentioned in the question ("..like responding to WM_KILLFOCUS and temporarily switching my application into a maximixed borderless window.."), but without the crippling delay problem:
Whenever the application enters dedicated fullscreen mode, it also captures the mouse with a call to SetCapture. This will not affect the user's ability to interact with other windows on monitor B, but it will ensure that any such de/activating interaction - like a mouse click in another application - will send a WM_LBUTTONDOWN to my application before it loses focus. Importantly, this happens immediately, unlike the WM_KILLFOCUS message that has significant latency.
When such a WM_LBUTTONDOWN message is received (while in fullscreen), the application checks whether the click happened outside its screen area. If so, it means it is about to lose focus and thus expose itself to all the complications brought up in the original question. So it temporarily exits dedicated fullscreen mode and "replaces" it with a (visually identical) borderless maximized window. When the application regains focus, it goes back into dedicated fullscreen.
This works OK, since you don't really care about the application's responsiveness when you're not interacting with it anyway. The biggest inconvenience here is the mode switch flickering that occurs on these focus transfers, but given the alternatives, I find it an acceptable price to pay for what I want to accomplish (but by all means - I'd be very interested in a better solution).
Edit 1: It is worth noting that since there are other ways for an application to lose focus than through mouse clicks, WM_KILLFOCUS is also handled.
Edit 2: I recently realized that handling the WM_BUTTONDOWN message is redundant. SetCapture alone will ensure that the WM_KILLFOCUS message is received quickly enough.

Transparent window on top of immersive full-screen mode

I am trying to draw on top of another process while it is in immersive full-screen mode.
I know this is possible using GDI and I have 2 questions:
Is it possible using a top-level transparent window ? (on top of the immersive process)
Is there a higher level API witch I can use instead of GDI?
Thank you :)
In Windows, you have two possibilities for creating a fullscreen window:
A full-screen application with exclusive drawing rights to the display.
A borderless window that extends to the full desktop resolution.
The first option allows you to change display properties like resolution, bit depth and refresh rate, while the second option is bound to use the same options here as a normal (windowed) desktop application.
Overlaying a fullscreen window with a top-level window is only possible if the fullscreen application is implemented with option 2. In that case however, any code that is able to create a transparent top-level window will do (be it pure WinAPI/GDI, or something more sophisticated, like Qt).
With option 1, as the description suggests, the fullscreen application has exclusive drawing rights to the display. Attempting to bring another window in front of it will either minimize the fullscreen application or force it into windowed mode.
There are some hacks how you can still get an overlay in this case, but they are rather invasive. For example, with a fullscreen application based on D3D, you can hook into D3D's Present routine and have D3D draw your overlay before displaying the back buffer. The important point here is that the code for drawing the overlay is executed from within the process of the fullscreen application, as that is the only process that is allowed draw to the screen at that point.
Note that some applications (in particular video games protected by anti-cheat software) do not like it very much if you inject code into the process this way.
Note that the Win API also provides an interface for so called hardware overlays, which allow drawing on top of exclusive fullscreen applications. Unfortunately, this mechanism is not widely supported on consumer hardware and might not work depending on which graphics card you are trying to run it on.

Creating a new window that stays on top even when in full screen mode (Qt on Linux)

I'm using Qt 4.6.3, and ubuntu linux on an embedded target. I call
dlg->setWindowState(Qt::WindowFullScreen);
on my windows in my application (so I don't loose any real-estate on the touch screen to task bar and status panel on the top and bottom of the screen. This all works fine and as expected. The issue comes in when I want to popup the on screen keyboard to allow the user to input some data. I use
m_keyProc= new QProcess();
m_keyProc->start("onboard -s 640x120");
This pops up the keyboard but it is behind the full screen window. The onbaord keyboards preferences are set such that it is always on top, but that seems to actually mean "except for full screen windows". I guess that makes sense and probably meets most use cases, but I need it to be really on top.
Can I either A) Not be full screen mode (so the keyboard works) and programmatically hide the task bars? or B) Force the keyboard to be on top despite my full screen status?
Note: On windows we call
m_keyProc->start("C:\\Windows\\system32\\osk.exe");
and the osk keyboard is on top despite the full screen status. So, I'm guessing this is a difference in window mangers on the different operating systems. So do I need to set some flag on the window with the linux window manager?
Qt doesn't seem to have a way to bring other, non-Qt process in front. You may need to get the native, platform process ID from QProcess by calling QProcess::pid() and call the underlying OS API to do it.

How do I place my app window in a certain position in the desktop window hierarchy on Windows using win32 api?

I want my application window to be in a certain spot in the window hierarchy. That is, say I have 3 windows on my desktop. At the very bottom I have Word, the window on top of word is explorer, and the active foreground window is itunes. I want to place my application window on top of word but beneath explorer. How can I achieve this with win32?
You might be able to use SetWindowPos - look at the hWndInsertAfter parameter. I'm not sure if this will work across process boundaries, but it's worth a shot. Perform this after your window is created but before you make it visible.
This is most likely not possible, because you will get caught by the code that tries to prevent focus stealing - it might work if your app initially has focus and you try to give it away (i.e. you are on top, then you try to hide behind the Explorer window)
If you want to maintain this arrangement, the simplest way is to create your window specifying Words window as your parent
Otherwise SetwindowPos is the all purpose worker for controlling a windows position, visibility and depth. But any z-ordering performed here will obviously be lost as soon as the user actually starts switching tasks.
One thing to watch out for: windows always raises the active window to the top of the z-order, and likewise, activates any window that is moved to the top of the z-order. There are restrictions however :- to prevent all manner of irritating behaviour Windows prevents applications from stealing activation without a user interaction - which means that, if word is currently the active window, SetWindowPos to place yourself above Word will only succeed if your app is allowed to take activation at that time.

Simulate fullscreen

I've seen an application that simulates a fullscreen application by removing the title bar and the window borders. I've done some research and found getWindowLongPtr() for that.
Now my question: How can I find and identify the application and get the appropriate window handle? How can I distinguish multiple instances of the application (running from different locations on disc)?
Just to make "simulate" more precise. If you make an application go fullscreen and you click on a different monitor, it minimizes itself. If the application runs in a window and you click on a different monitor, the window is not changed. If you remove the borders of the window and position it on the left or right monitor, you can still work with the other monitor without minimizing the application. Still it looks like the application running fullscreen on one of the monitors.
As an example: you can set Eve (www.eveonline.com) to fullscreen and windowed mode. In fullscreenmode you can not click on a second monitor without Eve minimizing itself. In window mode you can. There are tools like evemover that allow you to setup your window on one monitor, looking like fullscreen, but being in window mode. That's what I want to archieve. Evemover actually provides some of it's source code, that's why I know that removing the border and setting the position is done using the Win32-API with setWindowLongPtr and setWindowPos.
Many applications use divergent and confusing applications of the phrase "fullscreen".
A fullscreen application simply - occupies the full screen area.
DirectX applications can request a fullscreen exclusive mode. The advantage of this mode to DirectX applications is, with exclusive access to the (full) screen they are then allowed to change the resolution, bit depth etc, as well as gain access to vertical sync synchronized hardware buffering where the screen surface is 'flipped' between display intervals so that 'tearing' does not occur.
Anyway, the windows desktop understands 'fullscreen windows' - windows that occupy the full area of a monitor and have no non client elements. When windows like this are created, things like desktop gadgets and task bars automatically hide themselves. Modern games have come to call this mode 'fullscreen windowed'.
Back to your question: 'FindWindow' is the API used to discover other applications windows. Getting the path to the application that created the window is much harder. GetWindowThreadProcessId can get you the process id of the owning process. OpenProcess will get you a handle that you can pass to QueryFullProcessImageName (implemented on Vista and above) to get the full path to the process.
I think you are refering to applications like window aggregators, that 'plug in' to the system and act from outside the application.
Look at the code for the freeware app PuttyCM (for aggregating Putty (SSH) shell windows as tabs). IIRC, it ensures that the Window pointer passed to the application has the flags already set.
On applications running from different places, you will probably need some way of identifying it - registry entries / install log etc.