Bringing window to foreground (Qt)

Last edited on

Overview

When automating multiple applications or a single application with multiple windows it can be useful (or required) to bring one window to the foreground, or to make the non active application active.

The problem with this is that modern operating systems and window managers actively try to prevent that an application makes itself active. And this is something that Squish cannot change.

However, sometimes the following workarounds might work.

IMPORTANT - Additional settings for Linux

On Linux systems you may have to configure one of the following.

Ubuntu

Set the entry...

CompizConfig Settings Manager > General > General Options > Focus & Raise Behaviour > Focus Prevention Level

...to Off. (May require installing the CompizConfig Settings Manager.)

Other Linux distributions

Set the entry...

System Settings > "Window Behavior > Window Behavior > Focus > Focus stealing prevention level

...to None.

(German: "Fensterverhalten", "Fensterverhalten", "Aktivierung", "Vorbeugung gegen unerwünschte Aktivierung".)

IMPORTANT - Additional settings for Windows

On Windows you may have to configure the registry entry ForegroundLockTimeout ( google ForegroundLockTimeout ).

Reading the existing value in cmd.exe (Command Prompt):

reg query "HKEY_CURRENT_USER\Control Panel\Desktop" /v ForegroundLockTimeout

Setting (overwriting) the existing value in cmd.exe (Command Prompt):

reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ForegroundLockTimeout /t REG_DWORD /d 0 /f

Notes

Workaround #1: TopLevelWindow API

Squish offers the TopLevelWindow API for manipulating windows.

Workaround #2: raise() + activateWindow()

In general:

def main()
    startApplication("addressbook")
    o = waitForObject({"type": "MainWindow", "unnamed": 1, "visible": 1, "windowTitle": "Address Book"})
    o.show()
    getattr(o, "raise")()
    o.activateWindow()
test.py

Also see:

Workaround #3: Create, show and close a QMessageBox

This relies on the side effect that closing a QMessageBox will activate the respective application:

def main()
    # Start first instance:
    ctx1 = startApplication("addressbook")

    # Start second instance:
    ctx2 = startApplication("addressbook")

    # Make first instance the current context in Squish:
    setApplicationContext(ctx1)

    # Try to bring it to foreground:
    mainwindow_to_foreground()

def mainwindow_to_foreground():
    w = waitForObject({"type": "QMainWindow", "visible": 1})
    mb = QMessageBox(w)
    mb.show()
    clickButton(waitForObject({"text": "OK", "type": "QPushButton", "visible": 1}))
    snooze(0.1)
test.py