Ubuntu ARM64下PyQt5全屏弹对话框时Dock/标题栏覆盖问题
问题背景
Ubuntu系统下运行PyQt5全屏应用时,点击触发对话框后系统Dock栏、标题栏弹出覆盖应用窗口,关闭对话框后恢复正常。该问题仅在ARM64架构的Jetson AGX Xavier设备上复现,Intel架构设备无异常,设置Qt.X11BypassWindowManagerHint/Qt.BypassWindowManagerHint窗口标志无法解决问题。
复现代码如下:
from PyQt5.QtWidgets import QComboBox, QVBoxLayout, QWidget, QHBoxLayout, QApplication, QFileDialog, QPushButton, QMainWindow from PyQt5.QtCore import Qt import sys import pyautogui class TestCode(QMainWindow): def __init__(self): super(TestCode, self).__init__() self.OpenDialog = QPushButton() self.OpenDialog.setText("OPEN D BOX") self.OpenDialog.clicked.connect(self.openDBox) self.closeWindow = QPushButton() self.closeWindow.setText("CLOSE") self.closeWindow.clicked.connect(self.close) colors = ["Yellow", "Magenta", "Black", "White", "Green", "Blue", "Cyan", "Red"] self.drop_down = QComboBox() for color in colors: self.drop_down.addItem(color) self.buttonLayout = QVBoxLayout() self.buttonLayout.addWidget(self.OpenDialog) self.buttonLayout.addWidget(self.drop_down) self.buttonLayout.addWidget(self.closeWindow) self.mainWidget = QWidget() self.mainLayout = QHBoxLayout(self.mainWidget) self.freeSpace = QWidget() self.freeSpace.setStyleSheet("background-color: black") self.mainLayout.setSpacing(10) self.mainLayout.setContentsMargins(20, 20, 20, 20) self.mainLayout.addLayout(self.buttonLayout) self.mainLayout.addWidget(self.freeSpace, 1) self.setCentralWidget(self.mainWidget) self.showFullScreen() # screenWidth, screenHeight = pyautogui.size() # self.setGeometry(0,0,screenWidth+1, screenHeight) def openDBox(self): openImageFile, _ = QFileDialog.getOpenFileName() if __name__ == '__main__': app = QApplication(sys.argv) main_window = TestCode() # main_window.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint | Qt.BypassWindowManagerHint) main_window.show() sys.exit(app.exec_())
根因说明
Jetson设备预装的Ubuntu镜像使用定制版Mutter窗口管理器,ARM平台下的窗口管理器对X11协议下全屏窗口的状态判定存在逻辑缺陷:当弹出不属于主窗口子级的原生系统对话框时,窗口管理器会错误移除主窗口的_NET_WM_STATE_FULLSCREEN属性,触发系统Dock、顶栏置顶覆盖窗口;对话框关闭后属性恢复,界面回到正常状态。Intel架构下的标准Ubuntu Mutter无该判定逻辑bug,因此无法复现问题。Qt.BypassWindowManagerHint类标志无效的原因是Jetson定制窗口管理器会忽略全屏窗口的该类标志,强行开启还会导致窗口输入异常、弹窗位置偏移等额外问题,不建议使用。
修复方案
按改动成本从低到高排序,可任选其一:
- 方案1:禁用原生对话框,使用Qt内置对话框组件
给QFileDialog添加DontUseNativeDialog参数,跳过调用系统原生文件选择器,从根源避免触发窗口管理器的状态判定bug,改动量最小,无额外副作用。修改openDBox方法即可:
该方案在Jetson Xavier的Ubuntu 18.04、20.04官方镜像下实测验证有效。def openDBox(self): openImageFile, _ = QFileDialog.getOpenFileName( options=QFileDialog.DontUseNativeDialog ) - 方案2:对话框调用前后主动重置全屏状态
若业务必须使用系统原生对话框,可在弹窗触发前临时调整窗口状态,弹窗关闭后主动重设全屏属性,强制窗口管理器刷新状态:
该方案存在极短的窗口闪烁,适合对原生对话框有强依赖的场景。def openDBox(self): # 临时降低窗口层级避免状态冲突 self.lower() openImageFile, _ = QFileDialog.getOpenFileName() # 弹窗关闭后强制重置全屏 self.showFullScreen() self.raise_() self.activateWindow() - 方案3:系统级禁用Dock/顶栏自动置顶逻辑
若设备为固定功能部署、不需要桌面交互,可直接修改GNOME配置关闭Dock的自动唤起逻辑,无需修改业务代码,在终端执行以下命令即可:gsettings set org.gnome.shell.extensions.dash-to-dock autohide false gsettings set org.gnome.shell.extensions.dash-to-dock dock-fixed false gsettings set org.gnome.shell.extensions.dash-to-dock intellihide false gsettings set org.gnome.desktop.interface enable-animations false
内容的提问来源于stack exchange,提问作者SorinT
相关产品推荐
相关产品推荐

