Featured image of post Qt show(), raise(), and activateWindow() Call Order

Qt show(), raise(), and activateWindow() Call Order

A source-code-based explanation of what QWidget::show(), showNormal(), raise(), and activateWindow() each do, and why the recommended call order matters.

In Qt development, it is common to see code like this:

1
2
3
widget->show();
widget->raise();
widget->activateWindow();

Many people use this sequence, but not everyone can clearly explain what each call actually does or why this order is commonly recommended.

At first glance, all three may seem related to “bringing a window to the front.” But if you read the Qt source code, they operate at three different levels:

  • show(): makes the widget visible
  • raise(): adjusts the Z-order so the widget is stacked higher
  • activateWindow(): requests that the window become the active window and receive keyboard focus

These are not the same thing, so the order is not arbitrary.

1. show(): make the window visible first

Let’s start with QWidget::show():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
void QWidget::show()
{
    // Note: We don't call showNormal() as not to clobber Qt::Window(Max/Min)imized
    if (!isWindow()) {
        setVisible(true);
    } else {
        const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
        Qt::WindowState defaultState = platformIntegration->defaultWindowState(data->window_flags);
        if (defaultState == Qt::WindowFullScreen)
            showFullScreen();
        else if (defaultState == Qt::WindowMaximized)
            showMaximized();
        else
            setVisible(true);
    }
}

There are two key takeaways here.

1.1 show() is essentially setVisible(true)

For a normal child widget, show() simply calls setVisible(true).

For a top-level window, Qt first checks the platform integration and window flags to decide whether it should be shown as:

  • fullscreen via showFullScreen()
  • maximized via showMaximized()
  • normally visible via setVisible(true)

So the main job of show() is simply this: make the widget visible.

It does not:

  • bring the window to the top of the stack
  • force activation or focus
  • restore a minimized window to the normal state

1.2 show() does not clear minimized or maximized state

This source comment is especially important:

1
// Note: We don't call showNormal() as not to clobber Qt::Window(Max/Min)imized

That means show() does not call showNormal() automatically, because Qt does not want to overwrite an existing minimized or maximized state.

So if a window is already minimized, calling show() again does not necessarily mean “restore the window.” That is exactly why showNormal() is the better choice in many restore scenarios.

2. showNormal(): restore from minimized, maximized, or fullscreen

Now look at QWidget::showNormal():

1
2
3
4
5
6
7
8
void QWidget::showNormal()
{
    ensurePolished();
    setWindowState(windowState() & ~(Qt::WindowMinimized
                                     | Qt::WindowMaximized
                                     | Qt::WindowFullScreen));
    setVisible(true);
}

It does two things:

  1. Clears these state bits:
    • Qt::WindowMinimized
    • Qt::WindowMaximized
    • Qt::WindowFullScreen
  2. Calls setVisible(true)

So the meaning of showNormal() is very explicit: restore the window to the normal state and show it.

That makes it a better fit than show() in situations like these:

  • the main window has been minimized to the taskbar
  • a single-instance app is launched again and needs to restore the existing window
  • clicking a tray icon should bring a hidden or minimized window back to the desktop

In short:

  • show() answers “is it visible?”
  • showNormal() answers “is it restored to the normal state?”

3. raise(): adjust stacking order, not window activation

Here is QWidget::raise():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void QWidget::raise()
{
    Q_D(QWidget);
    if (!isWindow()) {
        QWidget *p = parentWidget();
        const int parentChildCount = p->d_func()->children.size();
        if (parentChildCount < 2)
            return;
        const int from = p->d_func()->children.indexOf(this);
        Q_ASSERT(from >= 0);
        if (from != parentChildCount -1)
            p->d_func()->children.move(from, parentChildCount - 1);
        if (!testAttribute(Qt::WA_WState_Created) && p->testAttribute(Qt::WA_WState_Created))
            create();
        else if (from == parentChildCount - 1)
            return;
        QRegion region(rect());
        d->subtractOpaqueSiblings(region);
        d->invalidateBackingStore(region);
    }
    if (testAttribute(Qt::WA_WState_Created))
        d->raise_sys();
    if (d->extra && d->extra->hasWindowContainer)
        QWindowContainer::parentWasRaised(this);
    QEvent e(QEvent::ZOrderChange);
    QCoreApplication::sendEvent(this, &e);
}

This function is easier to understand if you separate child widgets from top-level windows.

3.1 For child widgets, raise() mostly reorders the parent’s children list

