on xenial help sign in
implement maximizing windows horizontally/vertically
commit2989086f32c6323c3d7effdd3ab4432540b82777 authorLukáš Tinkl <lukas.tinkl@canonical.com> dateTue 19 Apr 2016, 11:13 (11 years ago) parentc72196c
7 files changed+97−42
plugins/Utils/windowstatestorage.h+12−2 qml/Components/WindowControlButtons.qml+12−1 qml/Stages/DecoratedWindow.qml+4 qml/Stages/DesktopStage.qml+39−33 qml/Stages/WindowDecoration.qml+4 qml/Stages/WindowResizeArea.qml+13−4 tests/mocks/Utils/windowstatestorage.h+13−2
plugins/Utils/windowstatestorage.h+12−2
@@ -25,9 +25,19 @@ class WindowStateStorage: public QObject
2525 Q_ENUMS(WindowState)
2626public:
2727 enum WindowState {
28− WindowStateNormal,
29− WindowStateMaximized
28+ WindowStateNormal = 1 << 0,
29+ WindowStateMaximized = 1 << 1,
30+ WindowStateMinimized = 1 << 2,
31+ WindowStateFullscreen = 1 << 3,
32+ WindowStateMaximizedLeft = 1 << 4,
33+ WindowStateMaximizedRight = 1 << 5,
34+ WindowStateMaximizedHorizontally = 1 << 6,
35+ WindowStateMaximizedVertically = 1 << 7
3036 };
37+ Q_DECLARE_FLAGS(WindowStates, WindowState)
38+#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
39+ Q_FLAG(WindowStates)
40+#endif
3141
3242 WindowStateStorage(QObject *parent = 0);
3343 virtual ~WindowStateStorage();
qml/Components/WindowControlButtons.qml+12−1
@@ -27,6 +27,8 @@ Row {
2727 signal close()
2828 signal minimize()
2929 signal maximize()
30+ signal maximizeVertically()
31+ signal maximizeHorizontally()
3032
3133 MouseArea {
3234 id: closeWindowButton
@@ -86,7 +88,16 @@ Row {
8688 hoverEnabled: true
8789 height: parent.height
8890 width: height
89− onClicked: root.maximize()
91+ acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
92+ onClicked: {
93+ if (mouse.button == Qt.LeftButton) {
94+ root.maximize();
95+ } else if (mouse.button == Qt.RightButton) {
96+ root.maximizeHorizontally();
97+ } else if (mouse.button == Qt.MiddleButton) {
98+ root.maximizeVertically();
99+ }
100+ }
90101
91102 Rectangle {
92103 anchors.centerIn: parent
qml/Stages/DecoratedWindow.qml+4
@@ -48,6 +48,8 @@ FocusScope {
4848
4949 signal close()
5050 signal maximize()
51+ signal maximizeHorizontally()
52+ signal maximizeVertically()
5153 signal minimize()
5254 signal decorationPressed()
5355
@@ -88,6 +90,8 @@ FocusScope {
8890
8991 onClose: root.close();
9092 onMaximize: { root.decorationPressed(); root.maximize(); }
93+ onMaximizeHorizontally: { root.decorationPressed(); root.maximizeHorizontally(); }
94+ onMaximizeVertically: { root.decorationPressed(); root.maximizeVertically(); }
9195 onMinimize: root.minimize();
9296 onPressed: root.decorationPressed();
9397 }
qml/Stages/DesktopStage.qml+39−33
@@ -89,7 +89,8 @@ AbstractStage {
8989 GlobalShortcut {
9090 id: minimizeRestoreShortcut
9191 shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Down
92− onTriggered: priv.focusedAppDelegate.maximized || priv.focusedAppDelegate.maximizedLeft || priv.focusedAppDelegate.maximizedRight
92+ onTriggered: priv.focusedAppDelegate.maximized || priv.focusedAppDelegate.maximizedLeft || priv.focusedAppDelegate.maximizedRight ||
93+ priv.focusedAppDelegate.maximizedHorizontally || priv.focusedAppDelegate.maximizedVertically
9394 ? priv.focusedAppDelegate.restoreFromMaximized() : priv.focusedAppDelegate.minimize()
9495 active: priv.focusedAppDelegate !== null
9596 }
@@ -262,19 +263,16 @@ AbstractStage {
262263 property alias widthIncrement: decoratedWindow.widthIncrement
263264 property alias heightIncrement: decoratedWindow.heightIncrement
264265
265− QtObject {
266− id: appDelegatePrivate
267− property bool maximized: false
268− property bool maximizedLeft: false
269− property bool maximizedRight: false
270− property bool minimized: false
271− }
272− readonly property alias maximized: appDelegatePrivate.maximized
273− readonly property alias maximizedLeft: appDelegatePrivate.maximizedLeft
274− readonly property alias maximizedRight: appDelegatePrivate.maximizedRight
275− readonly property alias minimized: appDelegatePrivate.minimized
266+ readonly property bool maximized: windowState & WindowStateStorage.WindowStateMaximized
267+ readonly property bool maximizedLeft: windowState & WindowStateStorage.WindowStateMaximizedLeft
268+ readonly property bool maximizedRight: windowState & WindowStateStorage.WindowStateMaximizedRight
269+ readonly property bool maximizedHorizontally: windowState & WindowStateStorage.WindowStateMaximizedHorizontally
270+ readonly property bool maximizedVertically: windowState & WindowStateStorage.WindowStateMaximizedVertically
271+ readonly property bool minimized: windowState & WindowStateStorage.WindowStateMinimized
276272 readonly property alias fullscreen: decoratedWindow.fullscreen
277273
274+ property int windowState: WindowStateStorage.WindowStateNormal
275+
278276 readonly property var application: model.application
279277 property bool animationsEnabled: true
280278 property alias title: decoratedWindow.title
@@ -372,43 +370,41 @@ AbstractStage {
372370
373371 function maximize(animated) {
374372 animationsEnabled = (animated === undefined) || animated;
375− appDelegatePrivate.minimized = false;
376− appDelegatePrivate.maximized = true;
377− appDelegatePrivate.maximizedLeft = false;
378− appDelegatePrivate.maximizedRight = false;
373+ windowState = WindowStateStorage.WindowStateMaximized;
379374 }
380375 function maximizeLeft() {
381− appDelegatePrivate.minimized = false;
382− appDelegatePrivate.maximized = false;
383− appDelegatePrivate.maximizedLeft = true;
384− appDelegatePrivate.maximizedRight = false;
376+ windowState = WindowStateStorage.WindowStateMaximizedLeft;
385377 }
386378 function maximizeRight() {
387− appDelegatePrivate.minimized = false;
388− appDelegatePrivate.maximized = false;
389− appDelegatePrivate.maximizedLeft = false;
390− appDelegatePrivate.maximizedRight = true;
379+ windowState = WindowStateStorage.WindowStateMaximizedRight;
380+ }
381+ function maximizeHorizontally() {
382+ windowState = WindowStateStorage.WindowStateMaximizedHorizontally;
383+ }
384+ function maximizeVertically() {
385+ windowState = WindowStateStorage.WindowStateMaximizedVertically;
391386 }
392387 function minimize(animated) {
393388 animationsEnabled = (animated === undefined) || animated;
394− appDelegatePrivate.minimized = true;
389+ windowState |= WindowStateStorage.WindowStateMinimized; // add the minimized bit
395390 }
396391 function restoreFromMaximized(animated) {
397392 animationsEnabled = (animated === undefined) || animated;
398− appDelegatePrivate.minimized = false;
399− appDelegatePrivate.maximized = false;
400− appDelegatePrivate.maximizedLeft = false;
401− appDelegatePrivate.maximizedRight = false;
393+ windowState = WindowStateStorage.WindowStateNormal;
402394 }
403395 function restore(animated) {
404396 animationsEnabled = (animated === undefined) || animated;
405− appDelegatePrivate.minimized = false;
397+ windowState &= ~WindowStateStorage.WindowStateMinimized; // clear the minimized bit
406398 if (maximized)
407399 maximize();
408400 else if (maximizedLeft)
409401 maximizeLeft();
410402 else if (maximizedRight)
411403 maximizeRight();
404+ else if (maximizedHorizontally)
405+ maximizeHorizontally();
406+ else if (maximizedVertically)
407+ maximizeVertically();
412408
413409 focus = true;
414410 }
@@ -439,8 +435,7 @@ AbstractStage {
439435 },
440436 State {
441437 name: "normal";
442− when: !appDelegate.maximized && !appDelegate.minimized
443− && !appDelegate.maximizedLeft && !appDelegate.maximizedRight
438+ when: appDelegate.windowState == WindowStateStorage.WindowStateNormal
444439 PropertyChanges {
445440 target: appDelegate;
446441 visuallyMinimized: false;
@@ -488,13 +483,21 @@ AbstractStage {
488483 requestedHeight: appContainer.height - PanelState.panelHeight
489484 }
490485 },
486+ State {
487+ name: "maximizedHorizontally"; when: appDelegate.maximizedHorizontally && !appDelegate.minimized
488+ PropertyChanges { target: appDelegate; x: root.leftMargin; requestedWidth: appContainer.width - root.leftMargin }
489+ },
490+ State {
491+ name: "maximizedVertically"; when: appDelegate.maximizedVertically && !appDelegate.minimized
492+ PropertyChanges { target: appDelegate; y: PanelState.panelHeight; requestedHeight: appContainer.height - PanelState.panelHeight }
493+ },
491494 State {
492495 name: "minimized"; when: appDelegate.minimized
493496 PropertyChanges {
494497 target: appDelegate;
495498 x: -appDelegate.width / 2;
496499 scale: units.gu(5) / appDelegate.width;
497− opacity: 0
500+ opacity: 0;
498501 visuallyMinimized: true;
499502 visuallyMaximized: false
500503 }
@@ -599,7 +602,10 @@ AbstractStage {
599602
600603 onClose: { appDelegate.close(); }
601604 onMaximize: appDelegate.maximized || appDelegate.maximizedLeft || appDelegate.maximizedRight
605+ || appDelegate.maximizedHorizontally || appDelegate.maximizedVertically
602606 ? appDelegate.restoreFromMaximized() : appDelegate.maximize()
607+ onMaximizeHorizontally: appDelegate.maximizedHorizontally ? appDelegate.restoreFromMaximized() : appDelegate.maximizeHorizontally()
608+ onMaximizeVertically: appDelegate.maximizedVertically ? appDelegate.restoreFromMaximized() : appDelegate.maximizeVertically()
603609 onMinimize: appDelegate.minimize()
604610 onDecorationPressed: { appDelegate.focus = true; }
605611 }
qml/Stages/WindowDecoration.qml+4
@@ -32,6 +32,8 @@ MouseArea {
3232 signal close()
3333 signal minimize()
3434 signal maximize()
35+ signal maximizeHorizontally()
36+ signal maximizeVertically()
3537
3638 onDoubleClicked: root.maximize()
3739
@@ -87,6 +89,8 @@ MouseArea {
8789 onClose: root.close();
8890 onMinimize: root.minimize();
8991 onMaximize: root.maximize();
92+ onMaximizeHorizontally: root.maximizeHorizontally();
93+ onMaximizeVertically: root.maximizeVertically();
9094 }
9195
9296 Label {
qml/Stages/WindowResizeArea.qml+13−4
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2014-2015 Canonical, Ltd.
2+ * Copyright (C) 2014-2016 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -82,14 +82,23 @@ MouseArea {
8282
8383 var windowState = windowStateStorage.getState(root.windowId, WindowStateStorage.WindowStateNormal)
8484 if (windowState === WindowStateStorage.WindowStateMaximized) {
85− target.maximize(false)
85+ target.maximize(false);
86+ } else if (windowState === WindowStateStorage.WindowStateMaximizedLeft) {
87+ target.maximizeLeft();
88+ } else if (windowState === WindowStateStorage.WindowStateMaximizedRight) {
89+ target.maximizeRight();
90+ } else if (windowState === WindowStateStorage.WindowStateMaximizedHorizontally) {
91+ target.maximizeHorizontally();
92+ } else if (windowState === WindowStateStorage.WindowStateMaximizedVertically) {
93+ target.maximizeVertically();
8694 }
95+
8796 priv.updateNormalGeometry();
8897 }
8998
9099 function saveWindowState() {
91− windowStateStorage.saveState(root.windowId, target.state == "maximized" ? WindowStateStorage.WindowStateMaximized : WindowStateStorage.WindowStateNormal)
92− windowStateStorage.saveGeometry(root.windowId, Qt.rect(priv.normalX, priv.normalY, priv.normalWidth, priv.normalHeight))
100+ windowStateStorage.saveState(root.windowId, target.windowState & ~WindowStateStorage.WindowStateMinimized); // clear the minimized bit when saving
101+ windowStateStorage.saveGeometry(root.windowId, Qt.rect(priv.normalX, priv.normalY, priv.normalWidth, priv.normalHeight));
93102 }
94103
95104 QtObject {
tests/mocks/Utils/windowstatestorage.h+13−2
@@ -25,9 +25,20 @@ class WindowStateStorage: public QObject
2525 Q_ENUMS(WindowState)
2626public:
2727 enum WindowState {
28− WindowStateNormal,
29− WindowStateMaximized
28+ WindowStateNormal = 1 << 0,
29+ WindowStateMaximized = 1 << 1,
30+ WindowStateMinimized = 1 << 2,
31+ WindowStateFullscreen = 1 << 3,
32+ WindowStateMaximizedLeft = 1 << 4,
33+ WindowStateMaximizedRight = 1 << 5,
34+ WindowStateMaximizedHorizontally = 1 << 6,
35+ WindowStateMaximizedVertically = 1 << 7
3036 };
37+ Q_DECLARE_FLAGS(WindowStates, WindowState)
38+#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
39+ Q_FLAG(WindowStates)
40+#endif
41+
3142 WindowStateStorage(QObject *parent = 0);
3243
3344 Q_INVOKABLE void saveState(const QString &windowId, WindowState state);