@@ -0,0 +1,219 @@
2+ * Copyright (C) 2016 Canonical, Ltd.
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.
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.
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/>.
18+import Ubuntu.Components 1.3
19+import Ubuntu.Gestures 0.1
20+import Unity.Application 0.1
21+import "../Components/PanelState"
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
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) {
47+ overlayTimer.start();
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;
60+ readonly property point tp: recognizedPress ? Qt.point(touchPoints[0].x, touchPoints[0].y) : Qt.point(-1, -1)
62+ if (recognizedDrag) {
63+ priv.handlePositionChanged(tp.x, tp.y);
72+ repeat: priv.dragging || (priv.resizeArea && priv.resizeArea.dragging)
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) {
85+ var pos = mapToItem(root.target, mouseX, mouseY);
86+ priv.distanceX = pos.x;
87+ priv.distanceY = pos.y;
88+ priv.dragging = true;
90+ priv.dragging = false;
94+ function handlePositionChanged(mouseX, mouseY) {
96+ var pos = mapToItem(root.target.parent, mouseX, mouseY);
97+ root.target.x = Math.round(pos.x - priv.distanceX);
98+ root.target.y = Math.round(Math.max(pos.y - priv.distanceY, PanelState.panelHeight));
103+ // the visual 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 {}
116+ readonly property bool anyMaximized: target && (target.maximized || target.maximizedLeft || target.maximizedRight)
119+ source: "graphics/arrows-centre.png"
122+ sourceSize: Qt.size(width, height)
123+ anchors.centerIn: parent
124+ visible: target && target.width > units.gu(12) && target.height > units.gu(12)
129+ anchors.fill: parent
130+ visible: overlay.visible
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)
141+ anchors.fill: parent
142+ visible: overlay.visible
145+ if (gestureArea.recognizedPress || gestureArea.recognizedDrag) {
146+ mouse.accepted = false;
150+ overlayTimer.stop();
151+ mouse.accepted = root.contains(Qt.point(mouse.x, mouse.y));
153+ propagateComposedEvents: true
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
164+ ResizeGrip { // top center
165+ anchors.horizontalCenter: parent.horizontalCenter
166+ anchors.verticalCenter: parent.top
168+ visible: target && !overlay.anyMaximized && !target.maximizedVertically
169+ resizeTarget: priv.resizeArea
172+ ResizeGrip { // top right
173+ anchors.horizontalCenter: parent.right
174+ anchors.verticalCenter: parent.top
176+ visible: target && !overlay.anyMaximized && !target.maximizedHorizontally && !target.maximizedVertically
177+ resizeTarget: priv.resizeArea
180+ ResizeGrip { // right
181+ anchors.horizontalCenter: parent.right
182+ anchors.verticalCenter: parent.verticalCenter
184+ visible: target && !target.maximizedRight && !target.maximized && !target.maximizedHorizontally
185+ resizeTarget: priv.resizeArea
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
195+ ResizeGrip { // bottom center
196+ anchors.horizontalCenter: parent.horizontalCenter
197+ anchors.verticalCenter: parent.bottom
199+ visible: target && !overlay.anyMaximized && !target.maximizedVertically
200+ resizeTarget: priv.resizeArea
203+ ResizeGrip { // bottom left
204+ anchors.horizontalCenter: parent.left
205+ anchors.verticalCenter: parent.bottom
207+ visible: target && !overlay.anyMaximized && !target.maximizedHorizontally && !target.maximizedVertically
208+ resizeTarget: priv.resizeArea
211+ ResizeGrip { // left
212+ anchors.horizontalCenter: parent.left
213+ anchors.verticalCenter: parent.verticalCenter
215+ visible: target && !target.maximizedLeft && !target.maximized && !target.maximizedHorizontally
216+ resizeTarget: priv.resizeArea