remove SingleApplication

This commit is contained in:
tobtoht 2024-10-01 04:21:42 +02:00
parent a53f6d4b2c
commit 4b197dd49c
No known key found for this signature in database
GPG key ID: E45B10DD027D2472
8 changed files with 150 additions and 42 deletions

3
.gitmodules vendored
View file

@ -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
View 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
View 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

View file

@ -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()

View file

@ -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();
} }

View file

@ -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);

View file

@ -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 +0,0 @@
Subproject commit 3e8e85d1a487e433751711a8a090659684d42e3b