From a4809bbde5c2aae6a57e7c925c40bdd886aa3431 Mon Sep 17 00:00:00 2001 From: "gaelle.braud" Date: Mon, 3 Feb 2025 14:39:06 +0100 Subject: [PATCH] fix #LINQT-1641 main window steals focus on macos --- Linphone/core/App.cpp | 11 +- Linphone/core/App.hpp | 4 + Linphone/tool/Utils.cpp | 8 + Linphone/tool/Utils.hpp | 2 + Linphone/view/Page/Window/AbstractWindow.qml | 510 ++++++++++--------- 5 files changed, 280 insertions(+), 255 deletions(-) diff --git a/Linphone/core/App.cpp b/Linphone/core/App.cpp index 622c2c258..fa27c6d59 100644 --- a/Linphone/core/App.cpp +++ b/Linphone/core/App.cpp @@ -866,6 +866,15 @@ void App::setMainWindow(QQuickWindow *data) { } } +QQuickWindow *App::getLastActiveWindow() const { + return mLastActiveWindow; +} +void App::setLastActiveWindow(QQuickWindow *data) { + if (mLastActiveWindow != data) { + mLastActiveWindow = data; + } +} + QSharedPointer App::getAccountList() const { return mAccountList; } @@ -1059,7 +1068,7 @@ bool App::event(QEvent *event) { receivedMessage(0, url.toLocal8Bit()); } else if (event->type() == QEvent::ApplicationStateChange) { auto state = static_cast(event); - if (state->applicationState() == Qt::ApplicationActive) Utils::smartShowWindow(getMainWindow()); + if (state->applicationState() == Qt::ApplicationActive) Utils::smartShowWindow(getLastActiveWindow()); } return SingleApplication::event(event); diff --git a/Linphone/core/App.hpp b/Linphone/core/App.hpp index 0b9ccd8ef..4375f28bd 100644 --- a/Linphone/core/App.hpp +++ b/Linphone/core/App.hpp @@ -131,6 +131,9 @@ public: QQuickWindow *getMainWindow() const; void setMainWindow(QQuickWindow *data); + QQuickWindow *getLastActiveWindow() const; + void setLastActiveWindow(QQuickWindow *data); + QSharedPointer getAccountList() const; void setAccountList(QSharedPointer data); Q_INVOKABLE AccountList *getAccounts() const; @@ -182,6 +185,7 @@ private: QSystemTrayIcon *mSystemTrayIcon = nullptr; QQuickWindow *mMainWindow = nullptr; QQuickWindow *mCallsWindow = nullptr; + QQuickWindow *mLastActiveWindow = nullptr; QSharedPointer mSettings; QSharedPointer mAccountList; QSharedPointer mCallList; diff --git a/Linphone/tool/Utils.cpp b/Linphone/tool/Utils.cpp index 347a4603a..72e91a8b0 100644 --- a/Linphone/tool/Utils.cpp +++ b/Linphone/tool/Utils.cpp @@ -212,6 +212,13 @@ QQuickWindow *Utils::getMainWindow() { return win; } +QQuickWindow *Utils::getLastActiveWindow() { + return App::getInstance()->getLastActiveWindow(); +} +void Utils::setLastActiveWindow(QQuickWindow *data) { + App::getInstance()->setLastActiveWindow(data); +} + void Utils::showInformationPopup(const QString &title, const QString &description, bool isSuccess, @@ -239,6 +246,7 @@ void Utils::smartShowWindow(QQuickWindow *window) { if (window->visibility() == QWindow::Maximized) // Avoid to change visibility mode window->showNormal(); else window->show(); + App::getInstance()->setLastActiveWindow(window); window->raise(); // Raise ensure to get focus on Mac window->requestActivate(); } diff --git a/Linphone/tool/Utils.hpp b/Linphone/tool/Utils.hpp index 2fbd3a778..74470c59a 100644 --- a/Linphone/tool/Utils.hpp +++ b/Linphone/tool/Utils.hpp @@ -75,6 +75,8 @@ public: Q_INVOKABLE static void setupConference(ConferenceInfoGui *confGui); Q_INVOKABLE static QQuickWindow *getMainWindow(); Q_INVOKABLE static void openCallsWindow(CallGui *call); + Q_INVOKABLE static QQuickWindow *getLastActiveWindow(); + Q_INVOKABLE static void setLastActiveWindow(QQuickWindow *data); Q_INVOKABLE static void showInformationPopup(const QString &title, const QString &description, bool isSuccess = true, diff --git a/Linphone/view/Page/Window/AbstractWindow.qml b/Linphone/view/Page/Window/AbstractWindow.qml index e8fcb3193..3bc6cfd77 100644 --- a/Linphone/view/Page/Window/AbstractWindow.qml +++ b/Linphone/view/Page/Window/AbstractWindow.qml @@ -9,269 +9,271 @@ import DesktopToolsCpp import 'qrc:/qt/qml/Linphone/view/Style/buttonStyle.js' as ButtonStyle ApplicationWindow { - id: mainWindow - x: 0 - y: 0 - width: Math.min(1512 * DefaultStyle.dp, Screen.desktopAvailableWidth) - height: Math.min(982 * DefaultStyle.dp, Screen.desktopAvailableHeight) - - property bool isFullscreen: visibility == Window.FullScreen - onIsFullscreenChanged: DesktopToolsCpp.screenSaverStatus = !isFullscreen - + id: mainWindow + x: 0 + y: 0 + width: Math.min(1512 * DefaultStyle.dp, Screen.desktopAvailableWidth) + height: Math.min(982 * DefaultStyle.dp, Screen.desktopAvailableHeight) - MouseArea { - anchors.fill: parent - onClicked: mainWindow.contentItem.forceActiveFocus() - } + onActiveChanged: UtilsCpp.setLastActiveWindow(this) - Component { - id: popupComp - InformationPopup{} - } + property bool isFullscreen: visibility == Window.FullScreen + onIsFullscreenChanged: DesktopToolsCpp.screenSaverStatus = !isFullscreen - Component{ - id: confirmPopupComp - Dialog { - property var requestDialog - property int index - property var callback: requestDialog?.result - signal closePopup(int index) - onClosed: closePopup(index) - text: requestDialog?.message - details: requestDialog?.details - firstButtonAccept: title.length === 0 - secondButtonAccept: title.length !== 0 - Component.onCompleted: if (details.length != 0) radius = 0 - // For C++, requestDialog need to be call directly - onAccepted: requestDialog ? requestDialog.result(1) : callback(1) - onRejected: requestDialog ? requestDialog.result(0) : callback(0) - width: title.length === 0 ? 278 * DefaultStyle.dp : 637 * DefaultStyle.dp - } - } - Popup { - id: startCallPopup - property FriendGui contact - property bool videoEnabled - // if currentCall, transfer call to contact - property CallGui currentCall - onContactChanged: { - console.log("contact changed", contact) - } - underlineColor: DefaultStyle.main1_500_main - anchors.centerIn: parent - width: 370 * DefaultStyle.dp - modal: true - leftPadding: 15 * DefaultStyle.dp - rightPadding: 15 * DefaultStyle.dp - topPadding: 20 * DefaultStyle.dp - bottomPadding: 25 * DefaultStyle.dp - contentItem: ColumnLayout { - spacing: 16 * DefaultStyle.dp - RowLayout { - spacing: 5 * DefaultStyle.dp - width: startCallPopup.width - Text { - text: qsTr("Quelle addresse souhaitez-vous appeler ?") - wrapMode: Text.Wrap - Layout.fillWidth: true - font { - pixelSize: 16 * DefaultStyle.dp - weight: 800 * DefaultStyle.dp - } - } - RoundButton { - Layout.alignment: Qt.AlignVCenter - style: ButtonStyle.noBackground - Layout.preferredWidth: 24 * DefaultStyle.dp - Layout.preferredHeight: 24 * DefaultStyle.dp - icon.source:AppIcons.closeX - onClicked: startCallPopup.close() - } - } - ListView { - id: popuplist - model: VariantList { - model: startCallPopup.contact && startCallPopup.contact.core.allAddresses || [] - } - Layout.fillWidth: true - Layout.preferredHeight: contentHeight - spacing: 10 * DefaultStyle.dp - delegate: Item { - width: popuplist.width - height: 56 * DefaultStyle.dp - ColumnLayout { - width: popuplist.width - anchors.verticalCenter: parent.verticalCenter - spacing: 10 * DefaultStyle.dp - ColumnLayout { - spacing: 7 * DefaultStyle.dp - Text { - Layout.leftMargin: 5 * DefaultStyle.dp - text: modelData.label + " :" - font { - pixelSize: 13 * DefaultStyle.dp - weight: 700 * DefaultStyle.dp - } - } - Text { - Layout.leftMargin: 5 * DefaultStyle.dp - text: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(modelData.address) : modelData.address - font { - pixelSize: 14 * DefaultStyle.dp - weight: 400 * DefaultStyle.dp - } - } - } - Rectangle { - visible: index != popuplist.model.count - 1 - Layout.fillWidth: true - Layout.preferredHeight: 1 * DefaultStyle.dp - color: DefaultStyle.main2_200 - } - } - MouseArea { - anchors.fill: parent - hoverEnabled: true - cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor - onClicked: { - if (startCallPopup.currentCall) startCallPopup.currentCall.core.lTransferCall(modelData.address) - else UtilsCpp.createCall(modelData.address, {'localVideoEnabled': startCallPopup.videoEnabled}) - startCallPopup.close() - } - } - } - } - } - } + MouseArea { + anchors.fill: parent + onClicked: mainWindow.contentItem.forceActiveFocus() + } - function startCallWithContact(contact, videoEnabled, parentItem) { - if (parentItem == undefined) parentItem = mainWindow.contentItem - startCallPopup.parent = parentItem - if (contact) { - console.log("START CALL WITH", contact.core.fullName, "addresses count", contact.core.allAddresses.length) - if (contact.core.allAddresses.length > 1) { - startCallPopup.contact = contact - startCallPopup.videoEnabled = videoEnabled - startCallPopup.open() + Component { + id: popupComp + InformationPopup{} + } - } else { - var addressToCall = contact.core.defaultAddress.length === 0 - ? contact.core.phoneNumbers.length === 0 - ? "" - : contact.core.phoneNumbers[0].address - : contact.core.defaultAddress - if (addressToCall.length != 0) UtilsCpp.createCall(addressToCall, {'localVideoEnabled':videoEnabled}) - } - } - } + Component{ + id: confirmPopupComp + Dialog { + property var requestDialog + property int index + property var callback: requestDialog?.result + signal closePopup(int index) + onClosed: closePopup(index) + text: requestDialog?.message + details: requestDialog?.details + firstButtonAccept: title.length === 0 + secondButtonAccept: title.length !== 0 + Component.onCompleted: if (details.length != 0) radius = 0 + // For C++, requestDialog need to be call directly + onAccepted: requestDialog ? requestDialog.result(1) : callback(1) + onRejected: requestDialog ? requestDialog.result(0) : callback(0) + width: title.length === 0 ? 278 * DefaultStyle.dp : 637 * DefaultStyle.dp + } + } - function transferCallToContact(call, contact, parentItem) { - if (!call || !contact) return - if (parentItem == undefined) parentItem = mainWindow.contentItem - startCallPopup.parent = parentItem - if (contact) { - console.log("[AbstractWindow] Transfer call to", contact.core.fullName, "addresses count", contact.core.allAddresses.length, call) - if (contact.core.allAddresses.length > 1) { - startCallPopup.contact = contact - startCallPopup.currentCall = call - startCallPopup.open() + Popup { + id: startCallPopup + property FriendGui contact + property bool videoEnabled + // if currentCall, transfer call to contact + property CallGui currentCall + onContactChanged: { + console.log("contact changed", contact) + } + underlineColor: DefaultStyle.main1_500_main + anchors.centerIn: parent + width: 370 * DefaultStyle.dp + modal: true + leftPadding: 15 * DefaultStyle.dp + rightPadding: 15 * DefaultStyle.dp + topPadding: 20 * DefaultStyle.dp + bottomPadding: 25 * DefaultStyle.dp + contentItem: ColumnLayout { + spacing: 16 * DefaultStyle.dp + RowLayout { + spacing: 5 * DefaultStyle.dp + width: startCallPopup.width + Text { + text: qsTr("Quelle addresse souhaitez-vous appeler ?") + wrapMode: Text.Wrap + Layout.fillWidth: true + font { + pixelSize: 16 * DefaultStyle.dp + weight: 800 * DefaultStyle.dp + } + } + RoundButton { + Layout.alignment: Qt.AlignVCenter + style: ButtonStyle.noBackground + Layout.preferredWidth: 24 * DefaultStyle.dp + Layout.preferredHeight: 24 * DefaultStyle.dp + icon.source:AppIcons.closeX + onClicked: startCallPopup.close() + } + } + ListView { + id: popuplist + model: VariantList { + model: startCallPopup.contact && startCallPopup.contact.core.allAddresses || [] + } + Layout.fillWidth: true + Layout.preferredHeight: contentHeight + spacing: 10 * DefaultStyle.dp + delegate: Item { + width: popuplist.width + height: 56 * DefaultStyle.dp + ColumnLayout { + width: popuplist.width + anchors.verticalCenter: parent.verticalCenter + spacing: 10 * DefaultStyle.dp + ColumnLayout { + spacing: 7 * DefaultStyle.dp + Text { + Layout.leftMargin: 5 * DefaultStyle.dp + text: modelData.label + " :" + font { + pixelSize: 13 * DefaultStyle.dp + weight: 700 * DefaultStyle.dp + } + } + Text { + Layout.leftMargin: 5 * DefaultStyle.dp + text: SettingsCpp.onlyDisplaySipUriUsername ? UtilsCpp.getUsername(modelData.address) : modelData.address + font { + pixelSize: 14 * DefaultStyle.dp + weight: 400 * DefaultStyle.dp + } + } + } + Rectangle { + visible: index != popuplist.model.count - 1 + Layout.fillWidth: true + Layout.preferredHeight: 1 * DefaultStyle.dp + color: DefaultStyle.main2_200 + } + } + MouseArea { + anchors.fill: parent + hoverEnabled: true + cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor + onClicked: { + if (startCallPopup.currentCall) startCallPopup.currentCall.core.lTransferCall(modelData.address) + else UtilsCpp.createCall(modelData.address, {'localVideoEnabled': startCallPopup.videoEnabled}) + startCallPopup.close() + } + } + } + } + } + } - } else { - var addressToCall = contact.core.defaultAddress.length === 0 - ? contact.core.phoneNumbers.length === 0 - ? "" - : contact.core.phoneNumbers[0].address - : contact.core.defaultAddress - if (addressToCall.length != 0) call.core.lTransferCall(addressToCall) - } - } - } + function startCallWithContact(contact, videoEnabled, parentItem) { + if (parentItem == undefined) parentItem = mainWindow.contentItem + startCallPopup.parent = parentItem + if (contact) { + console.log("START CALL WITH", contact.core.fullName, "addresses count", contact.core.allAddresses.length) + if (contact.core.allAddresses.length > 1) { + startCallPopup.contact = contact + startCallPopup.videoEnabled = videoEnabled + startCallPopup.open() - function removeFromPopupLayout(index) { - popupLayout.popupList.splice(index, 1) - } - function showInformationPopup(title, description, isSuccess) { - if (isSuccess == undefined) isSuccess = true - var infoPopup = popupComp.createObject(popupLayout, {"title": title, "description": description, "isSuccess": isSuccess}) - infoPopup.index = popupLayout.popupList.length - popupLayout.popupList.push(infoPopup) - infoPopup.open() - infoPopup.closePopup.connect(removeFromPopupLayout) - } - function showLoadingPopup(text, cancelButtonVisible, callback) { - if (cancelButtonVisible == undefined) cancelButtonVisible = false - loadingPopup.text = text - loadingPopup.callback = callback - loadingPopup.cancelButtonVisible = cancelButtonVisible - loadingPopup.open() - } - function closeLoadingPopup() { - loadingPopup.close() - } + } else { + var addressToCall = contact.core.defaultAddress.length === 0 + ? contact.core.phoneNumbers.length === 0 + ? "" + : contact.core.phoneNumbers[0].address + : contact.core.defaultAddress + if (addressToCall.length != 0) UtilsCpp.createCall(addressToCall, {'localVideoEnabled':videoEnabled}) + } + } + } - function showConfirmationPopup(requestDialog){ - console.log("Showing confirmation popup") - var popup = confirmPopupComp.createObject(popupLayout, {"requestDialog": requestDialog}) - popup.open() - popup.closePopup.connect(removeFromPopupLayout) - } - - function showConfirmationLambdaPopup(title,text, details, callback, firstButtonText, secondButtonText, customContent){ - console.log("Showing confirmation lambda popup") - var popup = confirmPopupComp.createObject(popupLayout, {"title": title, "text": text, "details":details,"callback":callback}) - if (firstButtonText != undefined) popup.firstButtonText = firstButtonText - if (secondButtonText != undefined) popup.secondButtonText = secondButtonText - if (customContent != undefined) popup.content = customContent - popup.titleColor = DefaultStyle.main1_500_main - popup.open() - popup.closePopup.connect(removeFromPopupLayout) - } - - ColumnLayout { - id: popupLayout - anchors.fill: parent - Layout.alignment: Qt.AlignBottom - property int nextY: mainWindow.height - property list popupList - property int popupCount: popupList.length - spacing: 15 * DefaultStyle.dp - onPopupCountChanged: { - nextY = mainWindow.height - for(var i = 0; i < popupCount; ++i) { - var popupItem = popupList[i] - if( popupItem ){ - popupItem.y = nextY - popupItem.height - popupItem.index = i - nextY = nextY - popupItem.height - 15 - } - } - } - } + function transferCallToContact(call, contact, parentItem) { + if (!call || !contact) return + if (parentItem == undefined) parentItem = mainWindow.contentItem + startCallPopup.parent = parentItem + if (contact) { + console.log("[AbstractWindow] Transfer call to", contact.core.fullName, "addresses count", contact.core.allAddresses.length, call) + if (contact.core.allAddresses.length > 1) { + startCallPopup.contact = contact + startCallPopup.currentCall = call + startCallPopup.open() - LoadingPopup { - id: loadingPopup - modal: true - closePolicy: Popup.NoAutoClose - anchors.centerIn: parent - padding: 20 * DefaultStyle.dp - underlineColor: DefaultStyle.main1_500_main - radius: 15 * DefaultStyle.dp - } - FPSCounter{ - anchors.top: parent.top - anchors.left: parent.left - height: 50 - width: fpsText.implicitWidth - z: 100 - visible: !SettingsCpp.hideFps - Text{ - id: fpsText - font.bold: true - font.italic: true - font.pixelSize: 14 * DefaultStyle.dp - text: parent.fps + " FPS" - color: parent.fps < 30 ? DefaultStyle.danger_500main : DefaultStyle.main2_900 - } - } + } else { + var addressToCall = contact.core.defaultAddress.length === 0 + ? contact.core.phoneNumbers.length === 0 + ? "" + : contact.core.phoneNumbers[0].address + : contact.core.defaultAddress + if (addressToCall.length != 0) call.core.lTransferCall(addressToCall) + } + } + } + + function removeFromPopupLayout(index) { + popupLayout.popupList.splice(index, 1) + } + function showInformationPopup(title, description, isSuccess) { + if (isSuccess == undefined) isSuccess = true + var infoPopup = popupComp.createObject(popupLayout, {"title": title, "description": description, "isSuccess": isSuccess}) + infoPopup.index = popupLayout.popupList.length + popupLayout.popupList.push(infoPopup) + infoPopup.open() + infoPopup.closePopup.connect(removeFromPopupLayout) + } + function showLoadingPopup(text, cancelButtonVisible, callback) { + if (cancelButtonVisible == undefined) cancelButtonVisible = false + loadingPopup.text = text + loadingPopup.callback = callback + loadingPopup.cancelButtonVisible = cancelButtonVisible + loadingPopup.open() + } + function closeLoadingPopup() { + loadingPopup.close() + } + + function showConfirmationPopup(requestDialog){ + console.log("Showing confirmation popup") + var popup = confirmPopupComp.createObject(popupLayout, {"requestDialog": requestDialog}) + popup.open() + popup.closePopup.connect(removeFromPopupLayout) + } + + function showConfirmationLambdaPopup(title,text, details, callback, firstButtonText, secondButtonText, customContent){ + console.log("Showing confirmation lambda popup") + var popup = confirmPopupComp.createObject(popupLayout, {"title": title, "text": text, "details":details,"callback":callback}) + if (firstButtonText != undefined) popup.firstButtonText = firstButtonText + if (secondButtonText != undefined) popup.secondButtonText = secondButtonText + if (customContent != undefined) popup.content = customContent + popup.titleColor = DefaultStyle.main1_500_main + popup.open() + popup.closePopup.connect(removeFromPopupLayout) + } + + ColumnLayout { + id: popupLayout + anchors.fill: parent + Layout.alignment: Qt.AlignBottom + property int nextY: mainWindow.height + property list popupList + property int popupCount: popupList.length + spacing: 15 * DefaultStyle.dp + onPopupCountChanged: { + nextY = mainWindow.height + for(var i = 0; i < popupCount; ++i) { + var popupItem = popupList[i] + if( popupItem ){ + popupItem.y = nextY - popupItem.height + popupItem.index = i + nextY = nextY - popupItem.height - 15 + } + } + } + } + + LoadingPopup { + id: loadingPopup + modal: true + closePolicy: Popup.NoAutoClose + anchors.centerIn: parent + padding: 20 * DefaultStyle.dp + underlineColor: DefaultStyle.main1_500_main + radius: 15 * DefaultStyle.dp + } + FPSCounter{ + anchors.top: parent.top + anchors.left: parent.left + height: 50 + width: fpsText.implicitWidth + z: 100 + visible: !SettingsCpp.hideFps + Text{ + id: fpsText + font.bold: true + font.italic: true + font.pixelSize: 14 * DefaultStyle.dp + text: parent.fps + " FPS" + color: parent.fps < 30 ? DefaultStyle.danger_500main : DefaultStyle.main2_900 + } + } }