From 88f6d99a02448f8b034990759afe92ae0924dfe1 Mon Sep 17 00:00:00 2001 From: Lasse Holmstedt Date: Thu, 19 May 2011 12:21:53 +0200 Subject: [PATCH] Window manager extension for wayland MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit maps clients to process id's so that each surface will have a PID associated to it. Reviewed-by: Samuel Rødal --- .../compositor_api/waylandcompositor.cpp | 1 + .../compositor_api/waylandsurface.cpp | 6 ++ src/qt-compositor/compositor_api/waylandsurface.h | 1 + src/qt-compositor/qt-compositor.pri | 1 + src/qt-compositor/wayland_wrapper/wlcompositor.cpp | 14 ++- src/qt-compositor/wayland_wrapper/wlcompositor.h | 3 + src/qt-compositor/wayland_wrapper/wlsurface.cpp | 20 ++++ src/qt-compositor/wayland_wrapper/wlsurface.h | 5 + .../wayland-windowmanager-protocol.c | 36 +++++++ .../wayland-windowmanager-server-protocol.h | 51 +++++++++ .../waylandwindowmanagerintegration.cpp | 115 +++++++++++++++++++++ .../waylandwindowmanagerintegration.h | 83 +++++++++++++++ .../windowmanagerprotocol/windowmanager.xml | 18 ++++ .../windowmanagerprotocol.pri | 11 ++ 14 files changed, 364 insertions(+), 1 deletion(-) create mode 100644 src/qt-compositor/windowmanagerprotocol/wayland-windowmanager-protocol.c create mode 100644 src/qt-compositor/windowmanagerprotocol/wayland-windowmanager-server-protocol.h create mode 100644 src/qt-compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp create mode 100644 src/qt-compositor/windowmanagerprotocol/waylandwindowmanagerintegration.h create mode 100644 src/qt-compositor/windowmanagerprotocol/windowmanager.xml create mode 100644 src/qt-compositor/windowmanagerprotocol/windowmanagerprotocol.pri diff --git a/src/qt-compositor/compositor_api/waylandcompositor.cpp b/src/qt-compositor/compositor_api/waylandcompositor.cpp index e992c18..01ad70d 100644 --- a/src/qt-compositor/compositor_api/waylandcompositor.cpp +++ b/src/qt-compositor/compositor_api/waylandcompositor.cpp @@ -58,6 +58,7 @@ WaylandCompositor::WaylandCompositor(QWidget *topLevelWidget) qRegisterMetaType("WaylandSurface*"); #endif m_compositor->initializeHardwareIntegration(); + m_compositor->initializeWindowManagerProtocol(); } WaylandCompositor::~WaylandCompositor() diff --git a/src/qt-compositor/compositor_api/waylandsurface.cpp b/src/qt-compositor/compositor_api/waylandsurface.cpp index ccc938d..a8c54eb 100644 --- a/src/qt-compositor/compositor_api/waylandsurface.cpp +++ b/src/qt-compositor/compositor_api/waylandsurface.cpp @@ -69,6 +69,12 @@ Wayland::Surface * WaylandSurface::handle() const return d->surface; } +qint64 WaylandSurface::processId() const +{ + Q_D(const WaylandSurface); + return d->surface->processId(); +} + void WaylandSurface::sendMousePressEvent(const QPoint &pos, Qt::MouseButton button) { Q_D(WaylandSurface); diff --git a/src/qt-compositor/compositor_api/waylandsurface.h b/src/qt-compositor/compositor_api/waylandsurface.h index b429190..93fbfb2 100644 --- a/src/qt-compositor/compositor_api/waylandsurface.h +++ b/src/qt-compositor/compositor_api/waylandsurface.h @@ -91,6 +91,7 @@ public: void setInputFocus(); Wayland::Surface *handle() const; + qint64 processId() const; signals: void mapped(const QRect &rect); diff --git a/src/qt-compositor/qt-compositor.pri b/src/qt-compositor/qt-compositor.pri index a3b1cf8..c1a3b89 100644 --- a/src/qt-compositor/qt-compositor.pri +++ b/src/qt-compositor/qt-compositor.pri @@ -20,3 +20,4 @@ include ($$PWD/util/util.pri) include ($$PWD/wayland_wrapper/wayland_wrapper.pri) include ($$PWD/hardware_integration/hardware_integration.pri) include ($$PWD/compositor_api/compositor_api.pri) +include ($$PWD/windowmanagerprotocol/windowmanagerprotocol.pri) diff --git a/src/qt-compositor/wayland_wrapper/wlcompositor.cpp b/src/qt-compositor/wayland_wrapper/wlcompositor.cpp index 200b760..0767784 100644 --- a/src/qt-compositor/wayland_wrapper/wlcompositor.cpp +++ b/src/qt-compositor/wayland_wrapper/wlcompositor.cpp @@ -68,6 +68,7 @@ #include #include "hardware_integration/graphicshardwareintegration.h" +#include "waylandwindowmanagerintegration.h" namespace Wayland { @@ -185,6 +186,7 @@ Compositor::Compositor(WaylandCompositor *qt_compositor) #if defined (QT_COMPOSITOR_WAYLAND_GL) m_graphics_hw_integration = GraphicsHardwareIntegration::createGraphicsHardwareIntegration(qt_compositor); #endif + m_windowManagerWaylandProtocol = new WindowManagerServerIntegration(this); if (wl_compositor_init(base(), &compositor_interface, m_display->handle())) { fprintf(stderr, "Fatal: Error initializing compositor\n"); @@ -234,6 +236,9 @@ void Compositor::createSurface(struct wl_client *client, int id) addClientResource(client, &surface->base()->resource, id, &wl_surface_interface, &surface_interface, destroy_surface); + quint32 processId = m_windowManagerWaylandProtocol->pidForClient(client); + // if there is no PID, the client does not support the protocol. + surface->setProcessId(processId); m_qt_compositor->surfaceCreated(surface->handle()); QList prevClientList = clients(); @@ -308,8 +313,10 @@ void Compositor::destroyClientForSurface(Surface *surface) { wl_client *client = surface->base()->client; - if (client) + if (client) { + m_windowManagerWaylandProtocol->removeClient(client); wl_client_destroy(client); + } } void Compositor::setInputFocus(Surface *surface) @@ -357,6 +364,11 @@ void Compositor::initializeHardwareIntegration() #endif } +void Compositor::initializeWindowManagerProtocol() +{ + m_windowManagerWaylandProtocol->initialize(m_display); +} + bool Compositor::setDirectRenderSurface(Surface *surface) { #ifdef QT_COMPOSITOR_WAYLAND_GL diff --git a/src/qt-compositor/wayland_wrapper/wlcompositor.h b/src/qt-compositor/wayland_wrapper/wlcompositor.h index f892eb4..719d2c7 100644 --- a/src/qt-compositor/wayland_wrapper/wlcompositor.h +++ b/src/qt-compositor/wayland_wrapper/wlcompositor.h @@ -52,6 +52,7 @@ class WaylandCompositor; class GraphicsHardwareIntegration; class QWidget; +class WindowManagerServerIntegration; namespace Wayland { @@ -89,6 +90,7 @@ public: GraphicsHardwareIntegration *graphicsHWIntegration() const; void initializeHardwareIntegration(); + void initializeWindowManagerProtocol(); bool setDirectRenderSurface(Surface *surface); Surface *directRenderSurface() const {return m_directRenderSurface;} @@ -138,6 +140,7 @@ private: #ifdef QT_COMPOSITOR_WAYLAND_GL GraphicsHardwareIntegration *m_graphics_hw_integration; #endif + WindowManagerServerIntegration *m_windowManagerWaylandProtocol; }; } diff --git a/src/qt-compositor/wayland_wrapper/wlsurface.cpp b/src/qt-compositor/wayland_wrapper/wlsurface.cpp index 56ca065..45b430a 100644 --- a/src/qt-compositor/wayland_wrapper/wlsurface.cpp +++ b/src/qt-compositor/wayland_wrapper/wlsurface.cpp @@ -67,6 +67,7 @@ public: , needsMap(false) , textureCreatedForBuffer(false) , directRenderBuffer(0) + , processId(0) , surfaceBuffer(0) , surfaceType(WaylandSurface::Invalid) { @@ -107,6 +108,7 @@ public: bool needsMap; bool textureCreatedForBuffer; wl_buffer *directRenderBuffer; + qint64 processId; private: struct wl_buffer *surfaceBuffer; @@ -289,6 +291,24 @@ WaylandSurface * Surface::handle() const return d->qtSurface; } +wl_client *Surface::clientHandle() const +{ + Q_D(const Surface); + return d->client; +} + +qint64 Surface::processId() const +{ + Q_D(const Surface); + return d->processId; +} + +void Surface::setProcessId(qint64 processId) +{ + Q_D(Surface); + d->processId = processId; +} + uint32_t toWaylandButton(Qt::MouseButton button) { switch (button) { diff --git a/src/qt-compositor/wayland_wrapper/wlsurface.h b/src/qt-compositor/wayland_wrapper/wlsurface.h index bcbd3e5..725acd9 100644 --- a/src/qt-compositor/wayland_wrapper/wlsurface.h +++ b/src/qt-compositor/wayland_wrapper/wlsurface.h @@ -96,6 +96,11 @@ public: void setInputFocus(); WaylandSurface *handle() const; + wl_client *clientHandle() const; + qint64 processId() const; + void setProcessId(qint64 processId); + void setSurfaceCreationFinished(bool isCreated); + protected: QScopedPointer d_ptr; private: diff --git a/src/qt-compositor/windowmanagerprotocol/wayland-windowmanager-protocol.c b/src/qt-compositor/windowmanagerprotocol/wayland-windowmanager-protocol.c new file mode 100644 index 0000000..48049d8 --- /dev/null +++ b/src/qt-compositor/windowmanagerprotocol/wayland-windowmanager-protocol.c @@ -0,0 +1,36 @@ +/* + * Copyright © 2010 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + + +#include +#include +#include "wayland-util.h" + +static const struct wl_message wl_windowmanager_requests[] = { + { "map_client_to_process", "u", NULL }, +}; + +WL_EXPORT const struct wl_interface wl_windowmanager_interface = { + "wl_windowmanager", 1, + ARRAY_LENGTH(wl_windowmanager_requests), wl_windowmanager_requests, + 0, NULL, +}; diff --git a/src/qt-compositor/windowmanagerprotocol/wayland-windowmanager-server-protocol.h b/src/qt-compositor/windowmanagerprotocol/wayland-windowmanager-server-protocol.h new file mode 100644 index 0000000..bde9d97 --- /dev/null +++ b/src/qt-compositor/windowmanagerprotocol/wayland-windowmanager-server-protocol.h @@ -0,0 +1,51 @@ +/* + * Copyright © 2010 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + + +#ifndef WAYLAND_WINDOWMANAGER_SERVER_PROTOCOL_H +#define WAYLAND_WINDOWMANAGER_SERVER_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "wayland-util.h" + +struct wl_client; + +struct wl_windowmanager; + +extern const struct wl_interface wl_windowmanager_interface; + +struct wl_windowmanager_interface { + void (*map_client_to_process)(struct wl_client *client, + struct wl_windowmanager *wl_windowmanager, + uint32_t processid); +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/qt-compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp b/src/qt-compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp new file mode 100644 index 0000000..3f19b3d --- /dev/null +++ b/src/qt-compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Compositor. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "waylandwindowmanagerintegration.h" + +#include "waylandobject.h" +#include "wayland_wrapper/wldisplay.h" +#include "wayland_wrapper/wlcompositor.h" + +#include "wayland-server.h" +#include "wayland-windowmanager-server-protocol.h" + +#include + +// the protocol files are generated with wayland-scanner, in the following manner: +// wayland-scanner client-header < windowmanager.xml > wayland-windowmanager-client-protocol.h +// wayland-scanner server-header < windowmanager.xml > wayland-windowmanager-server-protocol.h +// wayland-scanner code < windowmanager.xml > wayland-windowmanager-protocol.c +// +// wayland-scanner can be found from wayland sources. + +class WindowManagerObject : public Wayland::Object +{ +public: + + void mapClientToProcess(wl_client *client, uint32_t processId) + { + WindowManagerServerIntegration::instance()->mapClientToProcess(client, processId); + } + +}; + +void map_client_to_process(wl_client *client, struct wl_windowmanager *windowMgr, uint32_t processId) +{ + reinterpret_cast(windowMgr)->mapClientToProcess(client, processId); +} + +const static struct wl_windowmanager_interface windowmanager_interface = { + map_client_to_process +}; + +WindowManagerServerIntegration *WindowManagerServerIntegration::m_instance = 0; + +WindowManagerServerIntegration::WindowManagerServerIntegration(QObject *parent) + : QObject(parent) +{ + m_instance = this; +} + +void WindowManagerServerIntegration::initialize(Wayland::Display *waylandDisplay) +{ + m_windowManagerObject = new WindowManagerObject(); + waylandDisplay->addGlobalObject(m_windowManagerObject->base(), + &wl_windowmanager_interface, &windowmanager_interface, 0); +} + +void WindowManagerServerIntegration::removeClient(wl_client *client) +{ + m_clientToProcessId.remove(client); +} + +void WindowManagerServerIntegration::mapClientToProcess(wl_client *client, uint32_t processId) +{ + m_clientToProcessId.insert(client, processId); + emit clientMappedToProcess(client, processId); +} + + +qint64 WindowManagerServerIntegration::pidForClient(wl_client *client) const +{ + return m_clientToProcessId.value(client, 0); +} + +WindowManagerServerIntegration *WindowManagerServerIntegration::instance() +{ + return m_instance; +} diff --git a/src/qt-compositor/windowmanagerprotocol/waylandwindowmanagerintegration.h b/src/qt-compositor/windowmanagerprotocol/waylandwindowmanagerintegration.h new file mode 100644 index 0000000..e198c44 --- /dev/null +++ b/src/qt-compositor/windowmanagerprotocol/waylandwindowmanagerintegration.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Compositor. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WAYLANDWINDOWMANAGERINTEGRATION_H +#define WAYLANDWINDOWMANAGERINTEGRATION_H + +#include +#include +#include "wayland_wrapper/wldisplay.h" + +#include +#include + + +struct wl_client; + +class WindowManagerObject; + +class WindowManagerServerIntegration : public QObject +{ + Q_OBJECT +public: + WindowManagerServerIntegration(QObject *parent = 0); + static WindowManagerServerIntegration *instance(); + void initialize(Wayland::Display *waylandDisplay); + void removeClient(wl_client *client); + + qint64 pidForClient(wl_client *client) const; + +signals: + void clientMappedToProcess(wl_client *client, quint32 processId); + +private: + void mapClientToProcess(wl_client *client, uint32_t processId); + +private: + QMap m_clientToProcessId; + static WindowManagerServerIntegration *m_instance; + + WindowManagerObject *m_windowManagerObject; + + friend class WindowManagerObject; +}; + +#endif // WAYLANDWINDOWMANAGERINTEGRATION_H diff --git a/src/qt-compositor/windowmanagerprotocol/windowmanager.xml b/src/qt-compositor/windowmanagerprotocol/windowmanager.xml new file mode 100644 index 0000000..f29c337 --- /dev/null +++ b/src/qt-compositor/windowmanagerprotocol/windowmanager.xml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/src/qt-compositor/windowmanagerprotocol/windowmanagerprotocol.pri b/src/qt-compositor/windowmanagerprotocol/windowmanagerprotocol.pri new file mode 100644 index 0000000..b03b087 --- /dev/null +++ b/src/qt-compositor/windowmanagerprotocol/windowmanagerprotocol.pri @@ -0,0 +1,11 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/waylandwindowmanagerintegration.h \ + $$PWD/wayland-windowmanager-server-protocol.h + +SOURCES += \ + $$PWD/waylandwindowmanagerintegration.cpp \ + $$PWD/wayland-windowmanager-protocol.c + + -- 2.7.4