2 * Copyright (C) 2013-2017 Canonical, Ltd.
3 * Copyright (C) 2020 UBports Foundation
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 3.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 import Ubuntu.Components 1.3
20 import Ubuntu.Layouts 1.0
21 import Unity.Application 0.1
22 import Unity.Indicators 0.1
24 import Unity.ApplicationMenu 0.1
26 import QtQuick.Window 2.2
28 import "../ApplicationMenus"
29 import "../Components"
30 import "../Components/PanelState"
36 readonly property real panelHeight: panelArea.y + minimizedPanelHeight
37 readonly property bool fullyClosed: indicators.fullyClosed && applicationMenus.fullyClosed
39 property real minimizedPanelHeight: units.gu(3)
40 property real expandedPanelHeight: units.gu(7)
41 property real menuWidth: partialWidth ? units.gu(40) : width
42 property alias applicationMenuContentX: __applicationMenus.menuContentX
44 property alias applicationMenus: __applicationMenus
45 property alias indicators: __indicators
46 property bool fullscreenMode: false
47 property real panelAreaShowProgress: 1.0
48 property bool greeterShown: false
49 property bool hasKeyboard: false
50 property bool supportsMultiColorLed: true
52 // Whether our expanded menus should take up the full width of the panel
53 property bool partialWidth: width >= units.gu(60)
55 property string mode: "staged"
60 anchors.topMargin: panelHeight
61 visible: !indicators.fullyClosed || !applicationMenus.fullyClosed
63 hoverEnabled: true // should also eat hover events, otherwise they will pass through
66 __applicationMenus.hide();
73 property: "panelHeight"
74 value: minimizedPanelHeight
77 RegisteredApplicationMenuModel {
78 id: registeredMenuModel
79 persistentSurfaceId: PanelState.focusedPersistentSurfaceId
85 property bool revealControls: !greeterShown &&
86 !applicationMenus.shown &&
88 (decorationMouseArea.containsMouse || menuBarLoader.menusRequested)
90 property bool showWindowDecorationControls: (revealControls && PanelState.decorationsVisible) ||
91 PanelState.decorationsAlwaysVisible
93 property bool showPointerMenu: revealControls && enablePointerMenu &&
94 (PanelState.decorationsVisible || mode == "windowed")
96 property bool enablePointerMenu: applicationMenus.available &&
97 applicationMenus.model
99 property bool showTouchMenu: !greeterShown &&
101 !showWindowDecorationControls
103 property bool enableTouchMenus: showTouchMenu &&
104 applicationMenus.available &&
105 applicationMenus.model
110 objectName: "panelArea"
114 transform: Translate {
115 y: indicators.state === "initial"
116 ? (1.0 - panelAreaShowProgress) * - minimizedPanelHeight
121 id: indicatorsDropShadow
124 margins: -units.gu(1)
126 visible: !__indicators.fullyClosed
127 source: "graphics/rectangular_dropshadow.sci"
131 id: appmenuDropShadow
133 fill: __applicationMenus
134 margins: -units.gu(1)
136 visible: !__applicationMenus.fullyClosed
137 source: "graphics/rectangular_dropshadow.sci"
143 fill: panelAreaBackground
144 bottomMargin: -units.gu(1)
146 visible: PanelState.dropShadow
147 source: "graphics/rectangular_dropshadow.sci"
151 id: panelAreaBackground
152 color: callHint.visible ? theme.palette.normal.activity : theme.palette.normal.background
158 height: minimizedPanelHeight
160 Behavior on color { ColorAnimation { duration: UbuntuAnimation.FastDuration } }
164 id: decorationMouseArea
165 objectName: "windowControlArea"
170 height: minimizedPanelHeight
171 hoverEnabled: !__indicators.shown
173 if (callHint.visible) {
174 callHint.showLiveCall();
179 if (!callHint.visible) {
180 // let it fall through to the window decoration of the maximized window behind, if any
181 mouse.accepted = false;
183 var menubar = menuBarLoader.item;
185 menubar.invokeMenu(mouse);
193 // WindowControlButtons inside the mouse area, otherwise QML doesn't grok nested hover events :/
194 // cf. https://bugreports.qt.io/browse/QTBUG-32909
195 WindowControlButtons {
196 id: windowControlButtons
197 objectName: "panelWindowControlButtons"
198 height: indicators.minimizedPanelHeight
199 opacity: d.showWindowDecorationControls ? 1 : 0
200 visible: opacity != 0
201 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
203 active: PanelState.decorationsVisible || PanelState.decorationsAlwaysVisible
204 windowIsMaximized: true
205 onCloseClicked: PanelState.closeClicked()
206 onMinimizeClicked: PanelState.minimizeClicked()
207 onMaximizeClicked: PanelState.restoreClicked()
208 closeButtonShown: PanelState.closeButtonShown
213 objectName: "menuBarLoader"
214 height: parent.height
215 enabled: d.enablePointerMenu
216 opacity: d.showPointerMenu ? 1 : 0
217 visible: opacity != 0
218 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
219 active: d.showPointerMenu && !callHint.visible
221 width: parent.width - windowControlButtons.width - units.gu(2) - __indicators.barWidth
223 readonly property bool menusRequested: menuBarLoader.item ? menuBarLoader.item.showRequested : false
225 sourceComponent: MenuBar {
227 objectName: "menuBar"
228 anchors.left: parent ? parent.left : undefined
229 anchors.margins: units.gu(1)
230 height: menuBarLoader.height
231 enableKeyFilter: valid && PanelState.decorationsVisible
232 unityMenuModel: __applicationMenus.model
235 target: __applicationMenus
236 onShownChanged: bar.dismiss();
241 onShownChanged: bar.dismiss();
244 onDoubleClicked: PanelState.restoreClicked()
245 onPressed: mouse.accepted = false // let the parent mouse area handle this, so it can both unsnap window and show menu
252 objectName: "callHint"
254 anchors.centerIn: parent
255 height: minimizedPanelHeight
257 visible: active && indicators.state == "initial" && __applicationMenus.state == "initial"
258 greeterShown: root.greeterShown
263 id: __applicationMenus
266 model: registeredMenuModel.model
267 width: root.menuWidth
269 minimizedPanelHeight: root.minimizedPanelHeight
270 expandedPanelHeight: root.expandedPanelHeight
271 openedHeight: root.height
272 alignment: Qt.AlignLeft
273 enableHint: !callHint.active && !fullscreenMode
275 panelColor: panelAreaBackground.color
278 if (callHint.active) {
279 callHint.showLiveCall();
284 rowItemDelegate: ActionItem {
286 property int ownIndex: index
287 objectName: "appMenuItem"+index
288 enabled: model.sensitive
290 width: _title.width + units.gu(2)
291 height: parent.height
294 text: model.label.replace("_", "&")
299 anchors.centerIn: parent
300 text: actionItem.text
301 horizontalAlignment: Text.AlignLeft
302 color: enabled ? theme.palette.normal.backgroundText : theme.palette.disabled.backgroundText
306 pageDelegate: PanelMenuPage {
307 readonly property bool isCurrent: modelIndex == __applicationMenus.currentMenuIndex
308 onIsCurrentChanged: {
309 if (isCurrent && menuModel) {
310 menuModel.aboutToShow(modelIndex);
314 menuModel: __applicationMenus.model
315 submenuIndex: modelIndex
317 factory: ApplicationMenuItemFactory {
318 rootModel: __applicationMenus.model
322 enabled: d.enableTouchMenus
323 opacity: d.showTouchMenu ? 1 : 0
324 visible: opacity != 0
325 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
328 if (!enabled) hide();
336 leftMargin: units.gu(1)
337 right: __indicators.left
338 rightMargin: units.gu(1)
340 height: root.minimizedPanelHeight
346 right: root.partialWidth ? parent.right : parent.left
347 rightMargin: touchMenuIcon.width
349 objectName: "panelTitle"
350 height: root.minimizedPanelHeight
351 verticalAlignment: Text.AlignVCenter
352 elide: Text.ElideRight
355 font.weight: Font.Medium
356 color: theme.palette.selected.backgroundText
357 text: (root.partialWidth && !callHint.visible) ? PanelState.title : ""
358 opacity: __applicationMenus.visible && !__applicationMenus.expanded
359 Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.SnapDuration } }
360 visible: opacity !== 0
365 objectName: "touchMenuIcon"
368 leftMargin: rowLabel.contentWidth + units.dp(2)
369 verticalCenter: parent.verticalCenter
374 color: theme.palette.normal.backgroundText
375 opacity: !__applicationMenus.expanded && d.enableTouchMenus && !callHint.visible
376 Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.SnapDuration } }
377 visible: opacity !== 0
383 objectName: "indicators"
389 width: root.menuWidth
390 minimizedPanelHeight: root.minimizedPanelHeight
391 expandedPanelHeight: root.expandedPanelHeight
392 openedHeight: root.height
394 overFlowWidth: width - appMenuClear
395 enableHint: !callHint.active && !fullscreenMode
396 showOnClick: !callHint.visible
397 panelColor: panelAreaBackground.color
399 // On small screens, the Indicators' handle area is the entire top
400 // bar unless there is an application menu. In that case, our handle
401 // needs to allow for some room to clear the application menu.
402 property var appMenuClear: (d.enableTouchMenus && !partialWidth) ? units.gu(7) : 0
405 if (callHint.active) {
406 callHint.showLiveCall();
410 rowItemDelegate: IndicatorItem {
412 objectName: identifier+"-panelItem"
414 property int ownIndex: index
415 readonly property bool overflow: parent.width - (x - __indicators.rowContentX) > __indicators.overFlowWidth
416 readonly property bool hidden: !expanded && (overflow || !indicatorVisible || hideSessionIndicator || hideKeyboardIndicator)
417 // HACK for indicator-session
418 readonly property bool hideSessionIndicator: identifier == "indicator-session" && Math.min(Screen.width, Screen.height) <= units.gu(60)
419 // HACK for indicator-keyboard
420 readonly property bool hideKeyboardIndicator: identifier == "indicator-keyboard" && !hasKeyboard
422 height: parent.height
423 expanded: indicators.expanded
424 selected: ListView.isCurrentItem
426 identifier: model.identifier
427 busName: indicatorProperties.busName
428 actionsObjectPath: indicatorProperties.actionsObjectPath
429 menuObjectPath: indicatorProperties.menuObjectPath
431 opacity: hidden ? 0.0 : 1.0
432 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
434 width: ((expanded || indicatorVisible) && !hideSessionIndicator && !hideKeyboardIndicator) ? implicitWidth : 0
436 Behavior on width { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
439 pageDelegate: PanelMenuPage {
440 objectName: modelData.identifier + "-page"
443 menuModel: delegate.menuModel
445 factory: IndicatorMenuItemFactory {
447 var context = modelData.identifier;
448 if (context && context.indexOf("fake-") === 0) {
449 context = context.substring("fake-".length)
453 rootModel: delegate.menuModel
458 busName: modelData.indicatorProperties.busName
459 actionsObjectPath: modelData.indicatorProperties.actionsObjectPath
460 menuObjectPath: modelData.indicatorProperties.menuObjectPath
464 enabled: !applicationMenus.expanded
465 opacity: !callHint.visible && !applicationMenus.expanded ? 1 : 0
466 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
469 if (!enabled) hide();
476 supportsMultiColorLed: root.supportsMultiColorLed
481 name: "onscreen" //fully opaque and visible at top edge of screen
482 when: !fullscreenMode
490 name: "offscreen" //pushed off screen
495 if (indicators.state !== "initial") return 0;
496 if (applicationMenus.state !== "initial") return 0;
497 return -minimizedPanelHeight;
499 opacity: indicators.fullyClosed && applicationMenus.fullyClosed ? 0.0 : 1.0
502 target: indicators.showDragHandle;
503 anchors.bottomMargin: -units.gu(1)
506 target: applicationMenus.showDragHandle;
507 anchors.bottomMargin: -units.gu(1)
515 UbuntuNumberAnimation { target: panelArea; properties: "anchors.topMargin,opacity" }
519 UbuntuNumberAnimation { target: panelArea; properties: "anchors.topMargin,opacity" }