mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-09-10 12:03:18 +02:00
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
This commit is contained in:
parent
c19fb112bb
commit
3f476205fa
7 changed files with 60 additions and 171 deletions
2
qml.qrc
2
qml.qrc
|
@ -123,7 +123,6 @@
|
||||||
<file>src/mainview/components/VideoCallPageContextMenuDeviceItem.qml</file>
|
<file>src/mainview/components/VideoCallPageContextMenuDeviceItem.qml</file>
|
||||||
<file>src/mainview/components/SelectScreen.qml</file>
|
<file>src/mainview/components/SelectScreen.qml</file>
|
||||||
<file>src/mainview/components/ScreenRubberBand.qml</file>
|
<file>src/mainview/components/ScreenRubberBand.qml</file>
|
||||||
<file>src/mainview/components/VideoCallFullScreenWindowContainer.qml</file>
|
|
||||||
<file>src/mainview/components/ContactPicker.qml</file>
|
<file>src/mainview/components/ContactPicker.qml</file>
|
||||||
<file>src/mainview/components/PluginHandlerPicker.qml</file>
|
<file>src/mainview/components/PluginHandlerPicker.qml</file>
|
||||||
<file>src/mainview/components/ContactPickerItemDelegate.qml</file>
|
<file>src/mainview/components/ContactPickerItemDelegate.qml</file>
|
||||||
|
@ -135,7 +134,6 @@
|
||||||
<file>src/mainview/js/incomingcallpagecreation.js</file>
|
<file>src/mainview/js/incomingcallpagecreation.js</file>
|
||||||
<file>src/mainview/js/selectscreenwindowcreation.js</file>
|
<file>src/mainview/js/selectscreenwindowcreation.js</file>
|
||||||
<file>src/mainview/js/screenrubberbandcreation.js</file>
|
<file>src/mainview/js/screenrubberbandcreation.js</file>
|
||||||
<file>src/mainview/js/callfullscreenwindowcontainercreation.js</file>
|
|
||||||
<file>src/mainview/js/contactpickercreation.js</file>
|
<file>src/mainview/js/contactpickercreation.js</file>
|
||||||
<file>src/mainview/js/pluginhandlerpickercreation.js</file>
|
<file>src/mainview/js/pluginhandlerpickercreation.js</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
|
|
|
@ -39,6 +39,23 @@ import "commoncomponents"
|
||||||
ApplicationWindow {
|
ApplicationWindow {
|
||||||
id: root
|
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 {
|
enum LoadedSource {
|
||||||
WizardView = 0,
|
WizardView = 0,
|
||||||
MainView,
|
MainView,
|
||||||
|
@ -92,8 +109,7 @@ ApplicationWindow {
|
||||||
setY(Screen.height / 2 - height / 2)
|
setY(Screen.height / 2 - height / 2)
|
||||||
|
|
||||||
if (UtilsAdapter.getAccountListSize() !== 0) {
|
if (UtilsAdapter.getAccountListSize() !== 0) {
|
||||||
mainApplicationLoader.setSource(JamiQmlUtils.mainViewLoadPath,
|
mainApplicationLoader.setSource(JamiQmlUtils.mainViewLoadPath)
|
||||||
{"containerWindow": root})
|
|
||||||
} else {
|
} else {
|
||||||
mainApplicationLoader.setSource(JamiQmlUtils.wizardViewLoadPath)
|
mainApplicationLoader.setSource(JamiQmlUtils.wizardViewLoadPath)
|
||||||
}
|
}
|
||||||
|
@ -125,6 +141,7 @@ ApplicationWindow {
|
||||||
id: mainApplicationLoader
|
id: mainApplicationLoader
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
z: -1
|
||||||
|
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
visible: status == Loader.Ready
|
visible: status == Loader.Ready
|
||||||
|
@ -137,8 +154,7 @@ ApplicationWindow {
|
||||||
if (sourceToLoad === MainApplicationWindow.LoadedSource.WizardView)
|
if (sourceToLoad === MainApplicationWindow.LoadedSource.WizardView)
|
||||||
mainApplicationLoader.setSource(JamiQmlUtils.wizardViewLoadPath)
|
mainApplicationLoader.setSource(JamiQmlUtils.wizardViewLoadPath)
|
||||||
else
|
else
|
||||||
mainApplicationLoader.setSource(JamiQmlUtils.mainViewLoadPath,
|
mainApplicationLoader.setSource(JamiQmlUtils.mainViewLoadPath)
|
||||||
{"containerWindow": root})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,15 +175,22 @@ ApplicationWindow {
|
||||||
|
|
||||||
function onRestoreAppRequested() {
|
function onRestoreAppRequested() {
|
||||||
requestActivate()
|
requestActivate()
|
||||||
showNormal()
|
if (isFullScreen)
|
||||||
|
showFullScreen()
|
||||||
|
else
|
||||||
|
showNormal()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onNotificationClicked() {
|
function onNotificationClicked() {
|
||||||
requestActivate()
|
requestActivate()
|
||||||
raise()
|
raise()
|
||||||
if (visibility === Window.Hidden ||
|
if (visibility === Window.Hidden ||
|
||||||
visibility === Window.Minimized)
|
visibility === Window.Minimized) {
|
||||||
showNormal()
|
if (isFullScreen)
|
||||||
|
showFullScreen()
|
||||||
|
else
|
||||||
|
showNormal()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,14 +29,16 @@ Item {
|
||||||
readonly property string base64StringTitle: "data:image/png;base64,"
|
readonly property string base64StringTitle: "data:image/png;base64,"
|
||||||
|
|
||||||
property var mainApplicationScreen: ""
|
property var mainApplicationScreen: ""
|
||||||
|
|
||||||
property bool callIsFullscreen: false
|
property bool callIsFullscreen: false
|
||||||
|
signal fullScreenCallEnded
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: CallAdapter
|
target: CallAdapter
|
||||||
|
|
||||||
function onHasCallChanged() {
|
function onHasCallChanged() {
|
||||||
if (!CallAdapter.hasCall && callIsFullscreen)
|
if (!CallAdapter.hasCall && callIsFullscreen)
|
||||||
callIsFullscreen = false
|
fullScreenCallEnded()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,6 @@ Rectangle {
|
||||||
|
|
||||||
objectName: "mainView"
|
objectName: "mainView"
|
||||||
|
|
||||||
property var containerWindow: ""
|
|
||||||
|
|
||||||
property int sidePanelViewStackMinimumWidth: 300
|
property int sidePanelViewStackMinimumWidth: 300
|
||||||
property int mainViewStackPreferredWidth: 425
|
property int mainViewStackPreferredWidth: 425
|
||||||
property int settingsViewPreferredWidth: 460
|
property int settingsViewPreferredWidth: 460
|
||||||
|
@ -163,8 +161,8 @@ Rectangle {
|
||||||
|
|
||||||
var windowCurrentMinimizedSize = settingsViewPreferredWidth
|
var windowCurrentMinimizedSize = settingsViewPreferredWidth
|
||||||
+ sidePanelViewStackMinimumWidth + onWidthChangedTriggerDistance
|
+ sidePanelViewStackMinimumWidth + onWidthChangedTriggerDistance
|
||||||
if (containerWindow.width < windowCurrentMinimizedSize)
|
if (appWindow.width < windowCurrentMinimizedSize)
|
||||||
containerWindow.width = windowCurrentMinimizedSize
|
appWindow.width = windowCurrentMinimizedSize
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sidePanelViewStack.pop(StackView.Immediate)
|
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 {
|
StackLayout {
|
||||||
id: mainViewStackLayout
|
id: mainViewStackLayout
|
||||||
|
|
||||||
|
@ -614,12 +597,11 @@ Rectangle {
|
||||||
sequence: "F11"
|
sequence: "F11"
|
||||||
context: Qt.ApplicationShortcut
|
context: Qt.ApplicationShortcut
|
||||||
onActivated: {
|
onActivated: {
|
||||||
|
// Don't toggle fullscreen mode when we're already
|
||||||
|
// in a fullscreen call.
|
||||||
if (JamiQmlUtils.callIsFullscreen)
|
if (JamiQmlUtils.callIsFullscreen)
|
||||||
return
|
return
|
||||||
if (containerWindow.visibility !== Window.FullScreen)
|
appWindow.toggleFullScreen()
|
||||||
containerWindow.visibility = Window.FullScreen
|
|
||||||
else
|
|
||||||
containerWindow.visibility = Window.Windowed
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,6 +633,8 @@ Rectangle {
|
||||||
onActivated: {
|
onActivated: {
|
||||||
if (JamiQmlUtils.callIsFullscreen)
|
if (JamiQmlUtils.callIsFullscreen)
|
||||||
callStackView.toggleFullScreen()
|
callStackView.toggleFullScreen()
|
||||||
|
else if (appWindow.isFullScreen)
|
||||||
|
appWindow.toggleFullScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ import net.jami.Models 1.0
|
||||||
import net.jami.Adapters 1.0
|
import net.jami.Adapters 1.0
|
||||||
|
|
||||||
import "../js/incomingcallpagecreation.js" as IncomingCallPageCreation
|
import "../js/incomingcallpagecreation.js" as IncomingCallPageCreation
|
||||||
import "../js/callfullscreenwindowcontainercreation.js" as CallFullScreenWindowContainerCreation
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: callStackViewWindow
|
id: callStackViewWindow
|
||||||
|
@ -57,11 +56,9 @@ Rectangle {
|
||||||
return
|
return
|
||||||
if (callStackMainView.currentItem.stackNumber === CallStackView.AudioPageStack) {
|
if (callStackMainView.currentItem.stackNumber === CallStackView.AudioPageStack) {
|
||||||
audioCallPage.closeInCallConversation()
|
audioCallPage.closeInCallConversation()
|
||||||
CallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer()
|
|
||||||
audioCallPage.closeContextMenuAndRelatedWindows()
|
audioCallPage.closeContextMenuAndRelatedWindows()
|
||||||
} else if (callStackMainView.currentItem.stackNumber === CallStackView.VideoPageStack) {
|
} else if (callStackMainView.currentItem.stackNumber === CallStackView.VideoPageStack) {
|
||||||
videoCallPage.closeInCallConversation()
|
videoCallPage.closeInCallConversation()
|
||||||
CallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer()
|
|
||||||
videoCallPage.closeContextMenuAndRelatedWindows()
|
videoCallPage.closeContextMenuAndRelatedWindows()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,25 +121,36 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleFullScreen() {
|
function toggleFullScreen() {
|
||||||
JamiQmlUtils.callIsFullscreen = !JamiQmlUtils.callIsFullscreen
|
|
||||||
var callPage = callStackMainView.currentItem
|
var callPage = callStackMainView.currentItem
|
||||||
if (!callPage)
|
if (!callPage)
|
||||||
return
|
return
|
||||||
CallFullScreenWindowContainerCreation.createvideoCallFullScreenWindowContainerObject()
|
|
||||||
|
|
||||||
if (!CallFullScreenWindowContainerCreation.checkIfVisible()) {
|
// manual toggle here because of our fake fullscreen mode (F11)
|
||||||
CallFullScreenWindowContainerCreation.setAsContainerChild(callPage)
|
// TODO: handle and save window states, not just a boolean isFullScreen
|
||||||
CallFullScreenWindowContainerCreation.showVideoCallFullScreenWindowContainer()
|
if (!appWindow.isFullScreen && !JamiQmlUtils.callIsFullscreen)
|
||||||
} else {
|
appWindow.isFullScreen = true
|
||||||
callPage.parent = callStackMainView
|
else if (JamiQmlUtils.callIsFullscreen)
|
||||||
CallFullScreenWindowContainerCreation.closeVideoCallFullScreenWindowContainer()
|
appWindow.isFullScreen = false
|
||||||
}
|
|
||||||
|
|
||||||
|
JamiQmlUtils.callIsFullscreen = !JamiQmlUtils.callIsFullscreen
|
||||||
|
callPage.parent = JamiQmlUtils.callIsFullscreen ?
|
||||||
|
appContainer :
|
||||||
|
callStackMainView
|
||||||
if (callPage.stackNumber === CallStackView.VideoPageStack) {
|
if (callPage.stackNumber === CallStackView.VideoPageStack) {
|
||||||
videoCallPage.handleParticipantsInfo(CallAdapter.getConferencesInfos())
|
videoCallPage.handleParticipantsInfo(CallAdapter.getConferencesInfos())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: JamiQmlUtils
|
||||||
|
|
||||||
|
function onFullScreenCallEnded() {
|
||||||
|
if (appWindow.isFullScreen) {
|
||||||
|
toggleFullScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: CallAdapter
|
target: CallAdapter
|
||||||
|
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 by Savoir-faire Linux
|
|
||||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
|
||||||
*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 by Savoir-faire Linux
|
|
||||||
* Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
|
|
||||||
*
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 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()
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue