diff options
Diffstat (limited to 'src/compositor')
68 files changed, 6201 insertions, 0 deletions
diff --git a/src/compositor/compositor.pri b/src/compositor/compositor.pri new file mode 100644 index 000000000..de95dc4ce --- /dev/null +++ b/src/compositor/compositor.pri @@ -0,0 +1,32 @@ +CONFIG += module +MODULE_PRI += $$PWD/../../modules/qt_compositor.pri + +INCLUDEPATH += $$PWD +DEFINES += QT_WAYLAND_WINDOWMANAGER_SUPPORT +DEFINES += QT_BUILD_COMPOSITOR_LIB + +!mac:use_pkgconfig { + CONFIG += link_pkgconfig + PKGCONFIG += wayland-server + + #set the rpath + !isEmpty(QMAKE_LFLAGS_RPATH) { + WAYLAND_NEEDS_RPATH = $$system(pkg-config --libs-only-L wayland-server) + !isEmpty(WAYLAND_NEEDS_RPATH) { + WAYLAND_LIBDIR = $$system(pkg-config --variable=libdir wayland-server) + !isEmpty(WAYLAND_LIBDIR):QMAKE_LFLAGS += $${QMAKE_LFLAGS_RPATH}$${WAYLAND_LIBDIR} + } + } +} else { + INCLUDEPATH += $$PWD/../3rdparty/wayland + LIBS += -L$$PWD/../../lib + LIBS += -lwayland-server -lffi +} + +HEADERS += qtcompositorversion.h + +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/compositor/compositor.pro b/src/compositor/compositor.pro new file mode 100644 index 000000000..850e350dd --- /dev/null +++ b/src/compositor/compositor.pro @@ -0,0 +1,10 @@ +load(qt_module) + +TARGET = QtCompositor +QPRO_PWD = $$PWD + +include (compositor.pri) +load(qt_module_config) + +QT += gui-private + diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri new file mode 100644 index 000000000..374c7747d --- /dev/null +++ b/src/compositor/compositor_api/compositor_api.pri @@ -0,0 +1,22 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/waylandcompositor.h \ + $$PWD/waylandsurface.h + +SOURCES += \ + $$PWD/waylandcompositor.cpp \ + $$PWD/waylandsurface.cpp + +QT += core-private + +contains(QT_CONFIG, quick) { + SOURCES += $$PWD/waylandsurfaceitem.cpp + HEADERS += $$PWD/waylandsurfaceitem.h + + DEFINES += QT_COMPOSITOR_QUICK + + QT += quick + QT += quick-private gui-private +} + diff --git a/src/compositor/compositor_api/waylandcompositor.cpp b/src/compositor/compositor_api/waylandcompositor.cpp new file mode 100644 index 000000000..a21a7eaf2 --- /dev/null +++ b/src/compositor/compositor_api/waylandcompositor.cpp @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "waylandcompositor.h" + +#include "wayland_wrapper/wlcompositor.h" +#include "wayland_wrapper/wlsurface.h" +#include <QtCore/QCoreApplication> +#include <QtCore/QStringList> + +#include <QDebug> + +#ifdef QT_COMPOSITOR_DECLARATIVE +#include "waylandsurfaceitem.h" +#endif + +WaylandCompositor::WaylandCompositor(QWindow *window, const char *socketName) + : m_compositor(0) + , m_toplevel_widget(window) + , m_socket_name(socketName) +{ + QStringList arguments = QCoreApplication::instance()->arguments(); + + int socketArg = arguments.indexOf(QLatin1String("--wayland-socket-name")); + if (socketArg != -1 && socketArg + 1 < arguments.size()) + m_socket_name = arguments.at(socketArg + 1).toLocal8Bit(); + + m_compositor = new Wayland::Compositor(this); +#ifdef QT_COMPOSITOR_DECLARATIVE + qmlRegisterType<WaylandSurfaceItem>("WaylandCompositor", 1, 0, "WaylandSurfaceItem"); + qRegisterMetaType<WaylandSurface*>("WaylandSurface*"); +#endif + m_compositor->initializeHardwareIntegration(); + m_compositor->initializeWindowManagerProtocol(); +} + +WaylandCompositor::~WaylandCompositor() +{ + delete m_compositor; +} + +void WaylandCompositor::frameFinished(WaylandSurface *surface) +{ + Wayland::Surface *surfaceImpl = surface? surface->handle():0; + m_compositor->frameFinished(surfaceImpl); +} + +void WaylandCompositor::setInputFocus(WaylandSurface *surface) +{ + Wayland::Surface *surfaceImpl = surface? surface->handle():0; + m_compositor->setInputFocus(surfaceImpl); +} + +WaylandSurface *WaylandCompositor::inputFocus() const +{ + Wayland::Surface *surfaceImpl = m_compositor->keyFocus(); + return surfaceImpl ? surfaceImpl->handle() : 0; +} + +void WaylandCompositor::destroyClientForSurface(WaylandSurface *surface) +{ + m_compositor->destroyClientForSurface(surface->handle()); +} + +void WaylandCompositor::setDirectRenderSurface(WaylandSurface *surface) +{ + m_compositor->setDirectRenderSurface(surface ? surface->handle() : 0); +} + +WaylandSurface *WaylandCompositor::directRenderSurface() const +{ + Wayland::Surface *surf = m_compositor->directRenderSurface(); + return surf ? surf->handle() : 0; +} + +QWindow * WaylandCompositor::window() const +{ + return m_toplevel_widget; +} + +Wayland::Compositor * WaylandCompositor::handle() const +{ + return m_compositor; +} + +void WaylandCompositor::setRetainedSelectionEnabled(bool enable) +{ +// Wayland::Selection *sel = Wayland::Selection::instance(); +// sel->setRetainedSelection(enable); +// sel->setRetainedSelectionWatcher(retainedSelectionChanged, this); +} + +void WaylandCompositor::retainedSelectionChanged(QMimeData *mimeData, void *param) +{ + WaylandCompositor *self = static_cast<WaylandCompositor *>(param); + self->retainedSelectionReceived(mimeData); +} + +void WaylandCompositor::retainedSelectionReceived(QMimeData *) +{ +} + +void WaylandCompositor::overrideSelection(QMimeData *data) +{ +// Wayland::Selection *sel = Wayland::Selection::instance(); +// sel->overrideSelection(data); +} + +const char *WaylandCompositor::socketName() const +{ + if (m_socket_name.isEmpty()) + return 0; + return m_socket_name.constData(); +} + +/*! + Set the screen orientation based on accelerometer data or similar. +*/ +void WaylandCompositor::setScreenOrientation(Qt::ScreenOrientation orientation) +{ + m_compositor->setScreenOrientation(orientation); +} + +void WaylandCompositor::setOutputGeometry(const QRect &geometry) +{ + m_compositor->setOutputGeometry(geometry); +} + +bool WaylandCompositor::isDragging() const +{ + return m_compositor->isDragging(); +} + +void WaylandCompositor::sendDragMoveEvent(const QPoint &global, const QPoint &local, + WaylandSurface *surface) +{ + m_compositor->sendDragMoveEvent(global, local, surface ? surface->handle() : 0); +} + +void WaylandCompositor::sendDragEndEvent() +{ + m_compositor->sendDragEndEvent(); +} + +void WaylandCompositor::changeCursor(const QImage &image, int hotspotX, int hotspotY) +{ + Q_UNUSED(image); + Q_UNUSED(hotspotX); + Q_UNUSED(hotspotY); + qDebug() << "changeCursor" << image.size() << hotspotX << hotspotY; +} diff --git a/src/compositor/compositor_api/waylandcompositor.h b/src/compositor/compositor_api/waylandcompositor.h new file mode 100644 index 000000000..557aa6ce9 --- /dev/null +++ b/src/compositor/compositor_api/waylandcompositor.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef QTCOMP_H +#define QTCOMP_H + +#include "waylandexport.h" + +#include <QObject> +#include <QImage> +#include <QRect> + +class QWidget; +class QMimeData; +class WaylandSurface; + +namespace Wayland +{ + class Compositor; +} + +class Q_COMPOSITOR_EXPORT WaylandCompositor +{ +public: + WaylandCompositor(QWindow *window = 0, const char *socketName = 0); + virtual ~WaylandCompositor(); + + void frameFinished(WaylandSurface *surface = 0); + + void setInputFocus(WaylandSurface *surface); + WaylandSurface *inputFocus() const; + void destroyClientForSurface(WaylandSurface *surface); + + void setDirectRenderSurface(WaylandSurface *surface); + WaylandSurface *directRenderSurface() const; + + QWindow *window()const; + + virtual void surfaceCreated(WaylandSurface *surface) = 0; + + Wayland::Compositor *handle() const; + + void setRetainedSelectionEnabled(bool enable); + virtual void retainedSelectionReceived(QMimeData *mimeData); + void overrideSelection(QMimeData *data); + + const char *socketName() const; + + void setScreenOrientation(Qt::ScreenOrientation orientation); + void setOutputGeometry(const QRect &outputGeometry); + + bool isDragging() const; + void sendDragMoveEvent(const QPoint &global, const QPoint &local, WaylandSurface *surface); + void sendDragEndEvent(); + + virtual void changeCursor(const QImage &image, int hotspotX, int hotspotY); + +private: + static void retainedSelectionChanged(QMimeData *mimeData, void *param); + + Wayland::Compositor *m_compositor; + QWindow *m_toplevel_widget; + QByteArray m_socket_name; +}; + +#endif // QTCOMP_H diff --git a/src/compositor/compositor_api/waylandsurface.cpp b/src/compositor/compositor_api/waylandsurface.cpp new file mode 100644 index 000000000..8fdc7370c --- /dev/null +++ b/src/compositor/compositor_api/waylandsurface.cpp @@ -0,0 +1,161 @@ +#include "waylandsurface.h" + +#include <private/qobject_p.h> + +#include "wayland_wrapper/wlsurface.h" + +class WaylandSurfacePrivate : public QObjectPrivate +{ +public: + WaylandSurfacePrivate(Wayland::Surface *srfc) + : surface(srfc) + {} + + Wayland::Surface *surface; + QRect geometry; +}; + +WaylandSurface::WaylandSurface(Wayland::Surface *surface) + : QObject(*new WaylandSurfacePrivate(surface)) +{ + +} + +WaylandSurface::Type WaylandSurface::type() const +{ + Q_D(const WaylandSurface); + return d->surface->type(); +} + +bool WaylandSurface::isYInverted() const +{ + Q_D(const WaylandSurface); + return d->surface->isYInverted(); +} + +QRect WaylandSurface::geometry() const +{ + Q_D(const WaylandSurface); + return d->geometry; +} + +void WaylandSurface::setGeometry(const QRect &geometry) +{ + Q_D(WaylandSurface); + d->geometry = geometry; +} + +QImage WaylandSurface::image() const +{ + Q_D(const WaylandSurface); + return d->surface->image(); +} + +#ifdef QT_COMPOSITOR_WAYLAND_GL +GLuint WaylandSurface::texture(QOpenGLContext *context) const +{ + Q_D(const WaylandSurface); + return d->surface->textureId(context); +} +#else //QT_COMPOSITOR_WAYLAND_GL +uint WaylandSurface::texture(QOpenGLContext *) const +{ + return 0; +} +#endif + +Wayland::Surface * WaylandSurface::handle() const +{ + Q_D(const WaylandSurface); + return d->surface; +} + +qint64 WaylandSurface::processId() const +{ + Q_D(const WaylandSurface); + return d->surface->processId(); +} + +QByteArray WaylandSurface::authenticationToken() const +{ + Q_D(const WaylandSurface); + return d->surface->authenticationToken(); +} + +QVariantMap WaylandSurface::windowProperties() const +{ + Q_D(const WaylandSurface); + return d->surface->windowProperties(); +} + +void WaylandSurface::setWindowProperty(const QString &name, const QVariant &value) +{ + Q_D(WaylandSurface); + d->surface->setWindowProperty(name, value); +} + +void WaylandSurface::sendMousePressEvent(const QPoint &pos, Qt::MouseButton button) +{ + Q_D(WaylandSurface); + d->surface->sendMousePressEvent(pos.x(), pos.y(), button); +} + +void WaylandSurface::sendMouseReleaseEvent(const QPoint &pos, Qt::MouseButton button) +{ + Q_D(WaylandSurface); + d->surface->sendMouseReleaseEvent(pos.x(), pos.y(), button); +} + +void WaylandSurface::sendMouseMoveEvent(const QPoint &pos) +{ + Q_D(WaylandSurface); + d->surface->sendMouseMoveEvent(pos.x(), pos.y()); +} + +void WaylandSurface::sendKeyPressEvent(uint code) +{ + Q_D(WaylandSurface); + d->surface->sendKeyPressEvent(code); +} + +void WaylandSurface::sendKeyReleaseEvent(uint code) +{ + Q_D(WaylandSurface); + d->surface->sendKeyReleaseEvent(code); +} + +void WaylandSurface::sendTouchPointEvent(int id, int x, int y, Qt::TouchPointState state) +{ + Q_D(WaylandSurface); + d->surface->sendTouchPointEvent(id, x, y, state); +} + +void WaylandSurface::sendTouchFrameEvent() +{ + Q_D(WaylandSurface); + d->surface->sendTouchFrameEvent(); +} + +void WaylandSurface::sendTouchCancelEvent() +{ + Q_D(WaylandSurface); + d->surface->sendTouchCancelEvent(); +} + +void WaylandSurface::frameFinished() +{ + Q_D(WaylandSurface); + d->surface->frameFinished(); +} + +void WaylandSurface::setInputFocus() +{ + Q_D(WaylandSurface); + d->surface->setInputFocus(); +} + +void WaylandSurface::sendOnScreenVisibilityChange(bool visible) +{ + Q_D(WaylandSurface); + d->surface->sendOnScreenVisibilityChange(visible); +} diff --git a/src/compositor/compositor_api/waylandsurface.h b/src/compositor/compositor_api/waylandsurface.h new file mode 100644 index 000000000..d9f68d7c1 --- /dev/null +++ b/src/compositor/compositor_api/waylandsurface.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WAYLANDSURFACE_H +#define WAYLANDSURFACE_H + +#include "waylandexport.h" + +#include <QtCore/QScopedPointer> +#include <QtGui/QImage> +#include <QtCore/QVariantMap> + +#ifdef QT_COMPOSITOR_WAYLAND_GL +#include <QtGui/QOpenGLContext> +#include <QtGui/qopengl.h> +#endif + +class WaylandSurfacePrivate; + +namespace Wayland { +class Surface; +class SurfacePrivate; +} + +class Q_COMPOSITOR_EXPORT WaylandSurface : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(WaylandSurface) +public: + enum Type { + Invalid, + Shm, + Texture, + Direct + }; + + WaylandSurface(Wayland::Surface *surface); + + Type type() const; + bool isYInverted() const; + + void setGeometry(const QRect &geometry); + QRect geometry() const; + + QImage image() const; +#ifdef QT_COMPOSITOR_WAYLAND_GL + GLuint texture(QOpenGLContext *context) const; +#else + uint texture(QOpenGLContext *context) const; +#endif + + void sendMousePressEvent(const QPoint &pos, Qt::MouseButton button); + void sendMouseReleaseEvent(const QPoint &pos, Qt::MouseButton button); + void sendMouseMoveEvent(const QPoint &pos); + + void sendKeyPressEvent(uint code); + void sendKeyReleaseEvent(uint code); + + void sendTouchPointEvent(int id, int x, int y, Qt::TouchPointState state); + void sendTouchFrameEvent(); + void sendTouchCancelEvent(); + + void sendOnScreenVisibilityChange(bool visible); + + void frameFinished(); + void setInputFocus(); + + Wayland::Surface *handle() const; + qint64 processId() const; + QByteArray authenticationToken() const; + QVariantMap windowProperties() const; + void setWindowProperty(const QString &name, const QVariant &value); + +signals: + void mapped(const QSize &size); + void damaged(const QRect &rect); + + friend class Wayland::Surface; + friend class Wayland::SurfacePrivate; +}; + +#endif // WAYLANDSURFACE_H diff --git a/src/compositor/compositor_api/waylandsurfaceitem.cpp b/src/compositor/compositor_api/waylandsurfaceitem.cpp new file mode 100644 index 000000000..0de4f9884 --- /dev/null +++ b/src/compositor/compositor_api/waylandsurfaceitem.cpp @@ -0,0 +1,295 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "waylandsurfaceitem.h" +#include "waylandsurface.h" + +#include <QtQuick/QSGEngine> + +#include <QtGui/QKeyEvent> + +#include <QtQuick/QSGSimpleTextureNode> +#include <QtQuick/QSGSimpleRectNode> +#include <QtQuick/QQuickCanvas> + +class WaylandSurfaceTextureProvider : public QSGTextureProvider +{ +public: + WaylandSurfaceTextureProvider() : t(0) { } + + QSGTexture *texture() const { + if (t) + t->setFiltering(smooth ? QSGTexture::Linear : QSGTexture::Nearest); + return t; + } + + QSGTexture *t; + bool smooth; +}; + +void WaylandSurfaceItem::surfaceDamaged(const QRect &) +{ + m_damaged = true; + emit textureChanged(); + update(); +} + +WaylandSurfaceItem::WaylandSurfaceItem(QQuickItem *parent) + : QQuickItem(parent) + , m_surface(0) + , m_texture(0) + , m_provider(0) + , m_paintEnabled(true) + , m_touchEventsEnabled(false) +{ +} + +WaylandSurfaceItem::WaylandSurfaceItem(WaylandSurface *surface, QQuickItem *parent) + : QQuickItem(parent) + , m_surface(0) + , m_texture(0) + , m_provider(0) + , m_paintEnabled(true) + , m_touchEventsEnabled(false) +{ + init(surface); +} + +void WaylandSurfaceItem::init(WaylandSurface *surface) +{ + if (!surface) + return; + + m_surface = surface; + + setWidth(surface->geometry().width()); + setHeight(surface->geometry().height()); + + setSmooth(true); + setFlag(ItemHasContents); + setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton); + connect(surface, SIGNAL(mapped(const QSize &)), this, SLOT(surfaceMapped(const QSize &))); + connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *))); + connect(surface, SIGNAL(damaged(const QRect &)), this, SLOT(surfaceDamaged(const QRect &))); + + m_damaged = false; + +} + +WaylandSurfaceItem::~WaylandSurfaceItem() +{ + m_texture->deleteLater(); +} + +void WaylandSurfaceItem::setSurface(WaylandSurface *surface) +{ + init(surface); +} + +bool WaylandSurfaceItem::isYInverted() const +{ + return m_surface->isYInverted(); +} + +QSGTextureProvider *WaylandSurfaceItem::textureProvider() const +{ + if (!m_provider) + m_provider = new WaylandSurfaceTextureProvider(); + return m_provider; +} + +void WaylandSurfaceItem::mousePressEvent(QMouseEvent *event) +{ + if (m_surface) + m_surface->sendMousePressEvent(toSurface(event->pos()), event->button()); +} + +void WaylandSurfaceItem::mouseMoveEvent(QMouseEvent *event) +{ + if (m_surface) + m_surface->sendMouseMoveEvent(toSurface(event->pos())); +} + +void WaylandSurfaceItem::mouseReleaseEvent(QMouseEvent *event) +{ + if (m_surface) + m_surface->sendMouseReleaseEvent(toSurface(event->pos()), event->button()); +} + +void WaylandSurfaceItem::keyPressEvent(QKeyEvent *event) +{ + if (m_surface && hasFocus()) + m_surface->sendKeyPressEvent(event->nativeScanCode()); +} + +void WaylandSurfaceItem::keyReleaseEvent(QKeyEvent *event) +{ + if (m_surface && hasFocus()) + m_surface->sendKeyReleaseEvent(event->nativeScanCode()); +} + +void WaylandSurfaceItem::touchEvent(QTouchEvent *event) +{ + if (m_touchEventsEnabled && m_surface) { + event->accept(); + QList<QTouchEvent::TouchPoint> points = event->touchPoints(); + if (!points.isEmpty()) { + for (int i = 0; i < points.count(); ++i) { + const QTouchEvent::TouchPoint &point(points.at(i)); + // Wayland expects surface-relative coordinates. + m_surface->sendTouchPointEvent(point.id(), point.pos().x(), point.pos().y(), point.state()); + } + m_surface->sendTouchFrameEvent(); + } + } else { + event->ignore(); + } +} + +void WaylandSurfaceItem::takeFocus() +{ + setFocus(true); + + if (m_surface) + m_surface->setInputFocus(); +} + +QPoint WaylandSurfaceItem::toSurface(const QPointF &pos) const +{ + return pos.toPoint(); +} + +void WaylandSurfaceItem::surfaceMapped(const QSize &size) +{ + setWidth(size.width()); + setHeight(size.height()); +} + +void WaylandSurfaceItem::surfaceDestroyed(QObject *) +{ + m_surface = 0; +} + +bool WaylandSurfaceItem::paintEnabled() const +{ + return m_paintEnabled; +} + +void WaylandSurfaceItem::setPaintEnabled(bool enabled) +{ + m_paintEnabled = enabled; + update(); +} + +QSGNode *WaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode); + + if (m_damaged) { + QSGTexture *oldTexture = m_texture; + if (m_surface->type() == WaylandSurface::Texture) { + QOpenGLContext *context = QOpenGLContext::currentContext(); + + QSGEngine::TextureOption opt = useTextureAlpha() ? QSGEngine::TextureHasAlphaChannel : QSGEngine::TextureOption(0); + m_texture = canvas()->sceneGraphEngine()->createTextureFromId(m_surface->texture(context), + m_surface->geometry().size(), + opt); + } else { + m_texture = canvas()->sceneGraphEngine()->createTextureFromImage(m_surface->image()); + } + delete oldTexture; + m_damaged = false; + } + + if (m_provider) { + m_provider->t = m_texture; + m_provider->smooth = smooth(); + } + + if (!m_texture || !m_paintEnabled) { + delete oldNode; + return 0; + } + + if (!node) { + node = new QSGSimpleTextureNode(); + } + + if (surface()->isYInverted()) { + node->setRect(0, height(), width(), -height()); + } else { + node->setRect(0, 0, width(), height()); + } + + node->setTexture(m_texture); + node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest); + + return node; +} + +void WaylandSurfaceItem::setUseTextureAlpha(bool useTextureAlpha) +{ + m_useTextureAlpha = useTextureAlpha; + + if ((flags() & ItemHasContents) != 0) { + update(); + } +} + +void WaylandSurfaceItem::setClientRenderingEnabled(bool enabled) +{ + if (m_clientRenderingEnabled != enabled) { + m_clientRenderingEnabled = enabled; + + if (m_surface) { + m_surface->sendOnScreenVisibilityChange(enabled); + } + + emit clientRenderingEnabledChanged(); + } +} + +void WaylandSurfaceItem::setTouchEventsEnabled(bool enabled) +{ + if (m_touchEventsEnabled != enabled) { + m_touchEventsEnabled = enabled; + emit touchEventsEnabledChanged(); + } +} diff --git a/src/compositor/compositor_api/waylandsurfaceitem.h b/src/compositor/compositor_api/waylandsurfaceitem.h new file mode 100644 index 000000000..a66a2cead --- /dev/null +++ b/src/compositor/compositor_api/waylandsurfaceitem.h @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WAYLANDSURFACEITEM_H +#define WAYLANDSURFACEITEM_H + +#include "waylandexport.h" + +#include <QtQuick/QQuickItem> +#include <QtQuick/qsgtexture.h> + +#include <QtQuick/private/qsgtextureprovider_p.h> + +class WaylandSurface; +class WaylandSurfaceTextureProvider; + +Q_DECLARE_METATYPE(WaylandSurface*) + +class Q_COMPOSITOR_EXPORT WaylandSurfaceItem : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(WaylandSurface* surface READ surface WRITE setSurface) + Q_PROPERTY(bool paintEnabled READ paintEnabled WRITE setPaintEnabled) + Q_PROPERTY(bool useTextureAlpha READ useTextureAlpha WRITE setUseTextureAlpha NOTIFY useTextureAlphaChanged) + Q_PROPERTY(bool clientRenderingEnabled READ clientRenderingEnabled WRITE setClientRenderingEnabled NOTIFY clientRenderingEnabledChanged) + Q_PROPERTY(bool touchEventsEnabled READ touchEventsEnabled WRITE setTouchEventsEnabled NOTIFY touchEventsEnabledChanged) + +public: + WaylandSurfaceItem(QQuickItem *parent = 0); + WaylandSurfaceItem(WaylandSurface *surface, QQuickItem *parent = 0); + ~WaylandSurfaceItem(); + + void setSurface(WaylandSurface *surface); + WaylandSurface *surface() const {return m_surface; } + + Q_INVOKABLE bool isYInverted() const; + + bool isTextureProvider() const { return true; } + QSGTextureProvider *textureProvider() const; + + bool paintEnabled() const; + bool useTextureAlpha() const { return m_useTextureAlpha; } + bool clientRenderingEnabled() const { return m_clientRenderingEnabled; } + bool touchEventsEnabled() const { return m_touchEventsEnabled; } + + void setUseTextureAlpha(bool useTextureAlpha); + void setClientRenderingEnabled(bool enabled); + void setTouchEventsEnabled(bool enabled); + +protected: + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *event); + + void touchEvent(QTouchEvent *event); + +public slots: + void takeFocus(); + void setPaintEnabled(bool paintEnabled); + +private slots: + void surfaceMapped(const QSize &size); + void surfaceDestroyed(QObject *object); + void surfaceDamaged(const QRect &); + +signals: + void textureChanged(); + void useTextureAlphaChanged(); + void clientRenderingEnabledChanged(); + void touchEventsEnabledChanged(); + +protected: + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); + +private: + QPoint toSurface(const QPointF &pos) const; + void init(WaylandSurface *); + + WaylandSurface *m_surface; + QSGTexture *m_texture; + mutable WaylandSurfaceTextureProvider *m_provider; + bool m_paintEnabled; + bool m_useTextureAlpha; + bool m_clientRenderingEnabled; + bool m_touchEventsEnabled; + bool m_damaged; +}; + +#endif diff --git a/src/compositor/hardware_integration/dri2_xcb/README b/src/compositor/hardware_integration/dri2_xcb/README new file mode 100644 index 000000000..e99500df7 --- /dev/null +++ b/src/compositor/hardware_integration/dri2_xcb/README @@ -0,0 +1,3 @@ +This backend requires that you compile the xcb lighthouse plugin with the +defined: XCB_USE_DRI2. Please see in the xcb.pro file for an easy way to +enable it. diff --git a/src/compositor/hardware_integration/dri2_xcb/dri2_xcb.pri b/src/compositor/hardware_integration/dri2_xcb/dri2_xcb.pri new file mode 100644 index 000000000..641c7a91a --- /dev/null +++ b/src/compositor/hardware_integration/dri2_xcb/dri2_xcb.pri @@ -0,0 +1,14 @@ +INCLUDEPATH += $$PWD/../private +LIBS += -lxcb -lxcb-dri2 -lEGL + +DEFINES += QT_COMPOSITOR_DRI2_XCB + +SOURCES += \ + $$PWD/dri2xcbhwintegration.cpp \ + $$PWD/dri2xcbbuffer.cpp \ + $$PWD/../../../3rdparty/wayland/wayland-drm-protocol.c \ + +HEADERS += \ + $$PWD/dri2xcbhwintegration.h \ + $$PWD/dri2xcbbuffer.h \ + $$PWD/../../../3rdparty/wayland/wayland-drm-server-protocol.h \ diff --git a/src/compositor/hardware_integration/dri2_xcb/dri2xcbbuffer.cpp b/src/compositor/hardware_integration/dri2_xcb/dri2xcbbuffer.cpp new file mode 100644 index 000000000..eb516d1d2 --- /dev/null +++ b/src/compositor/hardware_integration/dri2_xcb/dri2xcbbuffer.cpp @@ -0,0 +1,46 @@ +#include "dri2xcbbuffer.h" + +#include "waylandobject.h" + +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> + +Dri2XcbBuffer::Dri2XcbBuffer(uint32_t id, uint32_t name, const QSize &size, uint32_t stride, wl_visual *visual, EGLDisplay eglDisplay, Wayland::Compositor *compositor) + :m_egl_display(eglDisplay) +{ + base()->compositor = compositor->base(); + base()->visual = visual; + base()->height = size.height(); + base()->width = size.width(); + base()->attach = 0; + base()->damage = 0; + + EGLint attribs[] = { + EGL_WIDTH, size.width(), + EGL_HEIGHT, size.height(), + EGL_DRM_BUFFER_STRIDE_MESA, stride /4, + EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, + EGL_NONE + }; + + m_image = eglCreateImageKHR(m_egl_display, + EGL_NO_CONTEXT, + EGL_DRM_BUFFER_MESA, + (EGLClientBuffer) name, attribs); +} + +Dri2XcbBuffer::~Dri2XcbBuffer() +{ + eglDestroyImageKHR (m_egl_display, m_image); +} + +void dri2XcbBufferDestroy(struct wl_client *client, struct wl_buffer *buffer) +{ + delete Wayland::wayland_cast<Dri2XcbBuffer *>(buffer); +} + +EGLImageKHR Dri2XcbBuffer::image() const +{ + return m_image; +} diff --git a/src/compositor/hardware_integration/dri2_xcb/dri2xcbbuffer.h b/src/compositor/hardware_integration/dri2_xcb/dri2xcbbuffer.h new file mode 100644 index 000000000..61d431ded --- /dev/null +++ b/src/compositor/hardware_integration/dri2_xcb/dri2xcbbuffer.h @@ -0,0 +1,38 @@ +#ifndef DRI2XCBBUFFER_H +#define DRI2XCBBUFFER_H + +#include "waylandobject.h" +#include "wayland_wrapper/wlcompositor.h" + +#include <wayland-server.h> + +#include <QtCore/QSize> +#include <QtWidgets/QApplication> +#include <QtCore/QTextStream> +#include <QtGui/QPlatformNativeInterface> + +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> + +class Dri2XcbBuffer : public Wayland::Object<struct wl_buffer> +{ +public: + Dri2XcbBuffer(uint32_t id, uint32_t name, const QSize &size, uint32_t stride, + wl_visual *visual, EGLDisplay eglDisplay, Wayland::Compositor *compositor); + ~Dri2XcbBuffer(); + + EGLImageKHR image() const; + +private: + EGLImageKHR m_image; + EGLDisplay m_egl_display; +}; + +void dri2XcbBufferDestroy(struct wl_client *client, struct wl_buffer *buffer); + +const static struct wl_buffer_interface dri2_xcb_buffer_interface = { + dri2XcbBufferDestroy +}; + +#endif // DRI2XCBBUFFER_H diff --git a/src/compositor/hardware_integration/dri2_xcb/dri2xcbhwintegration.cpp b/src/compositor/hardware_integration/dri2_xcb/dri2xcbhwintegration.cpp new file mode 100644 index 000000000..0d16f78c6 --- /dev/null +++ b/src/compositor/hardware_integration/dri2_xcb/dri2xcbhwintegration.cpp @@ -0,0 +1,130 @@ +#include "dri2xcbhwintegration.h" + +#include "dri2xcbbuffer.h" + +#include "waylandobject.h" +#include "wayland_wrapper/wldisplay.h" +#include "wayland_wrapper/wlcompositor.h" + +#include "wayland-server.h" +#include "wayland-drm-server-protocol.h" + +#include <QtCore/QDebug> + +#include <xcb/xcb.h> +#include <xcb/dri2.h> + +GraphicsHardwareIntegration * GraphicsHardwareIntegration::createGraphicsHardwareIntegration(WaylandCompositor *compositor) +{ + return new Dri2XcbHWIntegration(compositor); +} + +class DrmObject : public Wayland::Object<struct wl_object> +{ +public: + DrmObject(Wayland::Compositor *compositor, QWidget *window) + :m_compositor(compositor) + { + QPlatformNativeInterface *nativeInterface = QApplicationPrivate::platformIntegration()->nativeInterface(); + char *deviceName = static_cast<char *>(nativeInterface->nativeResourceForWidget("GraphicsDevice",window)); + m_device_name = QByteArray(deviceName); + + m_connection = static_cast<xcb_connection_t *>(nativeInterface->nativeResourceForWidget("Connection",window)); + m_egl_display = static_cast<EGLDisplay>(nativeInterface->nativeResourceForWidget("EglDisplay",window)); + } + QByteArray deviceName() + { + return m_device_name; + } + + void authenticate(struct wl_client *client, uint32_t id) + { + + xcb_screen_iterator_t screenIterator = xcb_setup_roots_iterator(xcb_get_setup(m_connection)); + xcb_dri2_authenticate_cookie_t authenticateCoockie = xcb_dri2_authenticate_unchecked(m_connection,screenIterator.data->root,id); + xcb_dri2_authenticate_reply_t *authenticate = xcb_dri2_authenticate_reply(m_connection,authenticateCoockie,NULL); + + if (authenticate && authenticate->authenticated) { + wl_client_post_event(client, base(), WL_DRM_AUTHENTICATED); + } else { + qDebug() << "Failed to authenticate drm :("; + } + + delete authenticate; + } + + void createBuffer(wl_client *client, uint32_t id, uint32_t name, const QSize &size, uint32_t stride, wl_visual *visual) + { + Dri2XcbBuffer *buffer = new Dri2XcbBuffer(id,name,size,stride,visual,m_egl_display, m_compositor); + Wayland::addClientResource(client,&buffer->base()->resource,id,&wl_buffer_interface,&dri2_xcb_buffer_interface,0); + } + +private: + QByteArray m_device_name; + xcb_connection_t *m_connection; + xcb_screen_t *m_screen; + EGLDisplay m_egl_display; + Wayland::Compositor *m_compositor; +}; + +void authenticate(struct wl_client *client, + struct wl_drm *drm, + uint32_t id) +{ + reinterpret_cast<DrmObject *>(drm)->authenticate(client,id); +} + +void create_buffer(struct wl_client *client, + struct wl_drm *drm, + uint32_t id, + uint32_t name, + int width, + int height, + uint32_t stride, + struct wl_visual *visual) +{ + DrmObject *drmObject = reinterpret_cast<DrmObject *>(drm); + drmObject->createBuffer(client,id,name,QSize(width,height),stride,visual); +} + +const static struct wl_drm_interface drm_interface = { + authenticate, + create_buffer +}; + +void post_drm_device(struct wl_client *client, struct wl_object *global) +{ + DrmObject *drmObject = Wayland::wayland_cast<DrmObject *>(global); + qDebug() << drmObject->deviceName().constData(); + wl_client_post_event(client, global, WL_DRM_DEVICE, drmObject->deviceName().constData()); +} + +Dri2XcbHWIntegration::Dri2XcbHWIntegration(WaylandCompositor *compositor) + : GraphicsHardwareIntegration(compositor) + , m_drm_object(0) +{ +} + +void Dri2XcbHWIntegration::initializeHardware(Wayland::Display *waylandDisplay) +{ + //we need a winId now. + m_compositor->window()->winId(); + + + m_drm_object = new DrmObject(m_compositor->handle(),m_compositor->window()); + + waylandDisplay->addGlobalObject(m_drm_object->base(),&wl_drm_interface,&drm_interface,post_drm_device); +} + +GLuint Dri2XcbHWIntegration::createTextureFromBuffer(wl_buffer *buffer, QOpenGLContext *) +{ + Dri2XcbBuffer *dri2Buffer = Wayland::wayland_cast<Dri2XcbBuffer *>(buffer); + + GLuint textureId = 0; + glGenTextures(1,&textureId); + glBindTexture(GL_TEXTURE_2D, textureId); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, dri2Buffer->image()); + + return textureId; +} diff --git a/src/compositor/hardware_integration/dri2_xcb/dri2xcbhwintegration.h b/src/compositor/hardware_integration/dri2_xcb/dri2xcbhwintegration.h new file mode 100644 index 000000000..9ed355815 --- /dev/null +++ b/src/compositor/hardware_integration/dri2_xcb/dri2xcbhwintegration.h @@ -0,0 +1,21 @@ +#ifndef DRI2XCBHWINTEGRATION_H +#define DRI2XCBHWINTEGRATION_H + +#include "hardware_integration/graphicshardwareintegration.h" + +class DrmObject; + +class Dri2XcbHWIntegration : public GraphicsHardwareIntegration +{ +public: + Dri2XcbHWIntegration(WaylandCompositor *compositor); + + void initializeHardware(Wayland::Display *waylandDisplay); + + GLuint createTextureFromBuffer(wl_buffer *buffer, QOpenGLContext *context); + +private: + DrmObject *m_drm_object; +}; + +#endif // DRI2XCBHWINTEGRATION_H diff --git a/src/compositor/hardware_integration/graphicshardwareintegration.cpp b/src/compositor/hardware_integration/graphicshardwareintegration.cpp new file mode 100644 index 000000000..c37598374 --- /dev/null +++ b/src/compositor/hardware_integration/graphicshardwareintegration.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "graphicshardwareintegration.h" + +GraphicsHardwareIntegration::GraphicsHardwareIntegration(WaylandCompositor *compositor) + : m_compositor(compositor) +{ +} diff --git a/src/compositor/hardware_integration/graphicshardwareintegration.h b/src/compositor/hardware_integration/graphicshardwareintegration.h new file mode 100644 index 000000000..9f1f409d0 --- /dev/null +++ b/src/compositor/hardware_integration/graphicshardwareintegration.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef GRAPHICSHARDWAREINTEGRATION_H +#define GRAPHICSHARDWAREINTEGRATION_H + +#include <QtOpenGL/qgl.h> +#include <wayland-server.h> + +#include "waylandcompositor.h" +#include "wayland_wrapper/wldisplay.h" + +class GraphicsHardwareIntegration +{ +public: + GraphicsHardwareIntegration(WaylandCompositor *compositor); + + virtual void initializeHardware(Wayland::Display *waylandDisplay) = 0; + + /** Bind the Wayland buffer to the textureId. The correct context is the current context, + so there is no need to do makeCurrent in this function. + **/ + virtual GLuint createTextureFromBuffer(struct wl_buffer *buffer, QOpenGLContext *context) = 0; + virtual bool isYInverted(struct wl_buffer *) const { return true; } + + virtual bool setDirectRenderSurface(WaylandSurface *) {return false;} + virtual bool postBuffer(struct wl_buffer *) {return false;} + + static GraphicsHardwareIntegration *createGraphicsHardwareIntegration(WaylandCompositor *compositor); + +protected: + WaylandCompositor *m_compositor; +}; + +#endif // GRAPHICSHARDWAREINTEGRATION_H diff --git a/src/compositor/hardware_integration/hardware_integration.pri b/src/compositor/hardware_integration/hardware_integration.pri new file mode 100644 index 000000000..6e65ea9a3 --- /dev/null +++ b/src/compositor/hardware_integration/hardware_integration.pri @@ -0,0 +1,48 @@ +isEmpty(QT_WAYLAND_GL_CONFIG):QT_WAYLAND_GL_CONFIG = $$(QT_WAYLAND_GL_CONFIG) + +!mac:contains(QT_CONFIG, opengl):!isEqual(QT_WAYLAND_GL_CONFIG,nogl) { + HEADERS += \ + $$PWD/graphicshardwareintegration.h + + SOURCES += \ + $$PWD/graphicshardwareintegration.cpp + + DEFINES += QT_COMPOSITOR_WAYLAND_GL + + isEqual(QT_WAYLAND_GL_CONFIG, custom) { + QT_WAYLAND_GL_INTEGRATION = $$QT_WAYLAND_GL_CONFIG + } else { + contains(QT_CONFIG, opengles2) { + isEqual(QT_WAYLAND_GL_CONFIG, xcomposite_egl) { + QT_WAYLAND_GL_INTEGRATION = xcomposite_egl + CONFIG += xcomposite_egl + } else:isEqual(QT_WAYLAND_GL_CONFIG,dri2_xcb) { + QT_WAYLAND_GL_INTEGRATION = $$QT_WAYLAND_GL_CONFIG + CONFIG += dri2_xcb + } else { + QT_WAYLAND_GL_INTEGRATION = $$QT_WAYLAND_GL_CONFIG + CONFIG += wayland_egl + DEFINES += MESA_EGL_NO_X11_HEADERS + } + } else { + QT_WAYLAND_GL_INTEGRATION = xcomposite_glx + CONFIG += xcomposite_glx + } + } + system(echo "Qt-Compositor configured with openGL: $$QT_WAYLAND_GL_INTEGRATION") +} else { + system(echo "Qt-Compositor configured as raster only compositor") +} + +wayland_egl { + include (wayland_egl/wayland_egl.pri) +} +dri2_xcb { + include (dri2_xcb/dri2_xcb.pri) +} +xcomposite_egl { + include (xcomposite_egl/xcomposite_egl.pri) +} +xcomposite_glx { + include (xcomposite_glx/xcomposite_glx.pri) +} diff --git a/src/compositor/hardware_integration/wayland_egl/wayland_egl.pri b/src/compositor/hardware_integration/wayland_egl/wayland_egl.pri new file mode 100644 index 000000000..258923904 --- /dev/null +++ b/src/compositor/hardware_integration/wayland_egl/wayland_egl.pri @@ -0,0 +1,9 @@ +LIBS += -lEGL + +DEFINES += QT_COMPOSITOR_MESA_EGL + +SOURCES += \ + $$PWD/waylandeglintegration.cpp + +HEADERS += \ + $$PWD/waylandeglintegration.h diff --git a/src/compositor/hardware_integration/wayland_egl/waylandeglintegration.cpp b/src/compositor/hardware_integration/wayland_egl/waylandeglintegration.cpp new file mode 100644 index 000000000..a232c4876 --- /dev/null +++ b/src/compositor/hardware_integration/wayland_egl/waylandeglintegration.cpp @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "waylandeglintegration.h" +#include "wayland_wrapper/wlcompositor.h" +#include "wayland_wrapper/wlsurface.h" +#include "compositor_api/waylandsurface.h" +#include <QtGui/QPlatformNativeInterface> +#include <QtGui/QGuiApplication> +#include <QtGui/QOpenGLContext> +#include <QtGui/QPlatformScreen> +#include <QtGui/QWindow> +#include <QtCore/QWeakPointer> + +#include <QDebug> + +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#define GL_GLEXT_PROTOTYPES +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +GraphicsHardwareIntegration * GraphicsHardwareIntegration::createGraphicsHardwareIntegration(WaylandCompositor *compositor) +{ + return new WaylandEglIntegration(compositor); +} + +class WaylandEglIntegrationPrivate +{ +public: + WaylandEglIntegrationPrivate() + : egl_display(EGL_NO_DISPLAY), valid(false), flipperConnected(false) + { } + EGLDisplay egl_display; + bool valid; + bool flipperConnected; +#ifdef EGL_WL_request_client_buffer_format + QWeakPointer<WaylandSurface> directRenderSurface; +#endif +}; + +WaylandEglIntegration::WaylandEglIntegration(WaylandCompositor *compositor) + : GraphicsHardwareIntegration(compositor) + , d_ptr(new WaylandEglIntegrationPrivate) +{ +} + +void WaylandEglIntegration::initializeHardware(Wayland::Display *waylandDisplay) +{ + Q_D(WaylandEglIntegration); + + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + if (nativeInterface) { + d->egl_display = nativeInterface->nativeResourceForWindow("EglDisplay", m_compositor->window()); + if (d->egl_display) { + const char *extensionString = eglQueryString(d->egl_display, EGL_EXTENSIONS); + if (extensionString && strstr(extensionString, "EGL_WL_bind_wayland_display") + && eglBindWaylandDisplayWL(d->egl_display, waylandDisplay->handle())) + { + d->valid = true; + } + } + + if (!d->valid) + qWarning("Failed to initialize egl display\n"); + } +} + +GLuint WaylandEglIntegration::createTextureFromBuffer(wl_buffer *buffer, QOpenGLContext *context) +{ + Q_D(WaylandEglIntegration); + if (!d->valid) { + qWarning("createTextureFromBuffer() failed\n"); + return 0; + } + + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + EGLContext egl_context = nativeInterface->nativeResourceForContext("EglContext", context); + + EGLImageKHR image = eglCreateImageKHR(d->egl_display, egl_context, + EGL_WAYLAND_BUFFER_WL, + buffer, NULL); + + GLuint textureId; + glGenTextures(1,&textureId); + + glBindTexture(GL_TEXTURE_2D, textureId); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + eglDestroyImageKHR(d->egl_display, image); + + return textureId; +} + +bool WaylandEglIntegration::isYInverted(struct wl_buffer *buffer) const +{ +#ifdef EGL_WL_request_client_buffer_format + return eglGetBufferYInvertedWL(buffer); +#else + return GraphicsHardwareIntegration::isYInverted(buffer); +#endif +} + + +bool WaylandEglIntegration::setDirectRenderSurface(WaylandSurface *surface) +{ + Q_D(WaylandEglIntegration); + + QPlatformScreen *screen = QPlatformScreen::platformScreenForWindow(m_compositor->window()); + QPlatformScreenPageFlipper *flipper = screen ? screen->pageFlipper() : 0; + if (flipper && !d->flipperConnected) { + QObject::connect(flipper, SIGNAL(bufferReleased(void*)), m_compositor->handle(), SLOT(releaseBuffer(void*))); + d->flipperConnected = true; + } +#ifdef EGL_WL_request_client_buffer_format + int buffer_format = surface ? EGL_SCANOUT_FORMAT_WL : EGL_RENDER_FORMAT_WL; + struct wl_client *client = 0; + if (surface) { + client = surface->handle()->clientHandle(); + } else { + WaylandSurface *oldSurface = d->directRenderSurface.data(); + if (oldSurface) + client = oldSurface->handle()->clientHandle(); + } + if (client) + eglRequestClientBufferFormatWL(d->egl_display, client, buffer_format); + d->directRenderSurface = surface; +#endif + return flipper; +} + + +bool WaylandEglIntegration::postBuffer(struct wl_buffer *buffer) +{ + QPlatformScreen *screen = QPlatformScreen::platformScreenForWindow(m_compositor->window()); + QPlatformScreenPageFlipper *flipper = screen->pageFlipper(); + + return flipper ? flipper->displayBuffer(buffer) : false; +} diff --git a/src/compositor/hardware_integration/wayland_egl/waylandeglintegration.h b/src/compositor/hardware_integration/wayland_egl/waylandeglintegration.h new file mode 100644 index 000000000..7add3df7d --- /dev/null +++ b/src/compositor/hardware_integration/wayland_egl/waylandeglintegration.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WAYLANDEGLINTEGRATION_H +#define WAYLANDEGLINTEGRATION_H + +#include "hardware_integration/graphicshardwareintegration.h" +#include <QtCore/QScopedPointer> + +class WaylandEglIntegrationPrivate; + +class WaylandEglIntegration : public GraphicsHardwareIntegration +{ + Q_DECLARE_PRIVATE(WaylandEglIntegration) +public: + WaylandEglIntegration(WaylandCompositor *compositor); + + void initializeHardware(Wayland::Display *waylandDisplay); + + GLuint createTextureFromBuffer(wl_buffer *buffer, QOpenGLContext *context); + bool isYInverted(struct wl_buffer *) const; + + bool setDirectRenderSurface(WaylandSurface *); + bool postBuffer(struct wl_buffer *); + +private: + Q_DISABLE_COPY(WaylandEglIntegration) + QScopedPointer<WaylandEglIntegrationPrivate> d_ptr; +}; + +#endif // WAYLANDEGLINTEGRATION_H diff --git a/src/compositor/hardware_integration/xcomposite_egl/xcomposite_egl.pri b/src/compositor/hardware_integration/xcomposite_egl/xcomposite_egl.pri new file mode 100644 index 000000000..f4be9a259 --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_egl/xcomposite_egl.pri @@ -0,0 +1,9 @@ +include (../xcomposite_share/xcomposite_share.pri) + +LIBS += -lXcomposite -lX11 -lEGL + +HEADERS += \ + $$PWD/xcompositeeglintegration.h + +SOURCES += \ + $$PWD/xcompositeeglintegration.cpp diff --git a/src/compositor/hardware_integration/xcomposite_egl/xcompositeeglintegration.cpp b/src/compositor/hardware_integration/xcomposite_egl/xcompositeeglintegration.cpp new file mode 100644 index 000000000..dad0c0298 --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_egl/xcompositeeglintegration.cpp @@ -0,0 +1,110 @@ +#include "xcompositeeglintegration.h" + +#include "waylandobject.h" +#include "wayland_wrapper/wlcompositor.h" +#include "wayland-xcomposite-server-protocol.h" + +#include <QtWidgets/QApplication> +#include <QtGui/QPlatformNativeInterface> +#include <QtGui/QPlatformOpenGLContext> + +#include "xcompositebuffer.h" +#include "xcompositehandler.h" +#include <X11/extensions/Xcomposite.h> + +#include <QtCore/QDebug> + +QVector<EGLint> eglbuildSpec() +{ + QVector<EGLint> spec; + + spec.append(EGL_SURFACE_TYPE); spec.append(EGL_WINDOW_BIT | EGL_PIXMAP_BIT); + spec.append(EGL_RENDERABLE_TYPE); spec.append(EGL_OPENGL_ES2_BIT); + spec.append(EGL_BIND_TO_TEXTURE_RGBA); spec.append(EGL_TRUE); + spec.append(EGL_ALPHA_SIZE); spec.append(8); + spec.append(EGL_NONE); + return spec; +} + + +struct wl_xcomposite_interface XCompositeHandler::xcomposite_interface = { + XCompositeHandler::create_buffer +}; + +GraphicsHardwareIntegration *GraphicsHardwareIntegration::createGraphicsHardwareIntegration(WaylandCompositor *compositor) +{ + return new XCompositeEglIntegration(compositor); +} + +XCompositeEglIntegration::XCompositeEglIntegration(WaylandCompositor *compositor) + : GraphicsHardwareIntegration(compositor) + , mDisplay(0) +{ + QPlatformNativeInterface *nativeInterface = QApplication::platformNativeInterface(); + if (nativeInterface) { + mDisplay = static_cast<Display *>(nativeInterface->nativeResourceForWindow("Display",m_compositor->window())); + if (!mDisplay) + qFatal("could not retireve Display from platform integration"); + mEglDisplay = static_cast<EGLDisplay>(nativeInterface->nativeResourceForWindow("EGLDisplay",m_compositor->window())); + if (!mEglDisplay) + qFatal("could not retrieve EGLDisplay from plaform integration"); + } else { + qFatal("Platform integration doesn't have native interface"); + } + mScreen = XDefaultScreen(mDisplay); +} + +void XCompositeEglIntegration::initializeHardware(Wayland::Display *waylandDisplay) +{ + XCompositeHandler *handler = new XCompositeHandler(m_compositor->handle(),mDisplay,m_compositor->window()); + wl_display_add_global(waylandDisplay->handle(),&wl_xcomposite_interface,handler,XCompositeHandler::xcomposite_bind_func); +} + +GLuint XCompositeEglIntegration::createTextureFromBuffer(wl_buffer *buffer, QOpenGLContext *) +{ + XCompositeBuffer *compositorBuffer = Wayland::wayland_cast<XCompositeBuffer *>(buffer); + Pixmap pixmap = XCompositeNameWindowPixmap(mDisplay, compositorBuffer->window()); + + QVector<EGLint> eglConfigSpec = eglbuildSpec(); + + EGLint matching = 0; + EGLConfig config; + bool matched = eglChooseConfig(mEglDisplay,eglConfigSpec.constData(),&config,1,&matching); + if (!matched || !matching) { + qWarning("Could not retrieve a suitable EGL config"); + return 0; + } + + QVector<EGLint> attribList; + + attribList.append(EGL_TEXTURE_FORMAT); + attribList.append(EGL_TEXTURE_RGBA); + attribList.append(EGL_TEXTURE_TARGET); + attribList.append(EGL_TEXTURE_2D); + attribList.append(EGL_NONE); + + EGLSurface surface = eglCreatePixmapSurface(mEglDisplay,config,pixmap,attribList.constData()); + if (surface == EGL_NO_SURFACE) { + qDebug() << "Failed to create eglsurface" << pixmap << compositorBuffer->window(); + } + + compositorBuffer->setInvertedY(false); + + GLuint textureId; + glGenTextures(1,&textureId); + glBindTexture(GL_TEXTURE_2D, textureId); + + if (!eglBindTexImage(mEglDisplay,surface,EGL_BACK_BUFFER)) { + qDebug() << "Failed to bind"; + } + + // eglDestroySurface(mEglDisplay,surface); + + return textureId; +} + +bool XCompositeEglIntegration::isYInverted(wl_buffer *buffer) const +{ + XCompositeBuffer *compositorBuffer = Wayland::wayland_cast<XCompositeBuffer *>(buffer); + return compositorBuffer->isYInverted(); +} diff --git a/src/compositor/hardware_integration/xcomposite_egl/xcompositeeglintegration.h b/src/compositor/hardware_integration/xcomposite_egl/xcompositeeglintegration.h new file mode 100644 index 000000000..9e3b16f33 --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_egl/xcompositeeglintegration.h @@ -0,0 +1,26 @@ +#ifndef XCOMPOSITEEGLINTEGRATION_H +#define XCOMPOSITEEGLINTEGRATION_H + +#include "hardware_integration/graphicshardwareintegration.h" + +#include "xlibinclude.h" + +#include <EGL/egl.h> + +class XCompositeEglIntegration : public GraphicsHardwareIntegration +{ +public: + XCompositeEglIntegration(WaylandCompositor *compositor); + + void initializeHardware(Wayland::Display *waylandDisplay); + + GLuint createTextureFromBuffer(struct wl_buffer *buffer, QOpenGLContext *context); + bool isYInverted(wl_buffer *) const; + +private: + Display *mDisplay; + EGLDisplay mEglDisplay; + int mScreen; +}; + +#endif // XCOMPOSITEEGLINTEGRATION_H diff --git a/src/compositor/hardware_integration/xcomposite_glx/xcomposite_glx.pri b/src/compositor/hardware_integration/xcomposite_glx/xcomposite_glx.pri new file mode 100644 index 000000000..e8d4d0134 --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_glx/xcomposite_glx.pri @@ -0,0 +1,9 @@ +include (../xcomposite_share/xcomposite_share.pri) + +LIBS += -lXcomposite -lX11 + +HEADERS += \ + $$PWD/xcompositeglxintegration.h + +SOURCES += \ + $$PWD/xcompositeglxintegration.cpp diff --git a/src/compositor/hardware_integration/xcomposite_glx/xcompositeglxintegration.cpp b/src/compositor/hardware_integration/xcomposite_glx/xcompositeglxintegration.cpp new file mode 100644 index 000000000..9d7043952 --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_glx/xcompositeglxintegration.cpp @@ -0,0 +1,113 @@ +#include "xcompositeglxintegration.h" + +#include "waylandobject.h" +#include "wayland_wrapper/wlcompositor.h" +#include "wayland-xcomposite-server-protocol.h" + +#include <QtGui/QPlatformNativeInterface> +#include <QtGui/QOpenGLContext> + +#include "xcompositebuffer.h" +#include "xcompositehandler.h" +#include <X11/extensions/Xcomposite.h> + +#include <QtCore/QDebug> + +QVector<int> qglx_buildSpec() +{ + QVector<int> spec(48); + int i = 0; + + spec[i++] = GLX_LEVEL; + spec[i++] = 0; + spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = GLX_PIXMAP_BIT | GLX_WINDOW_BIT; + spec[i++] = GLX_BIND_TO_TEXTURE_TARGETS_EXT; spec[i++] = GLX_TEXTURE_2D_BIT_EXT; + spec[i++] = GLX_BIND_TO_TEXTURE_RGB_EXT; spec[i++] = TRUE; + + spec[i++] = 0; + return spec; +} + + +struct wl_xcomposite_interface XCompositeHandler::xcomposite_interface = { + XCompositeHandler::create_buffer +}; + +GraphicsHardwareIntegration *GraphicsHardwareIntegration::createGraphicsHardwareIntegration(WaylandCompositor *compositor) +{ + return new XCompositeGLXIntegration(compositor); +} + +XCompositeGLXIntegration::XCompositeGLXIntegration(WaylandCompositor *compositor) + : GraphicsHardwareIntegration(compositor) + , mDisplay(0) +{ + QPlatformNativeInterface *nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface(); + if (nativeInterface) { + mDisplay = static_cast<Display *>(nativeInterface->nativeResourceForWindow("Display",m_compositor->window())); + if (!mDisplay) + qFatal("could not retireve Display from platform integration"); + } else { + qFatal("Platform integration doesn't have native interface"); + } + mScreen = XDefaultScreen(mDisplay); +} + +void XCompositeGLXIntegration::initializeHardware(Wayland::Display *waylandDisplay) +{ + XCompositeHandler *handler = new XCompositeHandler(m_compositor->handle(),mDisplay,m_compositor->window()); + wl_display_add_global(waylandDisplay->handle(),&wl_xcomposite_interface,handler,XCompositeHandler::xcomposite_bind_func); + + QOpenGLContext *glContext = new QOpenGLContext(); + glContext->create(); + + m_glxBindTexImageEXT = reinterpret_cast<PFNGLXBINDTEXIMAGEEXTPROC>(glContext->getProcAddress("glXBindTexImageEXT")); + if (!m_glxBindTexImageEXT) { + qDebug() << "Did not find glxBindTexImageExt, everything will FAIL!"; + } + m_glxReleaseTexImageEXT = reinterpret_cast<PFNGLXRELEASETEXIMAGEEXTPROC>(glContext->getProcAddress("glXReleaseTexImageEXT")); + if (!m_glxReleaseTexImageEXT) { + qDebug() << "Did not find glxReleaseTexImageExt"; + } + + delete glContext; +} + +GLuint XCompositeGLXIntegration::createTextureFromBuffer(wl_buffer *buffer, QOpenGLContext *) +{ + XCompositeBuffer *compositorBuffer = Wayland::wayland_cast<XCompositeBuffer *>(buffer); + Pixmap pixmap = XCompositeNameWindowPixmap(mDisplay, compositorBuffer->window()); + + QVector<int> glxConfigSpec = qglx_buildSpec(); + int numberOfConfigs; + GLXFBConfig *configs = glXChooseFBConfig(mDisplay,mScreen,glxConfigSpec.constData(),&numberOfConfigs); + + QVector<int> attribList; + attribList.append(GLX_TEXTURE_FORMAT_EXT); + attribList.append(GLX_TEXTURE_FORMAT_RGB_EXT); + attribList.append(GLX_TEXTURE_TARGET_EXT); + attribList.append(GLX_TEXTURE_2D_EXT); + attribList.append(0); + GLXPixmap glxPixmap = glXCreatePixmap(mDisplay,*configs,pixmap,attribList.constData()); + + uint inverted = 0; + glXQueryDrawable(mDisplay, glxPixmap, GLX_Y_INVERTED_EXT,&inverted); + compositorBuffer->setInvertedY(!inverted); + + XFree(configs); + + GLuint textureId; + glGenTextures(1,&textureId); + glBindTexture(GL_TEXTURE_2D, textureId); + m_glxBindTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT, 0); + //Do we need to change the api so that we do bind and release in the painevent? + //The specification states that when deleting the texture the color buffer is deleted +// m_glxReleaseTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT); + return textureId; +} + +bool XCompositeGLXIntegration::isYInverted(wl_buffer *buffer) const +{ + XCompositeBuffer *compositorBuffer = Wayland::wayland_cast<XCompositeBuffer *>(buffer); + return compositorBuffer->isYInverted(); +} diff --git a/src/compositor/hardware_integration/xcomposite_glx/xcompositeglxintegration.h b/src/compositor/hardware_integration/xcomposite_glx/xcompositeglxintegration.h new file mode 100644 index 000000000..43f062fdf --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_glx/xcompositeglxintegration.h @@ -0,0 +1,30 @@ +#ifndef XCOMPOSITEGLXINTEGRATION_H +#define XCOMPOSITEGLXINTEGRATION_H + +#include "hardware_integration/graphicshardwareintegration.h" + +#include "xlibinclude.h" + +#define GLX_GLXEXT_PROTOTYPES +#include <GL/glx.h> +#include <GL/glxext.h> + +class XCompositeGLXIntegration : public GraphicsHardwareIntegration +{ +public: + XCompositeGLXIntegration(WaylandCompositor *compositor); + + void initializeHardware(Wayland::Display *waylandDisplay); + + GLuint createTextureFromBuffer(struct wl_buffer *buffer, QOpenGLContext *context); + bool isYInverted(wl_buffer *) const; + +private: + PFNGLXBINDTEXIMAGEEXTPROC m_glxBindTexImageEXT; + PFNGLXRELEASETEXIMAGEEXTPROC m_glxReleaseTexImageEXT; + + Display *mDisplay; + int mScreen; +}; + +#endif // XCOMPOSITEGLXINTEGRATION_H diff --git a/src/compositor/hardware_integration/xcomposite_share/protocol/wayland-xcomposite.xml b/src/compositor/hardware_integration/xcomposite_share/protocol/wayland-xcomposite.xml new file mode 100644 index 000000000..7d68d64a0 --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_share/protocol/wayland-xcomposite.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="xcomposite"> + <!-- XComposite support. This object is created by the server and published + using the display's global event. --> + <interface name="wl_xcomposite" version="1"> + + <!-- Create a wayland buffer for X Window. --> + <request name="create_buffer"> + <arg name="id" type="new_id" interface="wl_buffer"/> + <arg name="x_window" type="uint"/> + <arg name="width" type="int"/> + <arg name="height" type="int"/> + </request> + + <!-- Notification of the root window to use for the X Window created + on the client side. Also passes in the Display name to use --> + <event name="root"> + <arg name="display_name" type="string"/> + <arg name="root_window" type="uint"/> + </event> + + </interface> + +</protocol> diff --git a/src/compositor/hardware_integration/xcomposite_share/wayland-xcomposite-client-protocol.h b/src/compositor/hardware_integration/xcomposite_share/wayland-xcomposite-client-protocol.h new file mode 100644 index 000000000..f502bbaf3 --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_share/wayland-xcomposite-client-protocol.h @@ -0,0 +1,74 @@ +#ifndef XCOMPOSITE_CLIENT_PROTOCOL_H +#define XCOMPOSITE_CLIENT_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stddef.h> +#include "wayland-util.h" + +struct wl_client; +struct wl_resource; + +struct wl_xcomposite; + +extern const struct wl_interface wl_xcomposite_interface; + +struct wl_xcomposite_listener { + void (*root)(void *data, + struct wl_xcomposite *wl_xcomposite, + const char *display_name, + uint32_t root_window); +}; + +static inline int +wl_xcomposite_add_listener(struct wl_xcomposite *wl_xcomposite, + const struct wl_xcomposite_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) wl_xcomposite, + (void (**)(void)) listener, data); +} + +#define WL_XCOMPOSITE_CREATE_BUFFER 0 + +static inline void +wl_xcomposite_set_user_data(struct wl_xcomposite *wl_xcomposite, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) wl_xcomposite, user_data); +} + +static inline void * +wl_xcomposite_get_user_data(struct wl_xcomposite *wl_xcomposite) +{ + return wl_proxy_get_user_data((struct wl_proxy *) wl_xcomposite); +} + +static inline void +wl_xcomposite_destroy(struct wl_xcomposite *wl_xcomposite) +{ + wl_proxy_destroy((struct wl_proxy *) wl_xcomposite); +} + +static inline struct wl_buffer * +wl_xcomposite_create_buffer(struct wl_xcomposite *wl_xcomposite, uint32_t x_window, int32_t width, int32_t height) +{ + struct wl_proxy *id; + + id = wl_proxy_create((struct wl_proxy *) wl_xcomposite, + &wl_buffer_interface); + if (!id) + return NULL; + + wl_proxy_marshal((struct wl_proxy *) wl_xcomposite, + WL_XCOMPOSITE_CREATE_BUFFER, id, x_window, width, height); + + return (struct wl_buffer *) id; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/compositor/hardware_integration/xcomposite_share/wayland-xcomposite-protocol.c b/src/compositor/hardware_integration/xcomposite_share/wayland-xcomposite-protocol.c new file mode 100644 index 000000000..1662ec823 --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_share/wayland-xcomposite-protocol.c @@ -0,0 +1,29 @@ +#include <stdlib.h> +#include <stdint.h> +#include "wayland-util.h" + +extern const struct wl_interface wl_buffer_interface; + +static const struct wl_interface *types[] = { + NULL, + NULL, + &wl_buffer_interface, + NULL, + NULL, + NULL, +}; + +static const struct wl_message wl_xcomposite_requests[] = { + { "create_buffer", "nuii", types + 2 }, +}; + +static const struct wl_message wl_xcomposite_events[] = { + { "root", "su", types + 0 }, +}; + +WL_EXPORT const struct wl_interface wl_xcomposite_interface = { + "wl_xcomposite", 1, + ARRAY_LENGTH(wl_xcomposite_requests), wl_xcomposite_requests, + ARRAY_LENGTH(wl_xcomposite_events), wl_xcomposite_events, +}; + diff --git a/src/compositor/hardware_integration/xcomposite_share/wayland-xcomposite-server-protocol.h b/src/compositor/hardware_integration/xcomposite_share/wayland-xcomposite-server-protocol.h new file mode 100644 index 000000000..dfbb24dde --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_share/wayland-xcomposite-server-protocol.h @@ -0,0 +1,34 @@ +#ifndef XCOMPOSITE_SERVER_PROTOCOL_H +#define XCOMPOSITE_SERVER_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stddef.h> +#include "wayland-util.h" + +struct wl_client; +struct wl_resource; + +struct wl_xcomposite; + +extern const struct wl_interface wl_xcomposite_interface; + +struct wl_xcomposite_interface { + void (*create_buffer)(struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + uint32_t x_window, + int32_t width, + int32_t height); +}; + +#define WL_XCOMPOSITE_ROOT 0 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/compositor/hardware_integration/xcomposite_share/xcomposite_share.pri b/src/compositor/hardware_integration/xcomposite_share/xcomposite_share.pri new file mode 100644 index 000000000..e4001a5bb --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_share/xcomposite_share.pri @@ -0,0 +1,14 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/wayland-xcomposite-server-protocol.h \ + $$PWD/xcompositebuffer.h \ + $$PWD/xcompositehandler.h \ + $$PWD/xlibinclude.h + +SOURCES += \ + $$PWD/wayland-xcomposite-protocol.c \ + $$PWD/xcompositebuffer.cpp \ + $$PWD/xcompositehandler.cpp + +QT += gui-private diff --git a/src/compositor/hardware_integration/xcomposite_share/xcompositebuffer.cpp b/src/compositor/hardware_integration/xcomposite_share/xcompositebuffer.cpp new file mode 100644 index 000000000..b5b2d03d6 --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_share/xcompositebuffer.cpp @@ -0,0 +1,45 @@ +#include "xcompositebuffer.h" + +XCompositeBuffer::XCompositeBuffer(Wayland::Compositor *compositor, Window window, const QSize &size) + : mWindow(window) + , mInvertedY(false) +{ + base()->height = size.height(); + base()->width = size.width(); +} + +struct wl_buffer_interface XCompositeBuffer::buffer_interface = { + XCompositeBuffer::buffer_interface_damage, + XCompositeBuffer::buffer_interface_destroy +}; + +void XCompositeBuffer::buffer_interface_damage(struct wl_client *client, + struct wl_resource *buffer, + int x, + int y, + int width, + int height) +{ + Q_UNUSED(client); + Q_UNUSED(buffer); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(width); + Q_UNUSED(height); +} + +void XCompositeBuffer::buffer_interface_destroy(wl_client *client, wl_resource *buffer) +{ + Q_UNUSED(client); + Q_UNUSED(buffer); +} + +void XCompositeBuffer::delete_resource(struct wl_resource *resource) +{ + delete reinterpret_cast<XCompositeBuffer *>(resource); +} + +Window XCompositeBuffer::window() +{ + return mWindow; +} diff --git a/src/compositor/hardware_integration/xcomposite_share/xcompositebuffer.h b/src/compositor/hardware_integration/xcomposite_share/xcompositebuffer.h new file mode 100644 index 000000000..52154d406 --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_share/xcompositebuffer.h @@ -0,0 +1,43 @@ +#ifndef XCOMPOSITEBUFFER_H +#define XCOMPOSITEBUFFER_H + +#include "waylandobject.h" +#include "wayland_wrapper/wlcompositor.h" + +#include <QtCore/QSize> + +#include <QtCore/QTextStream> +#include <QtCore/QDataStream> +#include <QtCore/QMetaType> +#include <QtCore/QVariant> +#include <QtWidgets/QWidget> + +#include <X11/X.h> + +class XCompositeBuffer : public Wayland::Object<struct wl_buffer> +{ +public: + XCompositeBuffer(Wayland::Compositor *compositor, Window window, const QSize &size); + + Window window(); + + static struct wl_buffer_interface buffer_interface; + static void delete_resource(struct wl_resource *resource); + + bool isYInverted() const { return mInvertedY; } + void setInvertedY(bool inverted) { mInvertedY = inverted; } +private: + Window mWindow; + bool mInvertedY; + + static void buffer_interface_destroy(struct wl_client *client, + struct wl_resource *buffer); + static void buffer_interface_damage(struct wl_client *client, + struct wl_resource *buffer, + int x, + int y, + int width, + int height); +}; + +#endif // XCOMPOSITORBUFFER_H diff --git a/src/compositor/hardware_integration/xcomposite_share/xcompositehandler.cpp b/src/compositor/hardware_integration/xcomposite_share/xcompositehandler.cpp new file mode 100644 index 000000000..a434c9aa4 --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_share/xcompositehandler.cpp @@ -0,0 +1,55 @@ +#include "xcompositehandler.h" + +#include "wayland-xcomposite-server-protocol.h" + +#include "xcompositebuffer.h" +#include <X11/extensions/Xcomposite.h> + +XCompositeHandler::XCompositeHandler(Wayland::Compositor *compositor, Display *display, QWindow *window) + : mCompositor(compositor) + , mwindow(window) + , mDisplay(display) +{ + mCompositor->window()->create(); + + mFakeRootWidget = new QWindow(mCompositor->window()); + mFakeRootWidget->setGeometry(QRect(-1,-1,1,1)); + mFakeRootWidget->create(); + mFakeRootWidget->show(); + int composite_event_base, composite_error_base; + if (XCompositeQueryExtension(mDisplay, &composite_event_base, &composite_error_base)) { + + } else { + qFatal("XComposite required"); + } +} + +void XCompositeHandler::createBuffer(struct wl_client *client, uint32_t id, Window window, const QSize &size) +{ + XCompositeBuffer *buffer = new XCompositeBuffer(mCompositor, window, size); + Wayland::addClientResource(client,&buffer->base()->resource, + id,&wl_buffer_interface, + &XCompositeBuffer::buffer_interface, + XCompositeBuffer::delete_resource); +} + +void XCompositeHandler::xcomposite_bind_func(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ + Q_UNUSED(version); + XCompositeHandler *handler = static_cast<XCompositeHandler *>(data); + wl_resource *resource = wl_client_add_object(client,&wl_xcomposite_interface,&xcomposite_interface,id,handler); + const char *displayString = XDisplayString(handler->mDisplay); + wl_resource_post_event(resource, WL_XCOMPOSITE_ROOT, displayString, handler->mFakeRootWidget->winId()); +} + +void XCompositeHandler::create_buffer(struct wl_client *client, + struct wl_resource *xcomposite, + uint32_t id, + uint32_t x_window, + int32_t width, + int32_t height) +{ + Window window = (Window)x_window; + XCompositeHandler *that = reinterpret_cast<XCompositeHandler *>(xcomposite); + that->createBuffer(client, id, window, QSize(width,height)); +} diff --git a/src/compositor/hardware_integration/xcomposite_share/xcompositehandler.h b/src/compositor/hardware_integration/xcomposite_share/xcompositehandler.h new file mode 100644 index 000000000..28f5cd3db --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_share/xcompositehandler.h @@ -0,0 +1,32 @@ +#ifndef XCOMPOSITEHANDLER_H +#define XCOMPOSITEHANDLER_H + +#include "wayland_wrapper/wlcompositor.h" + +#include "xlibinclude.h" + +class XCompositeHandler : public Wayland::Object<struct wl_object> +{ +public: + XCompositeHandler(Wayland::Compositor *compositor, Display *display, QWindow *window); + void createBuffer(struct wl_client *client, uint32_t id, Window window, const QSize &size); + + static void xcomposite_bind_func(struct wl_client *client, void *data, uint32_t version, uint32_t id); + static struct wl_xcomposite_interface xcomposite_interface; + +private: + Wayland::Compositor *mCompositor; + QWindow *mwindow; + QWindow *mFakeRootWidget; + Display *mDisplay; + + static void create_buffer(struct wl_client *client, + struct wl_resource *xcomposite, + uint32_t id, + uint32_t x_window, + int32_t width, + int32_t height); + +}; + +#endif // XCOMPOSITEHANDLER_H diff --git a/src/compositor/hardware_integration/xcomposite_share/xlibinclude.h b/src/compositor/hardware_integration/xcomposite_share/xlibinclude.h new file mode 100644 index 000000000..dfb0c2965 --- /dev/null +++ b/src/compositor/hardware_integration/xcomposite_share/xlibinclude.h @@ -0,0 +1,38 @@ +#ifndef XLIBINCLUDE_H +#define XLIBINCLUDE_H + +#include <QtCore/QEvent> +#include <QtCore/QTextStream> +#include <QtCore/QDataStream> +#include <QtCore/QMetaType> +#include <QtCore/QVariant> +#include <QtGui/QCursor> +#include <QtGui/private/qguiapplication_p.h> + +#include <X11/Xlib.h> +#include "X11/extensions/Xcomposite.h" + +enum { + XFocusOut = FocusOut, + XFocusIn = FocusIn, + XKeyPress = KeyPress, + XKeyRelease = KeyRelease, + XNone = None, + XRevertToParent = RevertToParent, + XGrayScale = GrayScale, + XCursorShape = CursorShape +}; +#undef FocusOut +#undef FocusIn +#undef KeyPress +#undef KeyRelease +#undef None +#undef RevertToParent +#undef GrayScale +#undef CursorShape + +#ifdef FontChange +#undef FontChange +#endif + +#endif //XLIBINCLUDE_H diff --git a/src/compositor/util/util.pri b/src/compositor/util/util.pri new file mode 100644 index 000000000..fe5e9e606 --- /dev/null +++ b/src/compositor/util/util.pri @@ -0,0 +1,5 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/waylandobject.h + diff --git a/src/compositor/util/waylandobject.h b/src/compositor/util/waylandobject.h new file mode 100644 index 000000000..a64cfd0c7 --- /dev/null +++ b/src/compositor/util/waylandobject.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WL_OBJECT_H +#define WL_OBJECT_H + +#include <wayland-server.h> + +#include <string.h> + +namespace Wayland { + +template <typename T> +class Object +{ +public: + Object() { memset(&m_waylandObject, 0, sizeof(T)); } + + const T *base() const { return &m_waylandObject; } + T *base() { return &m_waylandObject; } + +private: + T m_waylandObject; +}; + +template <typename To, typename From> +To wayland_cast(From *from) +{ + Object<From> *object = reinterpret_cast<Object<From> *>(from); + return static_cast<To>(object); +} + +template <typename Implementation> +void addClientResource(struct wl_client *client, + struct wl_resource *resource, + int id, const struct wl_interface *interface, + Implementation implementation, + void (*destroy)(struct wl_resource *resource)) +{ + resource->object.id = id; + resource->object.interface = interface; + resource->object.implementation = (void (**)(void))implementation; + resource->destroy = destroy; + + wl_client_add_resource(client, resource); +} + +} + +#endif //WL_OBJECT_H diff --git a/src/compositor/wayland_wrapper/wayland_wrapper.pri b/src/compositor/wayland_wrapper/wayland_wrapper.pri new file mode 100644 index 000000000..478b39982 --- /dev/null +++ b/src/compositor/wayland_wrapper/wayland_wrapper.pri @@ -0,0 +1,26 @@ +HEADERS += \ + $$PWD/wlcompositor.h \ + $$PWD/wldisplay.h \ + $$PWD/wloutput.h \ + $$PWD/wlshmbuffer.h \ + $$PWD/wlsurface.h \ + $$PWD/wlshell.h \ + $$PWD/wlinputdevice.h \ + $$PWD/wldatadevicemanager.h \ + $$PWD/wldatadevice.h \ + $$PWD/wldataoffer.h \ + $$PWD/wldatasource.h + +SOURCES += \ + $$PWD/wlcompositor.cpp \ + $$PWD/wldisplay.cpp \ + $$PWD/wloutput.cpp \ + $$PWD/wlshmbuffer.cpp \ + $$PWD/wlsurface.cpp \ + $$PWD/wlshell.cpp \ + $$PWD/wlinputdevice.cpp \ + $$PWD/wldatadevicemanager.cpp \ + $$PWD/wldatadevice.cpp \ + $$PWD/wldataoffer.cpp \ + $$PWD/wldatasource.cpp + diff --git a/src/compositor/wayland_wrapper/wlcompositor.cpp b/src/compositor/wayland_wrapper/wlcompositor.cpp new file mode 100644 index 000000000..168094734 --- /dev/null +++ b/src/compositor/wayland_wrapper/wlcompositor.cpp @@ -0,0 +1,428 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "wlcompositor.h" + +#include "waylandobject.h" +#include "wldisplay.h" +#include "wlshmbuffer.h" +#include "wlsurface.h" +#include "wlinputdevice.h" +#include "waylandcompositor.h" +#include "wldatadevicemanager.h" +#include "wldatadevice.h" + +#include <QWindow> +#include <QSocketNotifier> +#include <QDebug> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include <sys/mman.h> +#include <sys/select.h> +#include <sys/time.h> + +#include <wayland-server.h> + +#include "hardware_integration/graphicshardwareintegration.h" +#include "waylandwindowmanagerintegration.h" + +namespace Wayland { + +static Compositor *compositor; + +static void shmBufferDestroyed(ShmBuffer *buf) +{ +// if (currentCursor == buf) { +// compositor->qtCompositor()->changeCursor(QImage(), 0, 0); +// currentCursor = 0; +// } +} + +void destroy_surface(struct wl_resource *resource) +{ + Surface *surface = wayland_cast<Surface *>((wl_surface *)resource); + delete surface; +} + +void compositor_create_surface(struct wl_client *client, + struct wl_resource *resource, uint32_t id) +{ + static_cast<Compositor *>(resource->data)->createSurface(client,id); +} + +const static struct wl_compositor_interface compositor_interface = { + compositor_create_surface +}; + +void Compositor::bind_func(struct wl_client *client, void *data, + uint32_t version, uint32_t id) +{ + wl_client_add_object(client,&wl_compositor_interface, &compositor_interface, id,data); +} + + +Compositor *Compositor::instance() +{ + return compositor; +} + +Compositor::Compositor(WaylandCompositor *qt_compositor) + : m_display(new Display) + , m_shell(this) + , m_shm(m_display) + , m_current_frame(0) + , m_last_queued_buf(-1) + , m_qt_compositor(qt_compositor) + , m_orientation(Qt::UnknownOrientation) + , m_pointerFocusSurface(0) + , m_keyFocusSurface(0) + , m_directRenderSurface(0) +#if defined (QT_COMPOSITOR_WAYLAND_GL) + , m_graphics_hw_integration(0) +#endif +{ + compositor = this; + qDebug() << "Compositor instance is" << this; + m_shm.addDestroyCallback(shmBufferDestroyed); + +#if defined (QT_COMPOSITOR_WAYLAND_GL) + QWindow *window = qt_compositor->window(); + if (window && window->surfaceType() != QWindow::RasterSurface) + m_graphics_hw_integration = GraphicsHardwareIntegration::createGraphicsHardwareIntegration(qt_compositor); +#endif + m_windowManagerWaylandProtocol = new WindowManagerServerIntegration(this); + connect(m_windowManagerWaylandProtocol, + SIGNAL(windowPropertyChanged(wl_client*,wl_surface*,QString,QVariant)), + SLOT(windowPropertyChanged(wl_client*,wl_surface*,QString,QVariant))); + + wl_display_add_global(m_display->handle(),&wl_compositor_interface,this,Compositor::bind_func); + + m_input = new InputDevice(this); + + m_data_device_manager = new DataDeviceManager(this); + wl_display_add_global(m_display->handle(),&wl_output_interface,m_output.base(),Output::output_bind_func); + + wl_display_add_global(m_display->handle(), &wl_shell_interface, m_shell.base(), Shell::bind_func); + + + if (wl_display_add_socket(m_display->handle(), qt_compositor->socketName())) { + fprintf(stderr, "Fatal: Failed to open server socket\n"); + exit(EXIT_FAILURE); + } + + m_loop = wl_display_get_event_loop(m_display->handle()); + + int fd = wl_event_loop_get_fd(m_loop); + + QSocketNotifier *sockNot = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(sockNot, SIGNAL(activated(int)), this, SLOT(processWaylandEvents())); + + //initialize distancefieldglyphcache here +} + +Compositor::~Compositor() +{ + delete m_input; + delete m_data_device_manager; + + delete m_display; +} + +void Compositor::frameFinished(Surface *surface) +{ + if (surface && m_dirty_surfaces.contains(surface)) { + surface->sendFrameCallback(); + m_dirty_surfaces.remove(surface); + } else if (!surface) { + foreach (Surface *surface, m_dirty_surfaces) + surface->sendFrameCallback(); + m_dirty_surfaces.clear(); + } +} + +void Compositor::createSurface(struct wl_client *client, int id) +{ + Surface *surface = new Surface(client, this); + printf("Compositor::createSurface: %p %d\n", client, id); + + addClientResource(client, &surface->base()->resource, id, &wl_surface_interface, + &Surface::surface_interface, destroy_surface); + + QList<struct wl_client *> prevClientList = clients(); + m_surfaces << surface; + if (!prevClientList.contains(client)) { + m_windowManagerWaylandProtocol->setScreenOrientation(client, m_output.base(), m_orientation); + emit clientAdded(client); + } + + m_qt_compositor->surfaceCreated(surface->handle()); +} + +struct wl_client *Compositor::getClientFromWinId(uint winId) const +{ + Surface *surface = getSurfaceFromWinId(winId); + if (surface) + return surface->base()->resource.client; + + return 0; +} + +Surface *Compositor::getSurfaceFromWinId(uint winId) const +{ + foreach (Surface *surface, m_surfaces) { + if (surface->id() == winId) + return surface; + } + + return 0; +} + +QImage Compositor::image(uint winId) const +{ + printf("Compositor::image(%x)\n", winId); + foreach (Surface *surface, m_surfaces) { + if (surface->id() == winId) { + return surface->image(); + } + } + + return QImage(); +} + +uint Compositor::currentTimeMsecs() +{ + //### we throw away the time information + struct timeval tv; + int ret = gettimeofday(&tv, 0); + if (ret == 0) + return tv.tv_sec*1000 + tv.tv_usec/1000; + return 0; +} + +void Compositor::releaseBuffer(void *bufferHandle) +{ + struct wl_buffer *buffer = static_cast<struct wl_buffer*>(bufferHandle); + if (buffer) { + //qDebug() << "WL_BUFFER_RELEASE" << buffer<< buffer->resource.client; + wl_resource_post_event(&buffer->resource, WL_BUFFER_RELEASE); + } + +} + +void Compositor::processWaylandEvents() +{ + int ret = wl_event_loop_dispatch(m_loop, 0); + if (ret) + fprintf(stderr, "wl_event_loop_dispatch error: %d\n", ret); +} + +void Compositor::windowPropertyChanged(wl_client *client, wl_surface *changedSurface, const QString &name, const QVariant &value) +{ + for(int i = 0; i < m_surfaces.length(); ++i) { + Surface *surface = m_surfaces[i]; + if (surface->clientHandle() == client && surface->base() == changedSurface) { + surface->setWindowProperty(name, value, false); + } + } +} + +void Compositor::surfaceDestroyed(Surface *surface) +{ + m_surfaces.removeOne(surface); + if (m_keyFocusSurface == surface) + setKeyFocus(0); + if (m_pointerFocusSurface == surface) + setPointerFocus(0); + if (m_directRenderSurface == surface) + setDirectRenderSurface(0); +} + +void Compositor::markSurfaceAsDirty(Wayland::Surface *surface) +{ + m_dirty_surfaces.insert(surface); +} + +void Compositor::destroyClientForSurface(Surface *surface) +{ + wl_client *client = surface->base()->resource.client; + + if (client) { + m_windowManagerWaylandProtocol->removeClient(client); + wl_client_destroy(client); + } +} + +void Compositor::setInputFocus(Surface *surface) +{ + setKeyFocus(surface); + setPointerFocus(surface); +} + +void Compositor::setKeyFocus(Surface *surface) +{ + m_input->sendSelectionFocus(surface); + m_keyFocusSurface = surface; + wl_input_device_set_keyboard_focus(m_input->base(), surface ? surface->base() : 0, currentTimeMsecs()); +} + +Surface *Compositor::keyFocus() const +{ + return m_keyFocusSurface; +} + +void Compositor::setPointerFocus(Surface *surface, const QPoint &pos) +{ + m_pointerFocusSurface = surface; + wl_input_device_set_pointer_focus(m_input->base(), surface ? surface->base() : 0, currentTimeMsecs(), pos.x(), pos.y(), pos.x(), pos.y()); +} + +Surface *Compositor::pointerFocus() const +{ + return m_pointerFocusSurface; +} + +QWindow *Compositor::window() const +{ + return m_qt_compositor->window(); +} + +GraphicsHardwareIntegration * Compositor::graphicsHWIntegration() const +{ +#ifdef QT_COMPOSITOR_WAYLAND_GL + return m_graphics_hw_integration; +#else + return 0; +#endif +} + +void Compositor::initializeHardwareIntegration() +{ +#ifdef QT_COMPOSITOR_WAYLAND_GL + if (m_graphics_hw_integration) + m_graphics_hw_integration->initializeHardware(m_display); +#endif +} + +void Compositor::initializeWindowManagerProtocol() +{ + m_windowManagerWaylandProtocol->initialize(m_display); +} + +bool Compositor::setDirectRenderSurface(Surface *surface) +{ +#ifdef QT_COMPOSITOR_WAYLAND_GL + if (m_graphics_hw_integration && m_graphics_hw_integration->setDirectRenderSurface(surface ? surface->handle() : 0)) { + m_directRenderSurface = surface; + return true; + } +#else + Q_UNUSED(surface); +#endif + return false; +} + +QList<struct wl_client *> Compositor::clients() const +{ + QList<struct wl_client *> list; + foreach (Surface *surface, m_surfaces) { + struct wl_client *client = surface->base()->resource.client; + if (!list.contains(client)) + list.append(client); + } + return list; +} + +void Compositor::setScreenOrientation(Qt::ScreenOrientation orientation) +{ + m_orientation = orientation; + + QList<struct wl_client*> clientList = clients(); + for (int i = 0; i < clientList.length(); ++i) { + struct wl_client *client = clientList.at(i); + m_windowManagerWaylandProtocol->setScreenOrientation(client, m_output.base(), orientation); + } +} + +void Compositor::setOutputGeometry(const QRect &geometry) +{ + m_output.setGeometry(geometry); +} + +InputDevice* Compositor::defaultInputDevice() +{ + return m_input; +} + +QList<Wayland::Surface *> Compositor::surfacesForClient(wl_client *client) +{ + QList<Wayland::Surface *> ret; + + for (int i=0; i < m_surfaces.count(); ++i) { + if (m_surfaces.at(i)->clientHandle() == client) { + ret.append(m_surfaces.at(i)); + } + } + return ret; +} + +bool Compositor::isDragging() const +{ + return false; +} + +void Compositor::sendDragMoveEvent(const QPoint &global, const QPoint &local, + Surface *surface) +{ +// Drag::instance()->dragMove(global, local, surface); +} + +void Compositor::sendDragEndEvent() +{ +// Drag::instance()->dragEnd(); +} + +} // namespace Wayland diff --git a/src/compositor/wayland_wrapper/wlcompositor.h b/src/compositor/wayland_wrapper/wlcompositor.h new file mode 100644 index 000000000..9aaba776d --- /dev/null +++ b/src/compositor/wayland_wrapper/wlcompositor.h @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WL_COMPOSITOR_H +#define WL_COMPOSITOR_H + +#include <QtCore/QSet> + +#include "wloutput.h" +#include "wldisplay.h" +#include "wlshmbuffer.h" +#include "wlshell.h" + +#include <wayland-server.h> + +class WaylandCompositor; +class GraphicsHardwareIntegration; +class WindowManagerServerIntegration; + +namespace Wayland { + +class Surface; +class InputDevice; +class DataDeviceManager; + +class Compositor : public QObject +{ + Q_OBJECT + +public: + Compositor(WaylandCompositor *qt_compositor); + ~Compositor(); + + void frameFinished(Surface *surface = 0); + void setInputFocus(Surface *surface); + void setKeyFocus(Surface *surface); + Surface *keyFocus() const; + void setPointerFocus(Surface *surface, const QPoint &point = QPoint()); + Surface *pointerFocus() const; + + Surface *getSurfaceFromWinId(uint winId) const; + struct wl_client *getClientFromWinId(uint winId) const; + QImage image(uint winId) const; + + InputDevice *inputDevice() { return m_input; } + InputDevice *defaultInputDevice(); + + void createSurface(struct wl_client *client, int id); + void surfaceDestroyed(Surface *surface); + void markSurfaceAsDirty(Surface *surface); + + void destroyClientForSurface(Surface *surface); + + static uint currentTimeMsecs(); + + QWindow *window() const; + + GraphicsHardwareIntegration *graphicsHWIntegration() const; + void initializeHardwareIntegration(); + void initializeWindowManagerProtocol(); + bool setDirectRenderSurface(Surface *surface); + Surface *directRenderSurface() const {return m_directRenderSurface;} + + QList<Surface*> surfacesForClient(wl_client* client); + + WaylandCompositor *qtCompositor() const { return m_qt_compositor; } + + struct wl_display *wl_display() { return m_display->handle(); } + + static Compositor *instance(); + + QList<struct wl_client *> clients() const; + + void setScreenOrientation(Qt::ScreenOrientation orientation); + void setOutputGeometry(const QRect &geometry); + + bool isDragging() const; + void sendDragMoveEvent(const QPoint &global, const QPoint &local, Surface *surface); + void sendDragEndEvent(); + +public slots: + void releaseBuffer(void*); + +signals: + void clientAdded(wl_client *client); + +private slots: + void processWaylandEvents(); + void windowPropertyChanged(wl_client *client, wl_surface *surface, const QString &name, const QVariant &value); + +private: + Display *m_display; + + /* Input */ + InputDevice *m_input; + + /* Output */ + //make this a list of the available screens + Output m_output; + + Shell m_shell; + + /* shm/*/ + ShmHandler m_shm; + + DataDeviceManager *m_data_device_manager; + + QList<Surface *> m_surfaces; + QSet<Surface *> m_dirty_surfaces; + + /* Render state */ + uint32_t m_current_frame; + int m_last_queued_buf; + + wl_event_loop *m_loop; + + WaylandCompositor *m_qt_compositor; + Qt::ScreenOrientation m_orientation; + + Surface *m_pointerFocusSurface; + Surface *m_keyFocusSurface; + Surface *m_directRenderSurface; + +#ifdef QT_COMPOSITOR_WAYLAND_GL + GraphicsHardwareIntegration *m_graphics_hw_integration; +#endif + WindowManagerServerIntegration *m_windowManagerWaylandProtocol; + + static void bind_func(struct wl_client *client, void *data, + uint32_t version, uint32_t id); +}; + +} + +#endif //WL_COMPOSITOR_H diff --git a/src/compositor/wayland_wrapper/wldatadevice.cpp b/src/compositor/wayland_wrapper/wldatadevice.cpp new file mode 100644 index 000000000..e7bdfb434 --- /dev/null +++ b/src/compositor/wayland_wrapper/wldatadevice.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "wldatadevice.h" + +#include "wldatasource.h" +#include "wldataoffer.h" +#include "wldatadevicemanager.h" + +#include <stdlib.h> + +#include <QDebug> + +namespace Wayland { + +void DataDevice::start_drag(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *source, + struct wl_resource *surface, + uint32_t time) +{ + DataDevice *data_device = static_cast<DataDevice *>(resource->data); + DataSource *data_source = static_cast<DataSource *>(source->data); + + +} + +void DataDevice::attach(struct wl_client *client, + struct wl_resource *resource, + uint32_t time, + struct wl_resource *buffer, + int32_t x, + int32_t y) +{ + +} + +void DataDevice::set_selection(struct wl_client *client, + struct wl_resource *data_device_resource, + struct wl_resource *source, + uint32_t time) +{ + DataDevice *data_device = static_cast<DataDevice *>(data_device_resource->data); + DataSource *data_source = static_cast<DataSource *>(source->data); + + data_device->m_data_device_manager->setCurrentSelectionSource(data_source); + +} + +const struct wl_data_device_interface DataDevice::data_device_interface = { + DataDevice::start_drag, + DataDevice::attach, + DataDevice::set_selection +}; + +DataDevice::DataDevice(DataDeviceManager *data_device_manager, struct wl_client *client, uint32_t id) + : m_data_device_manager(data_device_manager) + , m_sent_selection_time(0) +{ + + static int i = 0; + qDebug() << "data device" << ++i; + m_data_device_resource = + wl_client_add_object(client,&wl_data_device_interface,&data_device_interface,id, this); +} + +void DataDevice::sendSelectionFocus() +{ + //do for all clipboards + DataSource *source = m_data_device_manager->currentSelectionSource(); + if (!source){ + return; + } + if (source->time() > m_sent_selection_time) { //this makes sure we don't resend + if (source->client() != m_data_device_resource->client) { //don't send selection to the client that owns the selection + DataOffer *data_offer = m_data_device_manager->currentSelectionSource()->dataOffer(); + wl_resource *client_resource = + data_offer->addDataDeviceResource(m_data_device_resource); + qDebug() << "sending data_offer for source" << source; + wl_resource_post_event(m_data_device_resource,WL_DATA_DEVICE_SELECTION,client_resource); + m_sent_selection_time = source->time(); + } + } +} + +struct wl_resource *DataDevice::dataDeviceResource() const +{ + return m_data_device_resource; +} + +} diff --git a/src/compositor/wayland_wrapper/wldatadevice.h b/src/compositor/wayland_wrapper/wldatadevice.h new file mode 100644 index 000000000..4be777dbf --- /dev/null +++ b/src/compositor/wayland_wrapper/wldatadevice.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WLDATADEVICE_H +#define WLDATADEVICE_H + +#include "wldatadevicemanager.h" + +namespace Wayland { + +class DataSource; +class DataDeviceManager; + +class DataDevice +{ +public: + DataDevice(DataDeviceManager *data_device_manager, struct wl_client *client, uint32_t id); + + void createAndSetSelectionSource(struct wl_client *client, uint32_t id, const char *name, uint32_t time); + void sendSelectionFocus(); + + struct wl_resource *dataDeviceResource() const; + + struct wl_display *display() const { return m_data_device_manager->display(); } +private: + DataDeviceManager *m_data_device_manager; + uint32_t m_sent_selection_time; + struct wl_resource *m_data_device_resource; + + static const struct wl_data_device_interface data_device_interface; + static void start_drag(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *source, + struct wl_resource *surface, + uint32_t time); + static void attach(struct wl_client *client, + struct wl_resource *resource, + uint32_t time, + struct wl_resource *buffer, + int32_t x, + int32_t y); + static void set_selection(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *source, + uint32_t time); +}; + +} + +#endif // WLDATADEVICE_H diff --git a/src/compositor/wayland_wrapper/wldatadevicemanager.cpp b/src/compositor/wayland_wrapper/wldatadevicemanager.cpp new file mode 100644 index 000000000..834ef9545 --- /dev/null +++ b/src/compositor/wayland_wrapper/wldatadevicemanager.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "wldatadevicemanager.h" + +#include "wldatadevice.h" +#include "wldatasource.h" +#include "wlinputdevice.h" +#include "wlcompositor.h" +#include "wldataoffer.h" + +#include <QtCore/QDebug> + +namespace Wayland { + +DataDeviceManager::DataDeviceManager(Compositor *compositor) + : m_compositor(compositor) + , m_current_selection_source(0) +{ + wl_display_add_global(compositor->wl_display(), &wl_data_device_manager_interface, base(), DataDeviceManager::bind_func_drag); +} +void DataDeviceManager::setCurrentSelectionSource(DataSource *source) +{ + if (m_current_selection_source) { + if (m_current_selection_source->time() >= source->time()) { + qDebug() << "Trying to set older selection"; + return; + } + } + m_current_selection_source = source; +} + +DataSource *DataDeviceManager::currentSelectionSource() +{ + return m_current_selection_source; +} + +struct wl_display *DataDeviceManager::display() const +{ + return m_compositor->wl_display(); +} + +void DataDeviceManager::bind_func_drag(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ + wl_client_add_object(client,&wl_data_device_manager_interface,&drag_interface,id,data); +} + +void DataDeviceManager::bind_func_data(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ +} + +void DataDeviceManager::get_data_device(struct wl_client *client, + struct wl_resource *data_device_manager_resource, + uint32_t id, + struct wl_resource *input_device_resource) +{ + DataDeviceManager *data_device_manager = static_cast<DataDeviceManager *>(data_device_manager_resource->data); + InputDevice *input_device = reinterpret_cast<InputDevice *>(input_device_resource->data); + input_device->clientRequestedDataDevice(data_device_manager,client,id); +} + +void DataDeviceManager::create_data_source(struct wl_client *client, + struct wl_resource *data_device_manager_resource, + uint32_t id) +{ + Q_UNUSED(data_device_manager_resource); + new DataSource(client,id, Compositor::currentTimeMsecs()); +} + +struct wl_data_device_manager_interface DataDeviceManager::drag_interface = { + DataDeviceManager::create_data_source, + DataDeviceManager::get_data_device +}; + +} //namespace diff --git a/src/compositor/wayland_wrapper/wldatadevicemanager.h b/src/compositor/wayland_wrapper/wldatadevicemanager.h new file mode 100644 index 000000000..87398c4cf --- /dev/null +++ b/src/compositor/wayland_wrapper/wldatadevicemanager.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WLDATADEVICEMANAGER_H +#define WLDATADEVICEMANAGER_H + +#include "waylandobject.h" + +#include "wlcompositor.h" + +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtGui/QClipboard> + + +namespace Wayland { + +class Compositor; + +class DataDevice; +class DataSource; + +class DataDeviceManager : public Object<struct wl_object> +{ +public: + DataDeviceManager(Compositor *compositor); + + void setCurrentSelectionSource(DataSource *source); + DataSource *currentSelectionSource(); + + struct wl_display *display() const; +private: + Compositor *m_compositor; + QList<DataDevice *> m_data_device_list; + + DataSource *m_current_selection_source; + + static void bind_func_drag(struct wl_client *client, void *data, + uint32_t version, uint32_t id); + static void bind_func_data(struct wl_client *client, void *data, + uint32_t version, uint32_t id); + static void get_data_device(struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + struct wl_resource *input_device); + static void create_data_source(struct wl_client *client, + struct wl_resource *resource, + uint32_t id); + static struct wl_data_device_manager_interface drag_interface; +}; + +} +#endif // WLDATADEVICEMANAGER_H diff --git a/src/compositor/wayland_wrapper/wldataoffer.cpp b/src/compositor/wayland_wrapper/wldataoffer.cpp new file mode 100644 index 000000000..882337352 --- /dev/null +++ b/src/compositor/wayland_wrapper/wldataoffer.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "wldataoffer.h" + +#include "wldatadevice.h" + +#include <wayland-server.h> + +#include <sys/time.h> + +#include <QtCore/QDebug> + +namespace Wayland +{ + +DataOffer::DataOffer(DataSource *data_source) + : m_data_source(data_source) +{ + +} + +DataOffer::~DataOffer() +{ +} + +struct wl_resource *DataOffer::addDataDeviceResource(struct wl_resource *data_device_resource) +{ + for (int i = 0; i < m_clients_data_resource.size(); i++) { + if (m_clients_data_resource.at(i)->client == data_device_resource->client) { + qDebug() << "This should not happen, the client tries to add twice to a data offer"; + return 0; + } + } + struct wl_resource *new_object = + wl_client_new_object(data_device_resource->client,&wl_data_offer_interface,&data_interface,this); + wl_resource_post_event(data_device_resource,WL_DATA_DEVICE_DATA_OFFER,new_object); + + m_clients_data_resource.append(new_object); + QList<QByteArray> offer_list = m_data_source->offerList(); + for (int i = 0; i < offer_list.size(); i++) { + wl_resource_post_event(new_object, WL_DATA_OFFER_OFFER, offer_list.at(i).constData()); + } + return new_object; +} + +void DataOffer::removeClient(struct wl_client *client) +{ + for (int i = 0; i < m_clients_data_resource.size(); i++) { + struct wl_resource *resource = m_clients_data_resource.at(i); + if (resource->client == client) { + wl_resource_destroy(resource,Compositor::currentTimeMsecs()); + m_clients_data_resource.removeAt(i); + break; + } + } +} + +const struct wl_data_offer_interface DataOffer::data_interface = { + DataOffer::accept, + DataOffer::receive, + DataOffer::destroy +}; + +void DataOffer::accept(wl_client *client, wl_resource *resource, uint32_t time, const char *type) +{ + +} + +void DataOffer::receive(wl_client *client, wl_resource *resource, const char *mime_type, int32_t fd) +{ + Q_UNUSED(client); + + DataOffer *offer = static_cast<DataOffer *>(resource->data); + offer->m_data_source->postSendEvent(mime_type,fd); + close(fd); +} + +void DataOffer::destroy(wl_client *client, wl_resource *resource) +{ + qDebug() << "dataOFFER DESTROY!"; + DataOffer *data_offer = static_cast<DataOffer *>(resource->data); + data_offer->removeClient(client); + + if (data_offer->m_clients_data_resource.size() == 0) { + delete data_offer; + } +} + + +} diff --git a/src/compositor/wayland_wrapper/wldataoffer.h b/src/compositor/wayland_wrapper/wldataoffer.h new file mode 100644 index 000000000..5db80f62b --- /dev/null +++ b/src/compositor/wayland_wrapper/wldataoffer.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WLDATAOFFER_H +#define WLDATAOFFER_H + +#include "wldatasource.h" + +namespace Wayland +{ + +class DataOffer +{ +public: + DataOffer(DataSource *data_source); + ~DataOffer(); + + struct wl_resource *addDataDeviceResource(struct wl_resource *client_resource); + void removeClient(struct wl_client *client); +private: + DataSource *m_data_source; + + QList<struct wl_resource *> m_clients_data_resource; + + static void accept(struct wl_client *client, + struct wl_resource *resource, + uint32_t time, + const char *type); + static void receive(struct wl_client *client, + struct wl_resource *resource, + const char *mime_type, + int32_t fd); + static void destroy(struct wl_client *client, + struct wl_resource *resource); + + static const struct wl_data_offer_interface data_interface; + +}; + +} + +#endif // WLDATAOFFER_H diff --git a/src/compositor/wayland_wrapper/wldatasource.cpp b/src/compositor/wayland_wrapper/wldatasource.cpp new file mode 100644 index 000000000..a3c75ec73 --- /dev/null +++ b/src/compositor/wayland_wrapper/wldatasource.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "wldatasource.h" + +#include "wldataoffer.h" + +#include <wayland-server.h> + +#include "wlcompositor.h" + +#include <QtCore/QDebug> + +namespace Wayland { + + +DataSource::DataSource(struct wl_client *client, uint32_t id, uint32_t time) + : m_time(time) +{ + m_data_source_resource = wl_client_add_object(client, &wl_data_source_interface, &DataSource::data_source_interface,id,this); + m_data_source_resource->destroy = resource_destroy; + m_data_offer = new DataOffer(this); +} + +DataSource::~DataSource() +{ + qDebug() << "destorying source"; + wl_resource_destroy(m_data_source_resource,Compositor::currentTimeMsecs()); +} + +void DataSource::resource_destroy(wl_resource *resource) +{ + DataSource *source = static_cast<DataSource *>(resource->data); + if (source && source->m_data_source_resource == resource) + source->m_data_source_resource = 0; + free(resource); +} + +uint32_t DataSource::time() const +{ + return m_time; +} + +QList<QByteArray> DataSource::offerList() const +{ + return m_offers; +} + +struct wl_data_source_interface DataSource::data_source_interface = { + DataSource::offer, + DataSource::destroy +}; + +void DataSource::offer(struct wl_client *client, + struct wl_resource *resource, + const char *type) +{ + Q_UNUSED(client); + qDebug() << "received offer" << type; + static_cast<DataSource *>(resource->data)->m_offers.append(type); +} + +void DataSource::destroy(struct wl_client *client, + struct wl_resource *resource) +{ + DataSource *self = static_cast<DataSource *>(resource->data); + delete self; +} + +DataOffer * DataSource::dataOffer() const +{ + return m_data_offer; +} + +void DataSource::postSendEvent(const QByteArray mimeType, int fd) +{ + if (m_data_source_resource) { + wl_resource_post_event(m_data_source_resource,WL_DATA_SOURCE_SEND,mimeType.constData(),fd); + } +} + +struct wl_client *DataSource::client() const +{ + if (m_data_source_resource) + return m_data_source_resource->client; + return 0; +} + +} diff --git a/src/compositor/wayland_wrapper/wldatasource.h b/src/compositor/wayland_wrapper/wldatasource.h new file mode 100644 index 000000000..59385ecc3 --- /dev/null +++ b/src/compositor/wayland_wrapper/wldatasource.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WLDATASOURCE_H +#define WLDATASOURCE_H + +#include <wayland-server-protocol.h> + +#include <QtCore/QByteArray> +#include <QtCore/QList> + +namespace Wayland { + +class DataOffer; + +class DataSource +{ +public: + DataSource(struct wl_client *client, uint32_t id, uint32_t time); + ~DataSource(); + uint32_t time() const; + QList<QByteArray> offerList() const; + + DataOffer *dataOffer() const; + + void postSendEvent(const QByteArray mimeType,int fd); + struct wl_client *client() const; + +private: + uint32_t m_time; + QList<QByteArray> m_offers; + struct wl_resource *m_data_source_resource; + + DataOffer *m_data_offer; + + static struct wl_data_source_interface data_source_interface; + static void offer(struct wl_client *client, + struct wl_resource *resource, + const char *type); + static void destroy(struct wl_client *client, + struct wl_resource *resource); + static void resource_destroy(struct wl_resource *resource); + +}; + +} + +#endif // WLDATASOURCE_H diff --git a/src/compositor/wayland_wrapper/wldisplay.cpp b/src/compositor/wayland_wrapper/wldisplay.cpp new file mode 100644 index 000000000..4277de166 --- /dev/null +++ b/src/compositor/wayland_wrapper/wldisplay.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "wldisplay.h" + +#include <QtCore/QDebug> + +#include <wayland-server-protocol.h> + +namespace Wayland { + +Display::Display() +{ + m_display = wl_display_create(); + + Q_ASSERT(m_display); +} + +Display::~Display() +{ + wl_display_destroy(m_display); +} + +} + diff --git a/src/compositor/wayland_wrapper/wldisplay.h b/src/compositor/wayland_wrapper/wldisplay.h new file mode 100644 index 000000000..5b2e5023d --- /dev/null +++ b/src/compositor/wayland_wrapper/wldisplay.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WL_DISPLAY_H +#define WL_DISPLAY_H + +#include <wayland-server.h> + +namespace Wayland { + +class Display +{ +public: + Display(); + ~Display(); + + struct wl_display *handle() const { return m_display; } + struct wl_display *handle() { return m_display; } + +private: + struct wl_display *m_display; +}; + +} + +#endif //WL_DISPLAY_H diff --git a/src/compositor/wayland_wrapper/wlinputdevice.cpp b/src/compositor/wayland_wrapper/wlinputdevice.cpp new file mode 100644 index 000000000..a7ce0d43a --- /dev/null +++ b/src/compositor/wayland_wrapper/wlinputdevice.cpp @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "wlinputdevice.h" + +#include "wlshmbuffer.h" +#include "wlcompositor.h" +#include "wldatadevice.h" +#include "wlsurface.h" + +#include <QtCore/QDebug> + +#include "waylandcompositor.h" + +namespace Wayland { + +static ShmBuffer *currentCursor; + +InputDevice::InputDevice(Compositor *compositor) +{ + wl_input_device_init(base()); + wl_display_add_global(compositor->wl_display(),&wl_input_device_interface,this,InputDevice::bind_func); +} + +void InputDevice::clientRequestedDataDevice(DataDeviceManager *data_device_manager, struct wl_client *client, uint32_t id) +{ + for (int i = 0; i < m_data_devices.size(); i++) { + struct wl_resource *data_device_resource = + m_data_devices.at(i)->dataDeviceResource(); + if (data_device_resource->client == client) { + qDebug() << "Client created data device, but already has one; removing the old one!"; + m_data_devices.removeAt(i); + free(data_device_resource); + break; + } + } + DataDevice *dataDevice = new DataDevice(data_device_manager,client,id); + m_data_devices.append(dataDevice); + qDebug("created datadevice %p resource %p", dataDevice, dataDevice->dataDeviceResource()); +} + +void InputDevice::sendSelectionFocus(Surface *surface) +{ + if (!surface) + return; + DataDevice *device = dataDevice(surface->base()->resource.client); + if (device) { + device->sendSelectionFocus(); + } +} + +DataDevice *InputDevice::dataDevice(struct wl_client *client) const +{ + for (int i = 0; i < m_data_devices.size();i++) { + if (m_data_devices.at(i)->dataDeviceResource()->client == client) { + return m_data_devices.at(i); + } + } + return 0; +} + +void InputDevice::bind_func(struct wl_client *client, void *data, + uint32_t version, uint32_t id) +{ + Q_UNUSED(version); + struct wl_resource *resource = wl_client_add_object(client,&wl_input_device_interface ,&input_device_interface,id,data); + + struct wl_input_device *input_device = static_cast<struct wl_input_device *>(data); + resource->destroy = destroy_resource; + wl_list_insert(&input_device->resource_list,&resource->link); +} + +void InputDevice::input_device_attach(struct wl_client *client, + struct wl_resource *device_resource, + uint32_t time, + struct wl_resource *buffer_resource, int32_t x, int32_t y) +{ + Q_UNUSED(client); + Q_UNUSED(time); + + struct wl_input_device *device_base = reinterpret_cast<struct wl_input_device *>(device_resource); + struct wl_buffer *buffer = reinterpret_cast<struct wl_buffer *>(buffer_resource); + qDebug() << "Client input device attach" << client << buffer << x << y; + +// Compositor *compositor = wayland_cast<Compositor *>(device_base->compositor); + ShmBuffer *shmBuffer = static_cast<ShmBuffer *>(buffer->user_data); + if (shmBuffer) { +// compositor->qtCompositor()->changeCursor(shmBuffer->image(), x, y); + currentCursor = shmBuffer; + } +} + +const struct wl_input_device_interface InputDevice::input_device_interface = { + InputDevice::input_device_attach, +}; + +void InputDevice::destroy_resource(wl_resource *resource) +{ + qDebug() << "input device resource destroy" << resource; + InputDevice *input_device = static_cast<InputDevice *>(resource->data); + if (input_device->base()->keyboard_focus_resource == resource) { + input_device->base()->keyboard_focus_resource = 0; + } + if (input_device->base()->pointer_focus_resource == resource) { + input_device->base()->pointer_focus_resource = 0; + } + + input_device->m_data_devices.clear(); + + wl_list_remove(&resource->link); + + free(resource); +} + +} diff --git a/src/compositor/wayland_wrapper/wlinputdevice.h b/src/compositor/wayland_wrapper/wlinputdevice.h new file mode 100644 index 000000000..7ea56a918 --- /dev/null +++ b/src/compositor/wayland_wrapper/wlinputdevice.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WLINPUTDEVICE_H +#define WLINPUTDEVICE_H + +#include "waylandobject.h" +#include <QtCore/QList> + +namespace Wayland { + +class Compositor; +class DataDevice; +class Surface; +class DataDeviceManager; + +class InputDevice : public Object<struct wl_input_device> +{ +public: + InputDevice(Compositor *compositor); + + void clientRequestedDataDevice(DataDeviceManager *dndSelection, struct wl_client *client, uint32_t id); + DataDevice *dataDevice(struct wl_client *client) const; + + void sendSelectionFocus(Surface *surface); + + static void bind_func(struct wl_client *client, void *data, + uint32_t version, uint32_t id); + static void input_device_attach(struct wl_client *client, + struct wl_resource *device_base, + uint32_t time, + struct wl_resource *buffer, int32_t x, int32_t y); + const static struct wl_input_device_interface input_device_interface; + static void destroy_resource(struct wl_resource *resource); + +private: + QList<DataDevice *>m_data_devices; + +}; + +} + +#endif // WLINPUTDEVICE_H diff --git a/src/compositor/wayland_wrapper/wloutput.cpp b/src/compositor/wayland_wrapper/wloutput.cpp new file mode 100644 index 000000000..0f61bc051 --- /dev/null +++ b/src/compositor/wayland_wrapper/wloutput.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "wloutput.h" +#include <QGuiApplication> +#include <QtGui/QScreen> +#include <QRect> + +namespace Wayland { + +void Output::output_bind_func(struct wl_client *client, void *data, + uint32_t version, uint32_t id) +{ + Q_UNUSED(version); + Output *output = static_cast<Output *>(data); + + struct wl_resource *resource = wl_client_add_object(client,&wl_output_interface,0,id,data); + wl_resource_post_event(resource, WL_OUTPUT_GEOMETRY, 0, 0, + output->size().width(), output->size().height(),0,"",""); + + wl_resource_post_event(resource,WL_OUTPUT_MODE, WL_OUTPUT_MODE_CURRENT|WL_OUTPUT_MODE_PREFERRED, + output->size().width(),output->size().height()); +} + + +Output::Output() + : m_displayId(-1) + , m_numQueued(0) +{ + QScreen *screen = QGuiApplication::primaryScreen(); + m_geometry = QRect(QPoint(0, 0), screen->availableGeometry().size()); +} + +void Output::setGeometry(const QRect &geometry) +{ + m_geometry = geometry; +} + +} // namespace Wayland diff --git a/src/compositor/wayland_wrapper/wloutput.h b/src/compositor/wayland_wrapper/wloutput.h new file mode 100644 index 000000000..84c91a2f5 --- /dev/null +++ b/src/compositor/wayland_wrapper/wloutput.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WL_OUTPUT_H +#define WL_OUTPUT_H + +#include "waylandobject.h" + +#include <QtCore/QRect> + +namespace Wayland { + +class Output : public Object<struct wl_object> +{ +public: + Output(); + + void setGeometry(const QRect &geometry); + + int x() const { return m_geometry.x(); } + int y() const { return m_geometry.y(); } + QSize size() const { return m_geometry.size(); } + + static void output_bind_func(struct wl_client *client, void *data, + uint32_t version, uint32_t id); +private: + QRect m_geometry; + int m_displayId; + int m_numQueued; +}; + + +} + +#endif //WL_OUTPUT_H diff --git a/src/compositor/wayland_wrapper/wlshell.cpp b/src/compositor/wayland_wrapper/wlshell.cpp new file mode 100644 index 000000000..e6ab73762 --- /dev/null +++ b/src/compositor/wayland_wrapper/wlshell.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "wlshell.h" + +#include "wlcompositor.h" + +#include "wlcompositor.h" + +#include <QtCore/qglobal.h> +#include <QtCore/QDebug> + +namespace Wayland { + +Shell::Shell(Compositor *compositor) +{ +} + +void Shell::bind_func(struct wl_client *client, void *data, + uint32_t version, uint32_t id) +{ + Q_UNUSED(version); + wl_client_add_object(client,&wl_shell_interface,&shell_interface,id,data); +} + +void Shell::shell_move(struct wl_client *client, + struct wl_resource *shell, + struct wl_resource *surface, + struct wl_resource *input_device, + uint32_t time) +{ + Q_UNUSED(client); + Q_UNUSED(shell); + Q_UNUSED(surface); + Q_UNUSED(input_device); + Q_UNUSED(time); + qDebug() << "shellMove"; +} + +void Shell::shell_resize(struct wl_client *client, + struct wl_resource *shell, + struct wl_resource *surface, + struct wl_resource *input_device, + uint32_t time, + uint32_t edges) +{ + Q_UNUSED(client); + Q_UNUSED(shell); + Q_UNUSED(surface); + Q_UNUSED(input_device); + Q_UNUSED(time); + Q_UNUSED(edges); + qDebug() << "shellResize"; +} + +void Shell::set_toplevel(struct wl_client *client, + struct wl_resource *wl_shell, + struct wl_resource *surface) +{ + Q_UNUSED(client); + Q_UNUSED(wl_shell); + Q_UNUSED(surface); +} + +void Shell::set_transient(struct wl_client *client, + struct wl_resource *wl_shell, + struct wl_resource *surface, + struct wl_resource *parent, + int x, + int y, + uint32_t flags) +{ + Q_UNUSED(client); + Q_UNUSED(wl_shell); + Q_UNUSED(surface); + Q_UNUSED(parent); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(flags); +} +void Shell::set_fullscreen(struct wl_client *client, + struct wl_resource *wl_shell, + struct wl_resource *surface) +{ + Q_UNUSED(client); + Q_UNUSED(wl_shell); + Q_UNUSED(surface); +} + +const struct wl_shell_interface Shell::shell_interface = { + shell_move, + shell_resize, + set_toplevel, + set_transient, + set_fullscreen +}; + +} diff --git a/src/compositor/wayland_wrapper/wlshell.h b/src/compositor/wayland_wrapper/wlshell.h new file mode 100644 index 000000000..a748186e8 --- /dev/null +++ b/src/compositor/wayland_wrapper/wlshell.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WLSHELL_H +#define WLSHELL_H + +#include "waylandobject.h" + +namespace Wayland { + +class Compositor; + +class Shell : public Object<struct wl_object> +{ +public: + Shell(Compositor *compositor); + + static void bind_func(struct wl_client *client, void *data, + uint32_t version, uint32_t id); + static void shell_move(struct wl_client *client, + struct wl_resource *shell, + struct wl_resource *surface, + struct wl_resource *input_device, + uint32_t time); + static void shell_resize(struct wl_client *client, + struct wl_resource *shell, + struct wl_resource *surface, + struct wl_resource *input_device, + uint32_t time, + uint32_t edges); + static void set_toplevel(struct wl_client *client, + struct wl_resource *shell, + struct wl_resource *surface); + static void set_transient(struct wl_client *client, + struct wl_resource *shell, + struct wl_resource *surface, + struct wl_resource *parent, + int x, + int y, + uint32_t flags); + static void set_fullscreen(struct wl_client *client, + struct wl_resource *shell, + struct wl_resource *surface); + const static struct wl_shell_interface shell_interface; +}; + +} + +#endif // WLSHELL_H diff --git a/src/compositor/wayland_wrapper/wlshmbuffer.cpp b/src/compositor/wayland_wrapper/wlshmbuffer.cpp new file mode 100644 index 000000000..c5126aeaa --- /dev/null +++ b/src/compositor/wayland_wrapper/wlshmbuffer.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "wlshmbuffer.h" + +#include "wldisplay.h" +#include "wlcompositor.h" + +#include <QtCore/QDebug> + +#include <sys/mman.h> + +namespace Wayland { + +ShmBuffer::ShmBuffer(struct wl_buffer *buffer) + : m_buffer(buffer) +{ + m_buffer->user_data = this; + m_data = wl_shm_buffer_get_data(m_buffer); + m_stride = wl_shm_buffer_get_stride(m_buffer); + + damage(); +} + +ShmBuffer::~ShmBuffer() +{ +} + +QImage ShmBuffer::image() const +{ + return m_image; +} + +QSize ShmBuffer::size() const +{ + return QSize(m_buffer->width, m_buffer->height); +} + +void ShmBuffer::damage() +{ + QImage::Format imageFormat = QImage::Format_Invalid; + + imageFormat = QImage::Format_ARGB32_Premultiplied; + + m_image = QImage(static_cast<uchar *>(m_data),m_buffer->width, m_buffer->height,m_stride,imageFormat); + +} + +static ShmHandler *handlerInstance; + +ShmHandler::ShmHandler(Display *display) + : m_display(display) +{ + handlerInstance = this; + m_shm = wl_shm_init(m_display->handle(),&shm_callbacks); +} + +ShmHandler::~ShmHandler() +{ + wl_shm_finish(m_shm); +} + +struct wl_shm_callbacks ShmHandler::shm_callbacks = { + buffer_created_callback, + buffer_damaged_callback, + buffer_destroyed_callback +}; + +void ShmHandler::buffer_created_callback(struct wl_buffer *buffer) +{ + ShmBuffer *newBuffer = new ShmBuffer(buffer); + Q_UNUSED(newBuffer); +} + +void ShmHandler::buffer_damaged_callback(struct wl_buffer *buffer, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + Q_UNUSED(buffer); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(width); + Q_UNUSED(height); + //damage has the responsibillity to update the QImage + //for now we just recrate the entire QImage as we need a new + //hash key for texture uploads + static_cast<ShmBuffer *>(buffer->user_data)->damage(); +} + +void ShmHandler::buffer_destroyed_callback(struct wl_buffer *buffer) +{ + ShmBuffer *shmbuf = static_cast<ShmBuffer *>(buffer->user_data); + for (int i = 0; i < handlerInstance->m_extraCallbacks.count(); ++i) + handlerInstance->m_extraCallbacks.at(i)(shmbuf); + delete shmbuf; +} + +void ShmHandler::addDestroyCallback(DestroyCallback callback) +{ + if (!m_extraCallbacks.contains(callback)) + m_extraCallbacks.append(callback); +} + +} diff --git a/src/compositor/wayland_wrapper/wlshmbuffer.h b/src/compositor/wayland_wrapper/wlshmbuffer.h new file mode 100644 index 000000000..e8092ce2a --- /dev/null +++ b/src/compositor/wayland_wrapper/wlshmbuffer.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WL_SHMBUFFER_H +#define WL_SHMBUFFER_H + +#include "waylandobject.h" + +#include <QtCore/QRect> +#include <QtGui/QImage> + + +namespace Wayland { + +class Surface; +class Display; + +class ShmBuffer +{ +public: + ShmBuffer(struct wl_buffer *buffer); + ~ShmBuffer(); + + QImage image() const; + QSize size() const; + + void damage(); + +private: + struct wl_buffer *m_buffer; + int m_stride; + void *m_data; + QImage m_image; +}; + +class ShmHandler +{ +public: + ShmHandler(Display *display); + ~ShmHandler(); + + typedef void (*DestroyCallback)(ShmBuffer *); + void addDestroyCallback(DestroyCallback callback); + +private: + Display *m_display; + struct wl_shm *m_shm; + + static struct wl_shm_callbacks shm_callbacks; + static void buffer_created_callback(struct wl_buffer *buffer); + static void buffer_damaged_callback(struct wl_buffer *buffer, + int32_t x, int32_t y, + int32_t width, int32_t height); + static void buffer_destroyed_callback(struct wl_buffer *buffer); + QList<DestroyCallback> m_extraCallbacks; +}; + +} + +#endif //WL_SHMBUFFER_H diff --git a/src/compositor/wayland_wrapper/wlsurface.cpp b/src/compositor/wayland_wrapper/wlsurface.cpp new file mode 100644 index 000000000..1edbeb7ea --- /dev/null +++ b/src/compositor/wayland_wrapper/wlsurface.cpp @@ -0,0 +1,510 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#include "wlsurface.h" + +#include "waylandsurface.h" + +#include "wlcompositor.h" +#include "wlshmbuffer.h" +#include "wlinputdevice.h" + +#include <QtCore/QDebug> + +#include <wayland-server.h> + +#ifdef Q_OS_LINUX +#include <linux/input.h> +#endif + +#ifdef QT_COMPOSITOR_WAYLAND_GL +#include "hardware_integration/graphicshardwareintegration.h" +#include <QtGui/QPlatformOpenGLContext> +#endif + +#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT +#include "waylandwindowmanagerintegration.h" +#endif + +namespace Wayland { + +const struct wl_surface_interface Surface::surface_interface = { + Surface::surface_destroy, + Surface::surface_attach, + Surface::surface_damage, + Surface::surface_frame +}; + +class SurfacePrivate +{ +public: + SurfacePrivate(struct wl_client *client, Compositor *compositor) + : client(client) + , compositor(compositor) + , textureCreatedForBuffer(false) + , directRenderBuffer(0) + , processId(0) + , previousBuffer(0) + , frame_callback(0) + , surfaceBuffer(0) + , surfaceType(WaylandSurface::Invalid) + + + { +#ifdef QT_COMPOSITOR_WAYLAND_GL + texture_id = 0; +#endif + } + + WaylandSurface::Type type() const { + if (surfaceType == WaylandSurface::Invalid) { + SurfacePrivate *that = const_cast<SurfacePrivate *>(this); + if (qtSurface->handle() == compositor->directRenderSurface()) { + that->surfaceType = WaylandSurface::Direct; + } else if (surfaceBuffer && wl_buffer_is_shm(surfaceBuffer)) { + that->surfaceType = WaylandSurface::Shm; + } else if (surfaceBuffer){ + that->surfaceType = WaylandSurface::Texture; + } + } + return surfaceType; + } + + void attach(struct wl_buffer *buffer) { + bool emitMap = !surfaceBuffer; + if (surfaceBuffer && ! textureCreatedForBuffer && surfaceBuffer != directRenderBuffer) { + qWarning() << "### WaylandSurface::attach() releasing undisplayed buffer ###"; + wl_resource_post_event(&surfaceBuffer->resource, WL_BUFFER_RELEASE); + } + surfaceBuffer = buffer; + surfaceType = WaylandSurface::Invalid; + textureCreatedForBuffer = false; + if (emitMap) { + qtSurface->mapped(QSize(surfaceBuffer->width,surfaceBuffer->height)); + } + } + + inline struct wl_buffer *buffer() const { return surfaceBuffer; } + + static void destroy_frame_callback(struct wl_resource *resource) + { + if (resource->data) + static_cast<SurfacePrivate *>(resource->data)->frame_callback = 0; + delete resource; + } + + struct wl_client *client; + Compositor *compositor; + WaylandSurface *qtSurface; + +#ifdef QT_COMPOSITOR_WAYLAND_GL + GLuint texture_id; +#endif + bool textureCreatedForBuffer; + struct wl_buffer *directRenderBuffer; + qint64 processId; + QByteArray authenticationToken; + QVariantMap windowProperties; + + QPoint lastMousePos; + + struct wl_buffer *previousBuffer; + struct wl_resource *frame_callback; +private: + struct wl_buffer *surfaceBuffer; + WaylandSurface::Type surfaceType; +}; + + +void Surface::surface_destroy(struct wl_client *client, struct wl_resource *surface_resource) +{ + Surface *surface = reinterpret_cast<Surface *>(surface_resource); + wl_resource_destroy(surface_resource,Compositor::currentTimeMsecs()); +} + +void Surface::surface_attach(struct wl_client *client, struct wl_resource *surface, + struct wl_resource *buffer, int x, int y) +{ + Q_UNUSED(client); + Q_UNUSED(x); + Q_UNUSED(y); + reinterpret_cast<Surface *>(surface)->attach(buffer); +} + +void Surface::surface_damage(struct wl_client *client, struct wl_resource *surface, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + Q_UNUSED(client); + reinterpret_cast<Surface *>(surface)->damage(QRect(x, y, width, height)); +} +void Surface::surface_frame(struct wl_client *client, + struct wl_resource *resource, + uint32_t callback) +{ + Surface *surface = reinterpret_cast<Surface *>(resource); + SurfacePrivate *d = surface->d_func(); + d->frame_callback = new struct wl_resource; + d->frame_callback->client = client; + d->frame_callback->object.interface = &wl_callback_interface; + d->frame_callback->object.id = callback; + d->frame_callback->data = d; + d->frame_callback->destroy = SurfacePrivate::destroy_frame_callback; + + wl_client_add_resource(client, d->frame_callback); +} + +Surface::Surface(struct wl_client *client, Compositor *compositor) + : d_ptr(new SurfacePrivate(client,compositor)) +{ + base()->resource.client = client; + d_ptr->qtSurface = new WaylandSurface(this); +} + +Surface::~Surface() +{ + Q_D(Surface); + d->compositor->surfaceDestroyed(this); +#ifdef QT_COMPOSITOR_WAYLAND_GL + if (d->compositor->graphicsHWIntegration()) + glDeleteTextures(1,&d->texture_id); + +#endif + delete d->qtSurface; +} + +WaylandSurface::Type Surface::type() const +{ + Q_D(const Surface); + return d->type(); +} + +bool Surface::isYInverted() const +{ +#ifdef QT_COMPOSITOR_WAYLAND_GL + Q_D(const Surface); + + if (d->compositor->graphicsHWIntegration()) { + if (d->type() == WaylandSurface::Texture) { + //if (textureId()) { + return d->compositor->graphicsHWIntegration()->isYInverted(d->buffer()); + //} + } else if (d->type() == WaylandSurface::Direct) { + return d->compositor->graphicsHWIntegration()->isYInverted(d->buffer()); + } + } +#endif + //shm surfaces are not flipped (in our "world") + return false; +} + +void Surface::damage(const QRect &rect) +{ + Q_D(Surface); + +#ifdef QT_COMPOSITOR_WAYLAND_GL + if (d->compositor->graphicsHWIntegration() && d->type() == WaylandSurface::Direct) { + //should the texture be deleted here, or should we explicitly delete it + //when going into direct mode... + if (d->textureCreatedForBuffer) { + glDeleteTextures(1,&d->texture_id); + d->textureCreatedForBuffer = false; + } + if (d->previousBuffer) { //previousBuffer means previous buffer turned into texture + wl_resource_post_event(&d->previousBuffer->resource,WL_BUFFER_RELEASE); + d->previousBuffer = 0; + } + if (d->compositor->graphicsHWIntegration()->postBuffer(d->buffer())) { + d->directRenderBuffer = d->buffer(); + emit d->qtSurface->damaged(rect); + return; + } + } +#endif + d->directRenderBuffer = 0; + d->compositor->markSurfaceAsDirty(this); + + emit d->qtSurface->damaged(rect); +} + +QImage Surface::image() const +{ + Q_D(const Surface); + if (d->type() == WaylandSurface::Shm) { + ShmBuffer *shmBuffer = static_cast<ShmBuffer *>(d->buffer()->user_data); + return shmBuffer->image(); + } + return QImage(); +} + +#ifdef QT_COMPOSITOR_WAYLAND_GL +GLuint Surface::textureId(QOpenGLContext *context) const +{ + Q_D(const Surface); + if (d->compositor->graphicsHWIntegration() && d->type() == WaylandSurface::Texture + && !d->textureCreatedForBuffer) { + if (d->texture_id) + glDeleteTextures(1,&d->texture_id); + if (d->previousBuffer) { + wl_resource_post_event(&d->previousBuffer->resource,WL_BUFFER_RELEASE); + } + Surface *that = const_cast<Surface *>(this); + GraphicsHardwareIntegration *hwIntegration = d->compositor->graphicsHWIntegration(); + that->d_func()->previousBuffer = d->buffer(); + that->d_func()->texture_id = hwIntegration->createTextureFromBuffer(d->buffer(), context); + that->d_func()->textureCreatedForBuffer = true; + } + return d->texture_id; +} +#endif // QT_COMPOSITOR_WAYLAND_GL + +void Surface::attach(struct wl_resource *buffer) +{ + Q_D(Surface); + d->attach(reinterpret_cast<struct wl_buffer *>(buffer)); +} + +WaylandSurface * Surface::handle() const +{ + Q_D(const Surface); + 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; +} + +QByteArray Surface::authenticationToken() const +{ + Q_D(const Surface); + return WindowManagerServerIntegration::instance()->managedClient(d->client)->authenticationToken(); +} + +QVariantMap Surface::windowProperties() const +{ + Q_D(const Surface); + return d->windowProperties; +} + +QVariant Surface::windowProperty(const QString &propertyName) const +{ + Q_D(const Surface); + QVariantMap props = d->windowProperties; + return props.value(propertyName); +} + +void Surface::setWindowProperty(const QString &name, const QVariant &value, bool writeUpdateToClient) +{ + Q_D(Surface); + d->windowProperties.insert(name, value); + if (writeUpdateToClient) + WindowManagerServerIntegration::instance()->setWindowProperty(d->client, base(), name, value); +} + +uint32_t toWaylandButton(Qt::MouseButton button) +{ +#ifndef BTN_LEFT +uint32_t BTN_LEFT = 0x110; +uint32_t BTN_RIGHT = 0x111; +uint32_t BTN_MIDDLE = 0x112; +#endif + switch (button) { + case Qt::LeftButton: + return BTN_LEFT; + case Qt::RightButton: + return BTN_RIGHT; + default: + return BTN_MIDDLE; + } + +} + +QPoint Surface::lastMousePos() const +{ + Q_D(const Surface); + return d->lastMousePos; +} + +void Surface::sendMousePressEvent(int x, int y, Qt::MouseButton button) +{ + Q_D(Surface); + sendMouseMoveEvent(x, y); + if (d->client) { + uint32_t time = d->compositor->currentTimeMsecs(); + struct wl_resource *pointer_focus_resource = d->compositor->defaultInputDevice()->base()->pointer_focus_resource; + if (pointer_focus_resource) { + wl_resource_post_event(d->compositor->defaultInputDevice()->base()->pointer_focus_resource, + WL_INPUT_DEVICE_BUTTON, time, toWaylandButton(button), 1); + } + } +} + +void Surface::sendMouseReleaseEvent(int x, int y, Qt::MouseButton button) +{ + Q_D(Surface); + sendMouseMoveEvent(x, y); + if (d->client) { + uint32_t time = d->compositor->currentTimeMsecs(); + struct wl_resource *pointer_focus_resource = d->compositor->defaultInputDevice()->base()->pointer_focus_resource; + if (pointer_focus_resource) { + wl_resource_post_event(pointer_focus_resource, + WL_INPUT_DEVICE_BUTTON, time, toWaylandButton(button), 0); + } + } +} + +void Surface::sendMouseMoveEvent(int x, int y) +{ + Q_D(Surface); + if (d->client) { + d->lastMousePos = QPoint(x, y); + uint32_t time = d->compositor->currentTimeMsecs(); + d->compositor->setPointerFocus(this, QPoint(x, y)); + struct wl_resource *pointer_focus_resource = d->compositor->defaultInputDevice()->base()->pointer_focus_resource; + if (pointer_focus_resource) { + wl_resource_post_event(pointer_focus_resource, + WL_INPUT_DEVICE_MOTION, time, x, y, x, y); + } + } +} + +void Surface::sendKeyPressEvent(uint code) +{ + Q_D(Surface); + if (d->compositor->defaultInputDevice()->base()->keyboard_focus_resource != NULL) { + uint32_t time = d->compositor->currentTimeMsecs(); + wl_resource_post_event(d->compositor->defaultInputDevice()->base()->keyboard_focus_resource, + WL_INPUT_DEVICE_KEY, time, code - 8, 1); + } +} + +void Surface::sendKeyReleaseEvent(uint code) +{ + Q_D(Surface); + if (d->compositor->defaultInputDevice()->base()->keyboard_focus_resource != NULL) { + uint32_t time = d->compositor->currentTimeMsecs(); + wl_resource_post_event(d->compositor->defaultInputDevice()->base()->keyboard_focus_resource, + WL_INPUT_DEVICE_KEY, time, code - 8, 0); + } +} + +void Surface::sendTouchPointEvent(int id, int x, int y, Qt::TouchPointState state) +{ + Q_D(Surface); + uint32_t time = d->compositor->currentTimeMsecs(); + struct wl_resource *resource = d->compositor->defaultInputDevice()->base()->pointer_focus_resource; + switch (state) { + case Qt::TouchPointPressed: + wl_resource_post_event(resource, WL_INPUT_DEVICE_TOUCH_DOWN, time, id, x, y); + break; + case Qt::TouchPointMoved: + wl_resource_post_event(resource, WL_INPUT_DEVICE_TOUCH_MOTION, time, id, x, y); + break; + case Qt::TouchPointReleased: + wl_resource_post_event(resource, WL_INPUT_DEVICE_TOUCH_UP, time, id); + break; + case Qt::TouchPointStationary: + // stationary points are not sent through wayland, the client must cache them + break; + default: + break; + } +} + +void Surface::sendTouchFrameEvent() +{ + Q_D(Surface); + struct wl_resource *resource = d->compositor->defaultInputDevice()->base()->pointer_focus_resource; + wl_resource_post_event(resource, + WL_INPUT_DEVICE_TOUCH_FRAME); +} + +void Surface::sendTouchCancelEvent() +{ + Q_D(Surface); + struct wl_resource *resource = d->compositor->defaultInputDevice()->base()->pointer_focus_resource; + wl_resource_post_event(resource, + WL_INPUT_DEVICE_TOUCH_CANCEL); +} + +void Surface::sendFrameCallback() +{ + Q_D(Surface); + if (d->frame_callback) { + wl_resource_post_event(d->frame_callback,WL_CALLBACK_DONE,Compositor::currentTimeMsecs()); + wl_resource_destroy(d->frame_callback,Compositor::currentTimeMsecs()); + } +} + +void Surface::frameFinished() +{ + Q_D(Surface); + d->compositor->frameFinished(this); +} + +void Surface::setInputFocus() +{ + Q_D(Surface); + d->compositor->setInputFocus(this); +} + +void Surface::sendOnScreenVisibilityChange(bool visible) +{ +#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT + Q_D(Surface); + WindowManagerServerIntegration::instance()->setVisibilityOnScreen(d->client, visible); +#endif +} + +} // namespace Wayland + diff --git a/src/compositor/wayland_wrapper/wlsurface.h b/src/compositor/wayland_wrapper/wlsurface.h new file mode 100644 index 000000000..4d037a26e --- /dev/null +++ b/src/compositor/wayland_wrapper/wlsurface.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** This file is part of QtCompositor** +** +** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation qt-info@nokia.com +** +** You may use this file under the terms of the BSD license as follows: +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** +** Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** +** Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +****************************************************************************/ + +#ifndef WL_SURFACE_H +#define WL_SURFACE_H + +#include "waylandobject.h" +#include "wlshmbuffer.h" +#include "waylandsurface.h" + +#include <QtCore/QRect> +#include <QtGui/QImage> + +#include <QtCore/QTextStream> +#include <QtCore/QMetaType> + +#ifdef QT_COMPOSITOR_WAYLAND_GL +#include <QtGui/QOpenGLContext> +#include <QtGui/qopengl.h> +#endif + +namespace Wayland { + +class Compositor; +class Buffer; + +class SurfacePrivate; + +class Surface : public Object<struct wl_surface> +{ + Q_DECLARE_PRIVATE(Surface) +public: + Surface(struct wl_client *client, Compositor *compositor); + ~Surface(); + + WaylandSurface::Type type() const; + bool isYInverted() const; + + uint id() const { return base()->resource.object.id; } + void attach(struct wl_resource *buffer); + + void damage(const QRect &rect); + + QImage image() const; + +#ifdef QT_COMPOSITOR_WAYLAND_GL + GLuint textureId(QOpenGLContext *context) const; +#endif + + void sendMousePressEvent(int x, int y, Qt::MouseButton button); + void sendMouseReleaseEvent(int x, int y, Qt::MouseButton button); + void sendMouseMoveEvent(int x, int y); + + void sendKeyPressEvent(uint code); + void sendKeyReleaseEvent(uint code); + + void sendTouchPointEvent(int id, int x, int y, Qt::TouchPointState state); + void sendTouchFrameEvent(); + void sendTouchCancelEvent(); + + void sendFrameCallback(); + + void frameFinished(); + void setInputFocus(); + + void sendOnScreenVisibilityChange(bool visible); + + WaylandSurface *handle() const; + wl_client *clientHandle() const; + qint64 processId() const; + void setProcessId(qint64 processId); + QByteArray authenticationToken() const; + void setAuthenticationToken(const QByteArray &authenticationToken); + + QVariantMap windowProperties() const; + QVariant windowProperty(const QString &propertyName) const; + void setWindowProperty(const QString &name, const QVariant &value, bool writeUpdateToClient = true); + + void setSurfaceCreationFinished(bool isCreated); + + QPoint lastMousePos() const; + + static const struct wl_surface_interface surface_interface; +protected: + QScopedPointer<SurfacePrivate> d_ptr; +private: + Q_DISABLE_COPY(Surface) + static void surface_destroy(struct wl_client *client, struct wl_resource *_surface); + static void surface_attach(struct wl_client *client, struct wl_resource *surface, + struct wl_resource *buffer, int x, int y); + static void surface_damage(struct wl_client *client, struct wl_resource *_surface, + int32_t x, int32_t y, int32_t width, int32_t height); + static void surface_frame(struct wl_client *client, struct wl_resource *resource, + uint32_t callback); + +}; + +} + +#endif //WL_SURFACE_H diff --git a/src/compositor/windowmanagerprotocol/wayland-windowmanager-protocol.c b/src/compositor/windowmanagerprotocol/wayland-windowmanager-protocol.c new file mode 100644 index 000000000..7e8861b67 --- /dev/null +++ b/src/compositor/windowmanagerprotocol/wayland-windowmanager-protocol.c @@ -0,0 +1,77 @@ +/* + * 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 plugins of the Qt Toolkit. + * + * $QT_BEGIN_LICENSE:LGPL$ + * GNU Lesser General Public License Usage + * 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. + * + * GNU General Public License Usage + * Alternatively, this file may be used under the terms of the GNU General + * Public License version 3.0 as published by the Free Software Foundation + * and appearing in the file LICENSE.GPL included in the packaging of this + * file. Please review the following information to ensure the GNU General + * Public License version 3.0 requirements will be met: + * http://www.gnu.org/copyleft/gpl.html. + * + * Other Usage + * Alternatively, this file may be used in accordance with the terms and + * conditions contained in a signed written agreement between you and Nokia. + * + * + * + * + * + * $QT_END_LICENSE$ + */ + +#include <stdlib.h> +#include <stdint.h> +#include "wayland-util.h" + +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface wl_output_interface; +extern const struct wl_interface wl_surface_interface; + +static const struct wl_interface *types[] = { + NULL, + &wl_surface_interface, + NULL, + NULL, + &wl_output_interface, + NULL, + &wl_surface_interface, + NULL, + NULL, +}; + +static const struct wl_message wl_windowmanager_requests[] = { + { "map_client_to_process", "u", types + 0 }, + { "authenticate_with_token", "s", types + 0 }, + { "update_generic_property", "osa", types + 1 }, +}; + +static const struct wl_message wl_windowmanager_events[] = { + { "client_onscreen_visibility", "i", types + 0 }, + { "set_screen_rotation", "oi", types + 4 }, + { "set_generic_property", "osa", types + 6 }, +}; + +WL_EXPORT const struct wl_interface wl_windowmanager_interface = { + "wl_windowmanager", 1, + ARRAY_LENGTH(wl_windowmanager_requests), wl_windowmanager_requests, + ARRAY_LENGTH(wl_windowmanager_events), wl_windowmanager_events, +}; + diff --git a/src/compositor/windowmanagerprotocol/wayland-windowmanager-server-protocol.h b/src/compositor/windowmanagerprotocol/wayland-windowmanager-server-protocol.h new file mode 100644 index 000000000..5b7dda247 --- /dev/null +++ b/src/compositor/windowmanagerprotocol/wayland-windowmanager-server-protocol.h @@ -0,0 +1,80 @@ +/* + * 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 plugins of the Qt Toolkit. + * + * $QT_BEGIN_LICENSE:LGPL$ + * GNU Lesser General Public License Usage + * 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. + * + * GNU General Public License Usage + * Alternatively, this file may be used under the terms of the GNU General + * Public License version 3.0 as published by the Free Software Foundation + * and appearing in the file LICENSE.GPL included in the packaging of this + * file. Please review the following information to ensure the GNU General + * Public License version 3.0 requirements will be met: + * http://www.gnu.org/copyleft/gpl.html. + * + * Other Usage + * Alternatively, this file may be used in accordance with the terms and + * conditions contained in a signed written agreement between you and Nokia. + * + * + * + * + * + * $QT_END_LICENSE$ + */ + +#ifndef WAYLAND_WINDOWMANAGER_SERVER_PROTOCOL_H +#define WAYLAND_WINDOWMANAGER_SERVER_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stddef.h> +#include "wayland-util.h" + +struct wl_client; +struct wl_resource; + +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_resource *resource, + uint32_t processid); + void (*authenticate_with_token)(struct wl_client *client, + struct wl_resource *resource, + const char *processid); + void (*update_generic_property)(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *surface, + const char *name, + struct wl_array *value); +}; + +#define WL_WINDOWMANAGER_CLIENT_ONSCREEN_VISIBILITY 0 +#define WL_WINDOWMANAGER_SET_SCREEN_ROTATION 1 +#define WL_WINDOWMANAGER_SET_GENERIC_PROPERTY 2 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp b/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp new file mode 100644 index 000000000..815032fbc --- /dev/null +++ b/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp @@ -0,0 +1,248 @@ +/**************************************************************************** +** +** 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" + +// 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: + + void mapClientToProcess(wl_client *client, uint32_t processId) + { + WindowManagerServerIntegration::instance()->mapClientToProcess(client, processId); + } + + void authenticateWithToken(wl_client *client, const char *authenticationToken) + { + WindowManagerServerIntegration::instance()->authenticateWithToken(client, authenticationToken); + } + + void changeScreenVisibility(wl_client *client, int visible) + { + WindowManagerServerIntegration::instance()->setVisibilityOnScreen(client, visible); + } + + void updateWindowProperty(wl_client *client, wl_surface *surface, const char *name, struct wl_array *value) + { + WindowManagerServerIntegration::instance()->updateWindowProperty(client, surface, name, value); + } + + static void bind_func(struct wl_client *client, void *data, + uint32_t version, uint32_t id); + + static void destroy_resource(wl_resource *resource); + + struct wl_resource *getWindowManagerResourceForClient(struct wl_client *client) { + for (int i = 0; i < m_client_resources.size(); i++) { + if (m_client_resources.at(i)->client == client) { + return m_client_resources.at(i); + } + } + return 0; + } + +private: + QList<struct wl_resource *>m_client_resources; + +}; + +void map_client_to_process(wl_client *client, struct wl_resource *windowMgrResource, uint32_t processId) +{ + WindowManagerObject *windowMgr = static_cast<WindowManagerObject *>(windowMgrResource->data); + windowMgr->mapClientToProcess(client,processId); +} + +void authenticate_with_token(wl_client *client, struct wl_resource *windowMgrResource, const char *wl_authentication_token) +{ + WindowManagerObject *windowMgr = static_cast<WindowManagerObject *>(windowMgrResource->data); + windowMgr->authenticateWithToken(client,wl_authentication_token); +} + +void update_generic_property(wl_client *client, struct wl_resource *windowMgrResource, wl_resource *surfaceResource, const char *name, struct wl_array *value) +{ + WindowManagerObject *windowMgr = static_cast<WindowManagerObject *>(windowMgrResource->data); + struct wl_surface *surface = static_cast<struct wl_surface *>(surfaceResource->data); + windowMgr->updateWindowProperty(client,surface,name,value); +} + +const static struct wl_windowmanager_interface windowmanager_interface = { + map_client_to_process, + authenticate_with_token, + update_generic_property +}; + +void WindowManagerObject::bind_func(struct wl_client *client, void *data, + uint32_t version, uint32_t id) +{ + Q_UNUSED(version); + WindowManagerObject *win_mgr_object= static_cast<WindowManagerObject *>(data); + struct wl_resource *resource =wl_client_add_object(client,&wl_windowmanager_interface,&windowmanager_interface,id,data); + resource->destroy = destroy_resource; + win_mgr_object->m_client_resources.append(resource); + qDebug("wm bind client %p resource %p", client, resource); +} + +void WindowManagerObject::destroy_resource(wl_resource *resource) +{ + qDebug("wm destroy resource %p", resource); + WindowManagerObject *win_mgr_object = static_cast<WindowManagerObject *>(resource->data); + win_mgr_object->m_client_resources.removeOne(resource); + free(resource); +} + +WindowManagerServerIntegration *WindowManagerServerIntegration::m_instance = 0; + +WindowManagerServerIntegration::WindowManagerServerIntegration(QObject *parent) + : QObject(parent) +{ + m_instance = this; +} + +void WindowManagerServerIntegration::initialize(Wayland::Display *waylandDisplay) +{ + m_windowManagerObject = new WindowManagerObject(); + wl_display_add_global(waylandDisplay->handle(),&wl_windowmanager_interface,m_windowManagerObject,WindowManagerObject::bind_func); +} + +void WindowManagerServerIntegration::removeClient(wl_client *client) +{ + WaylandManagedClient *managedClient = m_managedClients.take(client); + delete managedClient; +} + +void WindowManagerServerIntegration::mapClientToProcess(wl_client *client, uint32_t processId) +{ + WaylandManagedClient *managedClient = m_managedClients.value(client, new WaylandManagedClient); + managedClient->m_processId = processId; + m_managedClients.insert(client, managedClient); +} + +void WindowManagerServerIntegration::authenticateWithToken(wl_client *client, const char *token) +{ + Q_ASSERT(token != 0 && *token != 0); + + WaylandManagedClient *managedClient = m_managedClients.value(client, new WaylandManagedClient); + managedClient->m_authenticationToken = QByteArray(token); + m_managedClients.insert(client, managedClient); + + emit clientAuthenticated(client); +} + +void WindowManagerServerIntegration::setVisibilityOnScreen(wl_client *client, bool visible) +{ + struct wl_resource *win_mgr_resource = m_windowManagerObject->getWindowManagerResourceForClient(client); + wl_resource_post_event(win_mgr_resource,WL_WINDOWMANAGER_CLIENT_ONSCREEN_VISIBILITY,visible); +} + +void WindowManagerServerIntegration::setScreenOrientation(wl_client *client, wl_object *output, Qt::ScreenOrientation orientation) +{ + struct wl_resource *win_mgr_resource = m_windowManagerObject->getWindowManagerResourceForClient(client); + wl_resource_post_event(win_mgr_resource,WL_WINDOWMANAGER_SET_SCREEN_ROTATION,output, qint32(orientation)); +} + +// client -> server +void WindowManagerServerIntegration::updateWindowProperty(wl_client *client, wl_surface *surface, const char *name, struct wl_array *value) +{ + QVariant variantValue; + QByteArray byteValue((const char*)value->data, value->size); + QDataStream ds(&byteValue, QIODevice::ReadOnly); + ds >> variantValue; + + emit windowPropertyChanged(client, surface, QString(name), variantValue); +} + +// server -> client +void WindowManagerServerIntegration::setWindowProperty(wl_client *client, wl_surface *surface, const QString &name, const QVariant &value) +{ + QByteArray byteValue; + QDataStream ds(&byteValue, QIODevice::WriteOnly); + ds << value; + wl_array data; + data.size = byteValue.size(); + data.data = (void*) byteValue.constData(); + data.alloc = 0; + + struct wl_resource *win_mgr_resource = m_windowManagerObject->getWindowManagerResourceForClient(client); + wl_resource_post_event(win_mgr_resource,WL_WINDOWMANAGER_SET_GENERIC_PROPERTY,surface, name.toLatin1().constData(),&data); +} + +WaylandManagedClient *WindowManagerServerIntegration::managedClient(wl_client *client) const +{ + return m_managedClients.value(client, 0); +} + +WindowManagerServerIntegration *WindowManagerServerIntegration::instance() +{ + return m_instance; +} + +/// /// +/// / WaylandManagedClient +/// /// + +WaylandManagedClient::WaylandManagedClient() + : m_processId(0) +{ +} + +qint64 WaylandManagedClient::processId() const +{ + return m_processId; +} + +QByteArray WaylandManagedClient::authenticationToken() const +{ + return m_authenticationToken; +} diff --git a/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.h b/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.h new file mode 100644 index 000000000..950fed1dd --- /dev/null +++ b/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** 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 <qwindowdefs.h> +#include <stdint.h> + +#include <QObject> +#include <QMap> +#include <QVariant> + +struct wl_client; +struct wl_object; + +namespace Wayland { + class Display; +} + +class WindowManagerObject; +class WaylandManagedClient; + +class WindowManagerServerIntegration : public QObject +{ + Q_OBJECT +public: + WindowManagerServerIntegration(QObject *parent = 0); + static WindowManagerServerIntegration *instance(); + void initialize(Wayland::Display *waylandDisplay); + void removeClient(wl_client *client); + + WaylandManagedClient *managedClient(wl_client *client) const; + + void setVisibilityOnScreen(wl_client *client, bool visible); + void setScreenOrientation(wl_client *client, wl_object *output, Qt::ScreenOrientation orientationInDegrees); + void updateOrientation(wl_client *client); + + void updateWindowProperty(wl_client *client, struct wl_surface *surface, const char *name, struct wl_array *value); + void setWindowProperty(wl_client *client, struct wl_surface *surface, const QString &name, const QVariant &value); + +signals: + void clientAuthenticated(wl_client *client); + void windowPropertyChanged(wl_client *client, struct wl_surface *surface, const QString &name, const QVariant &value); + +private: + void mapClientToProcess(wl_client *client, uint32_t processId); + void authenticateWithToken(wl_client *client, const char *token); + +private: + QMap<wl_client*, WaylandManagedClient*> m_managedClients; + static WindowManagerServerIntegration *m_instance; + + WindowManagerObject *m_windowManagerObject; + + friend class WindowManagerObject; +}; + +class WaylandManagedClient +{ +public: + WaylandManagedClient(); + qint64 processId() const; + QByteArray authenticationToken() const; + +private: + qint64 m_processId; + QByteArray m_authenticationToken; + + friend class WindowManagerServerIntegration; +}; + +#endif // WAYLANDWINDOWMANAGERINTEGRATION_H diff --git a/src/compositor/windowmanagerprotocol/windowmanager.xml b/src/compositor/windowmanagerprotocol/windowmanager.xml new file mode 100644 index 000000000..6f0db5b6f --- /dev/null +++ b/src/compositor/windowmanagerprotocol/windowmanager.xml @@ -0,0 +1,87 @@ +<!-- +# /**************************************************************************** +# ** +# ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# ** Contact: Nokia Corporation (qt-info@nokia.com) +# ** +# ** This file is part of qt-compositor. +# ** +# ****************************************************************************/ +--> +<protocol name="wayland_windowmanager"> + + <copyright> + 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 plugins of the Qt Toolkit. + + $QT_BEGIN_LICENSE:LGPL$ + GNU Lesser General Public License Usage + 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. + + GNU General Public License Usage + Alternatively, this file may be used under the terms of the GNU General + Public License version 3.0 as published by the Free Software Foundation + and appearing in the file LICENSE.GPL included in the packaging of this + file. Please review the following information to ensure the GNU General + Public License version 3.0 requirements will be met: + http://www.gnu.org/copyleft/gpl.html. + + Other Usage + Alternatively, this file may be used in accordance with the terms and + conditions contained in a signed written agreement between you and Nokia. + + + + + + $QT_END_LICENSE$ + </copyright> + + <interface name="wl_windowmanager" version="1"> + <request name="map_client_to_process"> + <arg name="processid" type="uint" /> + </request> + <request name="authenticate_with_token"> + <arg name="processid" type="string" /> + </request> + + <!-- informs the client that it is visible/not visible on screen and can therfore stop / need to start rendering. + The client need to implement the handling of this by itself. This means, we cannot enforce the client to obey, + but we can encourage it to do so. --> + <event name="client_onscreen_visibility"> + <arg name="visible" type="int"/> + </event> + + <!-- Sets screen rotation, typically based on accelerometer/orientation sensor reading data --> + <event name="set_screen_rotation"> + <arg name="output" type="object" interface="wl_output"/> + <arg name="rotation" type="int"/> + </event> + + <!--sends a generic property to the client --> + <event name="set_generic_property"> + <arg name="surface" type="object" interface="wl_surface"/> + <arg name="name" type="string"/> + <arg name="value" type="array"/> + </event> + + <!-- update generic property from client to server --> + <request name="update_generic_property"> + <arg name="surface" type="object" interface="wl_surface"/> + <arg name="name" type="string"/> + <arg name="value" type="array"/> + </request> + </interface> +</protocol> diff --git a/src/compositor/windowmanagerprotocol/windowmanagerprotocol.pri b/src/compositor/windowmanagerprotocol/windowmanagerprotocol.pri new file mode 100644 index 000000000..b03b08778 --- /dev/null +++ b/src/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 + + |