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
27 changes: 24 additions & 3 deletions panels/dock/taskmanager/x11preview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Q_LOGGING_CATEGORY(x11WindowPreview, "org.deepin.dde.shell.dock.taskmanager.x11W
#define PREVIEW_CONTAINER_MARGIN 10
#define PREVIEW_HOVER_BORDER 4
#define PREVIEW_MINI_WIDTH 140
#define PREVIEW_WINDOW_DELAY 300
#define PREVIEW_HOVER_BORDER_COLOR QColor(0, 0, 0, 255 * 0.2)
#define PREVIEW_HOVER_BORDER_COLOR_DARK_MODE QColor(255, 255, 255, 255 * 0.3)
#define PREVIEW_BACKGROUND_COLOR QColor(0, 0, 0, 255 * 0.05)
Expand Down Expand Up @@ -378,12 +379,24 @@ X11WindowPreviewContainer::X11WindowPreviewContainer(X11WindowMonitor *monitor,
, m_monitor(monitor)
, m_sourceModel(nullptr)
, m_titleWidget(new QWidget())
, m_previewDelayTimer(nullptr)
, m_pendingPreviewWinId(0)
, m_direction(0)
{
m_hideTimer = new QTimer(this);
m_hideTimer->setSingleShot(true);
m_hideTimer->setInterval(500);

m_previewDelayTimer = new QTimer(this);
m_previewDelayTimer->setSingleShot(true);
m_previewDelayTimer->setInterval(PREVIEW_WINDOW_DELAY);
connect(m_previewDelayTimer, &QTimer::timeout, this, [this]() {
if (m_pendingPreviewWinId == 0 || m_monitor.isNull())
return;
if (WM_HELPER->hasComposite())
m_monitor->previewWindow(m_pendingPreviewWinId);
});
Comment on lines +393 to +398

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): The timeout callback previews m_pendingPreviewWinId without verifying that the cursor is still over that item. Moving from an item into empty space in the viewport does not necessarily emit the viewport's HoverLeave, so the pending window ID remains set and its preview appears after 300 ms even though the mouse has already left the item.

Triggers: When the preview viewport contains empty space, such as below the final row or between items.

Suggested fix: On timeout, validate the cursor position with m_view->indexAt(...) and only preview when it resolves to the same index/window ID; otherwise stop the timer and clear m_pendingPreviewWinId. Alternatively, cancel the timer on item-level hover leave.


setWindowFlags(Qt::ToolTip | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus | Qt::FramelessWindowHint);
setMouseTracking(true);
initUI();
Expand Down Expand Up @@ -415,9 +428,9 @@ X11WindowPreviewContainer::X11WindowPreviewContainer(X11WindowMonitor *monitor,

connect(m_view, &QListView::entered, this, [this](const QModelIndex &enter) {
m_closeAllButton->setVisible(false);
if (WM_HELPER->hasComposite()) {
m_monitor->previewWindow(enter.data(TaskManager::WinIdRole).toInt());
}
// 延迟预览:记录待预览窗口并重启定时器,300ms 后仍停留才显示窗口
m_pendingPreviewWinId = enter.data(TaskManager::WinIdRole).toUInt();
m_previewDelayTimer->start();

// 获取图标,优先使用窗口图标,如果为空则使用应用图标
QVariant iconData = enter.data(TaskManager::WinIconRole);
Expand Down Expand Up @@ -559,6 +572,9 @@ void X11WindowPreviewContainer::showEvent(QShowEvent *event)

void X11WindowPreviewContainer::hideEvent(QHideEvent*)
{
m_previewDelayTimer->stop();
m_pendingPreviewWinId = 0;

// 只通知监视器清空预览状态,让 TaskManager 统一管理模型清理
// 不要在这里断开模型连接,因为 clearPreviewState 信号会触发 TaskManager 的 clearFilter
// QPointer 会自动处理对象销毁的情况
Expand Down Expand Up @@ -766,6 +782,9 @@ bool X11WindowPreviewContainer::eventFilter(QObject *watched, QEvent *event)

switch (event->type()) {
case QEvent::HoverLeave: {
// 取消尚未触发的延迟预览
m_previewDelayTimer->stop();
m_pendingPreviewWinId = 0;
if (WM_HELPER->hasComposite()) {
m_monitor->cancelPreviewWindow();
}
Expand All @@ -781,6 +800,8 @@ bool X11WindowPreviewContainer::eventFilter(QObject *watched, QEvent *event)
if (mouseEvent->button() != Qt::LeftButton) return false;

// cancel preview b4 active window
m_previewDelayTimer->stop();
m_pendingPreviewWinId = 0;
if (WM_HELPER->hasComposite())
m_monitor->cancelPreviewWindow();

Expand Down
4 changes: 3 additions & 1 deletion panels/dock/taskmanager/x11preview.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand Down Expand Up @@ -106,6 +106,8 @@ private Q_SLOTS:
DIconButton* m_closeAllButton;

QTimer* m_hideTimer;
QTimer* m_previewDelayTimer;
uint32_t m_pendingPreviewWinId;

int32_t m_previewXoffset;
int32_t m_previewYoffset;
Expand Down
Loading