File indexing completed on 2024-04-14 04:53:15

0001 /* This file is part of the KDE project
0002     SPDX-FileCopyrightText: 1998, 1999 Simon Hausmann <hausmann@kde.org>
0003     SPDX-FileCopyrightText: 2000, 2006 David Faure <faure@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "KonquerorAdaptor.h"
0009 #include "konqmisc.h"
0010 #include "KonqMainWindowAdaptor.h"
0011 #include "konqmainwindow.h"
0012 #include "konqmainwindowfactory.h"
0013 #include "konqviewmanager.h"
0014 #include "konqview.h"
0015 #include "konqsettingsxt.h"
0016 #include "konqsettings.h"
0017 #include "konqapplication.h"
0018 
0019 #include "konqdebug.h"
0020 #include <KStartupInfo>
0021 #include <KWindowInfo>
0022 #include <kwindowsystem.h>
0023 
0024 #include <QFile>
0025 
0026 #if QT_VERSION_MAJOR < 6
0027 #include <QX11Info>
0028 #else
0029 #include <QtGui/private/qtx11extras_p.h>
0030 #endif
0031 
0032 #ifdef KActivities_FOUND
0033 #if QT_VERSION_MAJOR < 6
0034 #include <KActivities/Consumer>
0035 #else //QT_VERSION_MAJOR
0036 #include <PlasmaActivities/Consumer>
0037 #endif //QT_VERSION_MAJOR
0038 #endif //KActivities_FOUND
0039 
0040 // these DBus calls come from outside, so any windows created by these
0041 // calls would have old user timestamps (for KWin's no-focus-stealing),
0042 // it's better to reset the timestamp and rely on other means
0043 // of detecting the time when the user action that triggered all this
0044 // happened
0045 // TODO a valid timestamp should be passed in the DBus calls that
0046 // are not for user scripting
0047 
0048 KonquerorAdaptor::KonquerorAdaptor()
0049     : QObject(qApp)
0050 {
0051     QDBusConnection dbus = QDBusConnection::sessionBus();
0052     dbus.registerObject(KONQ_MAIN_PATH, this, QDBusConnection::ExportNonScriptableSlots);
0053 }
0054 
0055 KonquerorAdaptor::~KonquerorAdaptor()
0056 {
0057 }
0058 
0059 static void setStartupId(const QByteArray &startup_id)
0060 {
0061     KStartupInfo::setStartupId(startup_id);
0062     QX11Info::setAppUserTime(0);
0063 }
0064 
0065 QDBusObjectPath KonquerorAdaptor::openBrowserWindow(const QString &url, const QByteArray &startup_id)
0066 {
0067     setStartupId(startup_id);
0068     KonqMainWindow *res = KonqMainWindowFactory::createNewWindow(QUrl::fromUserInput(url));
0069     if (!res) {
0070         return QDBusObjectPath("/");
0071     }
0072     return QDBusObjectPath(res->dbusName());
0073 }
0074 
0075 QDBusObjectPath KonquerorAdaptor::createNewWindow(const QString &url, const QString &mimetype, const QByteArray &startup_id, bool tempFile)
0076 {
0077     setStartupId(startup_id);
0078     KParts::OpenUrlArguments args;
0079     args.setMimeType(mimetype);
0080     // Filter the URL, so that "kfmclient openURL gg:foo" works also when konq is already running
0081     QUrl finalURL = KonqMisc::konqFilteredURL(nullptr, url);
0082     KonqOpenURLRequest req;
0083     req.args = args;
0084     req.tempFile = tempFile;
0085     KonqMainWindow *res = KonqMainWindowFactory::createNewWindow(finalURL, req);
0086     if (!res) {
0087         return QDBusObjectPath("/");
0088     }
0089     res->show();
0090     return QDBusObjectPath(res->dbusName());
0091 }
0092 
0093 QDBusObjectPath KonquerorAdaptor::createNewWindowWithSelection(const QString &url, const QStringList &filesToSelect, const QByteArray &startup_id)
0094 {
0095     setStartupId(startup_id);
0096     KonqOpenURLRequest req;
0097     req.filesToSelect = QUrl::fromStringList(filesToSelect);
0098     KonqMainWindow *res = KonqMainWindowFactory::createNewWindow(QUrl::fromUserInput(url), req);
0099     if (!res) {
0100         return QDBusObjectPath("/");
0101     }
0102     res->show();
0103     return QDBusObjectPath(res->dbusName());
0104 }
0105 
0106 QList<QDBusObjectPath> KonquerorAdaptor::getWindows()
0107 {
0108     QList<QDBusObjectPath> lst;
0109     QList<KonqMainWindow *> *mainWindows = KonqMainWindow::mainWindowList();
0110     if (mainWindows) {
0111         for (KonqMainWindow *window: *mainWindows) {
0112             lst.append(QDBusObjectPath(window->dbusName()));
0113         }
0114     }
0115     return lst;
0116 }
0117 
0118 QStringList KonquerorAdaptor::urls() const
0119 {
0120     QStringList lst;
0121     QList<KonqMainWindow *> *mainWindows = KonqMainWindow::mainWindowList();
0122     if (mainWindows) {
0123         for (KonqMainWindow *window : *mainWindows) {
0124             if (!window->isPreloaded()) {
0125                 for (KonqView *view : window->viewMap()) {
0126                     lst.append(view->url().toString());
0127                 }
0128             }
0129         }
0130     }
0131     return lst;
0132 }
0133 
0134 QDBusObjectPath KonquerorAdaptor::windowForTab()
0135 {
0136     QList<KonqMainWindow *> *mainWindows = KonqMainWindow::mainWindowList();
0137     if (!mainWindows) {
0138         return QDBusObjectPath("/");
0139     }
0140     //Accept only windows which are on the current desktop and in the current activity
0141     //(if activities are enabled)
0142     auto filter = [](KonqMainWindow *mw) {
0143         KWindowInfo winfo(mw->winId(), NET::WMDesktop, NET::WM2Activities);
0144         QString currentActivity = KonquerorApplication::currentActivity();
0145         bool isInCurrentActivity = true;
0146         //if currentActivity is empty, it means that the activity service status is not running or that activity support is disabled,
0147         //so it's useless to check which activity the window is on
0148         if (!currentActivity.isEmpty()) {
0149             QStringList windowActivities = winfo.activities();
0150             //WARNING: a window is in the current activity either when windowActivities contains the current activity
0151             //or when windowActivities is empty, since KWindowInfo::activities() returns an empty list when the
0152             //window is on all activities
0153             isInCurrentActivity = windowActivities.isEmpty() || windowActivities.contains(currentActivity);
0154         }
0155         if (winfo.isOnCurrentDesktop() && (isInCurrentActivity)) {
0156             Q_ASSERT(!mw->dbusName().isEmpty());
0157             return true;
0158         } else {
0159             return false;
0160         }
0161     };
0162     QList<KonqMainWindow*> visibleWindows;
0163     std::copy_if(mainWindows->constBegin(), mainWindows->constEnd(), std::back_inserter(visibleWindows), filter);
0164 
0165     //Sort the windows according to the last deactivation order, so that windows deactivated last come first
0166     //(if a window is active, it'll come before the others)
0167     auto sorter = [](KonqMainWindow *w1, KonqMainWindow *w2) {
0168         if (w1->isActiveWindow()) {
0169             return true;
0170         } else if (w2->isActiveWindow()) {
0171             return false;
0172         } else {
0173             return w2->lastDeactivationTime() < w1->lastDeactivationTime();
0174         }
0175     };
0176     std::sort(visibleWindows.begin(), visibleWindows.end(), sorter);
0177     if (!visibleWindows.isEmpty()) {
0178         return QDBusObjectPath(visibleWindows.first()->dbusName());
0179     } else {
0180         return QDBusObjectPath("/");
0181     }
0182 }