Visitar URL original
fix(surface): give a title bar press only to the window under it · linuxdeepin/treeland@9ecd5f2 · GitHub
Skip to content

Commit 9ecd5f2

Browse files
committed
fix(surface): give a title bar press only to the window under it
1. A press can reach this window's title bar while the cursor is over the window on top: when that window owns no input at the point (a transparent margin or the window border) the press falls through, and the title bar below then activates its own window, which restacks it above the window that was pressed. 2. Cause: the title bar acted on every press it received, without asking whether it is the window under the cursor. 3. Fix: one MouseArea owns the title bar presses (click activates, double click toggles maximize, dragging past the drag threshold moves the window, right click and touch long press open the window menu), and the ownership test runs once per press. A TapHandler/DragHandler variant gated its drag on the cursor position at drag time and was reverted after the pointer wedged on real hardware; that cause is still unknown and is not addressed here. Log: 上层窗口没有输入的位置落到下层标题栏时,标题栏不再激活、移动本窗口或弹出窗口菜单。 Influence: 1. 上层窗口点击/拖动它的 SSD 标题栏,下层窗口不被抬起、不被激活。 2. 上层窗口是没有 Decoration 的状态(最大化/全屏/平铺)或 CSD 窗口时,按它透明的边角, 落到下层标题栏的位置,确认下层不被激活、不被抬起。 3. 标题栏单击激活、双击最大化/还原、拖动移动、右键菜单、触屏长按、三个窗口按钮均不受影响。 4. 拖动标题栏移动窗口时,过程中与松手后都不出现窗口菜单。 Multica Issue: WM-936
1 parent bc2f084 commit 9ecd5f2

1 file changed

Lines changed: 62 additions & 34 deletions

File tree

‎src/core/qml/TitleBar.qml‎

Lines changed: 62 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -40,45 +40,65 @@ Control {
4040
blocking: true
4141
}
4242

43-
// Left mouse button handler
44-
TapHandler {
45-
acceptedButtons: Qt.LeftButton
46-
onTapped: {
47-
WaylandServer.activateSurface(surface)
48-
}
49-
onDoubleTapped: {
50-
if (root.canToggleMaximize)
51-
surface.toggleMaximized()
43+
// One MouseArea owns every title bar press, so the ownership test below runs once per
44+
// press and a window move starts from the same grab. The TapHandler/DragHandler variant
45+
// could only gate its drag on the cursor position at drag time, and it was reverted after
46+
// the pointer wedged on real hardware; that cause is still unknown and is not addressed
47+
// by this file.
48+
MouseArea {
49+
anchors.fill: parent
50+
acceptedButtons: Qt.LeftButton | Qt.RightButton
51+
52+
property point pressPosition
53+
property bool movingWindow: false
54+
// A press the window above covers reached this title bar only through a hole
55+
// in that window's input: do not activate or move this window on it.
56+
property bool pressBelongsToWindow: true
57+
// onPressAndHold cannot tell the device, Qt stamps that event as
58+
// MouseEventSynthesizedByQt for mice too. Real pointer events arrive as
59+
// NotSynthesized (WSeat sends them so, see waylib wseat.cpp), touch screens as
60+
// a synthesized press. Compared by equality since MouseEvent.source is
61+
// deprecated: a Qt build without it then only loses touch long press.
62+
property bool pressWasTouch: false
63+
64+
onPressed: function (mouse) {
65+
pressPosition = Qt.point(mouse.x, mouse.y)
66+
movingWindow = false
67+
pressWasTouch = mouse.source === Qt.MouseEventSynthesizedByQt
68+
|| mouse.source === Qt.MouseEventSynthesizedBySystem
69+
pressBelongsToWindow = root.surface.isTopmostWindowAt(
70+
root.mapToItem(null, Qt.point(mouse.x, mouse.y)))
5271
}
53-
}
54-
55-
DragHandler {
56-
acceptedButtons: Qt.LeftButton
57-
target: null
58-
dragThreshold: Qt.styleHints.startDragDistance
59-
onActiveChanged: {
60-
if (active)
61-
surface.moveRequested()
72+
onPositionChanged: function (mouse) {
73+
if (!pressed || movingWindow || !pressBelongsToWindow
74+
|| !(mouse.buttons & Qt.LeftButton))
75+
return
76+
const dx = mouse.x - pressPosition.x
77+
const dy = mouse.y - pressPosition.y
78+
const threshold = Qt.styleHints.startDragDistance
79+
if (dx * dx + dy * dy < threshold * threshold)
80+
return
81+
movingWindow = true
82+
surface.moveRequested()
6283
}
63-
}
64-
65-
// Right mouse button handler
66-
TapHandler {
67-
acceptedButtons: Qt.RightButton
68-
onTapped: {
69-
surface.windowMenuRequested(eventPoint.position)
84+
onClicked: function (mouse) {
85+
if (!pressBelongsToWindow || movingWindow)
86+
return
87+
if (mouse.button === Qt.LeftButton)
88+
WaylandServer.activateSurface(surface)
89+
else
90+
surface.windowMenuRequested(Qt.point(mouse.x, mouse.y))
7091
}
71-
}
72-
73-
// Touch screen click
74-
TapHandler {
75-
acceptedButtons: Qt.NoButton
76-
acceptedDevices: PointerDevice.TouchScreen
77-
onDoubleTapped: {
78-
if (root.canToggleMaximize)
92+
onDoubleClicked: function (mouse) {
93+
if (pressBelongsToWindow && mouse.button === Qt.LeftButton && root.canToggleMaximize)
7994
surface.toggleMaximized()
8095
}
81-
onLongPressed: surface.windowMenuRequested(point.position)
96+
onPressAndHold: function (mouse) {
97+
// Touch screen only, and never mid-drag: this timer is not stopped by
98+
// movement, while a dragged window keeps the cursor over the same spot.
99+
if (pressBelongsToWindow && pressWasTouch && !movingWindow)
100+
surface.windowMenuRequested(Qt.point(mouse.x, mouse.y))
101+
}
82102
}
83103

84104
Rectangle {
@@ -121,6 +141,10 @@ Control {
121141
D.ColorSelector.inactived: !surface.isActivated
122142

123143
onClicked: {
144+
// A covered title bar can be reached through an area of the
145+
// window above that owns no input; its buttons stay inert then.
146+
if (!surface.isTopmostWindowUnderCursor())
147+
return
124148
surface.minimize()
125149
}
126150
}
@@ -138,6 +162,8 @@ Control {
138162
D.ColorSelector.inactived: !surface.isActivated
139163

140164
onClicked: {
165+
if (!surface.isTopmostWindowUnderCursor())
166+
return
141167
WaylandServer.activateSurface(surface)
142168
surface.toggleMaximized()
143169
}
@@ -162,6 +188,8 @@ Control {
162188
D.ColorSelector.inactived: !surface.isActivated
163189

164190
onClicked: {
191+
if (!surface.isTopmostWindowUnderCursor())
192+
return
165193
surface.closeSurface()
166194
}
167195
}

0 commit comments

Comments
 (0)