on 1ff9050 help sign in
unity8/qml/Stages/WindowControlsOverlay.qml
218 lines 7.8 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 readonly property alias overlayShown: overlay.visible
32 TouchGestureArea {
33 id: gestureArea
34 anchors.fill: parent
36 // NB: for testing set to 2, not to clash with unity7 touch overlay controls
37 minimumTouchPoints: 3
38 maximumTouchPoints: minimumTouchPoints
40 readonly property bool recognizedPress: status == TouchGestureArea.Recognized &&
41 touchPoints.length >= minimumTouchPoints &&
42 touchPoints.length <= maximumTouchPoints
43 onRecognizedPressChanged: {
44 if (recognizedPress) {
45 target.focus = true;
46 overlayTimer.start();
47 }
48 }
50 readonly property bool recognizedDrag: recognizedPress && dragging
51 onRecognizedDragChanged: {
52 if (recognizedDrag) {
53 priv.handlePressedChanged(true, tp.x, tp.y);
54 } else if (!moveHandler.containsPress) { // prevent interfering with the central piece drag/move
55 priv.dragging = false;
56 }
57 }
59 readonly property point tp: recognizedPress ? Qt.point(touchPoints[0].x, touchPoints[0].y) : Qt.point(-1, -1)
60 onUpdated: {
61 if (recognizedDrag) {
62 priv.handlePositionChanged(tp.x, tp.y);
63 }
64 }
65 }
67 // dismiss timer
68 Timer {
69 id: overlayTimer
70 interval: 2000
71 repeat: priv.dragging || (priv.resizeArea && priv.resizeArea.dragging)
72 }
74 QtObject {
75 id: priv
76 property real distanceX
77 property real distanceY
78 property bool dragging
80 readonly property var resizeArea: root.target && root.target.resizeArea ? root.target.resizeArea : null
82 function handlePressedChanged(pressed, mouseX, mouseY) {
83 if (pressed) {
84 var pos = mapToItem(root.target, mouseX, mouseY);
85 priv.distanceX = pos.x;
86 priv.distanceY = pos.y;
87 priv.dragging = true;
88 } else {
89 priv.dragging = false;
90 }
91 }
93 function handlePositionChanged(mouseX, mouseY) {
94 if (priv.dragging) {
95 var pos = mapToItem(root.target.parent, mouseX, mouseY);
96 root.target.x = Math.round(pos.x - priv.distanceX);
97 root.target.y = Math.round(Math.max(pos.y - priv.distanceY, PanelState.panelHeight));
98 }
99 }
100 }
102 // the visual overlay
103 Item {
104 id: overlay
105 objectName: "windowControlsOverlay"
106 anchors.fill: parent
107 enabled: overlayTimer.running
108 visible: opacity > 0
109 opacity: enabled ? 0.95 : 0
111 Behavior on opacity {
112 UbuntuNumberAnimation {}
113 }
115 readonly property bool anyMaximized: target && (target.maximized || target.maximizedLeft || target.maximizedRight)
117 Image {
118 source: "graphics/arrows-centre.png"
119 width: units.gu(10)
120 height: width
121 sourceSize: Qt.size(width, height)
122 anchors.centerIn: parent
123 visible: target && target.width > units.gu(12) && target.height > units.gu(12)
125 // move handler
126 MouseArea {
127 id: moveHandler
128 anchors.fill: parent
129 visible: overlay.visible
130 enabled: visible
131 hoverEnabled: true
132 cursorShape: priv.dragging ? Qt.ClosedHandCursor : (overlay.visible ? Qt.OpenHandCursor : Qt.ArrowCursor)
134 onPressedChanged: priv.handlePressedChanged(pressed, mouseX, mouseY)
135 onPositionChanged: priv.handlePositionChanged(mouseX, mouseY)
136 }
138 // dismiss area
139 InverseMouseArea {
140 anchors.fill: parent
141 visible: overlay.visible
142 enabled: visible
143 onPressed: {
144 if (gestureArea.recognizedPress || gestureArea.recognizedDrag) {
145 mouse.accepted = false;
146 return;
147 }
149 overlayTimer.stop();
150 mouse.accepted = root.contains(Qt.point(mouse.x, mouse.y));
151 }
152 propagateComposedEvents: true
153 }
154 }
156 ResizeGrip { // top left
157 anchors.horizontalCenter: parent.left
158 anchors.verticalCenter: parent.top
159 visible: target && !overlay.anyMaximized && !target.maximizedHorizontally && !target.maximizedVertically
160 resizeTarget: priv.resizeArea
161 }
163 ResizeGrip { // top center
164 anchors.horizontalCenter: parent.horizontalCenter
165 anchors.verticalCenter: parent.top
166 rotation: 45
167 visible: target && !overlay.anyMaximized && !target.maximizedVertically
168 resizeTarget: priv.resizeArea
169 }
171 ResizeGrip { // top right
172 anchors.horizontalCenter: parent.right
173 anchors.verticalCenter: parent.top
174 rotation: 90
175 visible: target && !overlay.anyMaximized && !target.maximizedHorizontally && !target.maximizedVertically
176 resizeTarget: priv.resizeArea
177 }
179 ResizeGrip { // right
180 anchors.horizontalCenter: parent.right
181 anchors.verticalCenter: parent.verticalCenter
182 rotation: 135
183 visible: target && !target.maximizedRight && !target.maximized && !target.maximizedHorizontally
184 resizeTarget: priv.resizeArea
185 }
187 ResizeGrip { // bottom right
188 anchors.horizontalCenter: parent.right
189 anchors.verticalCenter: parent.bottom
190 visible: target && !overlay.anyMaximized && !target.maximizedHorizontally && !target.maximizedVertically
191 resizeTarget: priv.resizeArea
192 }
194 ResizeGrip { // bottom center
195 anchors.horizontalCenter: parent.horizontalCenter
196 anchors.verticalCenter: parent.bottom
197 rotation: 45
198 visible: target && !overlay.anyMaximized && !target.maximizedVertically
199 resizeTarget: priv.resizeArea
200 }
202 ResizeGrip { // bottom left
203 anchors.horizontalCenter: parent.left
204 anchors.verticalCenter: parent.bottom
205 rotation: 90
206 visible: target && !overlay.anyMaximized && !target.maximizedHorizontally && !target.maximizedVertically
207 resizeTarget: priv.resizeArea
208 }
210 ResizeGrip { // left
211 anchors.horizontalCenter: parent.left
212 anchors.verticalCenter: parent.verticalCenter
213 rotation: 135
214 visible: target && !target.maximizedLeft && !target.maximized && !target.maximizedHorizontally
215 resizeTarget: priv.resizeArea
216 }
217 }