File indexing completed on 2024-11-10 04:57:25

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 #include "clientconnection.h"
0007 #include "display.h"
0008 #include "utils/executable_path.h"
0009 // Qt
0010 #include <QFileInfo>
0011 #include <QList>
0012 // Wayland
0013 #include <wayland-server.h>
0014 
0015 namespace KWin
0016 {
0017 class ClientConnectionPrivate
0018 {
0019 public:
0020     ClientConnectionPrivate(wl_client *c, Display *display, ClientConnection *q);
0021     ~ClientConnectionPrivate();
0022 
0023     wl_client *client;
0024     Display *display;
0025     pid_t pid = 0;
0026     uid_t user = 0;
0027     gid_t group = 0;
0028     QString executablePath;
0029     QString securityContextAppId;
0030     qreal scaleOverride = 1.0;
0031 
0032 private:
0033     static void destroyListenerCallback(wl_listener *listener, void *data);
0034     static void destroyLateListenerCallback(wl_listener *listener, void *data);
0035     ClientConnection *q;
0036     wl_listener destroyListener;
0037     wl_listener destroyLateListener;
0038     static QList<ClientConnectionPrivate *> s_allClients;
0039 };
0040 
0041 QList<ClientConnectionPrivate *> ClientConnectionPrivate::s_allClients;
0042 
0043 ClientConnectionPrivate::ClientConnectionPrivate(wl_client *c, Display *display, ClientConnection *q)
0044     : client(c)
0045     , display(display)
0046     , q(q)
0047 {
0048     s_allClients << this;
0049 
0050     destroyListener.notify = destroyListenerCallback;
0051     wl_client_add_destroy_listener(c, &destroyListener);
0052 
0053     destroyLateListener.notify = destroyLateListenerCallback;
0054     wl_client_add_destroy_late_listener(c, &destroyLateListener);
0055 
0056     wl_client_get_credentials(client, &pid, &user, &group);
0057     executablePath = executablePathFromPid(pid);
0058 }
0059 
0060 ClientConnectionPrivate::~ClientConnectionPrivate()
0061 {
0062     s_allClients.removeAt(s_allClients.indexOf(this));
0063 }
0064 
0065 void ClientConnectionPrivate::destroyListenerCallback(wl_listener *listener, void *data)
0066 {
0067     wl_client *client = reinterpret_cast<wl_client *>(data);
0068     auto it = std::find_if(s_allClients.constBegin(), s_allClients.constEnd(), [client](ClientConnectionPrivate *c) {
0069         return c->client == client;
0070     });
0071     Q_ASSERT(it != s_allClients.constEnd());
0072     auto p = (*it);
0073     auto q = p->q;
0074 
0075     Q_EMIT q->aboutToBeDestroyed();
0076     wl_list_remove(&p->destroyListener.link);
0077     Q_EMIT q->disconnected(q);
0078 }
0079 
0080 void ClientConnectionPrivate::destroyLateListenerCallback(wl_listener *listener, void *data)
0081 {
0082     wl_client *client = reinterpret_cast<wl_client *>(data);
0083     auto it = std::find_if(s_allClients.constBegin(), s_allClients.constEnd(), [client](ClientConnectionPrivate *c) {
0084         return c->client == client;
0085     });
0086     Q_ASSERT(it != s_allClients.constEnd());
0087     auto p = (*it);
0088     auto q = p->q;
0089 
0090     wl_list_remove(&p->destroyLateListener.link);
0091     delete q;
0092 }
0093 
0094 ClientConnection::ClientConnection(wl_client *c, Display *parent)
0095     : QObject(parent)
0096     , d(new ClientConnectionPrivate(c, parent, this))
0097 {
0098 }
0099 
0100 ClientConnection::~ClientConnection() = default;
0101 
0102 void ClientConnection::flush()
0103 {
0104     wl_client_flush(d->client);
0105 }
0106 
0107 void ClientConnection::destroy()
0108 {
0109     wl_client_destroy(d->client);
0110 }
0111 
0112 wl_resource *ClientConnection::getResource(quint32 id) const
0113 {
0114     return wl_client_get_object(d->client, id);
0115 }
0116 
0117 wl_client *ClientConnection::client() const
0118 {
0119     return d->client;
0120 }
0121 
0122 ClientConnection::operator wl_client *()
0123 {
0124     return d->client;
0125 }
0126 
0127 ClientConnection::operator wl_client *() const
0128 {
0129     return d->client;
0130 }
0131 
0132 Display *ClientConnection::display() const
0133 {
0134     return d->display;
0135 }
0136 
0137 gid_t ClientConnection::groupId() const
0138 {
0139     return d->group;
0140 }
0141 
0142 pid_t ClientConnection::processId() const
0143 {
0144     return d->pid;
0145 }
0146 
0147 uid_t ClientConnection::userId() const
0148 {
0149     return d->user;
0150 }
0151 
0152 QString ClientConnection::executablePath() const
0153 {
0154     return d->executablePath;
0155 }
0156 
0157 void ClientConnection::setScaleOverride(qreal scaleOveride)
0158 {
0159     Q_ASSERT(scaleOveride != 0);
0160     d->scaleOverride = scaleOveride;
0161     Q_EMIT scaleOverrideChanged();
0162 }
0163 
0164 qreal ClientConnection::scaleOverride() const
0165 {
0166     return d->scaleOverride;
0167 }
0168 
0169 void ClientConnection::setSecurityContextAppId(const QString &appId)
0170 {
0171     d->securityContextAppId = appId;
0172 }
0173 
0174 QString ClientConnection::securityContextAppId() const
0175 {
0176     return d->securityContextAppId;
0177 }
0178 }
0179 
0180 #include "moc_clientconnection.cpp"