KontactInterface

pimuniqueapplication.cpp
1/* This file is part of the KDE project
2
3 SPDX-FileCopyrightText: 2008 David Faure <faure@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7
8#include "pimuniqueapplication.h"
9using namespace Qt::Literals::StringLiterals;
10
11#include "config-kontactinterface.h"
12#include "kontactinterface_debug.h"
13
14#include <KAboutData>
15#include <KWindowSystem>
16
17#include "config-kontactinterface.h"
18#if KONTACTINTERFACE_HAVE_X11
19#include <KStartupInfo>
20#include <private/qtx11extras_p.h>
21#endif
22
23#ifdef Q_OS_WINDOWS
24#include <QFont>
25#include <Windows.h>
26#endif
27
28#include <QCommandLineParser>
29#include <QDir>
30
31#include <QMainWindow>
32#include <QWidget>
33
34#include <QDBusConnectionInterface>
35#include <QDBusInterface>
36
37using namespace KontactInterface;
38
39namespace
40{
41const char kChromiumFlagsEnv[] = "QTWEBENGINE_CHROMIUM_FLAGS";
42const char kDisableInProcessStackTraces[] = "--disable-in-process-stack-traces";
43
44}
45
46//@cond PRIVATE
47class Q_DECL_HIDDEN KontactInterface::PimUniqueApplication::PimUniqueApplicationPrivate
48{
49public:
50 PimUniqueApplicationPrivate()
51 : cmdArgs(new QCommandLineParser())
52 {
53 }
54
55 ~PimUniqueApplicationPrivate()
56 {
57 delete cmdArgs;
58 }
59
60 static void disableChromiumCrashHandler()
61 {
62 // Disable Chromium's own crash handler, which overrides DrKonqi.
63 auto flags = qgetenv(kChromiumFlagsEnv);
64 if (!flags.contains(kDisableInProcessStackTraces)) {
65 qputenv(kChromiumFlagsEnv, QByteArray(flags + " " + kDisableInProcessStackTraces));
66 }
67 }
68
69 QCommandLineParser *const cmdArgs;
70};
71//@endcond
72
73PimUniqueApplication::PimUniqueApplication(int &argc, char **argv[])
74 : QApplication(argc, *argv)
75 , d(new PimUniqueApplicationPrivate())
76{
77#ifdef Q_OS_WINDOWS
78 if (AttachConsole(ATTACH_PARENT_PROCESS)) {
79 freopen("CONOUT$", "w", stdout);
80 freopen("CONOUT$", "w", stderr);
81 }
82
83 setStyle(QStringLiteral("breeze"));
84 QFont font(QStringLiteral("Segoe UI Emoji"));
85 font.setPointSize(10);
86 font.setHintingPreference(QFont::PreferNoHinting);
87 setFont(font);
88#endif
89}
90
91PimUniqueApplication::~PimUniqueApplication() = default;
92
93QCommandLineParser *PimUniqueApplication::cmdArgs() const
94{
95 return d->cmdArgs;
96}
97
98void PimUniqueApplication::setAboutData(KAboutData &aboutData)
99{
101 aboutData.setupCommandLine(d->cmdArgs);
102 // This object name is used in start(), and also in kontact's UniqueAppHandler.
103 const QString objectName = QLatin1Char('/') + QApplication::applicationName() + "_PimApplication"_L1;
105 this,
108}
109
110static bool callNewInstance(const QString &appName, const QString &serviceName, const QByteArray &asn_id, const QStringList &arguments)
111{
112 const QString objectName = QLatin1Char('/') + appName + "_PimApplication"_L1;
113 QDBusInterface iface(serviceName, objectName, QStringLiteral("org.kde.PIMUniqueApplication"), QDBusConnection::sessionBus());
114 if (iface.isValid()) {
115 QDBusReply<int> reply = iface.call(QStringLiteral("newInstance"), asn_id, arguments, QDir::currentPath());
116 if (reply.isValid()) {
117 return true;
118 }
119 }
120 return false;
121}
122
123int PimUniqueApplication::newInstance()
124{
126}
127
129{
130 const QString appName = QApplication::applicationName();
131
132 // Try talking to /appName_PimApplication in org.kde.appName,
133 // (which could be kontact or the standalone application),
134 // otherwise the current app being started will register to DBus.
135
136 const QString serviceName = "org.kde."_L1 + appName;
137 if (QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName)) {
138 QByteArray new_asn_id;
140#if KONTACTINTERFACE_HAVE_X11
141 new_asn_id = QX11Info::nextStartupId();
142#endif
144 new_asn_id = qgetenv("XDG_ACTIVATION_TOKEN");
145 }
146
147 if (callNewInstance(appName, serviceName, new_asn_id, arguments)) {
148 return false; // success means that main() can exit now.
149 }
150 }
151
152 qCDebug(KONTACTINTERFACE_LOG) << "kontact not running -- start standalone application";
153
155
156 // Make sure we have DrKonqi
157 PimUniqueApplicationPrivate::disableChromiumCrashHandler();
158
159 static_cast<PimUniqueApplication *>(qApp)->activate(arguments, QDir::currentPath());
160 return true;
161}
162
163// This is called via DBus either by another instance that has just been
164// started or by Kontact when the module is activated
165int PimUniqueApplication::newInstance(const QByteArray &startupId, const QStringList &arguments, const QString &workingDirectory)
166{
168#if KONTACTINTERFACE_HAVE_X11
170#endif
173 }
174
175 const QWidgetList tlws = topLevelWidgets();
176 for (QWidget *win : tlws) {
178 win->show();
179 win->setAttribute(Qt::WA_NativeWindow, true);
180
181 KWindowSystem::activateWindow(win->windowHandle());
182 break;
183 }
184 }
185
186 activate(arguments, workingDirectory);
187 return 0;
188}
189
190int PimUniqueApplication::activate(const QStringList &arguments, const QString &workingDirectory)
191{
192 Q_UNUSED(arguments)
193 Q_UNUSED(workingDirectory)
194 return 0;
195}
196
197#include "moc_pimuniqueapplication.cpp"
static void setApplicationData(const KAboutData &aboutData)
bool setupCommandLine(QCommandLineParser *parser)
static void setStartupId(const QByteArray &startup_id)
static Q_INVOKABLE void activateWindow(QWindow *window, long time=0)
static bool isPlatformX11()
static Q_INVOKABLE void setCurrentXdgActivationToken(const QString &token)
static bool isPlatformWayland()
KDEPIM applications which can be integrated into kontact should use PimUniqueApplication instead of Q...
static bool start(const QStringList &arguments)
Register this process as a unique application, if not already running.
QCA_EXPORT QString appName()
QWidgetList topLevelWidgets()
QStringList arguments()
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
bool registerService(const QString &serviceName)
QDBusConnection sessionBus()
bool isValid() const const
QString currentPath()
PreferNoHinting
T qobject_cast(QObject *object)
QString fromUtf8(QByteArrayView str)
WA_NativeWindow
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:19:42 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.