mirror of
https://github.com/feather-wallet/feather.git
synced 2024-12-22 11:39:25 +00:00
remove SingleApplication
This commit is contained in:
parent
a53f6d4b2c
commit
4b197dd49c
8 changed files with 150 additions and 42 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,9 +1,6 @@
|
||||||
[submodule "monero"]
|
[submodule "monero"]
|
||||||
path = monero
|
path = monero
|
||||||
url = https://github.com/feather-wallet/monero.git
|
url = https://github.com/feather-wallet/monero.git
|
||||||
[submodule "src/third-party/singleapplication"]
|
|
||||||
path = src/third-party/singleapplication
|
|
||||||
url = https://github.com/itay-grudev/SingleApplication.git
|
|
||||||
[submodule "src/third-party/polyseed"]
|
[submodule "src/third-party/polyseed"]
|
||||||
path = src/third-party/polyseed
|
path = src/third-party/polyseed
|
||||||
url = https://github.com/tevador/polyseed.git
|
url = https://github.com/tevador/polyseed.git
|
||||||
|
|
100
src/Application.cpp
Normal file
100
src/Application.cpp
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// SPDX-FileCopyrightText: 2020-2024 The Monero Project
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <QLocalSocket>
|
||||||
|
#include <QLockFile>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr int WaitTimeoutMSec = 150;
|
||||||
|
const char BlockSizeProperty[] = "blockSize";
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
Application::Application(int& argc, char** argv)
|
||||||
|
: QApplication(argc, argv)
|
||||||
|
, m_alreadyRunning(false)
|
||||||
|
, m_lockFile(nullptr)
|
||||||
|
{
|
||||||
|
QString userName = qgetenv("USER");
|
||||||
|
if (userName.isEmpty()) {
|
||||||
|
userName = qgetenv("USERNAME");
|
||||||
|
}
|
||||||
|
QString identifier = "feather";
|
||||||
|
if (!userName.isEmpty()) {
|
||||||
|
identifier += "-" + userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString lockName = identifier + ".lock";
|
||||||
|
m_socketName = identifier + ".socket";
|
||||||
|
|
||||||
|
// According to documentation we should use RuntimeLocation on *nixes, but even Qt doesn't respect
|
||||||
|
// this and creates sockets in TempLocation, so let's be consistent.
|
||||||
|
m_lockFile = new QLockFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/" + lockName);
|
||||||
|
m_lockFile->setStaleLockTime(0);
|
||||||
|
m_lockFile->tryLock();
|
||||||
|
|
||||||
|
m_lockServer.setSocketOptions(QLocalServer::UserAccessOption);
|
||||||
|
connect(&m_lockServer, SIGNAL(newConnection()), this, SIGNAL(anotherInstanceStarted()));
|
||||||
|
connect(&m_lockServer, &QLocalServer::newConnection, this, &Application::processIncomingConnection);
|
||||||
|
|
||||||
|
switch (m_lockFile->error()) {
|
||||||
|
case QLockFile::NoError:
|
||||||
|
// No existing lock was found, start listener
|
||||||
|
m_lockServer.listen(m_socketName);
|
||||||
|
break;
|
||||||
|
case QLockFile::LockFailedError: {
|
||||||
|
// Attempt to connect to the existing instance
|
||||||
|
QLocalSocket client;
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
client.connectToServer(m_socketName);
|
||||||
|
if (client.waitForConnected(WaitTimeoutMSec)) {
|
||||||
|
// Connection succeeded, this will raise the existing window if minimized
|
||||||
|
client.abort();
|
||||||
|
m_alreadyRunning = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_alreadyRunning) {
|
||||||
|
// If we get here then the original instance is likely dead
|
||||||
|
qWarning() << "Existing single-instance lock file is invalid. Launching new instance.";
|
||||||
|
|
||||||
|
// forceably reset the lock file
|
||||||
|
m_lockFile->removeStaleLockFile();
|
||||||
|
m_lockFile->tryLock();
|
||||||
|
// start the listen server
|
||||||
|
m_lockServer.listen(m_socketName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
qWarning() << "The lock file could not be created. Single-instance mode disabled.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Application::~Application()
|
||||||
|
{
|
||||||
|
if (m_lockFile) {
|
||||||
|
m_lockFile->unlock();
|
||||||
|
delete m_lockFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Application::isAlreadyRunning() const
|
||||||
|
{
|
||||||
|
return m_alreadyRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::processIncomingConnection()
|
||||||
|
{
|
||||||
|
qDebug() << "We got an incoming connection";
|
||||||
|
if (m_lockServer.hasPendingConnections()) {
|
||||||
|
QLocalSocket* socket = m_lockServer.nextPendingConnection();
|
||||||
|
socket->setProperty(BlockSizeProperty, 0);
|
||||||
|
}
|
||||||
|
}
|
36
src/Application.h
Normal file
36
src/Application.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// SPDX-FileCopyrightText: 2020-2024 The Monero Project
|
||||||
|
|
||||||
|
#ifndef FEATHER_APPLICATION_H
|
||||||
|
#define FEATHER_APPLICATION_H
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QtNetwork/qlocalserver.h>
|
||||||
|
|
||||||
|
class QLockFile;
|
||||||
|
class QSocketNotifier;
|
||||||
|
|
||||||
|
class Application : public QApplication {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Application(int& argc, char** argv);
|
||||||
|
~Application() override;
|
||||||
|
|
||||||
|
bool isAlreadyRunning() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void anotherInstanceStarted();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void processIncomingConnection();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_alreadyRunning;
|
||||||
|
QLockFile* m_lockFile;
|
||||||
|
QLocalServer m_lockServer;
|
||||||
|
QString m_socketName;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //FEATHER_APPLICATION_H
|
|
@ -20,11 +20,6 @@ endif()
|
||||||
|
|
||||||
find_package(Qt6 REQUIRED COMPONENTS ${QT_COMPONENTS})
|
find_package(Qt6 REQUIRED COMPONENTS ${QT_COMPONENTS})
|
||||||
|
|
||||||
if (NOT APPLE)
|
|
||||||
set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication")
|
|
||||||
add_subdirectory(third-party/singleapplication)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (CHECK_UPDATES)
|
if (CHECK_UPDATES)
|
||||||
add_subdirectory(openpgp)
|
add_subdirectory(openpgp)
|
||||||
endif()
|
endif()
|
||||||
|
@ -280,10 +275,6 @@ target_link_libraries(feather PRIVATE
|
||||||
${BCUR_LIBRARY}
|
${BCUR_LIBRARY}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT APPLE)
|
|
||||||
target_link_libraries(feather PRIVATE SingleApplication::SingleApplication)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CHECK_UPDATES)
|
if(CHECK_UPDATES)
|
||||||
target_link_libraries(feather PRIVATE openpgp)
|
target_link_libraries(feather PRIVATE openpgp)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
|
|
||||||
#include "WindowManager.h"
|
#include "WindowManager.h"
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "dialog/PasswordDialog.h"
|
#include "dialog/PasswordDialog.h"
|
||||||
#include "dialog/SplashDialog.h"
|
#include "dialog/SplashDialog.h"
|
||||||
|
@ -33,6 +33,7 @@ WindowManager::WindowManager(QObject *parent)
|
||||||
connect(m_walletManager, &WalletManager::deviceError, this, &WindowManager::onDeviceError);
|
connect(m_walletManager, &WalletManager::deviceError, this, &WindowManager::onDeviceError);
|
||||||
connect(m_walletManager, &WalletManager::walletPassphraseNeeded, this, &WindowManager::onWalletPassphraseNeeded);
|
connect(m_walletManager, &WalletManager::walletPassphraseNeeded, this, &WindowManager::onWalletPassphraseNeeded);
|
||||||
|
|
||||||
|
connect(qApp, SIGNAL(anotherInstanceStarted()), this, SLOT(raise()));
|
||||||
connect(qApp, &QGuiApplication::lastWindowClosed, this, &WindowManager::quitAfterLastWindow);
|
connect(qApp, &QGuiApplication::lastWindowClosed, this, &WindowManager::quitAfterLastWindow);
|
||||||
|
|
||||||
m_tray = new QSystemTrayIcon(icons()->icon("appicons/64x64.png"));
|
m_tray = new QSystemTrayIcon(icons()->icon("appicons/64x64.png"));
|
||||||
|
@ -66,6 +67,7 @@ WindowManager::~WindowManager() {
|
||||||
qDebug() << "~WindowManager";
|
qDebug() << "~WindowManager";
|
||||||
m_cleanupThread->quit();
|
m_cleanupThread->quit();
|
||||||
m_cleanupThread->wait();
|
m_cleanupThread->wait();
|
||||||
|
qDebug() << "Cleanup thread done";
|
||||||
}
|
}
|
||||||
|
|
||||||
// ######################## APPLICATION LIFECYCLE ########################
|
// ######################## APPLICATION LIFECYCLE ########################
|
||||||
|
@ -100,6 +102,7 @@ void WindowManager::close() {
|
||||||
|
|
||||||
torManager()->stop();
|
torManager()->stop();
|
||||||
|
|
||||||
|
qDebug() << "Calling QApplication::quit()";
|
||||||
QApplication::quit();
|
QApplication::quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ public:
|
||||||
void closeWindow(MainWindow *window);
|
void closeWindow(MainWindow *window);
|
||||||
void showWizard(WalletWizard::Page startPage);
|
void showWizard(WalletWizard::Page startPage);
|
||||||
void restartApplication(const QString &binaryFilename);
|
void restartApplication(const QString &binaryFilename);
|
||||||
void raise();
|
|
||||||
|
|
||||||
void showSettings(Nodes *nodes, QWidget *parent, bool showProxyTab = false);
|
void showSettings(Nodes *nodes, QWidget *parent, bool showProxyTab = false);
|
||||||
|
|
||||||
|
@ -59,6 +58,7 @@ public slots:
|
||||||
void tryOpenWallet(const QString &path, const QString &password);
|
void tryOpenWallet(const QString &path, const QString &password);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void raise();
|
||||||
void onWalletOpened(Wallet *wallet);
|
void onWalletOpened(Wallet *wallet);
|
||||||
void onWalletCreated(Wallet *wallet);
|
void onWalletCreated(Wallet *wallet);
|
||||||
void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path);
|
void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path);
|
||||||
|
|
36
src/main.cpp
36
src/main.cpp
|
@ -1,17 +1,9 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
// SPDX-FileCopyrightText: 2020-2024 The Monero Project
|
// SPDX-FileCopyrightText: 2020-2024 The Monero Project
|
||||||
|
|
||||||
#include <QResource>
|
#include "Application.h"
|
||||||
#include <QApplication>
|
|
||||||
#include <QtCore>
|
|
||||||
#include <QtGui>
|
|
||||||
#if !defined(Q_OS_MAC)
|
|
||||||
#include <singleapplication.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "config-feather.h"
|
#include "config-feather.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "MainWindow.h"
|
|
||||||
#include "utils/EventFilter.h"
|
#include "utils/EventFilter.h"
|
||||||
#include "utils/os/Prestium.h"
|
#include "utils/os/Prestium.h"
|
||||||
#include "WindowManager.h"
|
#include "WindowManager.h"
|
||||||
|
@ -24,8 +16,6 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <vfw.h>
|
#include <vfw.h>
|
||||||
|
@ -89,12 +79,7 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);
|
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(Q_OS_MAC)
|
Application app(argc, argv);
|
||||||
// https://github.com/itay-grudev/SingleApplication/issues/136#issuecomment-1925441403
|
|
||||||
QApplication app(argc, argv);
|
|
||||||
#else
|
|
||||||
SingleApplication app(argc, argv);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QApplication::setApplicationName("Feather");
|
QApplication::setApplicationName("Feather");
|
||||||
QApplication::setApplicationVersion(FEATHER_VERSION);
|
QApplication::setApplicationVersion(FEATHER_VERSION);
|
||||||
|
@ -122,6 +107,11 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (app.isAlreadyRunning()) {
|
||||||
|
qWarning() << "Another instance of Feather is already running";
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
bool stagenet = parser.isSet(stagenetOption);
|
bool stagenet = parser.isSet(stagenetOption);
|
||||||
bool testnet = parser.isSet(testnetOption);
|
bool testnet = parser.isSet(testnetOption);
|
||||||
bool quiet = parser.isSet(quietModeOption);
|
bool quiet = parser.isSet(quietModeOption);
|
||||||
|
@ -193,8 +183,6 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
|
|
||||||
conf()->set(Config::restartRequired, false);
|
conf()->set(Config::restartRequired, false);
|
||||||
|
|
||||||
parser.process(app); // Parse again for --help and --version
|
|
||||||
|
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
QMap<QString, QString> info;
|
QMap<QString, QString> info;
|
||||||
info["Qt"] = QT_VERSION_STR;
|
info["Qt"] = QT_VERSION_STR;
|
||||||
|
@ -238,13 +226,7 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
auto wm = windowManager();
|
auto wm = windowManager();
|
||||||
wm->setEventFilter(&filter);
|
wm->setEventFilter(&filter);
|
||||||
|
|
||||||
#if !defined(Q_OS_MAC)
|
int exitCode = Application::exec();
|
||||||
QObject::connect(&app, &SingleApplication::instanceStarted, [&wm]() {
|
qDebug() << "Application::exec() returned";
|
||||||
wm->raise();
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int exitCode = QApplication::exec();
|
|
||||||
qDebug() << "QApplication::exec() returned";
|
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
|
|
1
src/third-party/singleapplication
vendored
1
src/third-party/singleapplication
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 3e8e85d1a487e433751711a8a090659684d42e3b
|
|
Loading…
Reference in a new issue