This line is the key:

1
2
if (from != parentChildCount -1)
    p->d_func()->children.move(from, parentChildCount - 1);

For a non-window widget, raise() moves the widget to the end of the parent’s children list, which changes the painting and stacking order among sibling widgets.

After that, Qt may also:

  • call create() if needed
  • recompute the affected region
  • call invalidateBackingStore(region) to trigger repainting

So for child widgets, the core meaning of raise() is: place this widget above its sibling widgets.

3.2 For top-level windows, the important part is d->raise_sys()

For windows, this line matters most:

1
2
if (testAttribute(Qt::WA_WState_Created))
    d->raise_sys();

This tells us two things:

  1. raise() eventually delegates to the platform layer
  2. it only does so if the native window has already been created

That leads to an easy-to-miss detail:

If a top-level window has not been created yet, calling raise() alone may do nothing.

A top-level window usually becomes fully created after show() or setVisible(true). So from the source-code perspective, calling show() before raise() is the sensible order.

3.3 raise() does not mean “give me focus”

raise() changes stacking order. It does not activate the window.

Even if a window is brought visually higher, that does not mean it has become the active window or received keyboard focus.

So this:

1
widget->raise();

only means “please bring this window higher in the stack,” not “the user can type into it immediately.”

4. activateWindow(): request activation of the top-level window

Now look at QWidget::activateWindow():

1
2
3
4
5
6
void QWidget::activateWindow()
{
    QWindow *const wnd = window()->windowHandle();
    if (wnd)
        wnd->requestActivate();
}

The implementation is short, but it reveals a lot.

4.1 It operates on the top-level window, not the current child widget itself

The code uses:

1
window()->windowHandle()

So even if you call activateWindow() on a child widget, Qt ultimately tries to activate the top-level window that contains it.

That means activateWindow() does not mean “give this exact widget focus.” It means:

Make the top-level window containing this widget become the active window.

4.2 It calls requestActivate(), not a force-activate API

The key line is:

1
wnd->requestActivate();

The word is request, not force.

Qt can ask the window system to activate the window, but whether that request succeeds depends on platform policy.

Qt’s own documentation is very explicit about this:

  • on X11, the result depends on the window manager
  • if you also want the window stacked on top, call raise() as well
  • the window must be visible, otherwise activateWindow() has no effect
  • on Windows, if your app is not currently the active application, the OS usually will not allow it to steal the foreground window; it may only highlight the taskbar entry instead

That is why activateWindow() sometimes seems to work and sometimes does not.

Qt is doing its part, but it cannot bypass the operating system’s foreground-window policy.

The source code makes the recommended order fairly direct.

5.1 First, make the window visible

The documentation for activateWindow() says:

the window must be visible, otherwise activateWindow() has no effect.

And internally it also depends on:

1
window()->windowHandle()

If the window has not been shown yet, the window handle may not be ready, and the call can effectively become a no-op.

So the first step should be show() or showNormal().

5.2 Then adjust the stacking order

raise() is responsible for bringing the window higher in the Z-order.

Qt’s documentation for activateWindow() even says:

If you want to ensure that the window is stacked on top as well you should also call raise().

In other words, activation and stacking order are separate concerns.

If you call only activateWindow(), some platforms may not place the window as prominently as you expect. raise() fills that gap.

5.3 Finally, request activation

Once the window is:

  • visible
  • already brought as high as possible in the stack

calling activateWindow() makes the intent complete.

So the common recommended sequence is:

1
2
3
widget->show();
widget->raise();
widget->activateWindow();

If the window may be minimized, an even better choice is:

1
2
3
widget->showNormal();
widget->raise();
widget->activateWindow();

6. Summary

From the Qt source code, the responsibilities of these APIs are clearly separated:

  • show(): make the window visible, but do not restore normal state or request focus
  • showNormal(): clear minimized, maximized, and fullscreen state, then show the window
  • raise(): adjust Z-order so the window is stacked higher
  • activateWindow(): ask the window system to activate the top-level window

So in practice:

  • if you want to restore a minimized window, use showNormal()
  • if you want to bring the window visually forward, use raise()
  • if you want to request focus, use activateWindow()
  • if you want the full “show it and try to bring it to the front” behavior, use showNormal() / show() + raise() + activateWindow()

The most commonly useful sequence, and the one that best matches the source-code semantics, is:

1
2
3
widget->showNormal();
widget->raise();
widget->activateWindow();

If the window is not minimized, you can replace showNormal() with show().