Skip to content
Snippets Groups Projects
Commit 3db33c4f authored by Andreas Traczyk's avatar Andreas Traczyk
Browse files

mainapplication: add URI start option

+ Refactors some window management logic in LayoutManagar.qml.
+ Refactors app start to support both a minimized start and a start
  URI. The start URI should force visibility.
+ StartMinimized now starts the application in a closed-to-tray
  state, instead of a minimized state.
+ The close-to-tray feature now saves the previous windowed state.
+ InstanceManager handles URI transfer to secondary instances.

This commit does not implement URI handling. The original
implementation supported only calls via a user infohash as the URI
parameter. A new and flexible protocol should be defined to support
multiple Jami features.

Gitlab: #655
Change-Id: I2c47028930e4e9d7ccca94d9362545df14b98160
parent f319c954
Branches
Tags
No related merge requests found
......@@ -20,6 +20,8 @@ import QtQuick
import QtQuick.Controls
import net.jami.Adapters 1.1
import net.jami.Enums 1.1
import net.jami.Constants 1.1
import "mainview/components"
......@@ -49,6 +51,73 @@ QtObject {
}
visibility = priv.windowedVisibility
}
appWindow.allowVisibleWindow = true
}
// Start in a hidden state.
function startMinimized(visibilitySetting) {
// Save the loaded setting for when the app is restored.
priv.windowedVisibility = visibilitySetting
appWindow.allowVisibleWindow = false
appWindow.hide();
}
// Close to a hidden state.
function closeToTray(visibilitySetting = undefined) {
// Save the current visibility.
priv.windowedVisibility = visibility
appWindow.hide();
}
// Save the window geometry and visibility settings.
function saveWindowSettings() {
var geometry = Qt.rect(appWindow.x, appWindow.y,
appWindow.width, appWindow.height)
AppSettingsManager.setValue(Settings.WindowGeometry, geometry)
// If closed-to-tray or minimized, save the cached windowedVisibility
// value instead.
if (isHidden) {
AppSettingsManager.setValue(Settings.WindowState, priv.windowedVisibility)
} else {
AppSettingsManager.setValue(Settings.WindowState, visibility)
}
}
// Restore the window geometry and visibility settings.
function restoreWindowSettings() {
var geometry = AppSettingsManager.getValue(Settings.WindowGeometry)
// Position.
if (!isNaN(geometry.x) && !isNaN(geometry.y)) {
appWindow.x = geometry.x
appWindow.y = geometry.y
}
// Dimensions.
appWindow.width = geometry.width ?
geometry.width :
JamiTheme.mainViewPreferredWidth
appWindow.height = geometry.height ?
geometry.height :
JamiTheme.mainViewPreferredHeight
appWindow.minimumWidth = JamiTheme.mainViewMinWidth
appWindow.minimumHeight = JamiTheme.mainViewMinHeight
// State.
const visibilityStr = AppSettingsManager.getValue(Settings.WindowState)
var visibilitySetting = parseInt(visibilityStr)
// We should never restore a hidden state here. Default to normal
// windowed state in such a case. This shouldn't happen.
if (visibilitySetting === Window.Hidden) {
visibilitySetting = Window.Windowed
}
if (MainApplication.startMinimized) {
startMinimized(visibilitySetting)
} else {
visibility = visibilitySetting
}
}
// Adds an item to the fullscreen item stack. Automatically puts
......
......@@ -53,6 +53,7 @@ ApplicationWindow {
}
property bool windowSettingsLoaded: false
property bool allowVisibleWindow: true
function checkLoadedSource() {
var sourceString = mainApplicationLoader.source.toString()
......@@ -83,19 +84,18 @@ ApplicationWindow {
if (force || !UtilsAdapter.getAppValue(Settings.MinimizeOnClose) ||
!UtilsAdapter.getAccountListSize()) {
// Save the window geometry and state before quitting.
var geometry = Qt.rect(appWindow.x, appWindow.y,
appWindow.width, appWindow.height)
AppSettingsManager.setValue(Settings.WindowGeometry, geometry)
AppSettingsManager.setValue(Settings.WindowState, appWindow.visibility)
layoutManager.saveWindowSettings()
Qt.quit()
} else {
hide()
layoutManager.closeToTray()
}
}
title: JamiStrings.appTitle
visible: mainApplicationLoader.status === Loader.Ready && windowSettingsLoaded
visible: mainApplicationLoader.status === Loader.Ready
&& windowSettingsLoaded
&& allowVisibleWindow
// To facilitate reparenting of the callview during
// fullscreen mode, we need QQuickItem based object.
......@@ -134,38 +134,21 @@ ApplicationWindow {
onSourceChanged: windowSettingsLoaded = false
onLoaded: {
if (UtilsAdapter.getAppValue(Settings.StartMinimized)) {
showMinimized()
if (checkLoadedSource() === MainApplicationWindow.LoadedSource.WizardView) {
// Onboarding wizard window, these settings are fixed.
// - window screen should default to the primary
// - position should default to being centered based on the
// following dimensions
// - the window will showNormal once windowSettingsLoaded is
// set to true(then forcing visible to true)
appWindow.width = JamiTheme.wizardViewMinWidth
appWindow.height = JamiTheme.wizardViewMinHeight
appWindow.minimumWidth = JamiTheme.wizardViewMinWidth
appWindow.minimumHeight = JamiTheme.wizardViewMinHeight
} else {
if (checkLoadedSource() === MainApplicationWindow.LoadedSource.WizardView) {
appWindow.width = JamiTheme.wizardViewMinWidth
appWindow.height = JamiTheme.wizardViewMinHeight
appWindow.minimumWidth = JamiTheme.wizardViewMinWidth
appWindow.minimumHeight = JamiTheme.wizardViewMinHeight
} else {
// Main window, load settings if possible.
var geometry = AppSettingsManager.getValue(Settings.WindowGeometry)
// Position.
if (!isNaN(geometry.x) && !isNaN(geometry.y)) {
appWindow.x = geometry.x
appWindow.y = geometry.y
}
// Dimensions.
appWindow.width = geometry.width ?
geometry.width :
JamiTheme.mainViewPreferredWidth
appWindow.height = geometry.height ?
geometry.height :
JamiTheme.mainViewPreferredHeight
appWindow.minimumWidth = JamiTheme.mainViewMinWidth
appWindow.minimumHeight = JamiTheme.mainViewMinHeight
// State.
const visibilityStr = AppSettingsManager.getValue(Settings.WindowState)
appWindow.visibility = parseInt(visibilityStr)
}
// Main window, load any valid app settings, and allow the
// layoutManager to handle as much as possible.
layoutManager.restoreWindowSettings()
}
// This will trigger `visible = true`.
......@@ -176,6 +159,9 @@ ApplicationWindow {
UpdateManager.checkForUpdates(true)
UpdateManager.setAutoUpdateCheck(true)
}
// Handle a start URI if set as start option.
MainApplication.handleUriAction();
}
}
......
......@@ -52,13 +52,20 @@ public:
{}
~Impl() = default;
bool tryToRun()
bool tryToRun(const QByteArray& startUri)
{
if (isAnotherRunning()) {
// This is a secondary instance,
// connect to the primary instance to trigger a restore
// then fail.
// This is a secondary instance, connect to the primary
// instance to trigger a restore then die.
if (connectToLocal()) {
// Okay we connected. Send the start uri if not empty.
if (startUri.size()) {
qDebug() << "Sending start URI to secondary instance." << startUri;
socket_->write(startUri);
socket_->waitForBytesWritten();
}
// Now this instance can die.
return false;
}
// If not connected, this means that the server doesn't exist
......@@ -99,7 +106,7 @@ public:
return;
}
socket_->write(reinterpret_cast<const char*>(terminateSeq_.data()), 4);
socket_->write(terminateSeq_);
socket_->waitForBytesWritten();
};
......@@ -139,10 +146,15 @@ private Q_SLOTS:
if (recievedData == terminateSeq_) {
qWarning() << "Received terminate signal.";
mainAppInstance_->quit();
} else {
qDebug() << "Received start URI:" << recievedData;
auto startUri = QString::fromLatin1(recievedData);
mainAppInstance_->handleUriAction(startUri);
}
});
// Restore primary instance
qDebug() << "Received wake-up from secondary instance.";
mainAppInstance_->restoreApp();
};
......@@ -193,9 +205,9 @@ InstanceManager::~InstanceManager()
}
bool
InstanceManager::tryToRun()
InstanceManager::tryToRun(const QByteArray& startUri)
{
return pimpl_->tryToRun();
return pimpl_->tryToRun(startUri);
}
void
......
......@@ -32,7 +32,7 @@ public:
explicit InstanceManager(MainApplication* mainApp);
~InstanceManager();
bool tryToRun();
bool tryToRun(const QByteArray& startUri);
void tryToKill();
private:
......
......@@ -106,9 +106,12 @@ main(int argc, char* argv[])
qWarning() << "Attempting to terminate other instances.";
im.tryToKill();
return 0;
} else if (!im.tryToRun()) {
qWarning() << "Another instance is running.";
return 0;
} else {
auto startUri = app.getOpt(MainApplication::Option::StartUri);
if (!im.tryToRun(startUri.toByteArray())) {
qWarning() << "Another instance is running.";
return 0;
}
}
if (!app.init()) {
......
......@@ -241,6 +241,10 @@ MainApplication::init()
lrcInstance_->accountModel().autoTransferFromTrusted = allowTransferFromTrusted;
lrcInstance_->accountModel().autoTransferSizeThreshold = acceptTransferBelow;
auto startMinimizedSetting = settingsManager_->getValue(Settings::Key::StartMinimized).toBool();
// The presence of start URI should override the startMinimized setting for this instance.
set_startMinimized(startMinimizedSetting && runOptions_[Option::StartUri].isNull());
initQmlLayer();
settingsManager_->setValue(Settings::Key::StartMinimized,
......@@ -257,6 +261,20 @@ MainApplication::restoreApp()
Q_EMIT lrcInstance_->restoreAppRequested();
}
void
MainApplication::handleUriAction(const QString& arg)
{
QString uri {};
if (arg.isEmpty() && !runOptions_[Option::StartUri].isNull()) {
uri = runOptions_[Option::StartUri].toString();
qDebug() << "URI action invoked by run option" << uri;
} else {
uri = arg;
qDebug() << "URI action invoked by secondary instance" << uri;
}
// TODO: implement URI protocol handling.
}
void
MainApplication::initLrc(const QString& downloadUrl, ConnectivityMonitor* cm, bool logDaemon)
{
......@@ -290,6 +308,13 @@ MainApplication::initLrc(const QString& downloadUrl, ConnectivityMonitor* cm, bo
void
MainApplication::parseArguments()
{
// See if the app is being started with a URI.
for (const auto& arg : QApplication::arguments()) {
if (arg.startsWith("jami:")) {
runOptions_[Option::StartUri] = arg;
}
}
QCommandLineParser parser;
parser.addHelpOption();
parser.addVersionOption();
......
......@@ -58,7 +58,7 @@ class MainApplication : public QApplication
{
Q_OBJECT
Q_DISABLE_COPY(MainApplication)
QML_RO_PROPERTY(bool, startMinimized)
public:
explicit MainApplication(int& argc, char** argv);
~MainApplication();
......@@ -66,6 +66,8 @@ public:
bool init();
void restoreApp();
Q_INVOKABLE void handleUriAction(const QString& uri = {});
enum class Option {
StartMinimized = 0,
Debug,
......@@ -73,7 +75,8 @@ public:
DebugToFile,
UpdateUrl,
MuteJamid,
TerminationRequested
TerminationRequested,
StartUri
};
QVariant getOpt(const Option opt)
{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment