File indexing completed on 2024-05-05 17:32:16
0001 // SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org> 0002 // SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru> 0003 // 0004 // SPDX-License-Identifier: LGPL-2.0-or-later 0005 0006 #include <QGuiApplication> 0007 0008 #include "config.h" 0009 #include "version.h" 0010 0011 #include <KAboutData> 0012 #include <KDBusService> 0013 #include <KLocalizedContext> 0014 #include <KLocalizedString> 0015 #include <KWaylandExtras> 0016 #include <KWindowSystem> 0017 #include <QCommandLineParser> 0018 #include <QIcon> 0019 #include <QObject> 0020 #include <QQuickStyle> 0021 #include <QQuickWindow> 0022 #include <QtQml> 0023 0024 #ifdef DIALER_BUILD_SHELL_OVERLAY 0025 #include "qwayland-kde-lockscreen-overlay-v1.h" 0026 #include <QDBusConnection> 0027 #include <QDBusMessage> 0028 #include <QDBusReply> 0029 #include <QWaylandClientExtensionTemplate> 0030 #include <qpa/qplatformnativeinterface.h> 0031 #endif // DIALER_BUILD_SHELL_OVERLAY 0032 0033 static QString parseTelArgument(const QString &numberArg) 0034 { 0035 QString result; 0036 if (numberArg.startsWith(QStringLiteral("tel:"))) { 0037 result = numberArg.mid(4); 0038 } 0039 if (numberArg.startsWith(QStringLiteral("callto:"))) { 0040 result = numberArg.mid(7); 0041 } 0042 return result; 0043 } 0044 0045 static void inputCallNumber(QWindow *window, const QString &number) 0046 { 0047 QMetaObject::invokeMethod(window, "call", Q_ARG(QVariant, number)); 0048 } 0049 0050 #ifdef DIALER_BUILD_SHELL_OVERLAY 0051 static void updateLockscreenMode(QWindow *window, bool mode) 0052 { 0053 QMetaObject::invokeMethod(window, "updateLockscreenMode", Q_ARG(QVariant, mode)); 0054 } 0055 #endif // DIALER_BUILD_SHELL_OVERLAY 0056 0057 struct ScreenSaverUtils { 0058 Q_GADGET 0059 public: 0060 Q_INVOKABLE static bool getActive() 0061 { 0062 bool active = false; 0063 #ifdef DIALER_BUILD_SHELL_OVERLAY 0064 QDBusMessage request = QDBusMessage::createMethodCall(QStringLiteral("org.freedesktop.ScreenSaver"), 0065 QStringLiteral("/ScreenSaver"), 0066 QStringLiteral("org.freedesktop.ScreenSaver"), 0067 QStringLiteral("GetActive")); 0068 const QDBusReply<bool> response = QDBusConnection::sessionBus().call(request); 0069 active = response.isValid() ? response.value() : false; 0070 #endif // DIALER_BUILD_SHELL_OVERLAY 0071 return active; 0072 } 0073 }; 0074 Q_DECLARE_METATYPE(ScreenSaverUtils) 0075 0076 #ifdef DIALER_BUILD_SHELL_OVERLAY 0077 class WaylandAboveLockscreen : public QWaylandClientExtensionTemplate<WaylandAboveLockscreen>, public QtWayland::kde_lockscreen_overlay_v1 0078 { 0079 public: 0080 WaylandAboveLockscreen() 0081 : QWaylandClientExtensionTemplate<WaylandAboveLockscreen>(1) 0082 { 0083 initialize(); 0084 } 0085 0086 void allowWindow(QWindow *window) 0087 { 0088 QPlatformNativeInterface *native = qGuiApp->platformNativeInterface(); 0089 wl_surface *surface = reinterpret_cast<wl_surface *>(native->nativeResourceForWindow(QByteArrayLiteral("surface"), window)); 0090 0091 Q_ASSERT(surface); 0092 allow(surface); 0093 } 0094 }; 0095 0096 #endif // DIALER_BUILD_SHELL_OVERLAY 0097 0098 // raiseWindow with lockscreen support if possible 0099 static void raiseWindow(QWindow *window) 0100 { 0101 #ifdef DIALER_BUILD_SHELL_OVERLAY 0102 bool screenLocked = ScreenSaverUtils::getActive(); 0103 updateLockscreenMode(window, screenLocked); 0104 if (screenLocked) { 0105 window->setVisibility(QWindow::Visibility::FullScreen); 0106 KWaylandExtras::requestXdgActivationToken(window, 0, QStringLiteral("org.kde.phone.dialer.desktop")); 0107 QObject::connect(KWaylandExtras::self(), &KWaylandExtras::xdgActivationTokenArrived, window, [window](int, const QString &token) { 0108 KWindowSystem::setCurrentXdgActivationToken(token); 0109 KWindowSystem::activateWindow(window); 0110 }); 0111 } 0112 #endif // DIALER_BUILD_SHELL_OVERLAY 0113 } 0114 0115 int main(int argc, char **argv) 0116 { 0117 QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 0118 QGuiApplication app(argc, argv); 0119 0120 if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE") && QQuickStyle::name().isEmpty()) { 0121 QQuickStyle::setStyle(QStringLiteral("org.kde.desktop")); 0122 } 0123 0124 QCoreApplication::setOrganizationName(QStringLiteral("KDE")); 0125 QCoreApplication::setOrganizationDomain(QStringLiteral("kde.org")); 0126 KLocalizedString::setApplicationDomain("plasma-dialer"); 0127 QCoreApplication::setApplicationName(QStringLiteral("dialer")); 0128 QCoreApplication::setApplicationVersion(QStringLiteral(PLASMADIALER_VERSION_STRING)); 0129 QGuiApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("dialer"))); 0130 QGuiApplication::setApplicationDisplayName(QStringLiteral("Phone")); 0131 0132 KAboutData aboutData(QStringLiteral("dialer"), 0133 i18n("Phone"), 0134 QStringLiteral(PLASMADIALER_VERSION_STRING), 0135 i18n("Plasma phone dialer"), 0136 KAboutLicense::GPL, 0137 i18n("© 2015-2022 KDE Community")); 0138 aboutData.setBugAddress("https://bugs.kde.org/describecomponents.cgi?product=Plasma%20Mobile%20Dialer"); 0139 aboutData.setDesktopFileName(QStringLiteral("org.kde.phone.dialer")); 0140 aboutData.addAuthor(i18n("Alexey Andreyev"), QString(), QStringLiteral("aa13q@ya.ru")); 0141 KAboutData::setApplicationData(aboutData); 0142 0143 QCommandLineParser parser; 0144 QCommandLineOption telSchemeOption(QStringList() << QStringLiteral("number"), 0145 QCoreApplication::translate("main", "Input a phone number"), 0146 QCoreApplication::translate("main", "phone number")); 0147 parser.addOption(telSchemeOption); 0148 parser.process(app); 0149 0150 QString telNumber = parser.value(telSchemeOption); 0151 0152 QQmlApplicationEngine engine; 0153 0154 auto config = Config::self(); 0155 0156 qmlRegisterSingletonInstance("org.kde.phone.dialer", 1, 0, "Config", config); 0157 0158 engine.rootContext()->setContextProperty(QStringLiteral("DialerAboutData"), QVariant::fromValue(aboutData)); 0159 0160 KDBusService service(KDBusService::Unique, &app); 0161 0162 engine.rootContext()->setContextObject(new KLocalizedContext(&engine)); 0163 0164 ScreenSaverUtils screenSaverUtils; 0165 engine.rootContext()->setContextProperty(QStringLiteral("ScreenSaverUtils"), QVariant::fromValue<ScreenSaverUtils>(screenSaverUtils)); 0166 0167 engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); 0168 0169 if (engine.rootObjects().isEmpty()) { 0170 return -1; 0171 } 0172 0173 QWindow *window = qobject_cast<QWindow *>(engine.rootObjects().at(0)); 0174 Q_ASSERT(window); 0175 0176 #ifdef DIALER_BUILD_SHELL_OVERLAY 0177 Q_ASSERT(!window->isVisible()); 0178 WaylandAboveLockscreen aboveLockscreen; 0179 Q_ASSERT(aboveLockscreen.isInitialized()); 0180 aboveLockscreen.allowWindow(window); 0181 #endif // DIALER_BUILD_SHELL_OVERLAY 0182 0183 raiseWindow(window); 0184 QObject::connect(&service, &KDBusService::activateRequested, window, [&window](const QStringList &arguments) { 0185 for (const auto &arg : arguments) { 0186 QString numberArg = parseTelArgument(arg); 0187 if (!numberArg.isEmpty()) { 0188 inputCallNumber(window, numberArg); 0189 break; 0190 } 0191 } 0192 raiseWindow(window); 0193 }); 0194 0195 if (!parser.positionalArguments().isEmpty()) { 0196 QString numberArg = parseTelArgument(parser.positionalArguments().constFirst()); 0197 if (!numberArg.isEmpty()) { 0198 telNumber = numberArg; 0199 } 0200 } 0201 0202 if (!telNumber.isEmpty()) { 0203 inputCallNumber(window, telNumber); 0204 } 0205 0206 return app.exec(); 0207 } 0208 0209 #include "main.moc"