Skip to content

[Bug]: Fullscreen mini-toolbar placed on the wrong host monitor, hiding desktop panels there #842

Description

@dr1fter

Summary

In fullscreen mode the mini-toolbar's outer window can be placed on a different
host monitor than the machine window it belongs to. Because that window is
screen-sized and carries _NET_WM_STATE_FULLSCREEN, the window manager treats
the unrelated monitor as having a fullscreen window on it, and desktop panels on
that monitor stop being drawn.

With a single guest screen on a three-monitor host, this makes the desktop panel
on an unrelated monitor disappear for as long as the VM runs.

Environment

Host OS       Arch Linux
Kernel        7.1.10-arch1-1
Session       X11, Cinnamon 6.6.9 / Muffin 6.6.3
VirtualBox    7.2.16
qt6-base      6.11.2
Monitors      3 x 1920x1200 side by side
Guest         monitorcount=1, GUI/Fullscreen=true

Host monitor layout, as enumerated by Qt:

[0] DP-2  1920x1200+1920+0
[1] DP-4  1920x1200+3840+0
[2] DP-0  1920x1200+0+0

Observed

The machine window is placed correctly on DP-2 (+1920+0). The mini-toolbar
outer window ends up on DP-4 (+3840+0):

win class="VirtualBox Machine"  pos=1920,0  1920x1200
    _NET_WM_STATE = FULLSCREEN

win class="VirtualBoxVM"        pos=3840,0  1920x1200
    _NET_WM_STATE = SKIP_PAGER, SKIP_TASKBAR, FULLSCREEN
    _NET_WM_WINDOW_TYPE = UTILITY
    WM_TRANSIENT_FOR = <the machine window>

VBox.log shows the toolbar being sent to a third monitor's origin entirely:

GUI: Adjust mini-toolbar for window #0
GUI:  Resize mini-toolbar for window #0 to 1920x1200
GUI:  Move mini-toolbar for window #0 to 0x0

Setting GUI/ShowMiniToolBar=false removes the stray window and the panel
behaves normally, which confirms the window's identity.

Cause

UIMiniToolBar::sltAdjust() resolves its host screen from the parent widget:

int iHostScreen = UIDesktopWidgetWatchdog::screenNumber(m_pParent);

UIDesktopWidgetWatchdog::screenNumber(const QWidget *) resolves through
pWidget->windowHandle()->screen(). During the fullscreen transition that
native screen association can still lag behind the geometry that
UIMachineWindowFullscreen::placeOnScreen() has already assigned to the
top-level widget, so the toolbar is placed relative to the wrong monitor.

The surrounding code already acknowledges this area is racy — the existing
WORKAROUND comment immediately below handles screenNumber() returning -1.

This is timing-sensitive rather than a Qt behaviour change: a minimal Qt program
that creates an ordinary window and compares windowHandle()->screen() against
QGuiApplication::screenAt(geometry().center()) gives identical, agreeing
results on Qt 6.11.1 and 6.11.2. But VirtualBox's own logs differ between those
two Qt versions with everything else held constant:

                        Qt 6.11.2     Qt 6.11.1
machine window          x=1920        x=1920
mini-toolbar target     x=0           x=1920

so a Qt patch-release timing change is enough to start losing the race.

Suggested fix

Resolve the screen from the geometry already assigned to the parent, rather than
from the native window association:

int iHostScreen =
    UIDesktopWidgetWatchdog::screenNumber(m_pParent->geometry().center());

screenNumber(const QPoint &) already exists and uses
QGuiApplication::screenAt(). The toolbar adjustment is queued from the
parent's show event, i.e. after placeOnScreen() has moved the parent, so the
geometry is authoritative at that point.

With this change the toolbar is co-located with the machine window
(Move mini-toolbar for window #0 to 1920x0, window at 1920,0), only the
intended monitor is fullscreen, and the unrelated panel is unaffected.

I have a patch and will open a PR against this issue.

Secondary note (separate, latent)

NativeWindowSubsystem::X11SetFullScreenMonitor() writes its uScreenId
argument straight into _NET_WM_FULLSCREEN_MONITORS. Per EWMH that property is
specified in the window manager's Xinerama monitor index space, while callers
pass a Qt screen index. These orders are not the same on this host:

Qt / RandR order   [0] DP-2 @1920  [1] DP-4 @3840  [2] DP-0 @0
WM order           [0] DP-0 @0     [1] DP-2 @1920  [2] DP-4 @3840

I could not demonstrate a user-visible failure from this on its own — with the
fix above applied the toolbar is placed correctly despite the hint value — so I
am noting it rather than proposing a change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions