diff --git a/src/app/main.cpp b/src/app/main.cpp index 9e4caf1e2e3..3292fef039b 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -70,8 +70,13 @@ static const char fixedOptionsC[] = "Options:\n" " -help Display this help\n" " -version Display program version\n" -" -client Attempt to connect to already running instance\n" -" -settingspath Override the default path where user settings are stored\n"; +" -client Attempt to connect to already running first instance\n" +" -settingspath Override the default path where user settings are stored\n" +#if !defined(Q_OS_WIN) +" -pid Attempt to connect to instance given by pid\n"; +#else +; +#endif static const char HELP_OPTION1[] = "-h"; static const char HELP_OPTION2[] = "-help"; @@ -80,6 +85,9 @@ static const char HELP_OPTION4[] = "--help"; static const char VERSION_OPTION[] = "-version"; static const char CLIENT_OPTION[] = "-client"; static const char SETTINGS_OPTION[] = "-settingspath"; +#if !defined(Q_OS_WIN) +static const char PID_OPTION[] = "-pid"; +#endif typedef QList PluginSpecSet; @@ -310,6 +318,9 @@ int main(int argc, char **argv) appOptions.insert(QLatin1String(HELP_OPTION4), false); appOptions.insert(QLatin1String(VERSION_OPTION), false); appOptions.insert(QLatin1String(CLIENT_OPTION), false); +#if !defined(Q_OS_WIN) + appOptions.insert(QLatin1String(PID_OPTION), true); +#endif QString errorMessage; if (!pluginManager.parseOptions(arguments, appOptions, &foundAppOptions, &errorMessage)) { displayError(errorMessage); @@ -348,19 +359,29 @@ int main(int argc, char **argv) return 0; } - const bool isFirstInstance = !app.isRunning(); - if (!isFirstInstance && foundAppOptions.contains(QLatin1String(CLIENT_OPTION))) { - if (app.sendMessage(pluginManager.serializedArguments())) + qint64 pid = -1; +#if !defined(Q_OS_WIN) + if (foundAppOptions.contains(QLatin1String(PID_OPTION))) { + QString pidString = foundAppOptions.value(QLatin1String(PID_OPTION)); + bool pidOk; + qint64 tmpPid = pidString.toInt(&pidOk); + if (pidOk) + pid = tmpPid; + } +#endif + + if (app.isRunning() && (pid != -1 || foundAppOptions.contains(QLatin1String(CLIENT_OPTION)))) { + if (app.sendMessage(pluginManager.serializedArguments(), 5000 /*timeout*/, pid)) return 0; // Message could not be send, maybe it was in the process of quitting - if (app.isRunning()) { + if (app.isRunning(pid)) { // Nah app is still running, ask the user int button = askMsgSendFailed(); while(button == QMessageBox::Retry) { - if (app.sendMessage(pluginManager.serializedArguments())) + if (app.sendMessage(pluginManager.serializedArguments(), 5000 /*timeout*/, pid)) return 0; - if (!app.isRunning()) // App quit while we were trying so start a new creator + if (!app.isRunning(pid)) // App quit while we were trying so start a new creator button = QMessageBox::Yes; else button = askMsgSendFailed(); @@ -380,13 +401,10 @@ int main(int argc, char **argv) errorOverview.exec(); } - if (isFirstInstance) { - // Set up lock and remote arguments for the first instance only. - // Silently fallback to unconnected instances for any subsequent instances. - app.initialize(); - QObject::connect(&app, SIGNAL(messageReceived(QString)), - &pluginManager, SLOT(remoteArguments(QString))); - } + // Set up lock and remote arguments. + app.initialize(); + QObject::connect(&app, SIGNAL(messageReceived(QString)), + &pluginManager, SLOT(remoteArguments(QString))); QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), coreplugin->plugin(), SLOT(fileOpenRequest(QString))); diff --git a/src/shared/qtsingleapplication/qtsingleapplication.cpp b/src/shared/qtsingleapplication/qtsingleapplication.cpp index 84f2e731b65..90eb5404343 100644 --- a/src/shared/qtsingleapplication/qtsingleapplication.cpp +++ b/src/shared/qtsingleapplication/qtsingleapplication.cpp @@ -41,8 +41,10 @@ namespace SharedTools { void QtSingleApplication::sysInit(const QString &appId) { actWin = 0; - peer = new QtLocalPeer(this, appId); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); + firstPeer = new QtLocalPeer(this, appId); + connect(firstPeer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); + pidPeer = new QtLocalPeer(this, appId + QLatin1Char('-') + QString::number(::getpid(), 10)); + connect(pidPeer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } @@ -56,6 +58,7 @@ QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) : QApplication(argc, argv) { + this->appId = appId; sysInit(appId); } @@ -84,6 +87,7 @@ QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE colormap) : QApplication(dpy, argc, argv, visual, colormap) { + this->appId = appId; sysInit(appId); } #endif @@ -98,30 +102,50 @@ bool QtSingleApplication::event(QEvent *event) return QApplication::event(event); } -bool QtSingleApplication::isRunning() +bool QtSingleApplication::isRunning(qint64 pid) { - return peer->isClient(); + if (pid == -1) + return firstPeer->isClient(); + + QtLocalPeer peer(this, appId + QLatin1Char('-') + QString::number(pid, 10)); + return peer.isClient(); } -bool QtSingleApplication::sendMessage(const QString &message, int timeout) +void QtSingleApplication::initialize(bool) { - return peer->sendMessage(message, timeout); + firstPeer->isClient(); + pidPeer->isClient(); } +bool QtSingleApplication::sendMessage(const QString &message, int timeout, qint64 pid) +{ + if (pid == -1) + return firstPeer->sendMessage(message, timeout); + + QtLocalPeer peer(this, appId + QLatin1Char('-') + QString::number(pid, 10)); + return peer.sendMessage(message, timeout); +} QString QtSingleApplication::id() const { - return peer->applicationId(); + return firstPeer->applicationId(); } +QString QtSingleApplication::applicationId() const +{ + return appId; +} void QtSingleApplication::setActivationWindow(QWidget *aw, bool activateOnMessage) { actWin = aw; - if (activateOnMessage) - connect(peer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow())); - else - disconnect(peer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow())); + if (activateOnMessage) { + connect(firstPeer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow())); + connect(pidPeer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow())); + } else { + disconnect(firstPeer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow())); + disconnect(pidPeer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow())); + } } diff --git a/src/shared/qtsingleapplication/qtsingleapplication.h b/src/shared/qtsingleapplication/qtsingleapplication.h index 42d83e36bd5..9b446269165 100644 --- a/src/shared/qtsingleapplication/qtsingleapplication.h +++ b/src/shared/qtsingleapplication/qtsingleapplication.h @@ -49,22 +49,23 @@ public: QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0); #endif - bool isRunning(); + bool isRunning(qint64 pid = -1); + QString id() const; void setActivationWindow(QWidget* aw, bool activateOnMessage = true); QWidget* activationWindow() const; bool event(QEvent *event); + QString applicationId() const; public Q_SLOTS: - bool sendMessage(const QString &message, int timeout = 5000); + bool sendMessage(const QString &message, int timeout = 5000, qint64 pid = -1); void activateWindow(); //Obsolete methods: public: - void initialize(bool = true) - { isRunning(); } + void initialize(bool = true); #if defined(Q_WS_X11) QtSingleApplication(Display* dpy, const QString &id, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); @@ -77,8 +78,10 @@ Q_SIGNALS: private: void sysInit(const QString &appId = QString()); - QtLocalPeer *peer; + QtLocalPeer *firstPeer; + QtLocalPeer *pidPeer; QWidget *actWin; + QString appId; }; } // namespace SharedTools