on a3abeec help sign in
unity8/qml/Stage/WindowControlsOverlay.qml
219 lines 7.9 kB history raw
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17import QtQuick 2.4
18import Ubuntu.Components 1.3
19import Ubuntu.Gestures 0.1
20import Unity.Application 0.1
21import "../Components/PanelState"
23Item {
24 id: root
25 enabled: target && !target.fullscreen
27 // to be set from outside
28 property Item target // appDelegate
30 // to be read from outside
31 readonly property alias overlayShown: overlay.visible
33 TouchGestureArea {
34 id: gestureArea
35 anchors.fill: parent
37 // NB: for testing set to 2, not to clash with unity7 touch overlay controls
38 minimumTouchPoints: 3
39 maximumTouchPoints: minimumTouchPoints
41 readonly property bool recognizedPress: status == TouchGestureArea.Recognized &&
42 touchPoints.length >= minimumTouchPoints &&
43 touchPoints.length <= maximumTouchPoints
44 onRecognizedPressChanged: {
45 if (recognizedPress) {
46 target.focus = true;
47 overlayTimer.start();
48 }
49 }
51 readonly property bool recognizedDrag: recognizedPress && dragging
52 onRecognizedDragChanged: {
53 if (recognizedDrag) {
54 priv.handlePressedChanged(true, tp.x, tp.y);
55 } else if (!moveHandler.containsPress) { // prevent interfering with the central piece drag/move
56 priv.dragging = false;
57 }
58 }
60 readonly property point tp: recognizedPress ? Qt.point(touchPoints[0].x, touchPoints[0].y) : Qt.point(-1, -1)
61 onUpdated: {
62 if (recognizedDrag) {
63 priv.handlePositionChanged(tp.x, tp.y);
64 }
65 }
66 }
68 // dismiss timer
69 Timer {
70 id: overlayTimer
71 interval: 2000
72 repeat: priv.dragging || (priv.resizeArea && priv.resizeArea.dragging)
73 }
75 QtObject {
76 id: priv
77 property real distanceX
78 property real distanceY
79 property bool dragging
81 readonly property var resizeArea: root.target && root.target.resizeArea ? root.target.resizeArea : null
83 function handlePressedChanged(pressed, mouseX, mouseY) {
84 if (pressed) {
85 var pos = mapToItem(root.target, mouseX, mouseY);
86 priv.distanceX = pos.x;
87 priv.distanceY = pos.y;
88 priv.dragging = true;
89 } else {
90 priv.dragging = false;
91 }
92 }
94 function handlePositionChanged(mouseX, mouseY) {
95 if (priv.dragging) {
96 var pos = mapToItem(root.target.parent, mouseX, mouseY);
97 root.target.windowedX = Math.round(pos.x - priv.distanceX);
98 root.target.windowedY = Math.round(Math.max(pos.y - priv.distanceY, PanelState.panelHeight));
99 }
100 }
101 }
103 // the visual overlay
104 Item {
105 id: overlay
106 objectName: "windowControlsOverlay"
107 anchors.fill: parent
108 enabled: overlayTimer.running
109 visible: opacity > 0
110 opacity: enabled ? 0.95 : 0
112 Behavior on opacity {
113 UbuntuNumberAnimation {}
114 }
116 readonly property bool anyMaximized: target && (target.maximized || target.maximizedLeft || target.maximizedRight)
118 Image {
119 source: "graphics/arrows-centre.png"
120 width: units.gu(10)
121 height: width
122 sourceSize: Qt.size(width, height)
123 anchors.centerIn: parent
124 visible: target && target.width > units.gu(12) && target.height > units.gu(12)
126 // move handler
127 MouseArea {
128 id: moveHandler
129 anchors.fill: parent
130 visible: overlay.visible
131 enabled: visible
132 hoverEnabled: true
133 cursorShape: priv.dragging ? Qt.ClosedHandCursor : (overlay.visible ? Qt.OpenHandCursor : Qt.ArrowCursor)
135 onPressedChanged: priv.handlePressedChanged(pressed, mouseX, mouseY)
136 onPositionChanged: priv.handlePositionChanged(mouseX, mouseY)
137 }
139 // dismiss area
140 InverseMouseArea {
141 anchors.fill: parent
142 visible: overlay.visible
143 enabled: visible
144 onPressed: {
145 if (gestureArea.recognizedPress || gestureArea.recognizedDrag) {
146 mouse.accepted = false;
147 return;
148 }
150 overlayTimer.stop();
151 mouse.accepted = root.contains(Qt.point(mouse.x, mouse.y));
152 }
153 propagateComposedEvents: true
154 }
155 }
157 ResizeGrip { // top left
158 anchors.horizontalCenter: parent.left
159 anchors.verticalCenter: parent.top
160 visible: target && !overlay.anyMaximized && !target.maximizedHorizontally && !target.maximizedVertically
161 resizeTarget: priv.resizeArea
162 }
164 ResizeGrip { // top center
165 anchors.horizontalCenter: parent.horizontalCenter
166 anchors.verticalCenter: parent.top
167 rotation: 45
168 visible: target && !overlay.anyMaximized && !target.maximizedVertically
169 resizeTarget: priv.resizeArea
170 }
172 ResizeGrip { // top right
173 anchors.horizontalCenter: parent.right
174 anchors.verticalCenter: parent.top
175 rotation: 90
176 visible: target && !overlay.anyMaximized && !target.maximizedHorizontally && !target.maximizedVertically
177 resizeTarget: priv.resizeArea
178 }
180 ResizeGrip { // right
181 anchors.horizontalCenter: parent.right
182 anchors.verticalCenter: parent.verticalCenter
183 rotation: 135
184 visible: target && !target.maximizedRight && !target.maximized && !target.maximizedHorizontally
185 resizeTarget: priv.resizeArea
186 }
188 ResizeGrip { // bottom right
189 anchors.horizontalCenter: parent.right
190 anchors.verticalCenter: parent.bottom
191 visible: target && !overlay.anyMaximized && !target.maximizedHorizontally && !target.maximizedVertically
192 resizeTarget: priv.resizeArea
193 }
195 ResizeGrip { // bottom center
196 anchors.horizontalCenter: parent.horizontalCenter
197 anchors.verticalCenter: parent.bottom
198 rotation: 45
199 visible: target && !overlay.anyMaximized && !target.maximizedVertically
200 resizeTarget: priv.resizeArea
201 }
203 ResizeGrip { // bottom left
204 anchors.horizontalCenter: parent.left
205 anchors.verticalCenter: parent.bottom
206 rotation: 90
207 visible: target && !overlay.anyMaximized && !target.maximizedHorizontally && !target.maximizedVertically
208 resizeTarget: priv.resizeArea
209 }
211 ResizeGrip { // left
212 anchors.horizontalCenter: parent.left
213 anchors.verticalCenter: parent.verticalCenter
214 rotation: 135
215 visible: target && !target.maximizedLeft && !target.maximized && !target.maximizedHorizontally
216 resizeTarget: priv.resizeArea
217 }
218 }