diff --git a/desktop/org.kde.spectacle.desktop.cmake b/desktop/org.kde.spectacle.desktop.cmake --- a/desktop/org.kde.spectacle.desktop.cmake +++ b/desktop/org.kde.spectacle.desktop.cmake @@ -140,13 +140,13 @@ Keywords[x-test]=xxsnapshotxx;xxcapturexx;xxprintxx;xxscreenshotxx;xxsnippingxx;xxsnipxx; Keywords[zh_CN]=snapshot;capture;print;screenshot;snipping;snip;快照;截图;抓取;屏幕截图;截屏;抓屏;截取; Keywords[zh_TW]=snapshot;capture;print;screenshot;snipping;snip;截圖;擷取;截圖程式 -Exec=@QtBinariesDir@/qdbus org.kde.Spectacle / StartAgent +Exec=${CMAKE_INSTALL_PREFIX}/bin/spectacle Icon=spectacle Type=Application Terminal=false StartupNotify=false Actions=FullScreenScreenShot;CurrentMonitorScreenShot;ActiveWindowScreenShot;RectangularRegionScreenShot; -X-DBUS-StartupType=Multi +X-DBUS-StartupType=Unique X-DBUS-ServiceName=org.kde.Spectacle X-KDE-Shortcuts=Print diff --git a/src/Main.cpp b/src/Main.cpp --- a/src/Main.cpp +++ b/src/Main.cpp @@ -36,12 +36,13 @@ { // set up the application - QApplication lApp(argc, argv); + QApplication app(argc, argv); - lApp.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); - lApp.setAttribute(Qt::AA_UseHighDpiPixmaps, true); + app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); + app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); KLocalizedString::setApplicationDomain("spectacle"); + QCoreApplication::setOrganizationDomain(QStringLiteral("org.kde")); KAboutData aboutData(QStringLiteral("spectacle"), i18n("Spectacle"), @@ -53,115 +54,55 @@ aboutData.addAuthor(QStringLiteral("David Redondo"), QString(), QStringLiteral("kde@david-redondo.de")); aboutData.setTranslator(i18nc("NAME OF TRANSLATORS", "Your names"), i18nc("EMAIL OF TRANSLATORS", "Your emails")); KAboutData::setApplicationData(aboutData); - lApp.setWindowIcon(QIcon::fromTheme(QStringLiteral("spectacle"))); + app.setWindowIcon(QIcon::fromTheme(QStringLiteral("spectacle"))); - // set up the command line options parser + SpectacleCore lCore; QCommandLineParser lCmdLineParser; aboutData.setupCommandLine(&lCmdLineParser); + lCore.populateCommandLineParser(&lCmdLineParser); - lCmdLineParser.addOptions({ - {{QStringLiteral("f"), QStringLiteral("fullscreen")}, i18n("Capture the entire desktop (default)")}, - {{QStringLiteral("m"), QStringLiteral("current")}, i18n("Capture the current monitor")}, - {{QStringLiteral("a"), QStringLiteral("activewindow")}, i18n("Capture the active window")}, - {{QStringLiteral("u"), QStringLiteral("windowundercursor")}, i18n("Capture the window currently under the cursor, including parents of pop-up menus")}, - {{QStringLiteral("t"), QStringLiteral("transientonly")}, i18n("Capture the window currently under the cursor, excluding parents of pop-up menus")}, - {{QStringLiteral("r"), QStringLiteral("region")}, i18n("Capture a rectangular region of the screen")}, - {{QStringLiteral("g"), QStringLiteral("gui")}, i18n("Start in GUI mode (default)")}, - {{QStringLiteral("b"), QStringLiteral("background")}, i18n("Take a screenshot and exit without showing the GUI")}, - {{QStringLiteral("s"), QStringLiteral("dbus")}, i18n("Start in DBus-Activation mode")}, - {{QStringLiteral("n"), QStringLiteral("nonotify")}, i18n("In background mode, do not pop up a notification when the screenshot is taken")}, - {{QStringLiteral("o"), QStringLiteral("output")}, i18n("In background mode, save image to specified file"), QStringLiteral("fileName")}, - {{QStringLiteral("d"), QStringLiteral("delay")}, i18n("In background mode, delay before taking the shot (in milliseconds)"), QStringLiteral("delayMsec")}, - {{QStringLiteral("c"), QStringLiteral("clipboard")}, i18n("In background mode, copy screenshot to clipboard")}, - {{QStringLiteral("w"), QStringLiteral("onclick")}, i18n("Wait for a click before taking screenshot. Invalidates delay")} - }); - - lCmdLineParser.process(lApp); + // first parsing for help-about + lCmdLineParser.process(app.arguments()); aboutData.processCommandLine(&lCmdLineParser); - // extract the capture mode - - Spectacle::CaptureMode lCaptureMode = Spectacle::CaptureMode::AllScreens; - if (lCmdLineParser.isSet(QStringLiteral("current"))) { - lCaptureMode = Spectacle::CaptureMode::CurrentScreen; - } else if (lCmdLineParser.isSet(QStringLiteral("activewindow"))) { - lCaptureMode = Spectacle::CaptureMode::ActiveWindow; - } else if (lCmdLineParser.isSet(QStringLiteral("region"))) { - lCaptureMode = Spectacle::CaptureMode::RectangularRegion; - } else if (lCmdLineParser.isSet(QStringLiteral("windowundercursor"))) { - lCaptureMode = Spectacle::CaptureMode::TransientWithParent; - } else if (lCmdLineParser.isSet(QStringLiteral("transientonly"))) { - lCaptureMode = Spectacle::CaptureMode::WindowUnderCursor; - } + // and new-instance + if (lCmdLineParser.isSet(QStringLiteral("new-instance"))){ + lCore.init(); - // are we running in background or dbus mode? + QObject::connect(&lCore, &SpectacleCore::allDone, &app, &QCoreApplication::quit, Qt::QueuedConnection); - SpectacleCore::StartMode lStartMode = SpectacleCore::StartMode::Gui; - bool lNotify = true; - bool lCopyToClipboard = false; - qint64 lDelayMsec = 0; - QString lFileName = QString(); + // fire it up + lCore.onActivateRequested(app.arguments(), QStringLiteral()); - if (lCmdLineParser.isSet(QStringLiteral("background"))) { - lStartMode = SpectacleCore::StartMode::Background; - } else if (lCmdLineParser.isSet(QStringLiteral("dbus"))) { - lStartMode = SpectacleCore::StartMode::DBus; + return app.exec(); } - switch(lStartMode) { - case SpectacleCore::StartMode::Background: - if (lCmdLineParser.isSet(QStringLiteral("nonotify"))) { - lNotify = false; - } - - if (lCmdLineParser.isSet(QStringLiteral("output"))) { - lFileName = lCmdLineParser.value(QStringLiteral("output")); - } - - if (lCmdLineParser.isSet(QStringLiteral("delay"))) { - bool lParseOk = false; - qint64 lDelayValue = lCmdLineParser.value(QStringLiteral("delay")).toLongLong(&lParseOk); - if (lParseOk) { - lDelayMsec = lDelayValue; - } - } - - if (lCmdLineParser.isSet(QStringLiteral("onclick"))) { - lDelayMsec = -1; - } - - if (lCmdLineParser.isSet(QStringLiteral("clipboard"))) { - lCopyToClipboard = true; - } - - lApp.setQuitOnLastWindowClosed(false); - break; - case SpectacleCore::StartMode::DBus: - lApp.setQuitOnLastWindowClosed(false); - break; - case SpectacleCore::StartMode::Gui: - break; - } + // Ensure that we only launch a new instance if we need to + // If there is already an instance running, we will quit here + // and activateRequested signal is triggered + // For some reason this does not work properly if behind an if + KDBusService service(KDBusService::Unique, &lCore); - // release the kraken + // Delay initialisation after we now we are in the single instance or new-instance was passed, to avoid doing it each time spectacle executable is called + lCore.init(); - SpectacleCore lCore(lStartMode, lCaptureMode, lFileName, lDelayMsec, lNotify, lCopyToClipboard); - QObject::connect(&lCore, &SpectacleCore::allDone, qApp, &QApplication::quit); + // set up the KDBusService activateRequested slot + QObject::connect(&service, &KDBusService::activateRequested, &lCore, &SpectacleCore::onActivateRequested); + QObject::connect(&lCore, &SpectacleCore::allDone, &app, &QCoreApplication::quit, Qt::QueuedConnection); QObject::connect(qApp, &QApplication::aboutToQuit, Settings::self(), &Settings::save); - - // create the dbus connections - new KDBusService(KDBusService::Multiple, &lCore); + // create the dbus connections SpectacleDBusAdapter *lDBusAdapter = new SpectacleDBusAdapter(&lCore); QObject::connect(&lCore, &SpectacleCore::grabFailed, lDBusAdapter, &SpectacleDBusAdapter::ScreenshotFailed); QObject::connect(ExportManager::instance(), &ExportManager::imageSaved, &lCore, [&](const QUrl &savedAt) { - emit lDBusAdapter->ScreenshotTaken(savedAt.toLocalFile()); + lDBusAdapter->ScreenshotTaken(savedAt.toLocalFile()); }); QDBusConnection::sessionBus().registerObject(QStringLiteral("/"), &lCore); QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.Spectacle")); // fire it up + lCore.onActivateRequested(app.arguments(), QStringLiteral()); - return lApp.exec(); + return app.exec(); } diff --git a/src/SpectacleCore.h b/src/SpectacleCore.h --- a/src/SpectacleCore.h +++ b/src/SpectacleCore.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include "ExportManager.h" #include "Gui/KSMainWindow.h" @@ -51,18 +52,15 @@ Background = 2 }; - explicit SpectacleCore(StartMode theStartMode, - Spectacle::CaptureMode theCaptureMode, - QString &theSaveFileName, - qint64 theDelayMsec, - bool theNotifyOnGrab, - bool theCopyToClipboard, - QObject *parent = nullptr); + explicit SpectacleCore(QObject *parent = nullptr); virtual ~SpectacleCore() = default; + void init(); QString filename() const; void setFilename(const QString &filename); + void populateCommandLineParser(QCommandLineParser *lCmdLineParser); + Q_SIGNALS: void errorMessage(const QString &errString); @@ -76,15 +74,15 @@ void showErrorMessage(const QString &theErrString); void screenshotUpdated(const QPixmap &thePixmap); void screenshotFailed(); - void dbusStartAgent(); void doStartDragAndDrop(); void doNotify(const QUrl &theSavedAt); void doCopyPath(const QUrl &savedAt); - private: + void onActivateRequested(QStringList arguments, const QString& /*workingDirectory */); + private: - void initGui(bool theIncludePointer, bool theIncludeDecorations); + void initGui(int theDelay, bool theIncludePointer, bool theIncludeDecorations); Platform::GrabMode toPlatformGrabMode(Spectacle::CaptureMode theCaptureMode); void setUpShortcuts(); diff --git a/src/SpectacleCore.cpp b/src/SpectacleCore.cpp --- a/src/SpectacleCore.cpp +++ b/src/SpectacleCore.cpp @@ -44,48 +44,25 @@ #include #include -SpectacleCore::SpectacleCore(StartMode theStartMode, - Spectacle::CaptureMode theCaptureMode, - QString &theSaveFileName, - qint64 theDelayMsec, - bool theNotifyOnGrab, - bool theCopyToClipboard, - QObject *parent) : +SpectacleCore::SpectacleCore(QObject *parent): QObject(parent), - mStartMode(theStartMode), - mNotify(theNotifyOnGrab), - mPlatform(loadPlatform()), mMainWindow(nullptr), mIsGuiInited(false), - mCopyToClipboard(theCopyToClipboard), mWaylandPlasmashell(nullptr) { - if (!(theSaveFileName.isEmpty() || theSaveFileName.isNull())) { - if (QDir::isRelativePath(theSaveFileName)) { - theSaveFileName = QDir::current().absoluteFilePath(theSaveFileName); - } - setFilename(theSaveFileName); - } +} + +void SpectacleCore::init() +{ + mPlatform = loadPlatform(); // essential connections connect(this, &SpectacleCore::errorMessage, this, &SpectacleCore::showErrorMessage); connect(mPlatform.get(), &Platform::newScreenshotTaken, this, &SpectacleCore::screenshotUpdated); connect(mPlatform.get(), &Platform::newScreenshotFailed, this, &SpectacleCore::screenshotFailed); - auto lImmediateAvailable = mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::Immediate); - auto lOnClickAvailable = mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::OnClick); - if ((!lOnClickAvailable) && (theDelayMsec < 0)) { - theDelayMsec = 0; - } - - // reset last region if it should not be remembered across restarts - if(!Settings::alwaysRememberRegion()) { - Settings::setCropRegion({0, 0, 0, 0}); - } - // set up the export manager auto lExportManager = ExportManager::instance(); - lExportManager->setCaptureMode(theCaptureMode); connect(lExportManager, &ExportManager::errorMessage, this, &SpectacleCore::showErrorMessage); connect(lExportManager, &ExportManager::imageSaved, this, &SpectacleCore::doCopyPath); connect(lExportManager, &ExportManager::forceNotify, this, &SpectacleCore::doNotify); @@ -108,26 +85,137 @@ registry->setup(); connection->roundtrip(); } + setUpShortcuts(); +} + +void SpectacleCore::onActivateRequested(QStringList arguments, const QString& /*workingDirectory */) +{ + // QCommandLineParser expects the first argument to be the executable name + // In the current version it just strips it away + arguments.prepend(qApp->applicationFilePath()); + + // We can't re-use QCommandLineParser instances, it preserves earlier parsed values + auto parser = new QCommandLineParser; + populateCommandLineParser(parser); + parser->parse(arguments); + + // extract the capture mode + Spectacle::CaptureMode lCaptureMode = Spectacle::CaptureMode::AllScreens; + if (parser->isSet(QStringLiteral("current"))) { + lCaptureMode = Spectacle::CaptureMode::CurrentScreen; + } else if (parser->isSet(QStringLiteral("activewindow"))) { + lCaptureMode = Spectacle::CaptureMode::ActiveWindow; + } else if (parser->isSet(QStringLiteral("region"))) { + lCaptureMode = Spectacle::CaptureMode::RectangularRegion; + } else if (parser->isSet(QStringLiteral("windowundercursor"))) { + lCaptureMode = Spectacle::CaptureMode::TransientWithParent; + } else if (parser->isSet(QStringLiteral("transientonly"))) { + lCaptureMode = Spectacle::CaptureMode::WindowUnderCursor; + } + + mStartMode = SpectacleCore::StartMode::Gui; + mNotify = true; + mCopyToClipboard = Settings::copyImageToClipboard(); + qint64 lDelayMsec = 0; + QString lFileName = QString(); + + // are we ask to run in background or dbus mode? + if (parser->isSet(QStringLiteral("background"))) { + mStartMode = SpectacleCore::StartMode::Background; + } else if (parser->isSet(QStringLiteral("dbus"))) { + mStartMode = SpectacleCore::StartMode::DBus; + } + + auto lExportManager = ExportManager::instance(); + lExportManager->setCaptureMode(lCaptureMode); + + auto lOnClickAvailable = mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::OnClick); + if ((!lOnClickAvailable) && (lDelayMsec < 0)) { + lDelayMsec = 0; + } + + if (!(lFileName.isEmpty() || lFileName.isNull())) { + if (QDir::isRelativePath(lFileName)) { + lFileName = QDir::current().absoluteFilePath(lFileName); + } + setFilename(lFileName); + } + + // reset last region if it should not be remembered across restarts + if(!Settings::alwaysRememberRegion()) { + Settings::setCropRegion({0, 0, 0, 0}); + } + + switch (mStartMode) { - switch (theStartMode) { case StartMode::DBus: + qApp->setQuitOnLastWindowClosed(false); break; + case StartMode::Background: { - auto lMsec = (KWindowSystem::compositingActive() ? 200 : 50) + theDelayMsec; - auto lShutterMode = lImmediateAvailable ? Platform::ShutterMode::Immediate : Platform::ShutterMode::OnClick; - auto lIncludePointer = Settings::includePointer(); - auto lIncludeDecorations = Settings::includeDecorations(); - const Platform::GrabMode lCaptureMode = toPlatformGrabMode(theCaptureMode); - QTimer::singleShot(lMsec, this, [ this, lCaptureMode, lShutterMode, lIncludePointer, lIncludeDecorations ]() { - mPlatform->doGrab(lShutterMode, lCaptureMode, lIncludePointer, lIncludeDecorations); - }); + if (parser->isSet(QStringLiteral("nonotify"))) { + mNotify = false; + } + + if (parser->isSet(QStringLiteral("output"))) { + lFileName = parser->value(QStringLiteral("output")); } + + if (parser->isSet(QStringLiteral("delay"))) { + bool lParseOk = false; + qint64 lDelayValue = parser->value(QStringLiteral("delay")).toLongLong(&lParseOk); + if (lParseOk) { + lDelayMsec = lDelayValue; + } + } + + if (parser->isSet(QStringLiteral("onclick"))) { + lDelayMsec = -1; + } + + if (parser->isSet(QStringLiteral("clipboard"))) { + mCopyToClipboard = true; + } + + if (!mIsGuiInited) { + static_cast(qApp->instance())->setQuitOnLastWindowClosed(false); + } + + auto lIncludePointer = Settings::includePointer(); + auto lIncludeDecorations = Settings::includeDecorations(); + takeNewScreenshot(lCaptureMode, lDelayMsec, lIncludePointer, lIncludeDecorations); + } break; + case StartMode::Gui: - initGui(Settings::includePointer(), Settings::includeDecorations()); + if (!mIsGuiInited) { + initGui(lDelayMsec, Settings::includePointer(), Settings::includeDecorations()); + } else { + using Actions = Settings::EnumPrintKeyActionRunning; + switch (Settings::printKeyActionRunning()) { + case Actions::TakeNewScreenshot: { + // 0 means Immediate, -1 onClick + int timeout = mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::Immediate) ? 0 : -1; + takeNewScreenshot(Settings::captureMode(), timeout, Settings::includePointer(), Settings::includeDecorations()); + break; + } + case Actions::FocusWindow: + if (mMainWindow->isMinimized()) { + mMainWindow->setWindowState(mMainWindow->windowState() & ~Qt::WindowMinimized); + } + mMainWindow->activateWindow(); + break; + case Actions::StartNewInstance: + QProcess newInstance; + newInstance.setProgram(QStringLiteral("spectacle")); + newInstance.setArguments({QStringLiteral("--new-instance")}); + newInstance.startDetached(); + break; + } + } + break; } - setUpShortcuts(); } void SpectacleCore::setUpShortcuts() @@ -154,53 +242,15 @@ mFileNameUrl = QUrl::fromUserInput(filename); } -// Slots - -void SpectacleCore::dbusStartAgent() -{ - qApp->setQuitOnLastWindowClosed(true); - - auto lConfig = KSharedConfig::openConfig(QStringLiteral("spectaclerc")); - KConfigGroup lGuiConfig(lConfig, "GuiConfig"); - auto lIncludePointer = lGuiConfig.readEntry("includePointer", true); - auto lIncludeDecorations = lGuiConfig.readEntry("includeDecorations", true); - - if (!(mStartMode == StartMode::Gui)) { - mStartMode = StartMode::Gui; - initGui(lIncludePointer, lIncludeDecorations); - } else { - using Actions = Settings::EnumPrintKeyActionRunning; - switch (Settings::printKeyActionRunning()) { - case Actions::TakeNewScreenshot: { - // 0 means Immediate, -1 onClick - int timeout = mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::Immediate) ? 0 : -1; - takeNewScreenshot(Settings::captureMode(), timeout, Settings::includePointer(), Settings::includeDecorations()); - break; - } - case Actions::FocusWindow: - if (mMainWindow->isMinimized()) { - mMainWindow->setWindowState(mMainWindow->windowState() & ~Qt::WindowMinimized); - } - mMainWindow->activateWindow(); - break; - case Actions::StartNewInstance: - QProcess newInstance; - newInstance.setProgram(QStringLiteral("spectacle")); - newInstance.startDetached(); - break; - } - } -} - void SpectacleCore::takeNewScreenshot(Spectacle::CaptureMode theCaptureMode, int theTimeout, bool theIncludePointer, bool theIncludeDecorations) { ExportManager::instance()->setCaptureMode(theCaptureMode); auto lGrabMode = toPlatformGrabMode(theCaptureMode); - if (theTimeout < 0) { + if (theTimeout < 0 || !mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::Immediate)) { mPlatform->doGrab(Platform::ShutterMode::OnClick, lGrabMode, theIncludePointer, theIncludeDecorations); return; } @@ -253,40 +303,39 @@ case StartMode::Background: case StartMode::DBus: { - if (mNotify) { - connect(lExportManager, &ExportManager::imageSaved, this, &SpectacleCore::doNotify); - } - if (mCopyToClipboard) { lExportManager->doCopyToClipboard(mNotify); } else { QUrl lSavePath = (mStartMode == StartMode::Background && mFileNameUrl.isValid() && mFileNameUrl.isLocalFile()) ? mFileNameUrl : QUrl(); - lExportManager->doSave(lSavePath); + lExportManager->doSave(lSavePath, mNotify); } - // if we notify, we emit allDone only if the user either dismissed the notification or pressed - // the "Open" button, otherwise the app closes before it can react to it. - if (!mNotify && mCopyToClipboard) { - // Allow some time for clipboard content to transfer if '--nonotify' is used, see Bug #411263 - // TODO: Find better solution - QTimer::singleShot(250, this, &SpectacleCore::allDone); - } else if (!mNotify) { - emit allDone(); + // if we don't have a Gui already opened, emit allDone + if (!this->mIsGuiInited) { + // if we notify, we emit allDone only if the user either dismissed the notification or pressed + // the "Open" button, otherwise the app closes before it can react to it. + if (!mNotify && mCopyToClipboard) { + // Allow some time for clipboard content to transfer if '--nonotify' is used, see Bug #411263 + // TODO: Find better solution + QTimer::singleShot(250, this, &SpectacleCore::allDone); + } else if (!mNotify) { + emit allDone(); + } } } break; case StartMode::Gui: mMainWindow->setScreenshotAndShow(thePixmap); bool autoSaveImage = Settings::autoSaveImage(); - bool copyImageToClipboard = Settings::copyImageToClipboard(); + bool mCopyImageToClipboard = Settings::copyImageToClipboard(); - if (autoSaveImage && copyImageToClipboard) { + if (autoSaveImage && mCopyImageToClipboard) { lExportManager->doSaveAndCopy(); } else if (autoSaveImage) { lExportManager->doSave(); - } else if (copyImageToClipboard) { + } else if (mCopyImageToClipboard) { lExportManager->doCopyToClipboard(false); } } @@ -355,16 +404,16 @@ if (index == 0) { new KRun(theSavedAt, nullptr); QTimer::singleShot(250, this, [this] { - if (mStartMode != StartMode::Gui || Settings::quitAfterSaveCopyExport()) { + if (!mIsGuiInited || Settings::quitAfterSaveCopyExport()) { emit allDone(); } }); } }); } connect(lNotify, &QObject::destroyed, this, [this] { - if (mStartMode != StartMode::Gui || Settings::quitAfterSaveCopyExport()) { + if (!mIsGuiInited || Settings::quitAfterSaveCopyExport()) { emit allDone(); } }); @@ -379,6 +428,27 @@ } } +void SpectacleCore::populateCommandLineParser(QCommandLineParser *lCmdLineParser) +{ + lCmdLineParser->addOptions({ + {{QStringLiteral("f"), QStringLiteral("fullscreen")}, i18n("Capture the entire desktop (default)")}, + {{QStringLiteral("m"), QStringLiteral("current")}, i18n("Capture the current monitor")}, + {{QStringLiteral("a"), QStringLiteral("activewindow")}, i18n("Capture the active window")}, + {{QStringLiteral("u"), QStringLiteral("windowundercursor")}, i18n("Capture the window currently under the cursor, including parents of pop-up menus")}, + {{QStringLiteral("t"), QStringLiteral("transientonly")}, i18n("Capture the window currently under the cursor, excluding parents of pop-up menus")}, + {{QStringLiteral("r"), QStringLiteral("region")}, i18n("Capture a rectangular region of the screen")}, + {{QStringLiteral("g"), QStringLiteral("gui")}, i18n("Start in GUI mode (default)")}, + {{QStringLiteral("b"), QStringLiteral("background")}, i18n("Take a screenshot and exit without showing the GUI")}, + {{QStringLiteral("s"), QStringLiteral("dbus")}, i18n("Start in DBus-Activation mode")}, + {{QStringLiteral("n"), QStringLiteral("nonotify")}, i18n("In background mode, do not pop up a notification when the screenshot is taken")}, + {{QStringLiteral("o"), QStringLiteral("output")}, i18n("In background mode, save image to specified file"), QStringLiteral("fileName")}, + {{QStringLiteral("d"), QStringLiteral("delay")}, i18n("In background mode, delay before taking the shot (in milliseconds)"), QStringLiteral("delayMsec")}, + {{QStringLiteral("c"), QStringLiteral("clipboard")}, i18n("In background mode, copy screenshot to clipboard")}, + {{QStringLiteral("w"), QStringLiteral("onclick")}, i18n("Wait for a click before taking screenshot. Invalidates delay")}, + {{QStringLiteral("i"), QStringLiteral("new-instance")}, i18n("Starts a new GUI instance of spectacle without registering to DBus")} + }); +} + void SpectacleCore::doStartDragAndDrop() { auto lExportManager = ExportManager::instance(); @@ -419,21 +489,16 @@ return Platform::GrabMode::InvalidChoice; } -void SpectacleCore::initGui(bool theIncludePointer, bool theIncludeDecorations) +void SpectacleCore::initGui(int theDelay, bool theIncludePointer, bool theIncludeDecorations) { if (!mIsGuiInited) { mMainWindow = std::make_unique(mPlatform->supportedGrabModes(), mPlatform->supportedShutterModes()); connect(mMainWindow.get(), &KSMainWindow::newScreenshotRequest, this, &SpectacleCore::takeNewScreenshot); connect(mMainWindow.get(), &KSMainWindow::dragAndDropRequest, this, &SpectacleCore::doStartDragAndDrop); mIsGuiInited = true; - - auto lShutterMode = mPlatform->supportedShutterModes().testFlag(Platform::ShutterMode::Immediate) ? Platform::ShutterMode::Immediate : Platform::ShutterMode::OnClick; - auto lGrabMode = toPlatformGrabMode(ExportManager::instance()->captureMode()); - - QTimer::singleShot(0, this, [this, lShutterMode, lGrabMode, theIncludePointer, theIncludeDecorations]() { - mPlatform->doGrab(lShutterMode, lGrabMode, theIncludePointer, theIncludeDecorations); - }); } + + takeNewScreenshot(ExportManager::instance()->captureMode(), theDelay, theIncludePointer, theIncludeDecorations); } diff --git a/src/SpectacleDBusAdapter.h b/src/SpectacleDBusAdapter.h --- a/src/SpectacleDBusAdapter.h +++ b/src/SpectacleDBusAdapter.h @@ -28,36 +28,6 @@ { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.Spectacle") - Q_CLASSINFO("D-Bus Introspection", "" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - "" - ) - public: SpectacleDBusAdapter(SpectacleCore *parent); @@ -67,7 +37,6 @@ public Q_SLOTS: - Q_NOREPLY void StartAgent(); Q_NOREPLY void FullScreen(bool includeMousePointer); Q_NOREPLY void CurrentScreen(bool includeMousePointer); Q_NOREPLY void ActiveWindow(bool includeWindowDecorations, bool includeMousePointer); diff --git a/src/SpectacleDBusAdapter.cpp b/src/SpectacleDBusAdapter.cpp --- a/src/SpectacleDBusAdapter.cpp +++ b/src/SpectacleDBusAdapter.cpp @@ -33,32 +33,27 @@ return static_cast(QObject::parent()); } -Q_NOREPLY void SpectacleDBusAdapter::StartAgent() -{ - parent()->dbusStartAgent(); -} - -Q_NOREPLY void SpectacleDBusAdapter::FullScreen(bool includeMousePointer) +void SpectacleDBusAdapter::FullScreen(bool includeMousePointer) { parent()->takeNewScreenshot(Spectacle::CaptureMode::AllScreens, 0, includeMousePointer, true); } -Q_NOREPLY void SpectacleDBusAdapter::CurrentScreen(bool includeMousePointer) +void SpectacleDBusAdapter::CurrentScreen(bool includeMousePointer) { parent()->takeNewScreenshot(Spectacle::CaptureMode::CurrentScreen, 0, includeMousePointer, true); } -Q_NOREPLY void SpectacleDBusAdapter::ActiveWindow(bool includeWindowDecorations, bool includeMousePointer) +void SpectacleDBusAdapter::ActiveWindow(bool includeWindowDecorations, bool includeMousePointer) { parent()->takeNewScreenshot(Spectacle::CaptureMode::ActiveWindow, 0, includeMousePointer, includeWindowDecorations); } -Q_NOREPLY void SpectacleDBusAdapter::WindowUnderCursor(bool includeWindowDecorations, bool includeMousePointer) +void SpectacleDBusAdapter::WindowUnderCursor(bool includeWindowDecorations, bool includeMousePointer) { parent()->takeNewScreenshot(Spectacle::CaptureMode::WindowUnderCursor, 0, includeMousePointer, includeWindowDecorations); } -Q_NOREPLY void SpectacleDBusAdapter::RectangularRegion(bool includeMousePointer) +void SpectacleDBusAdapter::RectangularRegion(bool includeMousePointer) { parent()->takeNewScreenshot(Spectacle::CaptureMode::RectangularRegion, 0, includeMousePointer, false); }