mirror of
https://github.com/fergalmoran/flameshot.git
synced 2026-01-10 05:10:49 +00:00
Reduce dependence on D-Bus (#2003)
* Handle captures without sigslots Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Set {app,organization}Name and version consistently Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Make 'full' dbus-free Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Move CaptureRequest::exportCapture to Controller We need to wait until the upload widget (or similar widgets) have finished before exiting. This must be done using a signal. The problem is that CaptureRequest can't be guaranteed to survive until the widget has finished what it's doing. Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Use QApplication with the 'full' subcommand Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Do unto 'screen' as we did to 'full' Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add FlameshotDaemon singleton class Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Support clipboard hosting for both pixmaps and text * Fix upload handling Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Do not show tray icon if not daemon Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Clean up handling of pin task Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove annoying Qt warning messages The messages were caused by the color wheel. Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix small bug in Controller::exportCapture * Fix --raw output * Make 'gui' dbus-independent Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix accept on select bug Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix compile error on Windows Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Make it work on Windows * Remove obsolete function in main.cpp Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Make 'launcher' work without dbus Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * clang-format, sigh Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Enable CLI parsing on MacOS Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Make 'config' work without dbus Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Small refactor of capture request handling Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove obsolete DBusUtils Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove unused D-Bus sigslots Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove D-Bus methods openConfig, autostartEnabled and trayIconEnabled Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove D-Bus method requestCapture Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Remove CaptureRequest id mechanism Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix 'launcher' crash Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Handle clipboard notifications properly Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add 'autoCloseIdleDaemon' option Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Document FlameshotDaemon class Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Make 'flameshot gui' run in single-application mode Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add `allowmultipleGuiInstances` config option Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix endless loop with multiple GUI instances Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Move upload confirmation dialog where it belongs Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Add the new config options to the GUI as well Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix failing build on Windows Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Handle persistence on MacOS Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * fixed notifications on macos * Fixed display on macos * Reformat tests/action_options.sh Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> * Fix infinite recursion in tests/action_options.sh Signed-off-by: Haris Gušić <harisgusic.dev@gmail.com> Co-authored-by: Dearsh Oberoi <59907159+deo002@users.noreply.github.com> Co-authored-by: Jeremy Borgman <borgman.jeremy@pm.me>
This commit is contained in:
266
src/main.cpp
266
src/main.cpp
@@ -11,6 +11,7 @@
|
||||
#include "src/config/styleoverride.h"
|
||||
#include "src/core/capturerequest.h"
|
||||
#include "src/core/controller.h"
|
||||
#include "src/core/flameshotdaemon.h"
|
||||
#include "src/utils/confighandler.h"
|
||||
#include "src/utils/filenamehandler.h"
|
||||
#include "src/utils/pathinfo.h"
|
||||
@@ -19,7 +20,7 @@
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QLibraryInfo>
|
||||
#include <QTextStream>
|
||||
#include <QSharedMemory>
|
||||
#include <QTimer>
|
||||
#include <QTranslator>
|
||||
|
||||
@@ -28,22 +29,12 @@
|
||||
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
|
||||
#include "src/core/flameshotdbusadapter.h"
|
||||
#include "src/utils/dbusutils.h"
|
||||
#include <QApplication>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
#include <desktopinfo.h>
|
||||
#endif
|
||||
|
||||
int waitAfterConnecting(int delay, QCoreApplication& app)
|
||||
{
|
||||
QTimer t;
|
||||
t.setInterval(delay + 1000 * 60 * 15); // 15 minutes timeout
|
||||
QObject::connect(&t, &QTimer::timeout, qApp, &QCoreApplication::quit);
|
||||
t.start();
|
||||
// wait
|
||||
return app.exec();
|
||||
}
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// source: https://github.com/ksnip/ksnip/issues/416
|
||||
void wayland_hacks()
|
||||
@@ -56,6 +47,42 @@ void wayland_hacks()
|
||||
}
|
||||
#endif
|
||||
|
||||
void requestCaptureAndWait(const CaptureRequest& req)
|
||||
{
|
||||
Controller* controller = Controller::getInstance();
|
||||
controller->requestCapture(req);
|
||||
QObject::connect(
|
||||
controller, &Controller::captureTaken, [&](QPixmap, QRect) {
|
||||
// Only useful on MacOS because each instance hosts its own widgets
|
||||
if (!FlameshotDaemon::isThisInstanceHostingWidgets()) {
|
||||
qApp->exit(0);
|
||||
}
|
||||
});
|
||||
QObject::connect(controller, &Controller::captureFailed, []() {
|
||||
// TODO use abstract logger
|
||||
// TODO do we have to do more stuff here?
|
||||
QTextStream(stderr) << "screenshot aborted\n";
|
||||
qApp->exit(1);
|
||||
});
|
||||
qApp->exec();
|
||||
}
|
||||
|
||||
QSharedMemory* guiMutexLock()
|
||||
{
|
||||
QString key = "org.flameshot.Flameshot-" APP_VERSION;
|
||||
auto* shm = new QSharedMemory(key);
|
||||
#ifdef Q_OS_UNIX
|
||||
// Destroy shared memory if the last instance crashed on Unix
|
||||
shm->attach();
|
||||
delete shm;
|
||||
shm = new QSharedMemory(key);
|
||||
#endif
|
||||
if (!shm->create(1)) {
|
||||
return nullptr;
|
||||
}
|
||||
return shm;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
@@ -67,7 +94,9 @@ int main(int argc, char* argv[])
|
||||
// required for the button serialization
|
||||
// TODO: change to QVector in v1.0
|
||||
qRegisterMetaTypeStreamOperators<QList<int>>("QList<int>");
|
||||
qApp->setApplicationVersion(static_cast<QString>(APP_VERSION));
|
||||
QCoreApplication::setApplicationVersion(APP_VERSION);
|
||||
QCoreApplication::setApplicationName(QStringLiteral("flameshot"));
|
||||
QCoreApplication::setOrganizationName(QStringLiteral("flameshot"));
|
||||
|
||||
// no arguments, just launch Flameshot
|
||||
if (argc == 1) {
|
||||
@@ -97,14 +126,14 @@ int main(int argc, char* argv[])
|
||||
"_",
|
||||
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
||||
|
||||
app.installTranslator(&translator);
|
||||
app.installTranslator(&qtTranslator);
|
||||
app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
|
||||
app.setApplicationName(QStringLiteral("flameshot"));
|
||||
app.setOrganizationName(QStringLiteral("flameshot"));
|
||||
qApp->installTranslator(&translator);
|
||||
qApp->installTranslator(&qtTranslator);
|
||||
qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
|
||||
|
||||
auto c = Controller::getInstance();
|
||||
#if not(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
|
||||
FlameshotDaemon::start();
|
||||
|
||||
#if !(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
|
||||
new FlameshotDBusAdapter(c);
|
||||
QDBusConnection dbus = QDBusConnection::sessionBus();
|
||||
if (!dbus.isConnected()) {
|
||||
@@ -114,20 +143,14 @@ int main(int argc, char* argv[])
|
||||
dbus.registerObject(QStringLiteral("/"), c);
|
||||
dbus.registerService(QStringLiteral("org.flameshot.Flameshot"));
|
||||
#endif
|
||||
// Exporting captures must be connected after the dbus interface
|
||||
// or the dbus signal gets blocked until we end the exports.
|
||||
c->enableExports();
|
||||
return app.exec();
|
||||
return qApp->exec();
|
||||
}
|
||||
|
||||
#if not(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
|
||||
#if !defined(Q_OS_WIN)
|
||||
/*--------------|
|
||||
* CLI parsing |
|
||||
* ------------*/
|
||||
QCoreApplication app(argc, argv);
|
||||
app.setApplicationName(QStringLiteral("flameshot"));
|
||||
app.setOrganizationName(QStringLiteral("flameshot"));
|
||||
app.setApplicationVersion(qApp->applicationVersion());
|
||||
new QCoreApplication(argc, argv);
|
||||
CommandLineParser parser;
|
||||
// Add description
|
||||
parser.setDescription(
|
||||
@@ -305,7 +328,7 @@ int main(int argc, char* argv[])
|
||||
checkOption },
|
||||
configArgument);
|
||||
// Parse
|
||||
if (!parser.parse(app.arguments())) {
|
||||
if (!parser.parse(qApp->arguments())) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
@@ -313,18 +336,28 @@ int main(int argc, char* argv[])
|
||||
//--------------
|
||||
if (parser.isSet(helpOption) || parser.isSet(versionOption)) {
|
||||
} else if (parser.isSet(launcherArgument)) { // LAUNCHER
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("openLauncher"));
|
||||
QDBusConnection sessionBus = QDBusConnection::sessionBus();
|
||||
if (!sessionBus.isConnected()) {
|
||||
SystemNotification().sendMessage(
|
||||
QObject::tr("Unable to connect via DBus"));
|
||||
}
|
||||
sessionBus.call(m);
|
||||
delete qApp;
|
||||
new QApplication(argc, argv);
|
||||
Controller* controller = Controller::getInstance();
|
||||
controller->openLauncherWindow();
|
||||
qApp->exec();
|
||||
} else if (parser.isSet(guiArgument)) { // GUI
|
||||
delete qApp;
|
||||
new QApplication(argc, argv);
|
||||
// Prevent multiple instances of 'flameshot gui' from running if not
|
||||
// configured to do so.
|
||||
if (!ConfigHandler().allowMultipleGuiInstances()) {
|
||||
auto* mutex = guiMutexLock();
|
||||
if (!mutex) {
|
||||
return 1;
|
||||
}
|
||||
QObject::connect(
|
||||
qApp, &QCoreApplication::aboutToQuit, qApp, [mutex]() {
|
||||
mutex->detach();
|
||||
delete mutex;
|
||||
});
|
||||
}
|
||||
|
||||
// Option values
|
||||
QString path = parser.value(pathOption);
|
||||
if (!path.isEmpty()) {
|
||||
@@ -338,7 +371,6 @@ int main(int argc, char* argv[])
|
||||
bool pin = parser.isSet(pinOption);
|
||||
bool upload = parser.isSet(uploadOption);
|
||||
bool acceptOnSelect = parser.isSet(acceptOnSelectOption);
|
||||
DBusUtils dbusUtils;
|
||||
CaptureRequest req(CaptureRequest::GRAPHICAL_MODE, delay, path);
|
||||
if (!region.isEmpty()) {
|
||||
req.setInitialSelection(Region().value(region).toRect());
|
||||
@@ -368,28 +400,12 @@ int main(int argc, char* argv[])
|
||||
req.addSaveTask();
|
||||
}
|
||||
}
|
||||
uint id = req.id();
|
||||
req.setStaticID(id);
|
||||
|
||||
// Send message
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("requestCapture"));
|
||||
m << req.serialize();
|
||||
QDBusConnection sessionBus = QDBusConnection::sessionBus();
|
||||
dbusUtils.checkDBusConnection(sessionBus);
|
||||
sessionBus.call(m);
|
||||
|
||||
if (raw) {
|
||||
dbusUtils.connectPrintCapture(sessionBus, id);
|
||||
return waitAfterConnecting(delay, app);
|
||||
} else if (printGeometry) {
|
||||
dbusUtils.connectSelectionCapture(sessionBus, id);
|
||||
return waitAfterConnecting(delay, app);
|
||||
}
|
||||
requestCaptureAndWait(req);
|
||||
} else if (parser.isSet(fullArgument)) { // FULL
|
||||
// Recreate the application as a QApplication
|
||||
// TODO find a way so we don't have to do this
|
||||
delete qApp;
|
||||
new QApplication(argc, argv);
|
||||
// Option values
|
||||
QString path = parser.value(pathOption);
|
||||
if (!path.isEmpty()) {
|
||||
@@ -421,33 +437,12 @@ int main(int argc, char* argv[])
|
||||
if (!clipboard && path.isEmpty() && !raw && !upload) {
|
||||
req.addSaveTask();
|
||||
}
|
||||
uint id = req.id();
|
||||
req.setStaticID(id);
|
||||
DBusUtils dbusUtils;
|
||||
|
||||
// Send message
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("requestCapture"));
|
||||
m << req.serialize();
|
||||
QDBusConnection sessionBus = QDBusConnection::sessionBus();
|
||||
dbusUtils.checkDBusConnection(sessionBus);
|
||||
sessionBus.call(m);
|
||||
|
||||
if (raw) {
|
||||
dbusUtils.connectPrintCapture(sessionBus, id);
|
||||
// timeout just in case
|
||||
QTimer t;
|
||||
t.setInterval(delay + 2000);
|
||||
QObject::connect(
|
||||
&t, &QTimer::timeout, qApp, &QCoreApplication::quit);
|
||||
t.start();
|
||||
// wait
|
||||
return app.exec();
|
||||
}
|
||||
requestCaptureAndWait(req);
|
||||
} else if (parser.isSet(screenArgument)) { // SCREEN
|
||||
// Recreate the application as a QApplication
|
||||
// TODO find a way so we don't have to do this
|
||||
delete qApp;
|
||||
new QApplication(argc, argv);
|
||||
QString numberStr = parser.value(screenNumberOption);
|
||||
// Option values
|
||||
int number =
|
||||
@@ -494,47 +489,21 @@ int main(int argc, char* argv[])
|
||||
req.addSaveTask();
|
||||
}
|
||||
|
||||
uint id = req.id();
|
||||
req.setStaticID(id);
|
||||
DBusUtils dbusUtils;
|
||||
|
||||
// Send message
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("requestCapture"));
|
||||
m << req.serialize();
|
||||
QDBusConnection sessionBus = QDBusConnection::sessionBus();
|
||||
dbusUtils.checkDBusConnection(sessionBus);
|
||||
sessionBus.call(m);
|
||||
|
||||
if (raw) {
|
||||
dbusUtils.connectPrintCapture(sessionBus, id);
|
||||
// timeout just in case
|
||||
QTimer t;
|
||||
t.setInterval(delay + 2000);
|
||||
QObject::connect(
|
||||
&t, &QTimer::timeout, qApp, &QCoreApplication::quit);
|
||||
t.start();
|
||||
// wait
|
||||
return app.exec();
|
||||
}
|
||||
requestCaptureAndWait(req);
|
||||
} else if (parser.isSet(configArgument)) { // CONFIG
|
||||
bool autostart = parser.isSet(autostartOption);
|
||||
bool filename = parser.isSet(filenameOption);
|
||||
bool tray = parser.isSet(trayOption);
|
||||
bool help = parser.isSet(showHelpOption);
|
||||
bool mainColor = parser.isSet(mainColorOption);
|
||||
bool contrastColor = parser.isSet(contrastColorOption);
|
||||
bool check = parser.isSet(checkOption);
|
||||
bool someFlagSet =
|
||||
(filename || tray || help || mainColor || contrastColor || check);
|
||||
(filename || tray || mainColor || contrastColor || check);
|
||||
if (check) {
|
||||
QTextStream stream(stderr);
|
||||
bool ok = ConfigHandler(true).checkForErrors(&stream);
|
||||
QTextStream err(stderr);
|
||||
bool ok = ConfigHandler(true).checkForErrors(&err);
|
||||
if (ok) {
|
||||
stream << QStringLiteral("No errors detected.\n");
|
||||
err << QStringLiteral("No errors detected.\n");
|
||||
goto finish;
|
||||
} else {
|
||||
return 1;
|
||||
@@ -542,22 +511,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
ConfigHandler config;
|
||||
if (autostart) {
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("autostartEnabled"));
|
||||
if (parser.value(autostartOption) == QLatin1String("false")) {
|
||||
m << false;
|
||||
} else if (parser.value(autostartOption) == QLatin1String("true")) {
|
||||
m << true;
|
||||
}
|
||||
QDBusConnection sessionBus = QDBusConnection::sessionBus();
|
||||
if (!sessionBus.isConnected()) {
|
||||
SystemNotification().sendMessage(
|
||||
QObject::tr("Unable to connect via DBus"));
|
||||
}
|
||||
sessionBus.call(m);
|
||||
config.setStartupLaunch(parser.value(autostartOption) == "true");
|
||||
}
|
||||
if (filename) {
|
||||
QString newFilename(parser.value(filenameOption));
|
||||
@@ -570,31 +524,10 @@ int main(int argc, char* argv[])
|
||||
.arg(fh.parsedPattern());
|
||||
}
|
||||
if (tray) {
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("trayIconEnabled"));
|
||||
if (parser.value(trayOption) == QLatin1String("false")) {
|
||||
m << false;
|
||||
} else if (parser.value(trayOption) == QLatin1String("true")) {
|
||||
m << true;
|
||||
}
|
||||
QDBusConnection sessionBus = QDBusConnection::sessionBus();
|
||||
if (!sessionBus.isConnected()) {
|
||||
SystemNotification().sendMessage(
|
||||
QObject::tr("Unable to connect via DBus"));
|
||||
}
|
||||
sessionBus.call(m);
|
||||
}
|
||||
if (help) {
|
||||
if (parser.value(showHelpOption) == QLatin1String("false")) {
|
||||
config.setShowHelp(false);
|
||||
} else if (parser.value(showHelpOption) == QLatin1String("true")) {
|
||||
config.setShowHelp(true);
|
||||
}
|
||||
config.setDisabledTrayIcon(parser.value(trayOption) == "false");
|
||||
}
|
||||
if (mainColor) {
|
||||
// TODO use value handler
|
||||
QString colorCode = parser.value(mainColorOption);
|
||||
QColor parsedColor(colorCode);
|
||||
config.setUiColor(parsedColor);
|
||||
@@ -607,17 +540,12 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Open gui when no options
|
||||
if (!someFlagSet) {
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("openConfig"));
|
||||
QDBusConnection sessionBus = QDBusConnection::sessionBus();
|
||||
if (!sessionBus.isConnected()) {
|
||||
SystemNotification().sendMessage(
|
||||
QObject::tr("Unable to connect via DBus"));
|
||||
}
|
||||
sessionBus.call(m);
|
||||
delete qApp;
|
||||
new QApplication(argc, argv);
|
||||
QObject::connect(
|
||||
qApp, &QApplication::lastWindowClosed, qApp, &QApplication::quit);
|
||||
Controller::getInstance()->openConfigWindow();
|
||||
qApp->exec();
|
||||
}
|
||||
}
|
||||
finish:
|
||||
|
||||
Reference in New Issue
Block a user