Skip to content

Commit b14219e

Browse files
caixr23deepin-bot[bot]
authored andcommitted
fix: use layer-shell for screen indicator on wayland
1. Replace absolute x/y positioning with DLayerShellWindow anchors in ScreenIndicator.qml (both display and personalization) 2. Use AnchorTop/Bottom/Left/Right for border indicator windows instead of virtualX/virtualY coordinates 3. Migrate ScreenRecognize.qml to use AnchorBottom with margin for centered-bottom positioning 4. Remove isX11 guard in DisplayMain.qml so indicators work on Wayland/Treeland 5. Add DDEShell dependency in CMakeLists.txt PMS: BUG-351883 Log: Fix screen indicator and recognition dialog not working on Treeland Wayland environment Influence: 1. Connect external monitor, open Display settings, click Identify - border indicators should correctly highlight each screen edge 2. On Treeland, drag to change screen arrangement and click Identify - indicator borders should appear on the correct monitor fix: 使用 layer-shell 实现屏幕指示器在 Wayland 下的正确定位 1. 将 ScreenIndicator.qml 中的绝对 x/y 坐标定位替换为 DLayerShellWindow 锚定方式(display 和 personalization 模块) 2. 使用 AnchorTop/Bottom/Left/Right 锚定边框指示窗口, 替代 virtualX/virtualY 坐标 3. 将 ScreenRecognize.qml 迁移到使用 AnchorBottom + margin 实现底部居中定位 4. 移除 DisplayMain.qml 中的 isX11 条件判断, 使指示器在 Wayland 下也能正常显示 5. 在 CMakeLists.txt 中添加 DDEShell 依赖 PMS: BUG-351883 Log: 修复 Treeland Wayland 环境下屏幕指示器和识别弹框不生效的问题 Influence: 1. 接入外接显示器,打开控制中心显示设置,点击识别 - 边框指示器应正确高亮各屏幕边缘 2. 在 Treeland 环境下,拖动切换屏幕拼接位置后点击识别 - 指示器边框应出现在正确的显示器上
1 parent f0e7e40 commit b14219e

5 files changed

Lines changed: 124 additions & 132 deletions

File tree

src/plugin-display/qml/DisplayMain.qml

