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
28 // to be set from outside
29 property Item target // appDelegate
30 property alias stageWidth: moveHandler.stageWidth
31 property alias stageHeight: moveHandler.stageHeight
33 // to be read from outside
34 readonly property alias overlayShown: overlay.visible
35 readonly property alias dragging: priv.dragging
37 signal fakeMaximizeAnimationRequested(real amount)
38 signal fakeMaximizeLeftAnimationRequested(real amount)
39 signal fakeMaximizeRightAnimationRequested(real amount)
40 signal fakeMaximizeTopLeftAnimationRequested(real amount)
41 signal fakeMaximizeTopRightAnimationRequested(real amount)
42 signal fakeMaximizeBottomLeftAnimationRequested(real amount)
43 signal fakeMaximizeBottomRightAnimationRequested(real amount)
44 signal stopFakeAnimation()
51 // NB: for testing set to 2, not to clash with unity7 touch overlay controls
53 maximumTouchPoints: minimumTouchPoints
55 readonly property bool recognizedPress: status == TouchGestureArea.Recognized &&
56 touchPoints.length >= minimumTouchPoints &&
57 touchPoints.length <= maximumTouchPoints
58 onRecognizedPressChanged: {
59 if (recognizedPress) {
65 readonly property bool recognizedDrag: recognizedPress && dragging
66 onRecognizedDragChanged: {
68 moveHandler.handlePressedChanged(true, Qt.LeftButton, tp.x, tp.y);
69 } else if (!mouseArea.containsPress) { // prevent interfering with the central piece drag/move
70 moveHandler.handlePressedChanged(false, Qt.LeftButton);
72 moveHandler.handleReleased(true);
76 readonly property point tp: recognizedPress ? Qt.point(touchPoints[0].x, touchPoints[0].y) : Qt.point(-1, -1)
79 moveHandler.handlePositionChanged(tp, priv.getSensingPoints());
93 readonly property var resizeArea: root.target && root.target.resizeArea ? root.target.resizeArea : null
94 readonly property bool ensureWindow: root.target.state == "normal" || root.target.state == "restored"
95 readonly property bool dragging: moveHandler.dragging || (resizeArea && resizeArea.dragging)
97 function getSensingPoints() {
100 for (var i = 0; i < gestureArea.touchPoints.length; i++) {
101 var pt = gestureArea.touchPoints[i];
106 var leftmost = Math.min.apply(Math, xPoints);
107 var rightmost = Math.max.apply(Math, xPoints);
108 var topmost = Math.min.apply(Math, yPoints);
109 var bottommost = Math.max.apply(Math, yPoints);
112 left: mapToItem(target.parent, leftmost, (topmost+bottommost)/2),
113 top: mapToItem(target.parent, (leftmost+rightmost)/2, topmost),
114 right: mapToItem(target.parent, rightmost, (topmost+bottommost)/2),
115 topLeft: mapToItem(target.parent, leftmost, topmost),
116 topRight: mapToItem(target.parent, rightmost, topmost),
117 bottomLeft: mapToItem(target.parent, leftmost, bottommost),
118 bottomRight: mapToItem(target.parent, rightmost, bottommost)
123 // the visual overlay
126 objectName: "windowControlsOverlay"
128 enabled: overlayTimer.running
130 opacity: enabled ? 0.95 : 0
132 Behavior on opacity {
133 UbuntuNumberAnimation {}
137 source: "graphics/arrows-centre.png"
140 sourceSize: Qt.size(width, height)
141 anchors.centerIn: parent
142 visible: target && target.width > units.gu(12) && target.height > units.gu(12)
148 visible: overlay.visible
152 onPressedChanged: moveHandler.handlePressedChanged(pressed, pressedButtons, mouseX, mouseY)
153 onPositionChanged: moveHandler.handlePositionChanged(mouse)
156 moveHandler.handleReleased();
162 objectName: "moveHandler"
165 onFakeMaximizeAnimationRequested: root.fakeMaximizeAnimationRequested(amount)
166 onFakeMaximizeLeftAnimationRequested: root.fakeMaximizeLeftAnimationRequested(amount)
167 onFakeMaximizeRightAnimationRequested: root.fakeMaximizeRightAnimationRequested(amount)
168 onFakeMaximizeTopLeftAnimationRequested: root.fakeMaximizeTopLeftAnimationRequested(amount)
169 onFakeMaximizeTopRightAnimationRequested: root.fakeMaximizeTopRightAnimationRequested(amount)
170 onFakeMaximizeBottomLeftAnimationRequested: root.fakeMaximizeBottomLeftAnimationRequested(amount)
171 onFakeMaximizeBottomRightAnimationRequested: root.fakeMaximizeBottomRightAnimationRequested(amount)
172 onStopFakeAnimation: root.stopFakeAnimation()
178 visible: overlay.visible
181 if (gestureArea.recognizedPress || gestureArea.recognizedDrag) {
182 mouse.accepted = false;
187 mouse.accepted = root.contains(mapToItem(root.target, mouse.x, mouse.y));
189 propagateComposedEvents: true
193 ResizeGrip { // top left
194 anchors.horizontalCenter: parent.left
195 anchors.verticalCenter: parent.top
196 visible: priv.ensureWindow || target.maximizedBottomRight
197 resizeTarget: priv.resizeArea
200 ResizeGrip { // top center
201 anchors.horizontalCenter: parent.horizontalCenter
202 anchors.verticalCenter: parent.top
204 visible: priv.ensureWindow || target.maximizedHorizontally || target.maximizedBottomLeft || target.maximizedBottomRight
205 resizeTarget: priv.resizeArea
208 ResizeGrip { // top right
209 anchors.horizontalCenter: parent.right
210 anchors.verticalCenter: parent.top
212 visible: priv.ensureWindow || target.maximizedBottomLeft
213 resizeTarget: priv.resizeArea
216 ResizeGrip { // right
217 anchors.horizontalCenter: parent.right
218 anchors.verticalCenter: parent.verticalCenter
220 visible: priv.ensureWindow || target.maximizedVertically || target.maximizedLeft ||
221 target.maximizedTopLeft || target.maximizedBottomLeft
222 resizeTarget: priv.resizeArea
225 ResizeGrip { // bottom right
226 anchors.horizontalCenter: parent.right
227 anchors.verticalCenter: parent.bottom
228 visible: priv.ensureWindow || target.maximizedTopLeft
229 resizeTarget: priv.resizeArea
232 ResizeGrip { // bottom center
233 anchors.horizontalCenter: parent.horizontalCenter
234 anchors.verticalCenter: parent.bottom
236 visible: priv.ensureWindow || target.maximizedHorizontally || target.maximizedTopLeft || target.maximizedTopRight
237 resizeTarget: priv.resizeArea
240 ResizeGrip { // bottom left
241 anchors.horizontalCenter: parent.left
242 anchors.verticalCenter: parent.bottom
244 visible: priv.ensureWindow || target.maximizedTopRight
245 resizeTarget: priv.resizeArea
249 anchors.horizontalCenter: parent.left
250 anchors.verticalCenter: parent.verticalCenter
252 visible: priv.ensureWindow || target.maximizedVertically || target.maximizedRight ||
253 target.maximizedTopRight || target.maximizedBottomRight
254 resizeTarget: priv.resizeArea