@@ -165,38 +165,105 @@ void LayerShellEmulation::onExclusionZoneChanged()
165165 xcb_ewmh_wm_strut_partial_t strut_partial;
166166 memset (&strut_partial, 0 , sizeof (xcb_ewmh_wm_strut_partial_t ));
167167 auto anchors = m_dlayerShellWindow->anchors ();
168- QRect rect = m_window->screen ()->geometry ();
169- if ((anchors == DLayerShellWindow::AnchorLeft) || (anchors ^ DLayerShellWindow::AnchorLeft) == (DLayerShellWindow::AnchorTop | DLayerShellWindow::AnchorBottom)) {
170- strut_partial.left = rect.x () + (m_dlayerShellWindow->exclusionZone ()) * scaleFactor;
171- strut_partial.left_start_y = rect.y ();
172- strut_partial.left_end_y = rect.y () + m_window->height ();
168+ QScreen *currentScreen = m_window->screen ();
169+ if ((anchors == DLayerShellWindow::AnchorLeft) || (anchors ^ DLayerShellWindow::AnchorLeft) == (DLayerShellWindow::AnchorTop | DLayerShellWindow::AnchorBottom)) {
170+ // 计算独占区域:屏幕X坐标 + 任务栏物理宽度
171+ // 注意:QScreen::geometry().x() 已经是设备无关像素,不需要缩放
172+ // 只有exclusionZone需要转换为物理像素
173+ strut_partial.left = static_cast <uint32_t >(currentScreen->geometry ().x () + m_dlayerShellWindow->exclusionZone () * scaleFactor);
174+ strut_partial.left_start_y = static_cast <uint32_t >(m_window->geometry ().y ());
175+ strut_partial.left_end_y = static_cast <uint32_t >(m_window->geometry ().y () + m_window->geometry ().height () * scaleFactor);
176+
177+ qCDebug (layershell) << " AnchorLeft: screen.x=" << currentScreen->geometry ().x () << " exclusionZone=" << m_dlayerShellWindow->exclusionZone ()
178+ << " result=" << strut_partial.left ;
173179 } else if ((anchors == DLayerShellWindow::AnchorRight) || (anchors ^ DLayerShellWindow::AnchorRight) == (DLayerShellWindow::AnchorTop | DLayerShellWindow::AnchorBottom)) {
174- int boundary = 0 ;
180+ // 找到桌面的最右边界(物理像素)
181+ // 注意:QScreen::geometry()返回混合坐标系统 - X/Y是物理像素,宽度/高度是逻辑像素
182+ int desktopRightBoundaryPhysical = 0 ;
175183 for (auto screen : qApp->screens ()) {
176- int right = screen->geometry ().x ()/scaleFactor + screen->geometry ().width ();
177- if (boundary < right)
178- boundary = right;
184+ // 屏幕物理右边界 = X坐标(物理) + 宽度(逻辑) * 缩放系数
185+ int screenRightPhysical = screen->geometry ().x () + static_cast <int >(screen->geometry ().width () * scaleFactor);
186+ if (desktopRightBoundaryPhysical < screenRightPhysical)
187+ desktopRightBoundaryPhysical = screenRightPhysical;
179188 }
180- strut_partial.right = (boundary - rect.right () + m_dlayerShellWindow->exclusionZone ()) * scaleFactor;
181- strut_partial.right_start_y = rect.y ();
182- strut_partial.right_end_y = rect.y () + m_window->height ();
183- } else if ((anchors == DLayerShellWindow::AnchorTop) || (anchors ^ DLayerShellWindow::AnchorTop) == (DLayerShellWindow::AnchorLeft | DLayerShellWindow::AnchorRight)) {
184- strut_partial.top = rect.y () + (m_dlayerShellWindow->exclusionZone ()) * scaleFactor;
185- strut_partial.top_start_x = rect.x ();
186- strut_partial.top_end_x = rect.x () + m_window->width ();
189+
190+ // 计算当前屏幕物理右边界
191+ int currentScreenRightPhysical = currentScreen->geometry ().x () + static_cast <int >(currentScreen->geometry ().width () * scaleFactor);
192+
193+ // 计算到桌面右边界的物理距离
194+ int distanceToDesktopRightPhysical = desktopRightBoundaryPhysical - currentScreenRightPhysical;
195+
196+ // 独占区域 = 到桌面右边界的物理距离 + 任务栏物理宽度
197+ strut_partial.right = static_cast <uint32_t >(distanceToDesktopRightPhysical + m_dlayerShellWindow->exclusionZone () * scaleFactor);
198+
199+ qCDebug (layershell) << " AnchorRight: desktopRightBoundary=" << desktopRightBoundaryPhysical << " currentScreenRight=" << currentScreenRightPhysical
200+ << " distance=" << distanceToDesktopRightPhysical << " result=" << strut_partial.right ;
201+
202+ strut_partial.right_start_y = static_cast <uint32_t >(m_window->geometry ().y ());
203+ strut_partial.right_end_y = static_cast <uint32_t >(m_window->geometry ().y () + m_window->geometry ().height () * scaleFactor);
204+ } else if ((anchors == DLayerShellWindow::AnchorTop) || (anchors ^ DLayerShellWindow::AnchorTop) == (DLayerShellWindow::AnchorLeft | DLayerShellWindow::AnchorRight)) {
205+ // 计算独占区域:屏幕Y坐标 + 任务栏物理高度
206+ // 注意:QScreen::geometry().y() 已经是设备无关像素,不需要缩放
207+ // 只有exclusionZone需要转换为物理像素
208+ strut_partial.top = static_cast <uint32_t >(currentScreen->geometry ().y () + m_dlayerShellWindow->exclusionZone () * scaleFactor);
209+ strut_partial.top_start_x = static_cast <uint32_t >(m_window->geometry ().x ());
210+ strut_partial.top_end_x = static_cast <uint32_t >(m_window->geometry ().x () + m_window->geometry ().width () * scaleFactor);
211+
212+ qCDebug (layershell) << " AnchorTop: screen.y=" << currentScreen->geometry ().y () << " exclusionZone=" << m_dlayerShellWindow->exclusionZone ()
213+ << " result=" << strut_partial.top ;
187214 } else if ((anchors == DLayerShellWindow::AnchorBottom) || (anchors ^ DLayerShellWindow::AnchorBottom) == (DLayerShellWindow::AnchorLeft | DLayerShellWindow::AnchorRight)) {
188- // Note: In the X environment,
189- // the upper screen's exclusive zone spans across the entire lower screen when there are multiple screens,
190- // but there is no issue.
191- int boundary = 0 ;
215+ // 计算当前屏幕的物理底边界(修正混合坐标系统)
216+ int currentScreenBottomPhysical = currentScreen->geometry ().y () + static_cast <int >(currentScreen->geometry ().height () * scaleFactor);
217+
218+ // 查找紧邻下方的屏幕,支持垂直布局
219+ // 算法:找到在当前屏幕下方且与当前屏幕水平重叠的屏幕
220+ int belowScreensHeight = 0 ;
221+ QRect currentRect = currentScreen->geometry ();
192222 for (auto screen : qApp->screens ()) {
193- int botton = screen->geometry ().y ()/scaleFactor + screen->geometry ().height ();
194- if (boundary < botton)
195- boundary = botton;
223+ if (screen == currentScreen)
224+ continue ;
225+ QRect screenRect = screen->geometry ();
226+
227+ // 检查屏幕是否在当前屏幕下方(使用物理坐标)
228+ if (screenRect.y () >= currentScreenBottomPhysical) {
229+ // 检查是否有水平重叠(支持垂直布局)
230+ // 使用物理坐标计算重叠
231+ int screenLeftPhysical = screenRect.x ();
232+ int screenRightPhysical = screenRect.x () + static_cast <int >(screenRect.width () * scaleFactor);
233+ int currentLeftPhysical = currentRect.x ();
234+ int currentRightPhysical = currentRect.x () + static_cast <int >(currentRect.width () * scaleFactor);
235+ bool hasHorizontalOverlap = (screenLeftPhysical < currentRightPhysical && screenRightPhysical > currentLeftPhysical);
236+ if (hasHorizontalOverlap) {
237+ // 累加下方屏幕的高度(逻辑像素)
238+ belowScreensHeight += screenRect.height ();
239+ qCDebug (layershell) << " Found below screen:" << screenRect.height () << " px" ;
240+ }
241+ }
242+ }
243+
244+ // 如果没有找到下方屏幕,使用修正的回退算法(支持水平布局)
245+ if (belowScreensHeight == 0 ) {
246+ // 找到桌面最底边的物理边界
247+ int desktopBottomBoundaryPhysical = 0 ;
248+ for (auto screen : qApp->screens ()) {
249+ int screenBottomPhysical = screen->geometry ().y () + static_cast <int >(screen->geometry ().height () * scaleFactor);
250+ if (desktopBottomBoundaryPhysical < screenBottomPhysical)
251+ desktopBottomBoundaryPhysical = screenBottomPhysical;
252+ }
253+
254+ // 计算物理距离,然后转换为逻辑像素用于后续计算
255+ int distancePhysical = desktopBottomBoundaryPhysical - currentScreenBottomPhysical;
256+ belowScreensHeight = static_cast <int >(distancePhysical / scaleFactor);
196257 }
197- strut_partial.bottom = (boundary - rect.bottom () + m_dlayerShellWindow->exclusionZone ()) * scaleFactor;
198- strut_partial.bottom_start_x = rect.x ();
199- strut_partial.bottom_end_x = rect.x () + m_window->width ();
258+
259+ // 独占区域 = 下方区域物理高度 + 任务栏物理高度
260+ strut_partial.bottom = static_cast <uint32_t >(belowScreensHeight * scaleFactor + m_dlayerShellWindow->exclusionZone () * scaleFactor);
261+
262+ qCDebug (layershell) << " AnchorBottom: belowScreensHeight=" << belowScreensHeight << " exclusionZone=" << m_dlayerShellWindow->exclusionZone ()
263+ << " result=" << strut_partial.bottom ;
264+
265+ strut_partial.bottom_start_x = static_cast <uint32_t >(m_window->geometry ().x ());
266+ strut_partial.bottom_end_x = static_cast <uint32_t >(m_window->geometry ().x () + m_window->geometry ().width () * scaleFactor);
200267 }
201268
202269 qCDebug (layershell) << " update exclusion zone, winId:" << m_window->winId ()
0 commit comments