Skip to content
Merged
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
59 changes: 57 additions & 2 deletions src/global_util/multiscreenmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@

#include <QApplication>
#include <QDebug>
#include <QJsonDocument>

Check warning on line 11 in src/global_util/multiscreenmanager.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QJsonDocument> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QJsonObject>

Check warning on line 12 in src/global_util/multiscreenmanager.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QJsonObject> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#ifndef ENABLE_DSS_SNIPE
#include <QX11Info>

Check warning on line 15 in src/global_util/multiscreenmanager.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QX11Info> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#else
#include <xcb/xproto.h>

Check warning on line 17 in src/global_util/multiscreenmanager.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <xcb/xproto.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#endif
#include <xcb/xcb.h>

Check warning on line 19 in src/global_util/multiscreenmanager.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <xcb/xcb.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include "dbusconstant.h"

MultiScreenManager::MultiScreenManager(QObject *parent)
Expand Down Expand Up @@ -114,6 +121,11 @@
return;
}

qCInfo(DDE_SHELL) << "onScreenAdded processing, screen:" << screen
<< ", name:" << screen->name()
<< ", geometry:" << screen->geometry()
<< ", existing frames count:" << m_frames.size();

QWidget* w = nullptr;
if (m_isCopyMode) {
// 如果m_frames不为空则直接退出
Expand Down Expand Up @@ -244,10 +256,53 @@

void MultiScreenManager::checkLockFrameLocation()
{
xcb_connection_t *connection = nullptr;
if (!QGuiApplication::platformName().startsWith("wayland", Qt::CaseInsensitive)) {
#ifndef ENABLE_DSS_SNIPE
connection = QX11Info::connection();
#else
auto *x11App = qGuiApp->nativeInterface<QNativeInterface::QX11Application>();
if (x11App)
connection = x11App->connection();
#endif
}

for (QScreen *screen : m_frames.keys()) {
if (screen) {
qCInfo(DDE_SHELL) << "Check lock frame location, screen:" << screen << ", location:" << screen->geometry()
<< ", lockframe:" << m_frames.value(screen) << ", location:" << m_frames.value(screen)->geometry();
QWidget *frame = m_frames.value(screen);
qCInfo(DDE_SHELL) << "Check lock frame location, screen:" << screen
<< ", screen name:" << screen->name()
<< ", screen geometry:" << screen->geometry()
<< ", lockframe:" << frame
<< ", Qt frame geometry:" << frame->geometry();

// 通过 XCB 检查窗口在 X Server 中的实际位置
// 注意:X11 下窗口位置不乘 DPR(与 RandR 物理坐标一致),窗口大小乘 DPR
if (connection && frame) {
auto cookie = xcb_get_geometry(connection, static_cast<xcb_window_t>(frame->winId()));
auto *reply = xcb_get_geometry_reply(connection, cookie, nullptr);
if (reply) {
QRect xcbGeometry(reply->x, reply->y, reply->width, reply->height);
const qreal dpr = frame->devicePixelRatioF();
QRect expectedPhysical(screen->geometry().x(), screen->geometry().y(),
qRound(screen->geometry().width() * dpr),
qRound(screen->geometry().height() * dpr));
bool positionMatch = (xcbGeometry == expectedPhysical);
qCInfo(DDE_SHELL) << " XCB actual geometry(physical):" << xcbGeometry
<< ", expected(physical):" << expectedPhysical
<< ", dpr:" << dpr
<< ", match:" << positionMatch;
if (!positionMatch) {
qCWarning(DDE_SHELL) << " *** POSITION MISMATCH DETECTED! ***"
<< "XCB geometry:" << xcbGeometry
<< "expected:" << expectedPhysical
<< "for screen" << screen->name();
}
free(reply);
} else {
qCWarning(DDE_SHELL) << " Failed to get XCB geometry for frame:" << frame;
}
}
}
}
}
Expand Down
69 changes: 66 additions & 3 deletions src/widgets/fullscreenbackground.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,17 @@
#include <QKeyEvent>
#include <QPainter>
#include <QScreen>
#include <QTimer>

Check warning on line 21 in src/widgets/fullscreenbackground.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QTimer> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QWindow>

Check warning on line 22 in src/widgets/fullscreenbackground.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QWindow> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#ifndef ENABLE_DSS_SNIPE
#include <QX11Info>

Check warning on line 25 in src/widgets/fullscreenbackground.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QX11Info> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#else
#include <xcb/xproto.h>
#endif
#include <xcb/xcb.h>

Check warning on line 29 in src/widgets/fullscreenbackground.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <xcb/xcb.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include "dbusconstant.h"

Check warning on line 31 in src/widgets/fullscreenbackground.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "dbusconstant.h" not found.

Q_LOGGING_CATEGORY(DDE_SS, "dss.active")

Expand Down Expand Up @@ -74,9 +81,53 @@
connect(m_resetGeometryTimer, &QTimer::timeout, this, [this] {
const auto &currentGeometry = geometry();
if (currentGeometry != m_geometryRect) {
qCDebug(DDE_SHELL) << "Current geometry:" << currentGeometry <<"setGeometry:" << m_geometryRect;
qCWarning(DDE_SHELL) << "Geometry mismatch detected! Qt cached geometry:" << currentGeometry
<< ", target geometry:" << m_geometryRect << ", this:" << this;
setGeometry(m_geometryRect);
}

// 通过 XCB 检查窗口在 X Server 中的实际位置
// 注意:X11 坐标系中,窗口位置不乘 DPR(与 X RandR 一致),窗口大小乘 DPR
if (!m_model->isUseWayland() && windowHandle()) {
xcb_connection_t *connection = nullptr;
#ifndef ENABLE_DSS_SNIPE
connection = QX11Info::connection();
#else
auto *x11App = qGuiApp->nativeInterface<QNativeInterface::QX11Application>();
if (x11App)
connection = x11App->connection();
#endif
if (connection) {
auto cookie = xcb_get_geometry(connection, static_cast<xcb_window_t>(winId()));
auto *reply = xcb_get_geometry_reply(connection, cookie, nullptr);
if (reply) {
QRect xcbGeometry(reply->x, reply->y, reply->width, reply->height);
const qreal dpr = devicePixelRatioF();
QRect expectedPhysical(m_geometryRect.x(), m_geometryRect.y(),
qRound(m_geometryRect.width() * dpr),
qRound(m_geometryRect.height() * dpr));
if (xcbGeometry != expectedPhysical) {
qCWarning(DDE_SHELL) << "XCB position mismatch! XCB geometry(physical):" << xcbGeometry
<< ", expected(physical):" << expectedPhysical
<< ", target(logical):" << m_geometryRect
<< ", dpr:" << dpr
<< ", this:" << this
<< ", screen:" << (m_screen ? m_screen->name() : "null");
// Qt 的 geometry() 缓存可能已经是正确值,但实际 X 窗口未移动。
// 强制重新绑定 screen 并调用 setGeometry,让 Qt 重新发送 XCB configure request。
if (!m_screen.isNull() && windowHandle()->screen() != m_screen) {
windowHandle()->setScreen(m_screen);
}
// 先 resize 到 0,0 再设目标值,破坏 Qt 的 "geometry 未变" 优化,强制重新下发
setGeometry(0, 0, 0, 0);
setGeometry(m_geometryRect);
} else {
qCInfo(DDE_SHELL) << "XCB position match, no need to set geometry";
}
free(reply);
}
}
}
});

connect(m_model, &SessionBaseModel::shutdownkModeChanged, this, [this] (bool value){
Expand Down Expand Up @@ -453,14 +504,20 @@
}

if (!m_screen.isNull()) {
if(m_model->isUseWayland())
// X11 下也需要将 QWindow 关联到正确的 QScreen,否则 Qt 可能将窗口归属到错误的 screen
if (windowHandle() && windowHandle()->screen() != m_screen) {
qCInfo(DDE_SHELL) << "bindWindowToScreen, windowHandle screen:" << windowHandle()->screen()->name()
<< ", target screen:" << m_screen->name() << ", this:" << this;
windowHandle()->setScreen(m_screen);
}
setddeGeometry(m_screen->geometry());

qCInfo(DDE_SHELL) << "Update geometry, screen:" << m_screen
<< ", screen name:" << m_screen->name()
<< ", screen geometry:" << m_screen->geometry()
<< ", lockFrame:" << this
<< ", frame geometry:" << this->geometry();
<< ", frame geometry:" << this->geometry()
<< ", windowHandle screen:" << (windowHandle() ? windowHandle()->screen()->name() : "null");
} else {
qCWarning(DDE_SHELL) << "Screen is nullptr";
}
Expand Down Expand Up @@ -735,6 +792,12 @@
//增加一个定时器,每隔50ms再设置一次Geometry,避免出现xorg初始化未完成的情况,导致界面显示不全
void FullScreenBackground::setddeGeometry(const QRect &rect)
{
qCInfo(DDE_SHELL) << "setddeGeometry called, this:" << this
<< ", target rect:" << rect
<< ", current geometry:" << geometry()
<< ", screen:" << (m_screen ? m_screen->name() : "null")
<< ", windowHandle screen:" << (windowHandle() ? windowHandle()->screen()->name() : "null")
<< ", dpr:" << devicePixelRatioF();
setGeometry(rect);
m_geometryRect = rect;
m_resetGeometryTimer->start(200);
Expand Down
Loading