Skip to content

Tiled window is spontaneously moved/resized several seconds after its dialog window closes (X11) #1822

Description

@popdjnz

Tiled window is spontaneously moved/resized several seconds after its dialog window closes (X11)

Summary

With auto-tiling enabled, when an application opens a file dialog and the user
closes it, pop-shell re-tiles the workspace a few seconds later, moving and/or
resizing the application's tiled main window — even though the dialog floated
correctly (it was never tiled) and the application issues no geometry requests
of its own.

The application's window can jump to a different position and change size
roughly 5 seconds after the dialog closes, with no user input in between. It
happens once per dialog open/close cycle.

Environment

  • Pop!_OS 22.04 LTS, GNOME Shell 42.9, X11 session
  • pop-shell 1.1.0~1775597027~22.04~67ef96c
  • Auto-tiling: enabled
  • org.gnome.mutter attach-modal-dialogs: false
  • Two monitors: 3840x2160 (primary, +0+0) and 1920x1200 (+1085+2160)
  • Reproduced with a PyQt6 (Qt 6.11) application; the dialog variant does not
    matter — see "Ruled out" below

Steps to reproduce

  1. Enable auto-tiling, with enough windows open that the test window gets a
    non-trivial tile (reproduced with the window sharing a workspace with 2–3
    other windows).
  2. Save the script below as repro.py and run it
    (pip install PyQt6 is its only dependency):
"""Minimal repro: tiled main window jumps after its file dialog closes.

Run under pop-shell auto-tiling, click "Load", select any file(s), click
Open, then don't touch anything for ~15 seconds. Geometry changes of the
main window are printed; spontaneous=True means the change came from the
window system, not the application.
"""
import sys, time
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import (QApplication, QFileDialog, QMainWindow,
                             QPushButton, QVBoxLayout, QWidget)

def log(msg):
    print(f"[{time.strftime('%H:%M:%S')}] {msg}", flush=True)

class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("dialog-jump repro")
        self.resize(1280, 720)
        central = QWidget(self)
        layout = QVBoxLayout(central)
        button = QPushButton("Load", central)
        button.clicked.connect(self.open_dialog)
        layout.addWidget(button)
        self.setCentralWidget(central)

    def open_dialog(self):
        dialog = QFileDialog(self, "Pick files")
        dialog.setOption(QFileDialog.Option.DontUseNativeDialog, True)
        dialog.setFileMode(QFileDialog.FileMode.ExistingFiles)
        dialog.setWindowModality(Qt.WindowModality.NonModal)
        dialog.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose)
        dialog.finished.connect(
            lambda _: log("dialog closed — hands off, watch ~15s"))
        dialog.show()
        log("dialog opened")

    def moveEvent(self, e):
        log(f"moved {e.oldPos().x()},{e.oldPos().y()} -> "
            f"{e.pos().x()},{e.pos().y()} spontaneous={e.spontaneous()}")
        super().moveEvent(e)

    def resizeEvent(self, e):
        log(f"resized {e.oldSize().width()}x{e.oldSize().height()} -> "
            f"{e.size().width()}x{e.size().height()} "
            f"spontaneous={e.spontaneous()}")
        super().resizeEvent(e)

app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
  1. Click Load. The dialog appears floating (correct — it is never tiled).
  2. Select one or more files and click Open (Cancel also works).
  3. Do not touch the mouse or keyboard and watch for ~15 seconds.

Observed behavior

A few seconds after the dialog closes, the main window is moved and resized
by the window manager with no user input. Captured output from a real run:

[18:52:30] dialog opened
[18:53:27] selected 7 files
[18:53:27] dialog closed — watch for spontaneous moves for ~15s
[18:53:32] resized 960x503 -> 960x1043 spontaneous=True
[18:53:32] moved 1920,1657 -> 2880,37 spontaneous=True

Note the 5-second gap between the dialog closing and the re-tile, and that
both events are spontaneous=True (window-system initiated — the application
made no geometry request; Qt sets this flag only for changes originating
outside the process). In this run the window was moved from one monitor to
the other and its tile grew from a quarter-height to a half-height slot.

The jump happens once per dialog open/close cycle: the window then stays put
until the next time a dialog is opened and closed.

Expected behavior

Closing a floating dialog should not change the tiling layout. The dialog was
never part of the tile tree (it floated, correctly), so its disappearance
should be a no-op for the tiled windows' geometry.

Ruled out

  • The application moving itself — both events report spontaneous=True;
    the app makes no move/resize calls after startup.
  • Modal attachmentorg.gnome.mutter attach-modal-dialogs is false.
  • Dialog type/toolkit specifics — reproduced identically with the GTK
    portal file chooser (native dialog), an application-modal Qt dialog, and
    the non-modal Qt dialog in the script; all of them float correctly while
    open, and the re-tile follows the close in every variant.
  • Anything unusual in the app — the original application embeds libvlc,
    but the repro above is a bare QMainWindow with one button.

Impact / workaround

Any Qt application that opens file dialogs gets its main window shuffled
around the workspace after every dialog use. We worked around it by embedding
the file picker inside the main window as a child widget so the application
never creates a second top-level window.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions