From 2dd473eb284f2d6e70492790df9513983555db28 Mon Sep 17 00:00:00 2001 From: "Vladimir Golovnev (Glassez)" Date: Tue, 20 Jan 2015 18:00:37 +0300 Subject: [PATCH] Use unmodified QtSingleApplication on Windows. Get running application instance PID without QtSingleApplication modification. --- src/app/application.cpp | 47 +++++++++++++++---- src/app/application.h | 17 +++---- src/app/main.cpp | 12 +---- src/app/qtsingleapplication/qtlocalpeer.cpp | 47 ------------------- src/app/qtsingleapplication/qtlocalpeer.h | 3 -- .../qtsingleapplication.cpp | 6 --- .../qtsingleapplication/qtsingleapplication.h | 4 -- 7 files changed, 47 insertions(+), 89 deletions(-) diff --git a/src/app/application.cpp b/src/app/application.cpp index b547efeba..2d2e776c5 100644 --- a/src/app/application.cpp +++ b/src/app/application.cpp @@ -32,6 +32,10 @@ #include #include #include +#ifdef Q_OS_WIN +#include +#include +#endif #if (!defined(DISABLE_GUI) && defined(Q_OS_MAC)) #include @@ -41,11 +45,7 @@ #include "preferences.h" Application::Application(const QString &id, int &argc, char **argv) -#ifndef DISABLE_GUI - : SessionApplication(id, argc, argv) -#else - : QtSingleCoreApplication(id, argc, argv) -#endif + : BaseApplication(id, argc, argv) { #if defined(Q_OS_MACX) && !defined(DISABLE_GUI) if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_8) { @@ -62,6 +62,33 @@ Application::Application(const QString &id, int &argc, char **argv) #endif } +#ifdef Q_OS_WIN +bool Application::isRunning() +{ + bool running = BaseApplication::isRunning(); + QSharedMemory *sharedMem = new QSharedMemory(id() + QLatin1String("-shared-memory-key"), this); + if (!running) { + // First instance creates shared memory and store PID + if (sharedMem->create(sizeof(DWORD)) && sharedMem->lock()) { + *(static_cast(sharedMem->data())) = ::GetCurrentProcessId(); + sharedMem->unlock(); + } + } + else { + // Later instances attach to shared memory and retrieve PID + if (sharedMem->attach() && sharedMem->lock()) { + ::AllowSetForegroundWindow(*(static_cast(sharedMem->data()))); + sharedMem->unlock(); + } + } + + if (!sharedMem->isAttached()) + qWarning() << "Failed to initialize shared memory: " << sharedMem->errorString(); + + return running; +} +#endif + void Application::initializeTranslation() { Preferences* const pref = Preferences::instance(); @@ -72,10 +99,10 @@ void Application::initializeTranslation() pref->setLocale(locale); } - if (qtTranslator_.load( + if (m_qtTranslator.load( #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) QString::fromUtf8("qtbase_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath)) || - qtTranslator_.load( + m_qtTranslator.load( #endif QString::fromUtf8("qt_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { qDebug("Qt %s locale recognized, using translation.", qPrintable(locale)); @@ -83,15 +110,15 @@ void Application::initializeTranslation() else { qDebug("Qt %s locale unrecognized, using default (en).", qPrintable(locale)); } - installTranslator(&qtTranslator_); + installTranslator(&m_qtTranslator); - if (translator_.load(QString::fromUtf8(":/lang/qbittorrent_") + locale)) { + if (m_translator.load(QString::fromUtf8(":/lang/qbittorrent_") + locale)) { qDebug("%s locale recognized, using translation.", qPrintable(locale)); } else { qDebug("%s locale unrecognized, using default (en).", qPrintable(locale)); } - installTranslator(&translator_); + installTranslator(&m_translator); #ifndef DISABLE_GUI if (locale.startsWith("ar") || locale.startsWith("he")) { diff --git a/src/app/application.h b/src/app/application.h index 7047faa09..1a98dc256 100644 --- a/src/app/application.h +++ b/src/app/application.h @@ -35,23 +35,24 @@ #ifndef DISABLE_GUI #include "sessionapplication.h" +typedef SessionApplication BaseApplication; #else #include "qtsinglecoreapplication.h" +typedef QtSingleCoreApplication BaseApplication; #endif -class Application -#ifndef DISABLE_GUI - : public SessionApplication -#else - : public QtSingleCoreApplication -#endif +class Application : public BaseApplication { public: Application(const QString &id, int &argc, char **argv); +#ifdef Q_OS_WIN + bool isRunning(); +#endif + private: - QTranslator qtTranslator_; - QTranslator translator_; + QTranslator m_qtTranslator; + QTranslator m_translator; void initializeTranslation(); }; diff --git a/src/app/main.cpp b/src/app/main.cpp index 2ddde2853..a2469e730 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -90,10 +90,6 @@ public: #include "main.moc" -#if defined(Q_OS_WIN) && !defined(QBT_HAS_GETCURRENTPID) -#error You seem to have updated QtSingleApplication without porting our custom QtSingleApplication::getRunningPid() function. Please see previous version to understate how it works. -#endif - // Signal handlers #if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN) void sigintHandler(int); @@ -217,14 +213,8 @@ int main(int argc, char *argv[]) #else qDebug("qBittorrent is already running for this user."); #endif + misc::msleep(300); -#ifdef Q_OS_WIN - DWORD pid = (DWORD)app->getRunningPid(); - if (pid > 0) { - BOOL b = AllowSetForegroundWindow(pid); - qDebug("AllowSetForegroundWindow() returns %s", b ? "TRUE" : "FALSE"); - } -#endif if (!params.torrents.isEmpty()) { QString message = params.torrents.join("|"); qDebug("Passing program parameters to running instance..."); diff --git a/src/app/qtsingleapplication/qtlocalpeer.cpp b/src/app/qtsingleapplication/qtlocalpeer.cpp index effa0a016..332b0643f 100644 --- a/src/app/qtsingleapplication/qtlocalpeer.cpp +++ b/src/app/qtsingleapplication/qtlocalpeer.cpp @@ -195,56 +195,9 @@ void QtLocalPeer::receiveConnection() return; } QString message(QString::fromUtf8(uMsg)); -#ifdef Q_OS_WIN - if (message == "qbt://pid") { - qint64 pid = GetCurrentProcessId(); - socket->write((const char *)&pid, sizeof pid); - } else { - socket->write(ack, qstrlen(ack)); - } -#else socket->write(ack, qstrlen(ack)); -#endif socket->waitForBytesWritten(1000); socket->waitForDisconnected(1000); // make sure client reads ack delete socket; -#ifdef Q_OS_WIN - if (message == "qbt://pid") - return; -#endif emit messageReceived(message); //### (might take a long time to return) } - -#ifdef Q_OS_WIN -qint64 QtLocalPeer::getRunningPid() { - if (!isClient()) - return 0; - - QLocalSocket socket; - bool connOk = false; - for (int i = 0; i < 2; i++) { - // Try twice, in case the other instance is just starting up - socket.connectToServer(socketName); - connOk = socket.waitForConnected(5000/2); - if (connOk || i) - break; - Sleep(250); - } - if (!connOk) return -1; - - const char* msg = "qbt://pid"; - QDataStream ds(&socket); - ds.writeBytes(msg, qstrlen(msg)); - bool res = socket.waitForBytesWritten(5000) && socket.waitForReadyRead(5000); - if (!res) return -1; - - DWORD pid; - qint64 pid_size = sizeof pid; - while (socket.bytesAvailable() < pid_size) - socket.waitForReadyRead(); - if (socket.read((char *)&pid, pid_size) < pid_size) - return -1; - - return pid; -} -#endif diff --git a/src/app/qtsingleapplication/qtlocalpeer.h b/src/app/qtsingleapplication/qtlocalpeer.h index ebe185445..1b533b1ab 100644 --- a/src/app/qtsingleapplication/qtlocalpeer.h +++ b/src/app/qtsingleapplication/qtlocalpeer.h @@ -57,9 +57,6 @@ public: bool sendMessage(const QString &message, int timeout); QString applicationId() const { return id; } -#ifdef Q_OS_WIN - qint64 getRunningPid(); -#endif Q_SIGNALS: void messageReceived(const QString &message); diff --git a/src/app/qtsingleapplication/qtsingleapplication.cpp b/src/app/qtsingleapplication/qtsingleapplication.cpp index 8a4c7f74d..d0fb15d76 100644 --- a/src/app/qtsingleapplication/qtsingleapplication.cpp +++ b/src/app/qtsingleapplication/qtsingleapplication.cpp @@ -345,9 +345,3 @@ void QtSingleApplication::activateWindow() \obsolete */ - -#ifdef Q_OS_WIN -qint64 QtSingleApplication::getRunningPid() { - return peer->getRunningPid(); -} -#endif diff --git a/src/app/qtsingleapplication/qtsingleapplication.h b/src/app/qtsingleapplication/qtsingleapplication.h index 80fe0d21e..049406f72 100644 --- a/src/app/qtsingleapplication/qtsingleapplication.h +++ b/src/app/qtsingleapplication/qtsingleapplication.h @@ -86,10 +86,6 @@ public: // Obsolete: void initialize(bool dummy = true) { isRunning(); Q_UNUSED(dummy) } -#ifdef Q_OS_WIN -#define QBT_HAS_GETCURRENTPID - qint64 getRunningPid(); -#endif public Q_SLOTS: bool sendMessage(const QString &message, int timeout = 5000);