Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions devel/0150.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# 任务 0150:修复演讲模式下光标移动导致的界面闪烁

## 问题描述
在 Windows 平台上,进入演讲模式后移动光标,重新渲染时界面会出现黑色到白色的闪烁跳动。

## 根因分析
演讲模式下 viewport 背景被设为黑色(`QPalette::Shadow`),但 beamer 幻灯片背景通常是白色。在 Windows 上,Qt 的 `QAbstractScrollArea` viewport 在子 widget 重绘前会自动填充背景色,导致黑色背景短暂显示后再被白色 backing pixmap 覆盖,产生闪烁。

## 修复方案
在演讲模式下关闭 viewport 的 `autoFillBackground`,并设置 `WA_OpaquePaintEvent`,防止 Qt 在 `paintEvent` 之前自动填充黑色背景。

## 验证方式
1. 单元测试验证进入/退出演讲模式时 viewport 属性正确设置
2. 在 Windows 上手动验证光标移动时无闪烁
6 changes: 4 additions & 2 deletions src/Plugins/Qt/qt_simple_widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,12 +481,12 @@ qt_simple_widget_rep::repaint_invalid_regions () {
backing_pos= origin;

QPixmap newBackingPixmap (backingPixmap->size ());
newBackingPixmap.fill (to_qcolor (tm_background));
QPainter p (&newBackingPixmap);
// newBackingPixmap.fill (Qt::black);
p.drawPixmap (-dx, -dy, *backingPixmap);
p.end ();
*backingPixmap= newBackingPixmap;
// cout << "SCROLL CONTENTS BY " << dx << " " << dy << LF;
cout << "[0150] Scroll backing pixmap, fill with tm_background" << "\n";

rectangles invalid;
while (!is_nil (invalid_regions)) {
Expand Down Expand Up @@ -537,6 +537,7 @@ qt_simple_widget_rep::repaint_invalid_regions () {
if (_newSize != _oldSize) {
// cout << "RESIZING BITMAP"<< LF;
QPixmap newBackingPixmap (_newSize);
newBackingPixmap.fill (to_qcolor (tm_background));
QPainter p (&newBackingPixmap);
p.drawPixmap (0, 0, *backingPixmap);
// p.fillRect (0, 0, _newSize.width(), _newSize.height(), Qt::red);
Expand All @@ -557,6 +558,7 @@ qt_simple_widget_rep::repaint_invalid_regions () {
}
p.end ();
*backingPixmap= newBackingPixmap;
cout << "[0150] Resize backing pixmap, fill with tm_background" << "\n";
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/Plugins/Qt/qt_tm_widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1846,6 +1846,10 @@ qt_tm_widget_rep::set_full_screen (bool flag) {
QWidget* viewport= scrollView->viewport ();
if (viewport) {
viewport->setBackgroundRole (QPalette::Shadow);
viewport->setAutoFillBackground (false);
viewport->setAttribute (Qt::WA_OpaquePaintEvent);
cout << "[0150] Enter presentation mode: disable viewport auto-fill"
<< "\n";
}
}
}
Expand Down Expand Up @@ -1883,6 +1887,10 @@ qt_tm_widget_rep::set_full_screen (bool flag) {
QWidget* viewport= scrollView->viewport ();
if (viewport) {
viewport->setBackgroundRole (QPalette::Mid);
viewport->setAutoFillBackground (true);
viewport->setAttribute (Qt::WA_OpaquePaintEvent, false);
cout << "[0150] Exit presentation mode: restore viewport auto-fill"
<< "\n";
}
}
#ifdef UNIFIED_TOOLBAR
Expand Down
46 changes: 46 additions & 0 deletions tests/Plugins/Qt/qt_presentation_mode_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

/******************************************************************************
* MODULE : qt_presentation_mode_test.cpp
* DESCRIPTION: test viewport settings in presentation mode to prevent flicker
* COPYRIGHT : (C) 2025 Darcy Shen
******************************************************************************/

#include "QTMScrollView.hpp"
#include <QApplication>
#include <QPalette>
#include <QtTest/QtTest>

class TestPresentationMode : public QObject {
Q_OBJECT

private slots:
void test_viewport_background_in_presentation_mode ();
};

void
TestPresentationMode::test_viewport_background_in_presentation_mode () {
QTMScrollView scrollView;
QWidget* viewport= scrollView.viewport ();
QVERIFY (viewport != nullptr);

// Simulate entering presentation mode
viewport->setBackgroundRole (QPalette::Shadow);
viewport->setAutoFillBackground (false);
viewport->setAttribute (Qt::WA_OpaquePaintEvent);

QCOMPARE (viewport->backgroundRole (), QPalette::Shadow);
QVERIFY (!viewport->autoFillBackground ());
QVERIFY (viewport->testAttribute (Qt::WA_OpaquePaintEvent));

// Simulate exiting presentation mode
viewport->setBackgroundRole (QPalette::Mid);
viewport->setAutoFillBackground (true);
viewport->setAttribute (Qt::WA_OpaquePaintEvent, false);

QCOMPARE (viewport->backgroundRole (), QPalette::Mid);
QVERIFY (viewport->autoFillBackground ());
QVERIFY (!viewport->testAttribute (Qt::WA_OpaquePaintEvent));
}

QTEST_MAIN (TestPresentationMode)
#include "qt_presentation_mode_test.moc"
Loading