blob: 2dba85faf418c50e91a8d62076ac7a5f4dbbb713 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qwaylandclient.h"
#include <QtCore/private/qobject_p.h>
#include <QtWaylandCompositor/QWaylandCompositor>
#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
#include <wayland-server-core.h>
#include <wayland-util.h>
QT_BEGIN_NAMESPACE
class QWaylandClientPrivate : public QObjectPrivate
{
public:
QWaylandClientPrivate(QWaylandCompositor *compositor, wl_client *_client)
: compositor(compositor)
, client(_client)
{
// Save client credentials
wl_client_get_credentials(client, &pid, &uid, &gid);
}
~QWaylandClientPrivate() override
{
}
static void client_destroy_callback(wl_listener *listener, void *data)
{
Q_UNUSED(data);
QWaylandClient *client = reinterpret_cast<Listener *>(listener)->parent;
Q_ASSERT(client != nullptr);
delete client;
}
QWaylandCompositor *compositor = nullptr;
wl_client *client = nullptr;
uid_t uid;
gid_t gid;
pid_t pid;
struct Listener {
wl_listener listener;
QWaylandClient *parent = nullptr;
};
Listener listener;
};
/*!
* \qmltype WaylandClient
* \inqmlmodule QtWayland.Compositor
* \since 5.8
* \brief Represents a client connecting to the WaylandCompositor.
*
* This type represents a client connecting to the compositor using the Wayland protocol.
* It corresponds to the Wayland interface wl_client.
*/
/*!
* \class QWaylandClient
* \inmodule QtWaylandCompositor
* \since 5.8
* \brief The QWaylandClient class represents a client connecting to the QWaylandCompositor.
*
* This class corresponds to a client connecting to the compositor using the Wayland protocol.
* It corresponds to the Wayland interface wl_client.
*/
/*!
* Constructs a QWaylandClient for the \a compositor and the Wayland \a client.
*/
QWaylandClient::QWaylandClient(QWaylandCompositor *compositor, wl_client *client)
: QObject(*new QWaylandClientPrivate(compositor, client))
{
Q_D(QWaylandClient);
// Destroy wrapper when the client goes away
d->listener.parent = this;
d->listener.listener.notify = QWaylandClientPrivate::client_destroy_callback;
wl_client_add_destroy_listener(client, &d->listener.listener);
QWaylandCompositorPrivate::get(compositor)->addClient(this);
}
/*!
* Destroys the QWaylandClient.
*/
QWaylandClient::~QWaylandClient()
{
Q_D(QWaylandClient);
// Remove listener from signal
wl_list_remove(&d->listener.listener.link);
QWaylandCompositorPrivate::get(d->compositor)->removeClient(this);
}
/*!
* Returns the QWaylandClient corresponding to the Wayland client \a wlClient and \a compositor.
* If a QWaylandClient has not already been created for a client, it is
* created and returned.
*/
QWaylandClient *QWaylandClient::fromWlClient(QWaylandCompositor *compositor, wl_client *wlClient)
{
if (!wlClient)
return nullptr;
QWaylandClient *client = nullptr;
wl_listener *l = wl_client_get_destroy_listener(wlClient,
QWaylandClientPrivate::client_destroy_callback);
if (l)
client = reinterpret_cast<QWaylandClientPrivate::Listener *>(
wl_container_of(l, (QWaylandClientPrivate::Listener *)nullptr, listener))->parent;
if (!client) {
// The original idea was to create QWaylandClient instances when
// a client bound wl_compositor, but it's legal for a client to
// bind several times resulting in multiple QWaylandClient
// instances for the same wl_client therefore we create it from
// here on demand
client = new QWaylandClient(compositor, wlClient);
}
return client;
}
/*!
* \qmlproperty WaylandCompositor QtWaylandCompositor::WaylandClient::compositor
*
* This property holds the compositor of this WaylandClient.
*/
/*!
* \property QWaylandClient::compositor
*
* This property holds the compositor of this QWaylandClient.
*/
QWaylandCompositor *QWaylandClient::compositor() const
{
Q_D(const QWaylandClient);
return d->compositor;
}
/*!
* Returns the Wayland client of this QWaylandClient.
*/
wl_client *QWaylandClient::client() const
{
Q_D(const QWaylandClient);
return d->client;
}
/*!
* \qmlproperty int QtWaylandCompositor::WaylandClient::userId
*
* This property holds the user id of this WaylandClient.
*/
/*!
* \property QWaylandClient::userId
* \readonly
*
* This property holds the user id of this QWaylandClient.
*/
qint64 QWaylandClient::userId() const
{
Q_D(const QWaylandClient);
return d->uid;
}
/*!
* \qmlproperty int QtWaylandCompositor::WaylandClient::groupId
* \readonly
*
* This property holds the group id of this WaylandClient.
*/
/*!
* \property QWaylandClient::groupId
*
* This property holds the group id of this QWaylandClient.
*/
qint64 QWaylandClient::groupId() const
{
Q_D(const QWaylandClient);
return d->gid;
}
/*!
* \qmlproperty int QtWaylandCompositor::WaylandClient::processId
* \readonly
*
* This property holds the process id of this WaylandClient.
*/
/*!
* \property QWaylandClient::processId
*
* This property holds the process id of this QWaylandClient.
*/
qint64 QWaylandClient::processId() const
{
Q_D(const QWaylandClient);
return d->pid;
}
/*!
* \qmlmethod void QtWaylandCompositor::WaylandClient::kill(signal)
*
* Kills the client with the specified \a signal.
*/
/*!
* Kills the client with the specified \a signal.
*/
void QWaylandClient::kill(int signal)
{
Q_D(QWaylandClient);
::kill(d->pid, signal);
}
/*!
* \qmlmethod void QtWaylandCompositor::WaylandClient::close()
*
* Closes the client
*/
/*!
* Closes the client.
*/
void QWaylandClient::close()
{
Q_D(QWaylandClient);
d->compositor->destroyClient(this);
}
QT_END_NAMESPACE