@@ -15,11 +15,8 @@
17import QtQuick 2.4
17import QtQuick 2.4
18−import Unity.Application 0.1 // For Mir singleton
19import Ubuntu.Components 1.3
18import Ubuntu.Components 1.3
21import "../Components"
19import "../Components"
22−import "../Components/PanelState"
24MouseArea {
21MouseArea {
@@ -30,8 +27,8 @@ MouseArea {
30 property alias maximizeButtonShown: buttons.maximizeButtonShown
27 property alias maximizeButtonShown: buttons.maximizeButtonShown
31 property bool active: false
28 property bool active: false
32 property alias overlayShown: buttons.overlayShown
29 property alias overlayShown: buttons.overlayShown
33− property int stageWidth
30+
34− property int stageHeight
31+ readonly property real buttonsWidth: buttons.width + row.spacing
36 acceptedButtons: Qt.AllButtons // prevent leaking unhandled mouse events
33 acceptedButtons: Qt.AllButtons // prevent leaking unhandled mouse events
37 hoverEnabled: true
34 hoverEnabled: true
@@ -42,187 +39,6 @@ MouseArea {
42 signal maximizeHorizontallyClicked()
39 signal maximizeHorizontallyClicked()
43 signal maximizeVerticallyClicked()
40 signal maximizeVerticallyClicked()
45− signal fakeMaximizeAnimationRequested(real progress)
46− signal fakeMaximizeLeftAnimationRequested(real progress)
47− signal fakeMaximizeRightAnimationRequested(real progress)
48− signal fakeMaximizeTopLeftAnimationRequested(real progress)
49− signal fakeMaximizeTopRightAnimationRequested(real progress)
50− signal fakeMaximizeBottomLeftAnimationRequested(real progress)
51− signal fakeMaximizeBottomRightAnimationRequested(real progress)
52− signal stopFakeAnimation()
56− if (target.canBeMaximized && mouse.button == Qt.LeftButton) {
57− priv.dragging = false; // do not interfere with a quick double click followed by a mouse move/drag
58− root.maximizeClicked();
64− property real distanceX
65− property real distanceY
66− property bool dragging
68− readonly property int triggerArea: units.gu(3)
69− property bool nearLeftEdge: target.maximizedLeft
70− property bool nearTopEdge: target.maximized
71− property bool nearRightEdge: target.maximizedRight
72− property bool nearTopLeftCorner: target.maximizedTopLeft
73− property bool nearTopRightCorner: target.maximizedTopRight
74− property bool nearBottomLeftCorner: target.maximizedBottomLeft
75− property bool nearBottomRightCorner: target.maximizedBottomRight
77− function resetEdges() {
78− nearLeftEdge = false;
79− nearRightEdge = false;
81− nearTopLeftCorner = false;
82− nearTopRightCorner = false;
83− nearBottomLeftCorner = false;
84− nearBottomRightCorner = false;
87− // return the progress of mouse pointer movement from 0 to 1 within a corner square of the screen
88− // 0 -> before the mouse enters the square
89− // 1 -> mouse is in the outer corner
90− // a is the corner, b is the mouse pos
91− function progressInCorner(ax, ay, bx, by) {
92− // distance of two points, a and b, in pixels
93− var distance = Math.sqrt(Math.pow(bx-ax, 2) + Math.pow(by-ay, 2));
94− // length of the triggerArea square diagonal
95− var diagLength = Math.sqrt(2 * priv.triggerArea * priv.triggerArea);
96− var ratio = 1 - (distance / diagLength);
97− return bx > 0 && bx <= stageWidth && by > 0 && by <= stageHeight ? ratio : 1; // everything "outside" of our square from the center is 1
99− property real progress: 0
103− if (pressed && pressedButtons == Qt.LeftButton) {
104− var pos = mapToItem(root.target, mouseX, mouseY);
105− if (target.anyMaximized) {
106− // keep distanceX relative to the normal window width minus the window control buttons (+spacing)
107− // so that dragging it back doesn't make the window jump around to weird positions, away from the mouse pointer
108− priv.distanceX = MathUtils.clampAndProject(pos.x, 0, root.target.width, buttons.width + row.spacing, root.target.resizeArea.normalWidth);
110− priv.distanceX = pos.x;
113− priv.distanceY = pos.y;
114− priv.dragging = true;
116− priv.dragging = false;
117− Mir.cursorName = "";
121− onPositionChanged: {
122− if (priv.dragging) {
123− Mir.cursorName = "grabbing";
125− if (target.anyMaximized) { // restore from maximized when dragging away from edges/corners
127− target.restore(false, WindowStateStorage.WindowStateNormal);
130− var pos = mapToItem(root.target.parent, mouseX, mouseY);
131− // Use integer coordinate values to ensure that target is left in a pixel-aligned
132− // position. Mouse movement could have subpixel precision, yielding a fractional
134− root.target.requestedX = Math.round(pos.x - priv.distanceX);
135− root.target.requestedY = Math.round(Math.max(pos.y - priv.distanceY, PanelState.panelHeight));
137− var globalPos = mapToItem(null, mouseX, mouseY);
138− var globalX = globalPos.x;
139− var globalY = globalPos.y;
140− if (globalX < priv.triggerArea && globalY < PanelState.panelHeight) { // top left
141− if (target.canBeCornerMaximized) {
142− priv.progress = priv.progressInCorner(0, PanelState.panelHeight, globalX, globalY);
144− priv.nearTopLeftCorner = true;
145− root.fakeMaximizeTopLeftAnimationRequested(priv.progress);
147− } else if (globalX > stageWidth - priv.triggerArea && globalY < PanelState.panelHeight) { // top right
148− if (target.canBeCornerMaximized) {
149− priv.progress = priv.progressInCorner(stageWidth, PanelState.panelHeight, globalX, globalY);
151− priv.nearTopRightCorner = true;
152− root.fakeMaximizeTopRightAnimationRequested(priv.progress);
154− } else if (globalX < priv.triggerArea && globalY > stageHeight - priv.triggerArea) { // bottom left
155− if (target.canBeCornerMaximized) {
156− priv.progress = priv.progressInCorner(0, stageHeight, globalX, globalY);
158− priv.nearBottomLeftCorner = true;
159− root.fakeMaximizeBottomLeftAnimationRequested(priv.progress);
161− } else if (globalX > stageWidth - priv.triggerArea && globalY > stageHeight - priv.triggerArea) { // bottom right
162− if (target.canBeCornerMaximized) {
163− priv.progress = priv.progressInCorner(stageWidth, stageHeight, globalX, globalY);
165− priv.nearBottomRightCorner = true;
166− root.fakeMaximizeBottomRightAnimationRequested(priv.progress);
168− } else if (globalX < priv.triggerArea) { // left
169− if (target.canBeMaximizedLeftRight) {
170− priv.progress = MathUtils.clampAndProject(globalX, priv.triggerArea, 0, 0, 1);
172− priv.nearLeftEdge = true;
173− root.fakeMaximizeLeftAnimationRequested(priv.progress);
175− } else if (globalX > stageWidth - priv.triggerArea) { // right
176− if (target.canBeMaximizedLeftRight) {
177− priv.progress = MathUtils.clampAndProject(globalX, stageWidth - priv.triggerArea, stageWidth, 0, 1);
179− priv.nearRightEdge = true;
180− root.fakeMaximizeRightAnimationRequested(priv.progress);
182− } else if (globalY < PanelState.panelHeight) { // top
183− if (target.canBeMaximized) {
184− priv.progress = MathUtils.clampAndProject(globalY, Math.max(PanelState.panelHeight, priv.triggerArea), 0, 0, 1);
186− priv.nearTopEdge = true;
187− root.fakeMaximizeAnimationRequested(priv.progress);
189− } else if (priv.nearLeftEdge || priv.nearRightEdge || priv.nearTopEdge || priv.nearTopLeftCorner || priv.nearTopRightCorner ||
190− priv.nearBottomLeftCorner || priv.nearBottomRightCorner) {
194− root.stopFakeAnimation();
200− print("Mouse released (left/top/right)", priv.nearLeftEdge, priv.nearTopEdge, priv.nearRightEdge)
201− if (mouse.button == Qt.LeftButton && (target.state == "normal" || target.state == "restored") && priv.progress == 0) {
202− // save the x/y to restore to
203− target.restoredX = target.x;
204− target.restoredY = target.y;
205− } else if (priv.progress < 0.3) { // cancel the preview shape if under 30%
208− root.stopFakeAnimation();
209− } else if (priv.nearLeftEdge) {
210− target.maximizeLeft();
211− } else if (priv.nearTopEdge) {
213− } else if (priv.nearRightEdge) {
214− target.maximizeRight();
215− } else if (priv.nearTopLeftCorner) {
216− target.maximizeTopLeft();
217− } else if (priv.nearTopRightCorner) {
218− target.maximizeTopRight();
219− } else if (priv.nearBottomLeftCorner) {
220− target.maximizeBottomLeft();
221− } else if (priv.nearBottomRightCorner) {
222− target.maximizeBottomRight();
226 // do not let unhandled wheel event pass thru the decoration
42 // do not let unhandled wheel event pass thru the decoration
227 onWheel: wheel.accepted = true;
43 onWheel: wheel.accepted = true;