-
Notifications
You must be signed in to change notification settings - Fork 57
sync: from linuxdeepin/dde-session-shell #489
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,9 +8,16 @@ | |
|
|
||
| #include <QApplication> | ||
| #include <QDebug> | ||
| #include <QJsonDocument> | ||
| #include <QJsonObject> | ||
|
|
||
| #ifndef ENABLE_DSS_SNIPE | ||
| #include <QX11Info> | ||
| #else | ||
| #include <xcb/xproto.h> | ||
| #endif | ||
| #include <xcb/xcb.h> | ||
|
|
||
| #include "dbusconstant.h" | ||
|
|
||
| MultiScreenManager::MultiScreenManager(QObject *parent) | ||
|
|
@@ -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不为空则直接退出 | ||
|
|
@@ -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); | ||
|
Comment on lines
271
to
+272
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Check that the frame pointer is non-null before dereferencing it. In this loop you only check |
||
| 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; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,10 +18,17 @@ | |
| #include <QKeyEvent> | ||
| #include <QPainter> | ||
| #include <QScreen> | ||
| #include <QTimer> | ||
| #include <QWindow> | ||
|
|
||
| #ifndef ENABLE_DSS_SNIPE | ||
| #include <QX11Info> | ||
| #else | ||
| #include <xcb/xproto.h> | ||
| #endif | ||
| #include <xcb/xcb.h> | ||
|
|
||
| #include "dbusconstant.h" | ||
|
|
||
| Q_LOGGING_CATEGORY(DDE_SS, "dss.active") | ||
|
|
||
|
|
@@ -74,9 +81,53 @@ | |
| connect(m_resetGeometryTimer, &QTimer::timeout, this, [this] { | ||
| const auto ¤tGeometry = 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()) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (complexity): Consider extracting the X11/XCB connection and geometry reconciliation logic into helper functions and centralizing the repeated logging to keep the timer callback and geometry-related methods simpler and easier to read. You can keep the new behavior but reduce complexity by extracting the XCB/X11 handling and geometry reconciliation into small helpers, and by centralizing the verbose logging. 1. Extract X11 connection acquisitionThe timer lambda and possibly other files duplicate the // In a suitable .cpp/.h (e.g. fullscreenbackground.cpp or a small X11 helper)
static xcb_connection_t *x11Connection()
{
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
return connection;
}Then use it in the timer: if (!m_model->isUseWayland() && windowHandle()) {
if (auto *connection = x11Connection()) {
auto cookie = xcb_get_geometry(connection, static_cast<xcb_window_t>(winId()));
auto *reply = xcb_get_geometry_reply(connection, cookie, nullptr);
// ...
}
}This removes preprocessor noise from the lambda and avoids duplication in other places. 2. Extract XCB geometry reconciliationThe DPR handling, XCB // In FullScreenBackground
void FullScreenBackground::ensureXcbGeometryMatches()
{
if (m_model->isUseWayland() || !windowHandle())
return;
xcb_connection_t *connection = x11Connection();
if (!connection)
return;
auto cookie = xcb_get_geometry(connection, static_cast<xcb_window_t>(winId()));
auto *reply = xcb_get_geometry_reply(connection, cookie, nullptr);
if (!reply)
return;
const QRect xcbGeometry(reply->x, reply->y, reply->width, reply->height);
free(reply);
const qreal dpr = devicePixelRatioF();
const QRect expectedPhysical(
m_geometryRect.x(),
m_geometryRect.y(),
qRound(m_geometryRect.width() * dpr),
qRound(m_geometryRect.height() * dpr));
if (xcbGeometry == expectedPhysical) {
qCInfo(DDE_SHELL) << "XCB position match, no need to set geometry";
return;
}
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");
if (!m_screen.isNull() && windowHandle()->screen() != m_screen)
windowHandle()->setScreen(m_screen);
setGeometry(0, 0, 0, 0);
setGeometry(m_geometryRect);
}Timer becomes much clearer: connect(m_resetGeometryTimer, &QTimer::timeout, this, [this] {
const auto ¤tGeometry = geometry();
if (currentGeometry != m_geometryRect) {
qCWarning(DDE_SHELL) << "Geometry mismatch detected! Qt cached geometry:" << currentGeometry
<< ", target geometry:" << m_geometryRect << ", this:" << this;
setGeometry(m_geometryRect);
}
ensureXcbGeometryMatches();
});3. Centralize repetitive logging
void FullScreenBackground::logGeometryInfo(const char *prefix, const QRect &target) const
{
qCInfo(DDE_SHELL) << prefix
<< "this:" << this
<< "target:" << target
<< "current geometry:" << geometry()
<< "screen:" << (m_screen ? m_screen->name() : "null")
<< "windowHandle screen:" << (windowHandle() ? windowHandle()->screen()->name() : "null")
<< "dpr:" << devicePixelRatioF();
}Use it where logging is currently verbose: void FullScreenBackground::setddeGeometry(const QRect &rect)
{
logGeometryInfo("setddeGeometry", rect);
setGeometry(rect);
m_geometryRect = rect;
m_resetGeometryTimer->start(200);
QTimer::singleShot(400 * 5, m_resetGeometryTimer, &QTimer::stop);
}And in |
||
| 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){ | ||
|
|
@@ -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() | ||
|
Comment on lines
+508
to
+509
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Guard against null QScreen when logging windowHandle()->screen()->name().
if (auto *win = windowHandle()) {
QScreen *curScreen = win->screen();
qCInfo(DDE_SHELL) << "bindWindowToScreen, windowHandle screen:"
<< (curScreen ? curScreen->name() : "null")
<< ", target screen:" << m_screen->name() << ", this:" << this;
if (curScreen != m_screen)
win->setScreen(m_screen);
} |
||
| << ", 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"; | ||
| } | ||
|
|
@@ -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") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Also guard windowHandle()->screen() in logging to prevent crashes when screen is null. The current ternary only guards |
||
| << ", dpr:" << devicePixelRatioF(); | ||
| setGeometry(rect); | ||
| m_geometryRect = rect; | ||
| m_resetGeometryTimer->start(200); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): Consider extracting the XCB connection retrieval and geometry-checking logic into reusable helper functions so
checkLockFrameLocationstays focused on high-level behavior.You can keep all the new checks/logging but reduce complexity by extracting the XCB-specific and geometry logic into small helpers, and centralizing XCB connection acquisition (also avoids duplication with
fullscreenbackground.cpp).1. Centralize XCB connection retrieval
Create a small helper (in a shared
.cppor anonymous namespace) and use it both here and infullscreenbackground.cpp:Then
checkLockFrameLocationbecomes simpler:2. Extract geometry calculation + logging
Move the DPR/geometry math and logging into a focused helper:
This keeps all current behavior and logging, but makes
checkLockFrameLocationread as high-level intent while encapsulating platform-specific and geometry details.