From 3f476205fa5fb096f39424d9d8c1fa35f58beb7d Mon Sep 17 00:00:00 2001 From: Andreas Traczyk Date: Tue, 13 Apr 2021 20:11:47 -0400 Subject: [PATCH] misc: change application fullscreen mechanism Use a simpler fullscreen mechanism that maintains the primary application window as a fullscreen container for the call view. GitLab: #339 Change-Id: Ib67ac4798c77117aea0830eece485e229680684d --- qml.qrc | 2 - src/MainApplicationWindow.qml | 37 +++++++-- src/constant/JamiQmlUtils.qml | 4 +- src/mainview/MainView.qml | 30 ++----- src/mainview/components/CallStackView.qml | 32 +++++--- .../VideoCallFullScreenWindowContainer.qml | 46 ----------- .../callfullscreenwindowcontainercreation.js | 80 ------------------- 7 files changed, 60 insertions(+), 171 deletions(-) delete mode 100644 src/mainview/components/VideoCallFullScreenWindowContainer.qml delete mode 100644 src/mainview/js/callfullscreenwindowcontainercreation.js diff --git a/qml.qrc b/qml.qrc index 1f5a159b..3b8d6be2 100644 --- a/qml.qrc +++ b/qml.qrc @@ -123,7 +123,6 @@ src/mainview/components/VideoCallPageContextMenuDeviceItem.qml src/mainview/components/SelectScreen.qml src/mainview/components/ScreenRubberBand.qml - src/mainview/components/VideoCallFullScreenWindowContainer.qml src/mainview/components/ContactPicker.qml src/mainview/components/PluginHandlerPicker.qml src/mainview/components/ContactPickerItemDelegate.qml @@ -135,7 +134,6 @@ src/mainview/js/incomingcallpagecreation.js src/mainview/js/selectscreenwindowcreation.js src/mainview/js/screenrubberbandcreation.js - src/mainview/js/callfullscreenwindowcontainercreation.js src/mainview/js/contactpickercreation.js src/mainview/js/pluginhandlerpickercreation.js diff --git a/src/MainApplicationWindow.qml b/src/MainApplicationWindow.qml index 9d89dd46..1cfd2b52 100644 --- a/src/MainApplicationWindow.qml +++ b/src/MainApplicationWindow.qml @@ -39,6 +39,23 @@ import "commoncomponents" ApplicationWindow { id: root + property ApplicationWindow appWindow : root + + // To facilitate reparenting of the callview during + // fullscreen mode, we need QQuickItem based object. + Item { + id: appContainer + anchors.fill: parent + } + property bool isFullScreen: false + visibility: !visible ? + Window.Hidden : (isFullScreen ? + Window.FullScreen : + Window.Windowed) + function toggleFullScreen() { + isFullScreen = !isFullScreen + } + enum LoadedSource { WizardView = 0, MainView, @@ -92,8 +109,7 @@ ApplicationWindow { setY(Screen.height / 2 - height / 2) if (UtilsAdapter.getAccountListSize() !== 0) { - mainApplicationLoader.setSource(JamiQmlUtils.mainViewLoadPath, - {"containerWindow": root}) + mainApplicationLoader.setSource(JamiQmlUtils.mainViewLoadPath) } else { mainApplicationLoader.setSource(JamiQmlUtils.wizardViewLoadPath) } @@ -125,6 +141,7 @@ ApplicationWindow { id: mainApplicationLoader anchors.fill: parent + z: -1 asynchronous: true visible: status == Loader.Ready @@ -137,8 +154,7 @@ ApplicationWindow { if (sourceToLoad === MainApplicationWindow.LoadedSource.WizardView) mainApplicationLoader.setSource(JamiQmlUtils.wizardViewLoadPath) else - mainApplicationLoader.setSource(JamiQmlUtils.mainViewLoadPath, - {"containerWindow": root}) + mainApplicationLoader.setSource(JamiQmlUtils.mainViewLoadPath) } } } @@ -159,15 +175,22 @@ ApplicationWindow { function onRestoreAppRequested() { requestActivate() - showNormal() + if (isFullScreen) + showFullScreen() + else + showNormal() } function onNotificationClicked() { requestActivate() raise() if (visibility === Window.Hidden || - visibility === Window.Minimized) - showNormal() + visibility === Window.Minimized) { + if (isFullScreen) + showFullScreen() + else + showNormal() + } } } diff --git a/src/constant/JamiQmlUtils.qml b/src/constant/JamiQmlUtils.qml index 9bb10775..9cacecaa 100644 --- a/src/constant/JamiQmlUtils.qml +++ b/src/constant/JamiQmlUtils.qml @@ -29,14 +29,16 @@ Item { readonly property string base64StringTitle: "data:image/png;base64," property var mainApplicationScreen: "" + property bool callIsFullscreen: false + signal fullScreenCallEnded Connections { target: CallAdapter function onHasCallChanged() { if (!CallAdapter.hasCall && callIsFullscreen) - callIsFullscreen = false + fullScreenCallEnded() } } diff --git a/src/mainview/MainView.qml b/src/mainview/MainView.qml index 9e2d63f2..635b099d 100644 --- a/src/mainview/MainView.qml +++ b/src/mainview/MainView.qml @@ -39,8 +39,6 @@ Rectangle { objectName: "mainView" - property var containerWindow: "" - property int sidePanelViewStackMinimumWidth: 300 property int mainViewStackPreferredWidth: 425 property int settingsViewPreferredWidth: 460 @@ -163,8 +161,8 @@ Rectangle { var windowCurrentMinimizedSize = settingsViewPreferredWidth + sidePanelViewStackMinimumWidth + onWidthChangedTriggerDistance - if (containerWindow.width < windowCurrentMinimizedSize) - containerWindow.width = windowCurrentMinimizedSize + if (appWindow.width < windowCurrentMinimizedSize) + appWindow.width = windowCurrentMinimizedSize } } else { sidePanelViewStack.pop(StackView.Immediate) @@ -243,21 +241,6 @@ Rectangle { } } - Connections { - target: JamiQmlUtils - - // TODO: call in fullscreen inside containerWindow - function onCallIsFullscreenChanged() { - if (JamiQmlUtils.callIsFullscreen) { - UtilsAdapter.setSystemTrayIconVisible(false) - containerWindow.hide() - } else { - UtilsAdapter.setSystemTrayIconVisible(true) - containerWindow.show() - } - } - } - StackLayout { id: mainViewStackLayout @@ -614,12 +597,11 @@ Rectangle { sequence: "F11" context: Qt.ApplicationShortcut onActivated: { + // Don't toggle fullscreen mode when we're already + // in a fullscreen call. if (JamiQmlUtils.callIsFullscreen) return - if (containerWindow.visibility !== Window.FullScreen) - containerWindow.visibility = Window.FullScreen - else - containerWindow.visibility = Window.Windowed + appWindow.toggleFullScreen() } } @@ -651,6 +633,8 @@ Rectangle { onActivated: { if (JamiQmlUtils.callIsFullscreen) callStackView.toggleFullScreen() + else if (appWindow.isFullScreen) + appWindow.toggleFullScreen() } } diff --git a/src/mainview/components/CallStackView.qml b/src/mainview/components/CallStackView.qml index 418816c8..31d7816f 100644 --- a/src/mainview/components/CallStackView.qml +++ b/src/mainview/components/CallStackView.qml @@ -25,7 +25,6 @@ import net.jami.Models 1.0 import net.jami.Adapters 1.0 import "../js/incomingcallpagecreation.js" as IncomingCallPageCreation -import "../js/callfullscreenwindowcontainercreation.js" as CallFullScreenWindowContainerCreation Rectangle { id: callStackViewWindow @@ -57,11 +56,9 @@ Rectangle { return if (callStackMainView.currentItem.stackNumber === CallStackView.AudioPageStack) { audioCallPage.closeInCallConversation() - CallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer() audioCallPage.closeContextMenuAndRelatedWindows() } else if (callStackMainView.currentItem.stackNumber === CallStackView.VideoPageStack) { videoCallPage.closeInCallConversation() - CallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer() videoCallPage.closeContextMenuAndRelatedWindows() } } @@ -124,25 +121,36 @@ Rectangle { } function toggleFullScreen() { - JamiQmlUtils.callIsFullscreen = !JamiQmlUtils.callIsFullscreen var callPage = callStackMainView.currentItem if (!callPage) return - CallFullScreenWindowContainerCreation.createvideoCallFullScreenWindowContainerObject() - if (!CallFullScreenWindowContainerCreation.checkIfVisible()) { - CallFullScreenWindowContainerCreation.setAsContainerChild(callPage) - CallFullScreenWindowContainerCreation.showVideoCallFullScreenWindowContainer() - } else { - callPage.parent = callStackMainView - CallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer() - } + // manual toggle here because of our fake fullscreen mode (F11) + // TODO: handle and save window states, not just a boolean isFullScreen + if (!appWindow.isFullScreen && !JamiQmlUtils.callIsFullscreen) + appWindow.isFullScreen = true + else if (JamiQmlUtils.callIsFullscreen) + appWindow.isFullScreen = false + JamiQmlUtils.callIsFullscreen = !JamiQmlUtils.callIsFullscreen + callPage.parent = JamiQmlUtils.callIsFullscreen ? + appContainer : + callStackMainView if (callPage.stackNumber === CallStackView.VideoPageStack) { videoCallPage.handleParticipantsInfo(CallAdapter.getConferencesInfos()) } } + Connections { + target: JamiQmlUtils + + function onFullScreenCallEnded() { + if (appWindow.isFullScreen) { + toggleFullScreen() + } + } + } + Connections { target: CallAdapter diff --git a/src/mainview/components/VideoCallFullScreenWindowContainer.qml b/src/mainview/components/VideoCallFullScreenWindowContainer.qml deleted file mode 100644 index cae72835..00000000 --- a/src/mainview/components/VideoCallFullScreenWindowContainer.qml +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Mingrui Zhang - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import QtQuick 2.14 -import QtQuick.Window 2.14 - -import net.jami.Models 1.0 - -Window { - id: videoWindow - - function setAsChild(obj) { - obj.parent = containerRect - } - - flags: Qt.FramelessWindowHint - - screen: JamiQmlUtils.mainApplicationScreen - - // +1 so that it does not fallback to the previous screen - x: screen.virtualX + 1 - y: screen.virtualY + 1 - - visible: false - - Rectangle { - id: containerRect - - anchors.fill: parent - } -} diff --git a/src/mainview/js/callfullscreenwindowcontainercreation.js b/src/mainview/js/callfullscreenwindowcontainercreation.js deleted file mode 100644 index 2ce42c14..00000000 --- a/src/mainview/js/callfullscreenwindowcontainercreation.js +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Mingrui Zhang - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// Global call full screen window container, object variable for creation. -var callFullScreenWindowContainerComponent -var callFullScreenWindowContainerObject - -function createvideoCallFullScreenWindowContainerObject() { - if (callFullScreenWindowContainerObject) - return - callFullScreenWindowContainerComponent = Qt.createComponent( - "../components/VideoCallFullScreenWindowContainer.qml") - if (callFullScreenWindowContainerComponent.status === Component.Ready) - finishCreation() - else if (callFullScreenWindowContainerComponent.status === Component.Error) - console.log("Error loading component:", - callFullScreenWindowContainerComponent.errorString()) -} - -function finishCreation() { - callFullScreenWindowContainerObject - = callFullScreenWindowContainerComponent.createObject() - if (callFullScreenWindowContainerObject === null) { - // Error Handling. - console.log("Error creating video call full screen window container object") - } - - // Signal connection. - callFullScreenWindowContainerObject.onClosing.connect( - destroyVideoCallFullScreenWindowContainer) -} - -function checkIfVisible() { - if (!callFullScreenWindowContainerObject) - return false - return callFullScreenWindowContainerObject.visible -} - -function setAsContainerChild(obj) { - if (callFullScreenWindowContainerObject) - callFullScreenWindowContainerObject.setAsChild(obj) -} - -// Destroy and reset callFullScreenWindowContainerObject when window is closed. -function destroyVideoCallFullScreenWindowContainer() { - if (!callFullScreenWindowContainerObject) - return - callFullScreenWindowContainerObject.destroy() - callFullScreenWindowContainerObject = false -} - -function showVideoCallFullScreenWindowContainer() { - if (callFullScreenWindowContainerObject) { - - // Hack: show first, then showFullScreen to make sure that the showFullScreen - // display on the correct screen. - callFullScreenWindowContainerObject.show() - callFullScreenWindowContainerObject.showFullScreen() - } -} - -function closeVideoCallFullScreenWindowContainer() { - if (callFullScreenWindowContainerObject) - callFullScreenWindowContainerObject.close() -}