I do really need to make my window to stay on top on Windows, but Windows itself does not seem willing to allow me to do this.
I cannot use the workaround with setting registry values because I am not able to ask the user to log-out/log-in.
Besides, I use QML and the solution with QWidget::raise() and QApplication::setActiveWindow() does not seem to work also because I have not managed to get the QML root object as a QWidget pointer with the following code:
QWidget* mainWin = qobject_cast<QWidget*>(engine.rootObjects().at(0));
if (mainWin)
{
mainWin->raise();
QApplication::setActiveWindow(mainWin);
mainWin->activateWindow();
}
I have also tried to make the window active right from the QML:
window.raise()
window.requestActivate()
but with no luck also.
Is there, either way to bring the window on top on Windows without changing the registry and, preferably, from the QML purely?
Edit:
currently used window flags are:
Qt.Popup
Qt.FramelessWindowHint
Qt.WindowStaysOnTopHint
Qt.CustomizeWindowHint
Qt.BypassWindowManagerHint
Qt.MSWindowsFixedSizeDialogHint
I am deploying Qt 5.7 app on the Windows 10 x64 machine.
I have found this two bugfixes:
https://bugreports.qt.io/browse/QTBUG-14062
https://bugreports.qt.io/browse/QTBUG-37435
from which I can conclude that QWidget::activateWindow() and QWindow::requestActive() should work on Windows XP and Windows 7.
Here is my mcve, as #derM asked:
import QtQuick 2.7
import QtQuick.Window 2.2
Window {
flags: Qt.WindowStaysOnTopHint
width: 100
height: 100
visible: true
}
It was compiled under Windows 10 x64 with MinGW x32.
Easier way to reproduce: run in the command prompt
timeout 5 && debug\Test.exe
where debug\Test.exe is a path to the mcve binary, then open File Explorer and navigate somewhere. When the window opens, it won`t be in the foreground.
Harder way: If you just run it, the window will stay on top as it should.
But if you press Run button in the Qt Creator and switch the focus (I suppose, mouse focus should be changed, just pressing Alt+Tab won`t help) to another process (in my case - File Explorer), the window is displayed under the current active File Explorer window, and even if I will bring it up by clicking, it will go background as soon as I choose any other application.
The real application is started from a service, so there often will be an app holding mouse focus when my app is started. I suppose that Qt ability to bring the window to foreground is implemented using SetForegroundWindow API call, which notes the following restrictions in it`s remarks:
The process is the foreground process.
The process was started by the foreground process.
The process received the last input event.
There is no foreground process.
The process is being debugged.
The foreground process is not a Modern Application or the Start Screen.
The foreground is not locked (see LockSetForegroundWindow).
The foreground lock time-out has expired (see - SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
No menus are active.
So I wonder is it possible at all to bring the window to foreground if the process has been started by a service, not a user (i. e. the process has not been an active process during startup).
As you have posted: If the window is created from the foreground process, we will just make sure, that our process is the foreground process before we create the window.
import QtQuick 2.7
import QtQuick.Window 2.2
Item {
id: root
Component { // Like a splash screen: Claim to be foreground process,
// then create main window.
id: winInit
Window {
flags: Qt.WindowStaysOnTopHint
width: 1
height: 1
Component.onCompleted: {
requestActivate()
mainWin.createObject(root)
}
}
}
Component {
id: mainWin
Window {
flags: Qt.WindowStaysOnTopHint
width: 100
height: 100
visible: true
}
}
Component.onCompleted: {
var w1 = winInit.createObject(null)
w1.destroy()
}
}
Related
I am building a Qml ApplicationWindow and I want it to be in fullscreen and always on top (I use visibility: FullScreen and the Qt.WindowStaysOnTopHint flag). It works, but when I launch background applications from the UI, the windows taskbar shows up and overlaps the UI.
I am running the application on Windows 7.
Any ideas on how to prevent the taskbar to show up ?
Thanks.
I'm currently trying to keep the Windows Touch Keyboard (TabTip.exe) over a fullscreen Qt QML application.
Unfortunately, after showing (and forcing it to be on top) it's dismissed again.
It does not matter if I start the keyboard before starting the application or while running the application in fullscreen, after Qt is gaining focus, the keyboard is behind.
Any ideas what this could cause? Is this a Qt or Windows issue?
I found a way to keep the Windows keyboard above my QML "fullscreen" application. What I noticed is that in non fullscreen application, the keyboard appears well above my QML application. So the idea was to simulate a fullscreen application giving the window application nearly the size of the screen. Some code will be better:
ApplicationWindow {
id: mainWindow
x: 0
y: 0
width: Screen.width
height: Screen.height + 1 //+1 because does not work if the window size is equal to screen resolution. In some way, it considers it's a real fullscreen application and the keyboard stays behind.
flags: Qt.FramelessWindowHint | Qt.Window //first flag to remove top right buttons such as close button, second flag to keep the application thumbnail in the Windows taskbar to close it if necessary.
visible: true
...
}
With that, I can open the Windowd keyboard clicking on a text field, close it, re open it, ... all that I want!
I'm using QML to build an OSX application with fullscreen mode support. My intention is to toggle fullscreen/normal mode by double-clicking the main area of the window, here is the minimal code:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
id: main
visible: true
width: 800; height: 480
flags: Qt.Window | Qt.WindowFullscreenButtonHint // for OSX native behavior support
MouseArea {
anchors.fill: parent
onDoubleClicked: {
if (main.visibility === Window.FullScreen) {
main.visibility = Window.AutomaticVisibility;
} else {
main.visibility = Window.FullScreen;
}
}
}
}
It's very simple, but the behavior is weird:
Whenever the visibility state of the application changes(enter or leave), the user must click in the window one more time before the window mode can change again, just like the application loses the mouse focus.
To validate what I'm thinking, I test something more, I add one more MouseArea(let's say mouseAreaTest) in the window, which split the window side by side and can receive onEntered and onExited event. Right after the application enter or exit fullscreen mode, mouseAreaTest will never receive any Enter or Exit event, unless you click on the window one more time, which is not what I want.
I know nothing about how OSX implement its own fullscreen mode, nor why QML on OSX has such a buggy problem. So I expect someone will tell me something about it.
Update
Later I doubted if this was only something about QML which related something about the Window System of QML, so I tried using traditional QtWidgets, and found the same result there.
Update
I tracked the mouse event of traditional widget, and found the problem: the double click event consisted of two click event(press-release-press-release), when the window state changd(fullscreen to normal or normal to fullscreen), the last RELEASE event will never be received UNLESS click one more time.
I also did more test: use a button to control window state, and the problem is gone, so I may probably consider this is a bug of mouse event handle.
By the way, post system info for a note:
OSX 10.10.1
Qt 5.4.1
This bug still exists in Qt 5.11. I found a workaround eventually.
The reason why the last mouse release event not received is that we toggled fullscreen immediately. Somehow the mouse release event was lost during transition to fullscreen.
So the fix was simple: we postpone toggling fullscreen till next mouse release event. i.e. when we need to toggle fullscreen, set a flag temporarily, then in mouseReleaseEvent, check the flag and do the real work.
If my wxWidgets application creates a new window while the application does not have focus, its taskbar icon blinks yellow until I switch to it, as shown here:
This is annoying. How can I prevent this from happening?
EDIT: The original version of this question suggested the blinking was happening during startup. After further investigation, this is not occurring right at application startup; rather, it occurs if I create an additional window while the application does not have focus.
To give a bit more background: my application is a sort of server, that opens windows in response to network events. If I boot up the application, then switch focus to something else and a network event comes in while the focus is elsewhere, my application will open a new window in the background (not grabbing focus) and this blinking will occur.
The windows are wxFrames; the application constructs them and their child widgets, then calls Show(true) on the frame.
Also, I've attempted to set a breakpoint on the FlashWindow Win32 API function, hoping to trap wherever in WX it's getting called, but haven't been able to make that work.
Maybe the following would work:
wxTopLevelWindow::ShowWithoutActivating ( )
http://docs.wxwidgets.org/trunk/classwx_top_level_window.html#a03e526f505716568318d601318527bd0
Yes. If you create a new top level window while the app does not have focus, then the task bar icon will flash. This is the intended behaviour of the windows operating system.
I've got two applications I'm developing using Qt on windows. I want the user to be able to press a button in one application which makes the other application come to the foreground. (The programs communicate using QLocalSocket and named pipes.)
Currently I'm using Qt's QWidget::activateWindow() which occasionally brings the application to the foreground, but most of the time it just highlights the program on the taskbar.
Can someone please tell me how to do this, preferably using Qt although failing that using the WIN32 API would be fine.
Unfortunately, I couldn't find a way to do this only with Qt. I solved it using Chris Becke's suggestion of calling SetForegroundWindow from the currently active application.
Are you sure this is not a debugging issue? The deal is, if an application HAS the foreground, it is allowed to change the foreground.
Clicking a button on window A will give that windows thread foreground activation. If it calls SetForegroundWindow (or equivalent) on the other window, that window WILL be given the foreground.
If, on the other hand, it simply sends a message to the other app, which tries to SetForeground on itself, that will fail. AllowSetForegroundWindow is used in situations where a 'legacy' app needs to be given permission - by a foreground app - to take the foreground. Once again, AllowSet... only works if called from a thread that owns the current active foreground window.
On top of the QWidget::activateWindow method, you should call QWidget::raise !
This is what is said here.
I have a similar case.
I have two Qt applications, A and B, which communicate on a socket.
I would like to bring a window of application B up, through a button on application A.
I found that sometimes the widget state is not set correctly, so in the event() function of my applicatons B's widget I did the following:
bool MyWidgetB:event ( QEvent * e )
{
QEvent::Type type = e->type ();
// Somehow the correct state of window is not getting set,
// so doing it manually
if( e->type() == QEvent::Hide)
{
this->setWindowState(WindowMinimized);
}
else if( e->type() == QEvent::Show )
{
this->setWindowState((this->windowState() & ~WindowMinimized) |
WindowActive);
}
return QWidget::event(e);
}
I'm sending a command from application A to B. On receiving it, application B calls the following function on itself:
void BringUpWidget(QWidget* pWidget)
{
pWidget ->showMinimized(); // This is to bring up the window if not minimized
// but beneath some other window
pWidget ->setWindowState(Qt::WindowActive);
pWidget ->showNormal();
}
This works for me, on Windows XP, with Qt 3.3. My MainWidget is is derived from a QWidget.
I have found this is also working with a widget derived from QMainWindow, but with some issues. Like if some other child windows are open.
For such a case I store the position of the child windows and hide them, then use the BringUpWidget function to bring my MainWindow widget, and then restore the child windows.
This is kind of cheesy, but it works for me:
this->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
this->show();
this->setWindowFlags(Qt::FramelessWindowHint);
this->show();
Or, if you don't have other flags,
this->setWindowFlags(Qt::WindowStaysOnTopHint);
this->show();
this->setWindowFlags(0);
this->show();
WindowStaysOnTopHint will almost always force the window to the foreground. Afterwards, you don't really want the window to always stay on top, so reset to whatever the previous flags were.
I think the APIs you need are AllowSetForegroundWindow() and SetForegroundWindow(). I don't know what the equivalent Qt calls are.
Use showNormal() to go from an iconified state to a visible state.