Skip to content

Commit 90db72d

Browse files
deepin-ci-robotyixinshark
authored andcommitted
sync: from linuxdeepin/dde-session-shell
Synchronize source files from linuxdeepin/dde-session-shell. Source-pull-request: linuxdeepin/dde-session-shell#58
1 parent 6ece17b commit 90db72d

2 files changed

Lines changed: 123 additions & 5 deletions

File tree

src/global_util/multiscreenmanager.cpp

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@
1111
#include <QJsonDocument>
1212
#include <QJsonObject>
1313

14+
#ifndef ENABLE_DSS_SNIPE
15+
#include <QX11Info>
16+
#else
17+
#include <xcb/xproto.h>
18+
#endif
19+
#include <xcb/xcb.h>
20+
1421
#include "dbusconstant.h"
1522

1623
MultiScreenManager::MultiScreenManager(QObject *parent)
@@ -114,6 +121,11 @@ void MultiScreenManager::onScreenAdded(QPointer<QScreen> screen)
114121
return;
115122
}
116123

124+
qCInfo(DDE_SHELL) << "onScreenAdded processing, screen:" << screen
125+
<< ", name:" << screen->name()
126+
<< ", geometry:" << screen->geometry()
127+
<< ", existing frames count:" << m_frames.size();
128+
117129
QWidget* w = nullptr;
118130
if (m_isCopyMode) {
119131
// 如果m_frames不为空则直接退出
@@ -244,10 +256,53 @@ void MultiScreenManager::onDisplayModeChanged(const QString &)
244256

245257
void MultiScreenManager::checkLockFrameLocation()
246258
{
259+
xcb_connection_t *connection = nullptr;
260+
if (!QGuiApplication::platformName().startsWith("wayland", Qt::CaseInsensitive)) {
261+
#ifndef ENABLE_DSS_SNIPE
262+
connection = QX11Info::connection();
263+
#else
264+
auto *x11App = qGuiApp->nativeInterface<QNativeInterface::QX11Application>();
265+
if (x11App)
266+
connection = x11App->connection();
267+
#endif
268+
}
269+
247270
for (QScreen *screen : m_frames.keys()) {
248271
if (screen) {
249-
qCInfo(DDE_SHELL) << "Check lock frame location, screen:" << screen << ", location:" << screen->geometry()
250-
<< ", lockframe:" << m_frames.value(screen) << ", location:" << m_frames.value(screen)->geometry();
272+
QWidget *frame = m_frames.value(screen);
273+
qCInfo(DDE_SHELL) << "Check lock frame location, screen:" << screen
274+
<< ", screen name:" << screen->name()
275+
<< ", screen geometry:" << screen->geometry()
276+
<< ", lockframe:" << frame
277+
<< ", Qt frame geometry:" << frame->geometry();
278+
279+
// 通过 XCB 检查窗口在 X Server 中的实际位置
280+
// 注意:X11 下窗口位置不乘 DPR(与 RandR 物理坐标一致),窗口大小乘 DPR
281+
if (connection && frame) {
282+
auto cookie = xcb_get_geometry(connection, static_cast<xcb_window_t>(frame->winId()));
283+
auto *reply = xcb_get_geometry_reply(connection, cookie, nullptr);
284+
if (reply) {
285+
QRect xcbGeometry(reply->x, reply->y, reply->width, reply->height);
286+
const qreal dpr = frame->devicePixelRatioF();
287+
QRect expectedPhysical(screen->geometry().x(), screen->geometry().y(),
288+
qRound(screen->geometry().width() * dpr),
289+
qRound(screen->geometry().height() * dpr));
290+
bool positionMatch = (xcbGeometry == expectedPhysical);
291+
qCInfo(DDE_SHELL) << " XCB actual geometry(physical):" << xcbGeometry
292+
<< ", expected(physical):" << expectedPhysical
293+
<< ", dpr:" << dpr
294+
<< ", match:" << positionMatch;
295+
if (!positionMatch) {
296+
qCWarning(DDE_SHELL) << " *** POSITION MISMATCH DETECTED! ***"
297+
<< "XCB geometry:" << xcbGeometry
298+
<< "expected:" << expectedPhysical
299+
<< "for screen" << screen->name();
300+
}
301+
free(reply);
302+
} else {
303+
qCWarning(DDE_SHELL) << " Failed to get XCB geometry for frame:" << frame;
304+
}
305+
}
251306
}
252307
}
253308
}

src/widgets/fullscreenbackground.cpp

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@
2121
#include <QTimer>
2222
#include <QWindow>
2323

24+
#ifndef ENABLE_DSS_SNIPE
25+
#include <QX11Info>
26+
#else
27+
#include <xcb/xproto.h>
28+
#endif
29+
#include <xcb/xcb.h>
30+
2431
#include "dbusconstant.h"
2532

2633
Q_LOGGING_CATEGORY(DDE_SS, "dss.active")
@@ -74,9 +81,53 @@ FullScreenBackground::FullScreenBackground(SessionBaseModel *model, QWidget *par
7481
connect(m_resetGeometryTimer, &QTimer::timeout, this, [this] {
7582
const auto &currentGeometry = geometry();
7683
if (currentGeometry != m_geometryRect) {
77-
qCDebug(DDE_SHELL) << "Current geometry:" << currentGeometry <<"setGeometry:" << m_geometryRect;
84+
qCWarning(DDE_SHELL) << "Geometry mismatch detected! Qt cached geometry:" << currentGeometry
85+
<< ", target geometry:" << m_geometryRect << ", this:" << this;
7886
setGeometry(m_geometryRect);
7987
}
88+
89+
// 通过 XCB 检查窗口在 X Server 中的实际位置
90+
// 注意:X11 坐标系中,窗口位置不乘 DPR(与 X RandR 一致),窗口大小乘 DPR
91+
if (!m_model->isUseWayland() && windowHandle()) {
92+
xcb_connection_t *connection = nullptr;
93+
#ifndef ENABLE_DSS_SNIPE
94+
connection = QX11Info::connection();
95+
#else
96+
auto *x11App = qGuiApp->nativeInterface<QNativeInterface::QX11Application>();
97+
if (x11App)
98+
connection = x11App->connection();
99+
#endif
100+
if (connection) {
101+
auto cookie = xcb_get_geometry(connection, static_cast<xcb_window_t>(winId()));
102+
auto *reply = xcb_get_geometry_reply(connection, cookie, nullptr);
103+
if (reply) {
104+
QRect xcbGeometry(reply->x, reply->y, reply->width, reply->height);
105+
const qreal dpr = devicePixelRatioF();
106+
QRect expectedPhysical(m_geometryRect.x(), m_geometryRect.y(),
107+
qRound(m_geometryRect.width() * dpr),
108+
qRound(m_geometryRect.height() * dpr));
109+
if (xcbGeometry != expectedPhysical) {
110+
qCWarning(DDE_SHELL) << "XCB position mismatch! XCB geometry(physical):" << xcbGeometry
111+
<< ", expected(physical):" << expectedPhysical
112+
<< ", target(logical):" << m_geometryRect
113+
<< ", dpr:" << dpr
114+
<< ", this:" << this
115+
<< ", screen:" << (m_screen ? m_screen->name() : "null");
116+
// Qt 的 geometry() 缓存可能已经是正确值,但实际 X 窗口未移动。
117+
// 强制重新绑定 screen 并调用 setGeometry,让 Qt 重新发送 XCB configure request。
118+
if (!m_screen.isNull() && windowHandle()->screen() != m_screen) {
119+
windowHandle()->setScreen(m_screen);
120+
}
121+
// 先 resize 到 0,0 再设目标值,破坏 Qt 的 "geometry 未变" 优化,强制重新下发
122+
setGeometry(0, 0, 0, 0);
123+
setGeometry(m_geometryRect);
124+
} else {
125+
qCInfo(DDE_SHELL) << "XCB position match, no need to set geometry";
126+
}
127+
free(reply);
128+
}
129+
}
130+
}
80131
});
81132

82133
connect(m_model, &SessionBaseModel::shutdownkModeChanged, this, [this] (bool value){
@@ -453,14 +504,20 @@ void FullScreenBackground::updateGeometry()
453504
}
454505

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

460515
qCInfo(DDE_SHELL) << "Update geometry, screen:" << m_screen
516+
<< ", screen name:" << m_screen->name()
461517
<< ", screen geometry:" << m_screen->geometry()
462518
<< ", lockFrame:" << this
463-
<< ", frame geometry:" << this->geometry();
519+
<< ", frame geometry:" << this->geometry()
520+
<< ", windowHandle screen:" << (windowHandle() ? windowHandle()->screen()->name() : "null");
464521
} else {
465522
qCWarning(DDE_SHELL) << "Screen is nullptr";
466523
}
@@ -735,6 +792,12 @@ bool FullScreenBackground::getScaledBlurImage(const QString &originPath, QString
735792
//增加一个定时器,每隔50ms再设置一次Geometry,避免出现xorg初始化未完成的情况,导致界面显示不全
736793
void FullScreenBackground::setddeGeometry(const QRect &rect)
737794
{
795+
qCInfo(DDE_SHELL) << "setddeGeometry called, this:" << this
796+
<< ", target rect:" << rect
797+
<< ", current geometry:" << geometry()
798+
<< ", screen:" << (m_screen ? m_screen->name() : "null")
799+
<< ", windowHandle screen:" << (windowHandle() ? windowHandle()->screen()->name() : "null")
800+
<< ", dpr:" << devicePixelRatioF();
738801
setGeometry(rect);
739802
m_geometryRect = rect;
740803
m_resetGeometryTimer->start(200);

0 commit comments

Comments
 (0)