diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c933bdd6f1..044cd9a7cb 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -13,6 +13,15 @@ target_sources(flameshot PRIVATE qguiappcurrentscreen.cpp ) -IF (WIN32) +if (USE_KDSINGLEAPPLICATION) +if (NOT WIN32) +target_sources(flameshot PRIVATE + signaldaemon.h + signaldaemon.cpp +) +endif () +endif () + +if (WIN32) target_sources(flameshot PRIVATE globalshortcutfilter.h globalshortcutfilter.cpp) -ENDIF () +endif () \ No newline at end of file diff --git a/src/core/signaldaemon.cpp b/src/core/signaldaemon.cpp new file mode 100644 index 0000000000..a3ecf91961 --- /dev/null +++ b/src/core/signaldaemon.cpp @@ -0,0 +1,62 @@ +#include "signaldaemon.h" +#include +#include +#include +#include +#include +#include + +int SignalDaemon::sigintFd[2]; +int SignalDaemon::sigtermFd[2]; + +SignalDaemon::SignalDaemon(QObject* parent) + : QObject(parent) +{ + if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigintFd)) + qFatal("Couldn't create INT socketpair"); + + if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigtermFd)) + qFatal("Couldn't create TERM socketpair"); + snInt = new QSocketNotifier(sigintFd[1], QSocketNotifier::Read, this); + connect( + snInt, SIGNAL(activated(QSocketDescriptor)), this, SLOT(handleSigInt())); + snTerm = new QSocketNotifier(sigtermFd[1], QSocketNotifier::Read, this); + connect(snTerm, + SIGNAL(activated(QSocketDescriptor)), + this, + SLOT(handleSigTerm())); +} + +void SignalDaemon::intSignalHandler(int) +{ + char msg = 1; + ::write(sigintFd[0], &msg, sizeof(msg)); +} + +void SignalDaemon::termSignalHandler(int) +{ + char msg = 1; + ::write(sigtermFd[0], &msg, sizeof(msg)); +} + +void SignalDaemon::handleSigTerm() +{ + snTerm->setEnabled(false); + char tmp = 0; + ::read(sigtermFd[1], &tmp, sizeof(tmp)); + + QApplication::quit(); + snTerm->setEnabled(true); +} + +void SignalDaemon::handleSigInt() +{ + snInt->setEnabled(false); + + char tmp = 0; + ::read(sigintFd[1], &tmp, sizeof(tmp)); + + QApplication::quit(); + + snInt->setEnabled(true); +} diff --git a/src/core/signaldaemon.h b/src/core/signaldaemon.h new file mode 100644 index 0000000000..441167497f --- /dev/null +++ b/src/core/signaldaemon.h @@ -0,0 +1,27 @@ +#include +#include + +class SignalDaemon : public QObject +{ + Q_OBJECT + +public: + SignalDaemon(QObject* parent = 0); + ~SignalDaemon() = default; + + // Unix signal handlers. + static void intSignalHandler(int unused); + static void termSignalHandler(int unused); + +public slots: + // Qt signal handlers. + void handleSigInt(); + void handleSigTerm(); + +private: + static int sigintFd[2]; + static int sigtermFd[2]; + + QSocketNotifier* snInt; + QSocketNotifier* snTerm; +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index d025e0b4ce..4077412822 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,10 @@ #ifdef USE_KDSINGLEAPPLICATION #include "kdsingleapplication.h" +#ifdef Q_OS_UNIX +#include "core/signaldaemon.h" +#include "csignal" +#endif #endif #include "abstractlogger.h" @@ -34,6 +38,31 @@ // Required for saving button list QList Q_DECLARE_METATYPE(QList) +#if defined(USE_KDSINGLEAPPLICATION) && defined(Q_OS_UNIX) +static int setup_unix_signal_handlers() +{ + struct sigaction sint, term; + + sint.sa_handler = SignalDaemon::intSignalHandler; + sigemptyset(&sint.sa_mask); + sint.sa_flags = 0; + sint.sa_flags |= SA_RESTART; + + if (sigaction(SIGINT, &sint, 0)) + return 1; + + term.sa_handler = SignalDaemon::termSignalHandler; + sigemptyset(&term.sa_mask); + term.sa_flags = 0; + term.sa_flags |= SA_RESTART; + + if (sigaction(SIGTERM, &term, 0)) + return 2; + + return 0; +} +#endif + int requestCaptureAndWait(const CaptureRequest& req) { Flameshot* flameshot = Flameshot::instance(); @@ -149,11 +178,13 @@ int main(int argc, char* argv[]) QApplication app(argc, argv); #ifdef USE_KDSINGLEAPPLICATION - KDSingleApplication kdsa(QStringLiteral("flameshot")); +#ifdef Q_OS_UNIX + setup_unix_signal_handlers(); + auto signalDaemon = SignalDaemon(); +#endif + auto kdsa = KDSingleApplication(QStringLiteral("flameshot")); if (!kdsa.isPrimaryInstance()) { - // AbstractLogger::warning() - // << QStringLiteral("Closing second Flameshot instance!"); return 0; // Quit } #endif