mirror of
https://github.com/feather-wallet/feather.git
synced 2024-12-21 19:19:23 +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"]
|
||||
path = monero
|
||||
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"]
|
||||
path = src/third-party/polyseed
|
||||
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})
|
||||
|
||||
if (NOT APPLE)
|
||||
set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication")
|
||||
add_subdirectory(third-party/singleapplication)
|
||||
endif()
|
||||
|
||||
if (CHECK_UPDATES)
|
||||
add_subdirectory(openpgp)
|
||||
endif()
|
||||
|
@ -280,10 +275,6 @@ target_link_libraries(feather PRIVATE
|
|||
${BCUR_LIBRARY}
|
||||
)
|
||||
|
||||
if(NOT APPLE)
|
||||
target_link_libraries(feather PRIVATE SingleApplication::SingleApplication)
|
||||
endif()
|
||||
|
||||
if(CHECK_UPDATES)
|
||||
target_link_libraries(feather PRIVATE openpgp)
|
||||
endif()
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
|
||||
#include "WindowManager.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QWindow>
|
||||
|
||||
#include "Application.h"
|
||||
#include "constants.h"
|
||||
#include "dialog/PasswordDialog.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::walletPassphraseNeeded, this, &WindowManager::onWalletPassphraseNeeded);
|
||||
|
||||
connect(qApp, SIGNAL(anotherInstanceStarted()), this, SLOT(raise()));
|
||||
connect(qApp, &QGuiApplication::lastWindowClosed, this, &WindowManager::quitAfterLastWindow);
|
||||
|
||||
m_tray = new QSystemTrayIcon(icons()->icon("appicons/64x64.png"));
|
||||
|
@ -66,6 +67,7 @@ WindowManager::~WindowManager() {
|
|||
qDebug() << "~WindowManager";
|
||||
m_cleanupThread->quit();
|
||||
m_cleanupThread->wait();
|
||||
qDebug() << "Cleanup thread done";
|
||||
}
|
||||
|
||||
// ######################## APPLICATION LIFECYCLE ########################
|
||||
|
@ -100,6 +102,7 @@ void WindowManager::close() {
|
|||
|
||||
torManager()->stop();
|
||||
|
||||
qDebug() << "Calling QApplication::quit()";
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ public:
|
|||
void closeWindow(MainWindow *window);
|
||||
void showWizard(WalletWizard::Page startPage);
|
||||
void restartApplication(const QString &binaryFilename);
|
||||
void raise();
|
||||
|
||||
void showSettings(Nodes *nodes, QWidget *parent, bool showProxyTab = false);
|
||||
|
||||
|
@ -59,6 +58,7 @@ public slots:
|
|||
void tryOpenWallet(const QString &path, const QString &password);
|
||||
|
||||
private slots:
|
||||
void raise();
|
||||
void onWalletOpened(Wallet *wallet);
|
||||
void onWalletCreated(Wallet *wallet);
|
||||
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-FileCopyrightText: 2020-2024 The Monero Project
|
||||
|
||||
#include <QResource>
|
||||
#include <QApplication>
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
#if !defined(Q_OS_MAC)
|
||||
#include <singleapplication.h>
|
||||
#endif
|
||||
|
||||
#include "Application.h"
|
||||
#include "config-feather.h"
|
||||
#include "constants.h"
|
||||
#include "MainWindow.h"
|
||||
#include "utils/EventFilter.h"
|
||||
#include "utils/os/Prestium.h"
|
||||
#include "WindowManager.h"
|
||||
|
@ -24,8 +16,6 @@
|
|||
#include <fstream>
|
||||
#endif
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <windows.h>
|
||||
#include <vfw.h>
|
||||
|
@ -89,12 +79,7 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
|||
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
// https://github.com/itay-grudev/SingleApplication/issues/136#issuecomment-1925441403
|
||||
QApplication app(argc, argv);
|
||||
#else
|
||||
SingleApplication app(argc, argv);
|
||||
#endif
|
||||
Application app(argc, argv);
|
||||
|
||||
QApplication::setApplicationName("Feather");
|
||||
QApplication::setApplicationVersion(FEATHER_VERSION);
|
||||
|
@ -122,6 +107,11 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
|||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if (app.isAlreadyRunning()) {
|
||||
qWarning() << "Another instance of Feather is already running";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
bool stagenet = parser.isSet(stagenetOption);
|
||||
bool testnet = parser.isSet(testnetOption);
|
||||
bool quiet = parser.isSet(quietModeOption);
|
||||
|
@ -193,8 +183,6 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
|||
|
||||
conf()->set(Config::restartRequired, false);
|
||||
|
||||
parser.process(app); // Parse again for --help and --version
|
||||
|
||||
if (!quiet) {
|
||||
QMap<QString, QString> info;
|
||||
info["Qt"] = QT_VERSION_STR;
|
||||
|
@ -238,13 +226,7 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
|||
auto wm = windowManager();
|
||||
wm->setEventFilter(&filter);
|
||||
|
||||
#if !defined(Q_OS_MAC)
|
||||
QObject::connect(&app, &SingleApplication::instanceStarted, [&wm]() {
|
||||
wm->raise();
|
||||
});
|
||||
#endif
|
||||
|
||||
int exitCode = QApplication::exec();
|
||||
qDebug() << "QApplication::exec() returned";
|
||||
int exitCode = Application::exec();
|
||||
qDebug() << "Application::exec() returned";
|
||||
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