Lines changed: 29 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ DccObject {
1414
property var activeDialogs: []
1515
property bool screensFormRect: dccData.screensFormRect
1616
property bool isExtendMode: dccData.displayMode === "EXTEND"
17+
property var indicatorScreen: null // 用于显示屏幕边框指示器的属性
1718
property var scaleModelConst: [{
1819
"text": qsTr("100%"),
1920
"value": 1.0
@@ -141,14 +142,6 @@ DccObject {
141142
closeInvalidDialogs()
142143
}
143144
}
144-
Component {
145-
id: indicator
146-
ScreenIndicator {}
147-
}
148-
Component {
149-
id: recognize
150-
ScreenRecognize {}
151-
}
152145
DccTitleObject {
153146
name: "multipleDisplays"
154147
parentName: "display"
@@ -245,11 +238,9 @@ DccObject {
245238
function pressedItem(item) {
246239
hasMove = false
247240
root.screen = item.screen
248-
if (dccData.isX11) {
249-
indicator.createObject(this, {
250-
"screen": getQtScreen(item.screen)
251-
}).show()
252-
}
241+
// 使用 indicatorScreen 属性统一显示边框指示器
242+
root.indicatorScreen = null
243+
root.indicatorScreen = getQtScreen(item.screen)
253244
}
254245
function positionChangedItem(item) {
255246
monitorControl.effective = false
@@ -359,43 +350,38 @@ DccObject {
359350
}
360351
D.Button {
361352
id: identifyBut
362-
property var recognizes: []
353+
property bool identifyActive: false
363354
implicitHeight: 24
364355
implicitWidth: 72
365356
anchors.right: parent.right
366357
anchors.verticalCenter: parent.verticalCenter
367358
anchors.rightMargin: 7
368359
text: dccObj.displayName
369-
function closeWindow() {
370-
recognizeTimer.stop()
371-
for (var obj of identifyBut.recognizes) {
372-
obj.close()
373-
}
374-
identifyBut.recognizes = []
375-
}
376360
Timer {
377361
id: recognizeTimer
378362
repeat: false
379363
interval: 5000
380-
onTriggered: identifyBut.closeWindow()
364+
onTriggered: identifyBut.identifyActive = false
381365
}
382366
onClicked: {
383-
// if (!dccData.isX11) {
384-
// return
385-
// }
386-
identifyBut.closeWindow()
387-
for (var i = 0; i < dccData.virtualScreens.length; i++) {
388-
var item = dccData.virtualScreens[i]
389-
var obj = recognize.createObject(this, {
390-
"screen": getQtScreen(item),
391-
"name": item.name
392-
})
393-
obj.show()
394-
obj.escPressed.connect(identifyBut.closeWindow)
395-
recognizes.push(obj)
396-
}
367+
identifyBut.identifyActive = true
397368
recognizeTimer.restart()
398369
}
370+
// 使用 Repeater + Loader 创建多个 ScreenRecognize 窗口
371+
Repeater {
372+
id: recognizeRepeater
373+
model: identifyBut.identifyActive ? dccData.virtualScreens : []
374+
Loader {
375+
sourceComponent: ScreenRecognize {
376+
onEscPressed: identifyBut.identifyActive = false
377+
}
378+
onLoaded: {
379+
item.screen = getQtScreen(modelData)
380+
item.name = modelData.name
381+
item.show()
382+
}
383+
}
384+
}
399385
}
400386
}
401387
}
@@ -595,14 +581,16 @@ DccObject {
595581
onScreenClicked: function (screen) {
596582
if (screen && screen !== root.screen) {
597583
root.screen = screen
598-
if (dccData.isX11) {
599-
indicator.createObject(this, {
600-
"screen": getQtScreen(root.screen)
601-
}).show()
602-
}
584+
// 设置 indicatorScreen 属性显示边框指示器
585+
root.indicatorScreen = null
586+
root.indicatorScreen = getQtScreen(root.screen)
603587
}
604588
}
605589
}
590+
ScreenIndicator{
591+
screen: root.indicatorScreen
592+
onClosed: root.indicatorScreen = null
593+
}
606594
}
607595
component BrightnessComponent: RowLayout {
608596
property var screenItem
Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,51 @@
1-
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
22
// SPDX-License-Identifier: GPL-3.0-or-later
33
import QtQuick 2.15
44

5+
import org.deepin.ds 1.0 as DS
56
import org.deepin.dcc 1.0
67

7-
Window {
8+
Loader {
89
id: root
9-
flags: Qt.CoverWindow | Qt.WindowStaysOnTopHint | Qt.SplashScreen | Qt.FramelessWindowHint | Qt.X11BypassWindowManagerHint
10-
color: "#2ca7f8"
11-
x: screen.virtualX
12-
y: screen.virtualY
13-
width: screen.width
14-
height: 10
15-
onClosing: destroy(10)
10+
property var screen: null
11+
signal closed
12+
active: screen !== null
1613
Timer {
1714
interval: 1000
18-
running: root.visible
19-
onTriggered: root.close()
15+
running: root.active
16+
onTriggered: root.closed()
2017
}
21-
Window {
22-
flags: Qt.CoverWindow | Qt.WindowStaysOnTopHint | Qt.SplashScreen | Qt.FramelessWindowHint | Qt.X11BypassWindowManagerHint
23-
visible: root.visible
24-
color: root.color
18+
19+
component IndicatorBorder: Window {
2520
screen: root.screen
26-
x: screen.virtualX
27-
y: screen.virtualY + screen.height - 10
28-
width: screen.width
21+
color: "#2ca7f8"
22+
23+
flags: Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint
24+
DS.DLayerShellWindow.layer: DS.DLayerShellWindow.LayerOverlay
25+
DS.DLayerShellWindow.exclusionZone: -1
26+
Component.onCompleted: show()
2927
height: 10
30-
}
31-
Window {
32-
flags: Qt.CoverWindow | Qt.WindowStaysOnTopHint | Qt.SplashScreen | Qt.FramelessWindowHint | Qt.X11BypassWindowManagerHint
33-
visible: root.visible
34-
color: root.color
35-
screen: root.screen
36-
x: screen.virtualX
37-
y: screen.virtualY
3828
width: 10
39-
height: screen.height
4029
}
41-
Window {
42-
flags: Qt.CoverWindow | Qt.WindowStaysOnTopHint | Qt.SplashScreen | Qt.FramelessWindowHint | Qt.X11BypassWindowManagerHint
43-
visible: root.visible
44-
color: root.color
45-
screen: root.screen
46-
x: screen.virtualX + screen.width - 10
47-
y: screen.virtualY
48-
width: 10
49-
height: screen.height
30+
31+
sourceComponent: IndicatorBorder {
32+
DS.DLayerShellWindow.anchors: DS.DLayerShellWindow.AnchorTop
33+
| DS.DLayerShellWindow.AnchorLeft
34+
| DS.DLayerShellWindow.AnchorRight
35+
IndicatorBorder {
36+
DS.DLayerShellWindow.anchors: DS.DLayerShellWindow.AnchorBottom
37+
| DS.DLayerShellWindow.AnchorLeft
38+
| DS.DLayerShellWindow.AnchorRight
39+
}
40+
IndicatorBorder {
41+
DS.DLayerShellWindow.anchors: DS.DLayerShellWindow.AnchorLeft
42+
| DS.DLayerShellWindow.AnchorTop
43+
| DS.DLayerShellWindow.AnchorBottom
44+
}
45+
IndicatorBorder {
46+
DS.DLayerShellWindow.anchors: DS.DLayerShellWindow.AnchorRight
47+
| DS.DLayerShellWindow.AnchorTop
48+
| DS.DLayerShellWindow.AnchorBottom
49+
}
5050
}
5151
}

src/plugin-display/qml/ScreenRecognize.qml

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
1-
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd.
22
// SPDX-License-Identifier: GPL-3.0-or-later
33
import QtQuick 2.15
44
import QtQuick.Controls 2.0
55
import org.deepin.dtk 1.0 as D
6+
import org.deepin.ds 1.0 as DS
67
import org.deepin.dcc 1.0
78

89
Window {
910
id: root
1011
property string name: "screen"
1112
signal escPressed
1213

13-
flags: Qt.CoverWindow | Qt.WindowStaysOnTopHint | Qt.SplashScreen | Qt.FramelessWindowHint | Qt.X11BypassWindowManagerHint
14+
flags: Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint
1415
D.DWindow.enabled: true
15-
x: screen.virtualX + (screen.width - width) * 0.5
16-
y: screen.virtualY + screen.height - height - 220
17-
width: control.implicitWidth + 44
18-
height: control.implicitHeight + 24
19-
minimumWidth: 200
16+
color: D.DTK.palette.window
17+
// 使用 DLayerShellWindow 定位窗口:X轴居中,Y轴锚定底部偏上1/4处
18+
DS.DLayerShellWindow.anchors: DS.DLayerShellWindow.AnchorBottom
19+
DS.DLayerShellWindow.layer: DS.DLayerShellWindow.LayerOverlay
20+
DS.DLayerShellWindow.bottomMargin: (root.screen && root.screen.height > 0) ? Math.max(0, root.screen.height * 0.25 - height * 0.5) : 400
21+
22+
width: control.implicitWidth
23+
height: control.implicitHeight
2024
onClosing: destroy(10)
2125
Text {
2226
id: control
23-
anchors.centerIn: parent
27+
leftPadding: 22
28+
topPadding: 12
29+
rightPadding: leftPadding
30+
bottomPadding: topPadding
2431
text: root.name
2532
font: D.DTK.fontManager.t4
26-
color: control.palette.brightText
33+
color: D.DTK.palette.brightText
2734
}
2835
Shortcut {
2936
sequence: "Esc"
Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,51 @@
1-
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
1+
// SPDX-FileCopyrightText: 2025 - 2026 UnionTech Software Technology Co., Ltd.
22
// SPDX-License-Identifier: GPL-3.0-or-later
3-
43
import QtQuick 2.15
4+
5+
import org.deepin.ds 1.0 as DS
56
import org.deepin.dcc 1.0
67

7-
Window {
8+
Loader {
89
id: root
9-
flags: Qt.CoverWindow | Qt.WindowStaysOnTopHint | Qt.SplashScreen | Qt.FramelessWindowHint | Qt.X11BypassWindowManagerHint
10-
color: "#2ca7f8"
11-
x: screen.virtualX
12-
y: screen.virtualY
13-
width: screen.width
14-
height: 10
15-
onClosing: destroy(10)
10+
property var screen: null
11+
signal closed
12+
active: screen !== null
1613
Timer {
1714
interval: 1000
18-
running: root.visible
19-
onTriggered: root.close()
15+
running: root.active
16+
onTriggered: root.closed()
2017
}
21-
Window {
22-
flags: Qt.CoverWindow | Qt.WindowStaysOnTopHint | Qt.SplashScreen | Qt.FramelessWindowHint | Qt.X11BypassWindowManagerHint
23-
visible: root.visible
24-
color: root.color
18+
19+
component IndicatorBorder: Window {
2520
screen: root.screen
26-
x: screen.virtualX
27-
y: screen.virtualY + screen.height - 10
28-
width: screen.width
21+
color: "#2ca7f8"
22+
23+
flags: Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint
24+
DS.DLayerShellWindow.layer: DS.DLayerShellWindow.LayerOverlay
25+
DS.DLayerShellWindow.exclusionZone: -1
26+
Component.onCompleted: show()
2927
height: 10
30-
}
31-
Window {
32-
flags: Qt.CoverWindow | Qt.WindowStaysOnTopHint | Qt.SplashScreen | Qt.FramelessWindowHint | Qt.X11BypassWindowManagerHint
33-
visible: root.visible
34-
color: root.color
35-
screen: root.screen
36-
x: screen.virtualX
37-
y: screen.virtualY
3828
width: 10
39-
height: screen.height
4029
}
41-
Window {
42-
flags: Qt.CoverWindow | Qt.WindowStaysOnTopHint | Qt.SplashScreen | Qt.FramelessWindowHint | Qt.X11BypassWindowManagerHint
43-
visible: root.visible
44-
color: root.color
45-
screen: root.screen
46-
x: screen.virtualX + screen.width - 10
47-
y: screen.virtualY
48-
width: 10
49-
height: screen.height
30+
31+
sourceComponent: IndicatorBorder {
32+
DS.DLayerShellWindow.anchors: DS.DLayerShellWindow.AnchorTop
33+
| DS.DLayerShellWindow.AnchorLeft
34+
| DS.DLayerShellWindow.AnchorRight
35+
IndicatorBorder {
36+
DS.DLayerShellWindow.anchors: DS.DLayerShellWindow.AnchorBottom
37+
| DS.DLayerShellWindow.AnchorLeft
38+
| DS.DLayerShellWindow.AnchorRight
39+
}
40+
IndicatorBorder {
41+
DS.DLayerShellWindow.anchors: DS.DLayerShellWindow.AnchorLeft
42+
| DS.DLayerShellWindow.AnchorTop
43+
| DS.DLayerShellWindow.AnchorBottom
44+
}
45+
IndicatorBorder {
46+
DS.DLayerShellWindow.anchors: DS.DLayerShellWindow.AnchorRight
47+
| DS.DLayerShellWindow.AnchorTop
48+
| DS.DLayerShellWindow.AnchorBottom
49+
}
5050
}
5151
}

src/plugin-personalization/qml/WallpaperPage.qml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,19 @@ DccObject {
2929
visible: dccData.model.screens.length > 1
3030
page: ScreenTab {
3131
id: screemTab
32+
property var indicatorScreen: null
3233
model: dccData.model.screens
3334
screen: dccData.model.currentSelectScreen
3435
onScreenChanged: {
3536
if (screen !== dccData.model.currentSelectScreen) {
3637
dccData.model.currentSelectScreen = screen
37-
if (true) {
38-
indicator.createObject(this, {
39-
"screen": getQtScreen(screemTab.screen)
40-
}).show()
41-
}
38+
indicatorScreen = null
39+
indicatorScreen = getQtScreen(screemTab.screen)
4240
}
4341
}
44-
45-
Component {
46-
id: indicator
47-
ScreenIndicator {}
42+
ScreenIndicator{
43+
screen: screemTab.indicatorScreen
44+
onClosed: screemTab.indicatorScreen = null
4845
}
4946

5047
function getQtScreen(screenName) {

0 commit comments

Comments
 (0)