diff --git a/src/ipc.cpp b/src/ipc.cpp index 69f193d02..83171c7f6 100644 --- a/src/ipc.cpp +++ b/src/ipc.cpp @@ -191,9 +191,16 @@ bool IPC::isCurrentOwner() */ void IPC::registerEventHandler(const QString& name, IPCEventHandler handler, void* userData) { + const std::lock_guard lock(eventHandlersMutex); eventHandlers[name] = {handler, userData}; } +void IPC::unregisterEventHandler(const QString& name) +{ + const std::lock_guard lock(eventHandlersMutex); + eventHandlers.remove(name); +} + bool IPC::isEventAccepted(time_t time) { bool result = false; @@ -309,6 +316,7 @@ void IPC::processEvents() // Non-main instance is limited to events destined for specific profile it runs } + const std::lock_guard lock(eventHandlersMutex); while (IPCEvent* evt = fetchEvent()) { QString name = QString::fromUtf8(evt->name); auto it = eventHandlers.find(name); diff --git a/src/ipc.h b/src/ipc.h index 57642cdce..9bc90c7be 100644 --- a/src/ipc.h +++ b/src/ipc.h @@ -26,6 +26,7 @@ #include #include #include +#include using IPCEventHandler = std::function; @@ -42,7 +43,7 @@ protected: static const int OWNERSHIP_TIMEOUT_S = 5; public: - IPC(uint32_t profileId_); + explicit IPC(uint32_t profileId_); ~IPC(); struct IPCEvent @@ -69,6 +70,7 @@ public: time_t postEvent(const QString& name, const QByteArray& data = QByteArray(), uint32_t dest = 0); bool isCurrentOwner(); void registerEventHandler(const QString& name, IPCEventHandler handler, void* userData); + void unregisterEventHandler(const QString& name); bool isEventAccepted(time_t time); bool waitUntilAccepted(time_t time, int32_t timeout = -1); bool isAttached() const; @@ -93,5 +95,6 @@ private: uint64_t globalId; uint32_t profileId; QSharedMemory globalMemory; + mutable std::mutex eventHandlersMutex; QMap eventHandlers; }; diff --git a/src/main.cpp b/src/main.cpp index 47b3018f0..ddaeb6a28 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -369,7 +369,7 @@ int main(int argc, char* argv[]) if (firstParam.startsWith("tox:")) { eventType = "uri"; } else if (firstParam.endsWith(".tox")) { - eventType = "save"; + eventType = ToxSave::eventHandlerKey; } else { qCritical() << "Invalid argument"; return EXIT_FAILURE; @@ -403,6 +403,7 @@ int main(int argc, char* argv[]) // cannot be integrated into a central model object yet nexus.setSettings(settings.get()); nexus.setMessageBoxManager(messageBoxManager.get()); + nexus.setIpc(&ipc); auto& cameraSource = Nexus::getCameraSource(); // Autologin // TODO (kriby): Shift responsibility of linking views to model objects from nexus @@ -427,19 +428,19 @@ int main(int argc, char* argv[]) } uriDialog = std::unique_ptr(new ToxURIDialog(nullptr, profile->getCore(), *messageBoxManager)); - toxSave = std::unique_ptr(new ToxSave{*settings}); + toxSave = std::unique_ptr(new ToxSave{*settings, ipc}); if (ipc.isAttached()) { // Start to accept Inter-process communication ipc.registerEventHandler("uri", &toxURIEventHandler, uriDialog.get()); - ipc.registerEventHandler("save", &ToxSave::toxSaveEventHandler, toxSave.get()); - ipc.registerEventHandler("activate", &toxActivateEventHandler, nullptr); + ipc.registerEventHandler(ToxSave::eventHandlerKey, &ToxSave::toxSaveEventHandler, toxSave.get()); + nexus.registerActivate(); } // Event was not handled by already running instance therefore we handle it ourselves if (eventType == "uri") { uriDialog->handleToxURI(firstParam); - } else if (eventType == "save") { + } else if (eventType == ToxSave::eventHandlerKey) { toxSave->handleToxSave(firstParam); } diff --git a/src/nexus.cpp b/src/nexus.cpp index 746732941..dc2b316a2 100644 --- a/src/nexus.cpp +++ b/src/nexus.cpp @@ -235,7 +235,8 @@ void Nexus::showMainGUI() assert(profile); // Create GUI - widget = new Widget(*profile, *audioControl, *cameraSource, *settings, *style); + widget = new Widget(*profile, *audioControl, *cameraSource, *settings, *style, + *ipc); // Start GUI widget->init(); @@ -349,6 +350,16 @@ void Nexus::setMessageBoxManager(IMessageBoxManager* messageBoxManager_) messageBoxManager = messageBoxManager_; } +void Nexus::setIpc(IPC* ipc_) +{ + ipc = ipc_; +} + +void Nexus::registerActivate() +{ + widget->registerActivate(); +} + #ifdef Q_OS_MAC void Nexus::retranslateUi() { diff --git a/src/nexus.h b/src/nexus.h index 28e7b4c09..d94b5b158 100644 --- a/src/nexus.h +++ b/src/nexus.h @@ -35,6 +35,7 @@ class QCommandLineParser; class CameraSource; class Style; class IMessageBoxManager; +class IPC; #ifdef Q_OS_MAC class QMenuBar; @@ -53,12 +54,14 @@ public: void showMainGUI(); void setSettings(Settings* settings_); void setMessageBoxManager(IMessageBoxManager* messageBoxManager); + void setIpc(IPC* ipc); void setParser(QCommandLineParser* parser_); static Nexus& getInstance(); static void destroyInstance(); Profile* getProfile(); static Widget* getDesktopGUI(); static CameraSource& getCameraSource(); + void registerActivate(); #ifdef Q_OS_MAC @@ -113,4 +116,5 @@ private: std::unique_ptr cameraSource; std::unique_ptr