diff options
author | Paul Olav Tvete <paul.tvete@theqtcompany.com> | 2015-09-10 12:17:45 +0200 |
---|---|---|
committer | Paul Olav Tvete <paul.tvete@theqtcompany.com> | 2015-09-11 11:38:25 +0000 |
commit | 2deffa537c82e2f21e01dff5c8f5ba283dd06032 (patch) | |
tree | 50a43a5db178a5798b1729aadf601ec416377f9d | |
parent | 12a6bd37916802d06ac331fcbcd487ad6b4fafe6 (diff) | |
download | qtwayland-2deffa537c82e2f21e01dff5c8f5ba283dd06032.tar.gz |
New window compositor example
Start rewriting the QWindow-based compositor example to use
QOpenGLWindow and QOpenGLTextureBlitter. Also, make a better
separation between the compositor logic and the GUI.
Not yet feature complete.
Change-Id: I3e4fd839c79bc9dbf055c3a0f9939a68392deea9
Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
-rw-r--r-- | examples/wayland/qwindow-compositor/compositorwindow.cpp | 132 | ||||
-rw-r--r-- | examples/wayland/qwindow-compositor/compositorwindow.h | 47 | ||||
-rw-r--r-- | examples/wayland/qwindow-compositor/main.cpp | 33 | ||||
-rw-r--r-- | examples/wayland/qwindow-compositor/qwindow-compositor.pro | 13 | ||||
-rw-r--r-- | examples/wayland/qwindow-compositor/qwindowcompositor.cpp | 522 | ||||
-rw-r--r-- | examples/wayland/qwindow-compositor/qwindowcompositor.h | 130 | ||||
-rw-r--r-- | examples/wayland/qwindow-compositor/textureblitter.cpp | 166 | ||||
-rw-r--r-- | examples/wayland/qwindow-compositor/windowcompositor.cpp | 185 | ||||
-rw-r--r-- | examples/wayland/qwindow-compositor/windowcompositor.h (renamed from examples/wayland/qwindow-compositor/textureblitter.h) | 68 |
9 files changed, 397 insertions, 899 deletions
diff --git a/examples/wayland/qwindow-compositor/compositorwindow.cpp b/examples/wayland/qwindow-compositor/compositorwindow.cpp index 7d855016..95ab1c63 100644 --- a/examples/wayland/qwindow-compositor/compositorwindow.cpp +++ b/examples/wayland/qwindow-compositor/compositorwindow.cpp @@ -39,23 +39,127 @@ ****************************************************************************/ #include "compositorwindow.h" -#include <QTouchEvent> -CompositorWindow::CompositorWindow(const QSurfaceFormat &format, const QRect &geometry) - : m_format(format) +#include <QMouseEvent> +#include <QOpenGLWindow> +#include <QOpenGLTexture> +#include <QOpenGLFunctions> +#include <QMatrix4x4> + +#include "windowcompositor.h" +#include <QtWaylandCompositor/qwaylandinput.h> + +void CompositorWindow::initializeGL() +{ + QImage backgroundImage = QImage(QLatin1String(":/background.jpg")); + m_backgroundTexture = new QOpenGLTexture(backgroundImage, QOpenGLTexture::DontGenerateMipMaps); + m_backgroundImageSize = backgroundImage.size(); + m_textureBlitter.create(); +} + +void CompositorWindow::drawBackground() +{ + for (int y = 0; y < height(); y += m_backgroundImageSize.height()) { + for (int x = 0; x < width(); x += m_backgroundImageSize.width()) { + QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(QRect(QPoint(x,y), m_backgroundImageSize), QRect(QPoint(0,0), size())); + m_textureBlitter.blit(m_backgroundTexture->textureId(), + targetTransform, + QOpenGLTextureBlitter::OriginTopLeft); + } + } +} + +void CompositorWindow::paintGL() +{ + m_compositor->startRender(); + QOpenGLFunctions *functions = context()->functions(); + functions->glClearColor(1.f, .6f, .0f, 0.5f); + functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + m_textureBlitter.bind(); + drawBackground(); + + functions->glEnable(GL_BLEND); + functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + Q_FOREACH (WindowCompositorView *view, m_compositor->views()) { + GLuint textureId = view->getTexture(); + QWaylandSurface *surface = view->surface(); + if (surface && surface->isMapped()) { + QSize s = surface->size(); + if (!s.isEmpty()) { + QRectF surfaceGeometry(view->requestedPosition(), s); + //qDebug() << surface << surface->views().first() << view << s; + QOpenGLTextureBlitter::Origin surfaceOrigin = + view->currentBuffer().origin() == QWaylandSurface::OriginTopLeft + ? QOpenGLTextureBlitter::OriginTopLeft + : QOpenGLTextureBlitter::OriginBottomLeft; + QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(surfaceGeometry, QRect(QPoint(), size())); + m_textureBlitter.blit(textureId, targetTransform, surfaceOrigin); + } + } + } + functions->glDisable(GL_BLEND); + + m_textureBlitter.release(); + m_compositor->endRender(); +} + +void resizeGL(int w, int h) +{ +} + +WindowCompositorView *CompositorWindow::viewAt(const QPointF &point) +{ + WindowCompositorView *ret = 0; + Q_FOREACH (WindowCompositorView *view, m_compositor->views()) { + QPointF topLeft = view->requestedPosition(); + QWaylandSurface *surface = view->surface(); + QRectF geo(topLeft, surface->size()); + if (geo.contains(point)) + ret = view; + } + return ret; +} + +void CompositorWindow::mousePressEvent(QMouseEvent *e) +{ + if (m_mouseView.isNull()) { + m_mouseView = viewAt(e->localPos()); + QMouseEvent moveEvent(QEvent::MouseMove, e->localPos(), e->globalPos(), Qt::NoButton, Qt::NoButton, e->modifiers()); + sendMouseEvent(&moveEvent, m_mouseView); + } + sendMouseEvent(e, m_mouseView); +} + +void CompositorWindow::mouseReleaseEvent(QMouseEvent *e) +{ + sendMouseEvent(e, m_mouseView); + if (e->buttons() == Qt::NoButton) + m_mouseView = 0; +} + +void CompositorWindow::mouseMoveEvent(QMouseEvent *e) +{ + sendMouseEvent(e, m_mouseView); +} + +void CompositorWindow::sendMouseEvent(QMouseEvent *e, QWaylandView *target) +{ + if (!target) + return; + + QPointF mappedPos = e->localPos() - target->requestedPosition(); + QMouseEvent viewEvent(e->type(), mappedPos, e->localPos(), e->button(), e->buttons(), e->modifiers()); + m_compositor->handleMouseEvent(target, &viewEvent); +} + +void CompositorWindow::keyPressEvent(QKeyEvent *e) { - setSurfaceType(QWindow::OpenGLSurface); - setGeometry(geometry); - setFormat(format); - create(); - m_context = new QOpenGLContext; - m_context->setFormat(format); - m_context->create(); + m_compositor->defaultInputDevice()->sendKeyPressEvent(e->nativeScanCode()); } -void CompositorWindow::touchEvent(QTouchEvent *event) +void CompositorWindow::keyReleaseEvent(QKeyEvent *e) { - // Do not want any automatically synthesized mouse events - // so make sure the touch is always accepted. - event->accept(); + m_compositor->defaultInputDevice()->sendKeyReleaseEvent(e->nativeScanCode()); } diff --git a/examples/wayland/qwindow-compositor/compositorwindow.h b/examples/wayland/qwindow-compositor/compositorwindow.h index 24c50c53..57395d8a 100644 --- a/examples/wayland/qwindow-compositor/compositorwindow.h +++ b/examples/wayland/qwindow-compositor/compositorwindow.h @@ -41,24 +41,47 @@ #ifndef COMPOSITORWINDOW_H #define COMPOSITORWINDOW_H -#include <QWindow> -#include <QOpenGLContext> -#include <QSurfaceFormat> +#include <QOpenGLWindow> +#include <QPointer> +#include <QtGui/private/qopengltextureblitter_p.h> +#include <QtWaylandCompositor/QWaylandView> -class CompositorWindow : public QWindow +QT_BEGIN_NAMESPACE + +class WindowCompositor; +class WindowCompositorView; +class QOpenGLTexture; + +class CompositorWindow : public QOpenGLWindow { public: - CompositorWindow(const QSurfaceFormat &format, const QRect &geometry); - QOpenGLContext* context() { return m_context; } - bool makeCurrent() { return m_context->makeCurrent(this); } - void swapBuffers() { m_context->swapBuffers(this); } - + CompositorWindow() : m_backgroundTexture(0), m_compositor(0) {} + void setCompositor(WindowCompositor *comp) { + m_compositor = comp; + } protected: - void touchEvent(QTouchEvent *event); + void initializeGL() Q_DECL_OVERRIDE; + void paintGL() Q_DECL_OVERRIDE; +// void resizeGL(int w, int h) Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + + void keyPressEvent(QKeyEvent *e); + void keyReleaseEvent(QKeyEvent *e); private: - QOpenGLContext *m_context; - QSurfaceFormat m_format; + WindowCompositorView *viewAt(const QPointF &point); + void drawBackground(); + void sendMouseEvent(QMouseEvent *e, QWaylandView *target); + + QOpenGLTextureBlitter m_textureBlitter; + QSize m_backgroundImageSize; + QOpenGLTexture *m_backgroundTexture; + WindowCompositor *m_compositor; + QPointer<QWaylandView> m_mouseView; }; +QT_END_NAMESPACE + #endif // COMPOSITORWINDOW_H diff --git a/examples/wayland/qwindow-compositor/main.cpp b/examples/wayland/qwindow-compositor/main.cpp index a87d03f4..7f939a03 100644 --- a/examples/wayland/qwindow-compositor/main.cpp +++ b/examples/wayland/qwindow-compositor/main.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the Qt Compositor. +** This file is part of the examples of the Qt Wayland module ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: @@ -38,37 +38,20 @@ ** ****************************************************************************/ -#include "compositorwindow.h" -#include "qwindowcompositor.h" - #include <QGuiApplication> -#include <QStringList> -#include <QScreen> -#include <QSurfaceFormat> +#include "compositorwindow.h" +#include "windowcompositor.h" int main(int argc, char *argv[]) { - // Enable the following to have touch events generated from mouse events. - // Very handy for testing touch event delivery without a real touch device. - // QGuiApplication::setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true); - QGuiApplication app(argc, argv); - QScreen *screen = QGuiApplication::primaryScreen(); - QRect screenGeometry = screen->availableGeometry(); - - QSurfaceFormat format; - format.setDepthBufferSize(16); - format.setStencilBufferSize(8); - - QRect geom = screenGeometry; - if (QCoreApplication::arguments().contains(QLatin1String("-nofullscreen"))) - geom = QRect(screenGeometry.width() / 4, screenGeometry.height() / 4, - screenGeometry.width() / 2, screenGeometry.height() / 2); - CompositorWindow window(format, geom); - QWindowCompositor compositor(&window); - compositor.create(); + CompositorWindow window; + window.resize(1500,800); + WindowCompositor comp(&window); + window.setCompositor(&comp); + comp.create(); window.show(); return app.exec(); diff --git a/examples/wayland/qwindow-compositor/qwindow-compositor.pro b/examples/wayland/qwindow-compositor/qwindow-compositor.pro index a924cfd6..994276d9 100644 --- a/examples/wayland/qwindow-compositor/qwindow-compositor.pro +++ b/examples/wayland/qwindow-compositor/qwindow-compositor.pro @@ -1,25 +1,18 @@ QT += gui gui-private core-private waylandcompositor waylandcompositor-private LIBS += -L ../../lib -#include (../../src/qt-compositor/qt-compositor.pri) HEADERS += \ compositorwindow.h \ - qwindowcompositor.h \ - textureblitter.h + windowcompositor.h SOURCES += main.cpp \ compositorwindow.cpp \ - qwindowcompositor.cpp \ - textureblitter.cpp + windowcompositor.cpp -# to make QtCompositor/... style includes working without installing +# to make QtWaylandCompositor/... style includes working without installing INCLUDEPATH += $$PWD/../../include -# if you want to compile QtCompositor as part of the application -# instead of linking to it, remove the QT += waylandcompositor and uncomment -# the following line -#include(../../src/compositor/compositor.pri) RESOURCES += qwindow-compositor.qrc diff --git a/examples/wayland/qwindow-compositor/qwindowcompositor.cpp b/examples/wayland/qwindow-compositor/qwindowcompositor.cpp deleted file mode 100644 index c8502ec8..00000000 --- a/examples/wayland/qwindow-compositor/qwindowcompositor.cpp +++ /dev/null @@ -1,522 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Compositor. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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 The Qt Company Ltd 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwindowcompositor.h" - -#include <QMouseEvent> -#include <QKeyEvent> -#include <QTouchEvent> -#include <QOpenGLFunctions> -#include <QOpenGLTexture> -#include <QGuiApplication> -#include <QCursor> -#include <QPixmap> -#include <QLinkedList> -#include <QScreen> -#include <QPainter> - -#include <QtWaylandCompositor/qwaylandinput.h> -#include <QtWaylandCompositor/qwaylandbufferref.h> -#include <QtWaylandCompositor/qwaylandview.h> -#include <QtWaylandCompositor/qwaylandoutput.h> -#include <QtWaylandCompositor/qwaylandoutputspace.h> - -#include <QtWaylandCompositor/QWaylandShellSurface> -#include <QtWaylandCompositor/private/qwlextendedsurface_p.h> - -QT_BEGIN_NAMESPACE - -class Surface : public QWaylandSurface -{ -public: - Surface(QWaylandCompositor *compositor, QWaylandClient *client, uint id, int version) - : QWaylandSurface(compositor, client, id, version) - , shellSurface(Q_NULLPTR) - , extSurface(Q_NULLPTR) - , hasSentOnScreen(false) - { } - - QWaylandShellSurface *shellSurface; - QtWayland::ExtendedSurface *extSurface; - bool hasSentOnScreen; -}; - -class SurfaceView : public QWaylandView -{ -public: - SurfaceView() - : QWaylandView(Q_NULLPTR) - , m_texture(0) - {} - - ~SurfaceView() - { - if (m_texture) - glDeleteTextures(1, &m_texture); - } - - GLuint updateTextureToCurrentBuffer() - { - if (advance()) { - if (m_texture) - glDeleteTextures(1, &m_texture); - - glGenTextures(1, &m_texture); - glBindTexture(GL_TEXTURE_2D, m_texture); - currentBuffer().bindToTexture(); - } - return m_texture; - } - -private: - GLuint m_texture; -}; - -QWindowCompositor::QWindowCompositor(CompositorWindow *window) - : QWaylandCompositor() - , m_window(window) - , m_backgroundTexture(0) - , m_textureBlitter(0) - , m_renderScheduler(this) - , m_draggingWindow(0) - , m_dragKeyIsPressed(false) - , m_cursorHotspotX(0) - , m_cursorHotspotY(0) - , m_modifiers(Qt::NoModifier) - , m_shell(new QWaylandShell(this)) -{ - m_window->makeCurrent(); - - m_textureBlitter = new TextureBlitter(); - m_backgroundImage = makeBackgroundImage(QLatin1String(":/background.jpg")); - - QOpenGLFunctions *functions = m_window->context()->functions(); - functions->glGenFramebuffers(1, &m_surface_fbo); - - connect(m_shell, &QWaylandShell::createShellSurface, this, &QWindowCompositor::onCreateShellSurface); - - QtWayland::SurfaceExtensionGlobal *extSurfGlob = new QtWayland::SurfaceExtensionGlobal(this); - connect(extSurfGlob, &QtWayland::SurfaceExtensionGlobal::extendedSurfaceReady, this, &QWindowCompositor::extendedSurfaceCreated); - -} - -QWindowCompositor::~QWindowCompositor() -{ - delete m_textureBlitter; -} - -void QWindowCompositor::create() -{ - QWaylandCompositor::create(); - - new QWaylandOutput(defaultOutputSpace(), m_window); - - m_renderScheduler.setSingleShot(true); - connect(&m_renderScheduler, &QTimer::timeout, this, &QWindowCompositor::render); - connect(this, &QWaylandCompositor::createSurface, this, &QWindowCompositor::onCreateSurface); - connect(this, &QWaylandCompositor::surfaceCreated, this, &QWindowCompositor::onSurfaceCreated); - connect(defaultInputDevice(), &QWaylandInputDevice::cursorSurfaceRequest, this, &QWindowCompositor::adjustCursorSurface); - - m_window->installEventFilter(this); - - setRetainedSelectionEnabled(true); -} - -QImage QWindowCompositor::makeBackgroundImage(const QString &fileName) -{ - Q_ASSERT(m_window); - - int width = m_window->width(); - int height = m_window->height(); - QImage baseImage(fileName); - QImage patternedBackground(width, height, baseImage.format()); - QPainter painter(&patternedBackground); - - QSize imageSize = baseImage.size(); - for (int y = 0; y < height; y += imageSize.height()) { - for (int x = 0; x < width; x += imageSize.width()) { - painter.drawImage(x, y, baseImage); - } - } - - return patternedBackground; -} - -void QWindowCompositor::ensureKeyboardFocusSurface(QWaylandSurface *oldSurface) -{ - QWaylandSurface *kbdFocus = defaultInputDevice()->keyboardFocus(); - if (kbdFocus == oldSurface || !kbdFocus) - defaultInputDevice()->setKeyboardFocus(m_visibleSurfaces.isEmpty() ? 0 : m_visibleSurfaces.last()); -} - -void QWindowCompositor::surfaceDestroyed() -{ - QWaylandSurface *surface = static_cast<QWaylandSurface *>(sender()); - ensureKeyboardFocusSurface(surface); - m_renderScheduler.start(0); -} - -void QWindowCompositor::surfaceMappedChanged() -{ - QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); - if (surface->isMapped()) - surfaceMapped(surface); - else - surfaceUnmapped(surface); -} -void QWindowCompositor::surfaceMapped(QWaylandSurface *surface) -{ - Q_ASSERT(!m_visibleSurfaces.contains(surface)); - QWaylandShellSurface *shellSurface = QWaylandShellSurface::findIn(surface); - QPoint pos; - if (!shellSurface || (shellSurface->surfaceType() != QWaylandShellSurface::Popup)) { - uint px = 0; - uint py = 0; - if (!QCoreApplication::arguments().contains(QLatin1String("-stickytopleft"))) { - px = 1 + (qrand() % (m_window->width() - surface->size().width() - 2)); - py = 1 + (qrand() % (m_window->height() - surface->size().height() - 2)); - } - pos = QPoint(px, py); - QWaylandView *view = surface->views().first(); - view->setRequestedPosition(pos); - } - if (shellSurface && shellSurface->surfaceType() == QWaylandShellSurface::Popup) { - QWaylandView *view = shellSurface->view(); - view->setRequestedPosition(shellSurface->transientParent()->views().first()->requestedPosition() + shellSurface->transientOffset()); - } - - m_visibleSurfaces.append(surface); - - if (!surface->isCursorSurface()) - defaultInputDevice()->setKeyboardFocus(surface); - - m_renderScheduler.start(0); -} - -void QWindowCompositor::surfaceUnmapped(QWaylandSurface *surface) -{ - m_visibleSurfaces.removeOne(surface); - - ensureKeyboardFocusSurface(surface); - m_renderScheduler.start(0); -} - -void QWindowCompositor::surfaceCommittedSlot() -{ - QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); - surfaceCommitted(surface); -} - -void QWindowCompositor::surfacePosChanged() -{ - m_renderScheduler.start(0); -} - -void QWindowCompositor::surfaceCommitted(QWaylandSurface *surface) -{ - Q_UNUSED(surface) - m_renderScheduler.start(0); -} - -void QWindowCompositor::onCreateSurface(QWaylandClient *client, uint id, int version) -{ - new Surface(this, client, id, version); -} - -void QWindowCompositor::onSurfaceCreated(QWaylandSurface *surface) -{ - connect(surface, &QWaylandSurface::surfaceDestroyed, this, &QWindowCompositor::surfaceDestroyed); - connect(surface, &QWaylandSurface::mappedChanged, this, &QWindowCompositor::surfaceMappedChanged); - connect(surface, &QWaylandSurface::redraw, this, &QWindowCompositor::surfaceCommittedSlot); -} - -void QWindowCompositor::onCreateShellSurface(QWaylandSurface *s, QWaylandClient *client, uint id) -{ - Surface *surface = static_cast<Surface *>(s); - SurfaceView *newView = new SurfaceView(); - newView->setSurface(surface); - newView->setOutput(output(m_window)); - QWaylandShellSurface *shellSurface = new QWaylandShellSurface(m_shell, surface, newView, client, id); - surface->shellSurface = shellSurface; - m_renderScheduler.start(0); -} - -void QWindowCompositor::extendedSurfaceCreated(QtWayland::ExtendedSurface *extendedSurface, QWaylandSurface *surface) -{ - Surface *s = static_cast<Surface *>(surface); - Q_ASSERT(!s->extSurface); - s->extSurface = extendedSurface; -} - -void QWindowCompositor::updateCursor(bool hasBuffer) -{ - Q_UNUSED(hasBuffer) - if (!m_cursorView.surface()) - return; - - m_cursorView.advance(); - - QImage image = m_cursorView.currentBuffer().image(); - - QCursor cursor(QPixmap::fromImage(image), m_cursorHotspotX, m_cursorHotspotY); - static bool cursorIsSet = false; - if (cursorIsSet) { - QGuiApplication::changeOverrideCursor(cursor); - } else { - QGuiApplication::setOverrideCursor(cursor); - cursorIsSet = true; - } -} - -QPointF QWindowCompositor::toView(QWaylandView *view, const QPointF &pos) const -{ - return pos - view->requestedPosition(); -} - -void QWindowCompositor::adjustCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY) -{ - if ((m_cursorView.surface() != surface)) { - if (m_cursorView.surface()) - disconnect(m_cursorView.surface(), &QWaylandSurface::configure, this, &QWindowCompositor::updateCursor); - if (surface) - connect(surface, &QWaylandSurface::configure, this, &QWindowCompositor::updateCursor); - } - - m_cursorView.setSurface(surface); - m_cursorHotspotX = hotspotX; - m_cursorHotspotY = hotspotY; -} - -QWaylandView *QWindowCompositor::viewAt(const QPointF &point, QPointF *local) -{ - for (int i = m_visibleSurfaces.size() - 1; i >= 0; --i) { - QWaylandSurface *surface = m_visibleSurfaces.at(i); - foreach (QWaylandView *view, surface->views()) { - QRectF geo(view->requestedPosition(), surface->size()); - if (geo.contains(point)) { - if (local) - *local = toView(view, point); - return view; - } - } - } - return 0; -} - -void QWindowCompositor::render() -{ - m_window->makeCurrent(); - defaultOutput()->frameStarted(); - - cleanupGraphicsResources(); - - if (!m_backgroundTexture) - m_backgroundTexture = new QOpenGLTexture(m_backgroundImage, QOpenGLTexture::DontGenerateMipMaps); - - m_textureBlitter->bind(); - // Draw the background image texture - m_textureBlitter->drawTexture(m_backgroundTexture->textureId(), - QRect(QPoint(0, 0), m_backgroundImage.size()), - m_window->size(), - 0, false, true); - - foreach (QWaylandSurface *surface, m_visibleSurfaces) { - if (!surface->isMapped()) - continue; - drawSubSurface(QPoint(), surface); - } - - m_textureBlitter->release(); - defaultOutput()->sendFrameCallbacks(); - - // N.B. Never call glFinish() here as the busylooping with vsync 'feature' of the nvidia binary driver is not desirable. - m_window->swapBuffers(); -} - -void QWindowCompositor::drawSubSurface(const QPoint &offset, QWaylandSurface *s) -{ - Surface *surface = static_cast<Surface *>(s); - SurfaceView *view = Q_NULLPTR; - if (surface->shellSurface && surface->shellSurface->view()) - view = static_cast<SurfaceView *>(surface->shellSurface->view()); - else if (surface->views().size()) - view = static_cast<SurfaceView *>(surface->views().first()); - - if (!view) - return; - - GLuint texture = view->updateTextureToCurrentBuffer(); - bool invert_y = view->currentBuffer().origin() == QWaylandSurface::OriginTopLeft; - QPoint pos = view->requestedPosition().toPoint() + offset; - QRect geo(pos, surface->size()); - bool onscreen = (QRect(QPoint(0, 0), m_window->size()).contains(pos)); - if (surface->extSurface && onscreen != surface->hasSentOnScreen) { - surface->extSurface->sendOnScreenVisibilityChange(onscreen); - surface->hasSentOnScreen = onscreen; - } - - if (surface->isMapped() && onscreen) { - m_textureBlitter->drawTexture(texture, geo, m_window->size(), 0, false, invert_y); - } -} - -bool QWindowCompositor::eventFilter(QObject *obj, QEvent *event) -{ - if (obj != m_window) - return false; - - QWaylandInputDevice *input = defaultInputDevice(); - - switch (event->type()) { - case QEvent::FocusOut: - m_dragKeyIsPressed = false; - case QEvent::Expose: - m_renderScheduler.start(0); - if (m_window->isExposed()) { - // Alt-tabbing away normally results in the alt remaining in - // pressed state in the clients xkb state. Prevent this by sending - // a release. This is not an issue in a "real" compositor but - // is very annoying when running in a regular window on xcb. - Qt::KeyboardModifiers mods = QGuiApplication::queryKeyboardModifiers(); - if (m_modifiers != mods && input->keyboardFocus()) { - Qt::KeyboardModifiers stuckMods = m_modifiers ^ mods; - if (stuckMods & Qt::AltModifier) - input->sendKeyReleaseEvent(64); // native scancode for left alt - m_modifiers = mods; - } - } - break; - case QEvent::MouseButtonPress: { - QPointF local; - QMouseEvent *me = static_cast<QMouseEvent *>(event); - QWaylandView *target = viewAt(me->localPos(), &local); - if (m_dragKeyIsPressed && target) { - m_draggingWindow = target; - m_drag_diff = local; - } else { - if (target && input->keyboardFocus() != target->surface()) { - input->setKeyboardFocus(target->surface()); - m_visibleSurfaces.removeOne(target->surface()); - m_visibleSurfaces.append(target->surface()); - m_renderScheduler.start(0); - } - input->sendMousePressEvent(me->button()); - } - return true; - } - case QEvent::MouseButtonRelease: { - QWaylandView *target = input->mouseFocus(); - if (m_draggingWindow) { - m_draggingWindow = 0; - m_drag_diff = QPointF(); - } else { - QMouseEvent *me = static_cast<QMouseEvent *>(event); - QPointF localPos; - if (target) - localPos = toView(target, me->localPos()); - input->sendMouseReleaseEvent(me->button()); - } - return true; - } - case QEvent::MouseMove: { - QMouseEvent *me = static_cast<QMouseEvent *>(event); - if (m_draggingWindow) { - m_draggingWindow->setRequestedPosition(me->localPos() - m_drag_diff); - m_renderScheduler.start(0); - } else { - QPointF local; - QWaylandView *target = viewAt(me->localPos(), &local); - input->sendMouseMoveEvent(target, local, me->localPos()); - } - break; - } - case QEvent::Wheel: { - QWheelEvent *we = static_cast<QWheelEvent *>(event); - input->sendMouseWheelEvent(we->orientation(), we->delta()); - break; - } - case QEvent::KeyPress: { - QKeyEvent *ke = static_cast<QKeyEvent *>(event); - if (ke->key() == Qt::Key_Meta || ke->key() == Qt::Key_Super_L) { - m_dragKeyIsPressed = true; - } - m_modifiers = ke->modifiers(); - QWaylandSurface *targetSurface = input->keyboardFocus(); - if (targetSurface) - input->sendKeyPressEvent(ke->nativeScanCode()); - break; - } - case QEvent::KeyRelease: { - QKeyEvent *ke = static_cast<QKeyEvent *>(event); - if (ke->key() == Qt::Key_Meta || ke->key() == Qt::Key_Super_L) { - m_dragKeyIsPressed = false; - } - m_modifiers = ke->modifiers(); - QWaylandSurface *targetSurface = input->keyboardFocus(); - if (targetSurface) - input->sendKeyReleaseEvent(ke->nativeScanCode()); - break; - } - case QEvent::TouchBegin: - case QEvent::TouchUpdate: - case QEvent::TouchEnd: - { - QWaylandView *target = 0; - QTouchEvent *te = static_cast<QTouchEvent *>(event); - QList<QTouchEvent::TouchPoint> points = te->touchPoints(); - QPoint pointPos; - if (!points.isEmpty()) { - pointPos = points.at(0).pos().toPoint(); - target = viewAt(pointPos); - } - if (target && target != input->mouseFocus()) - input->sendMouseMoveEvent(target, pointPos, pointPos); - if (input->mouseFocus()) - input->sendFullTouchEvent(te); - break; - } - default: - break; - } - return false; -} - -QT_END_NAMESPACE diff --git a/examples/wayland/qwindow-compositor/qwindowcompositor.h b/examples/wayland/qwindow-compositor/qwindowcompositor.h deleted file mode 100644 index 30ee3323..00000000 --- a/examples/wayland/qwindow-compositor/qwindowcompositor.h +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Compositor. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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 The Qt Company Ltd 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWINDOWCOMPOSITOR_H -#define QWINDOWCOMPOSITOR_H - -#include <QtWaylandCompositor/QWaylandCompositor> -#include <QtWaylandCompositor/QWaylandSurface> -#include <QtWaylandCompositor/QWaylandView> -#include "textureblitter.h" -#include "compositorwindow.h" - -#include <QtGui/private/qopengltexturecache_p.h> -#include <QObject> -#include <QTimer> - -QT_BEGIN_NAMESPACE - -namespace QtWayland { - class ExtendedSurface; -} - -class QWaylandView; -class QWaylandShell; -class QOpenGLTexture; - -class QWindowCompositor : public QWaylandCompositor -{ - Q_OBJECT -public: - QWindowCompositor(CompositorWindow *window); - ~QWindowCompositor(); - - void create() Q_DECL_OVERRIDE; -private slots: - void surfaceMappedChanged(); - void surfaceDestroyed(); - void surfaceCommittedSlot(); - void surfacePosChanged(); - - void render(); - void onCreateSurface(QWaylandClient *client, uint id, int version); - void onSurfaceCreated(QWaylandSurface *surface); - void onCreateShellSurface(QWaylandSurface *s, QWaylandClient *client, uint id); - -protected: - QWaylandSurface *createDefaultSurfaceType() Q_DECL_OVERRIDE; - void surfaceCommitted(QWaylandSurface *surface); - - QWaylandView* viewAt(const QPointF &point, QPointF *local = 0); - - bool eventFilter(QObject *obj, QEvent *event); - QPointF toView(QWaylandView *view, const QPointF &pos) const; - - void adjustCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY); - - void ensureKeyboardFocusSurface(QWaylandSurface *oldSurface); - QImage makeBackgroundImage(const QString &fileName); - -private slots: - void extendedSurfaceCreated(QtWayland::ExtendedSurface *extSurface, QWaylandSurface *surface); - void updateCursor(bool hasBuffer); - -private: - void surfaceMapped(QWaylandSurface *surface); - void surfaceUnmapped(QWaylandSurface *surface); - void drawSubSurface(const QPoint &offset, QWaylandSurface *surface); - - CompositorWindow *m_window; - QImage m_backgroundImage; - QOpenGLTexture *m_backgroundTexture; - QList<QWaylandSurface *> m_visibleSurfaces; - TextureBlitter *m_textureBlitter; - GLuint m_surface_fbo; - QTimer m_renderScheduler; - - //Dragging windows around - QWaylandView *m_draggingWindow; - bool m_dragKeyIsPressed; - QPointF m_drag_diff; - - //Cursor - QWaylandView m_cursorView; - int m_cursorHotspotX; - int m_cursorHotspotY; - - Qt::KeyboardModifiers m_modifiers; - QWaylandShell *m_shell; -}; - -QT_END_NAMESPACE - -#endif // QWINDOWCOMPOSITOR_H diff --git a/examples/wayland/qwindow-compositor/textureblitter.cpp b/examples/wayland/qwindow-compositor/textureblitter.cpp deleted file mode 100644 index a9acfc02..00000000 --- a/examples/wayland/qwindow-compositor/textureblitter.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Compositor. -** -** $QT_BEGIN_LICENSE:BSD$ -** 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 The Qt Company Ltd 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." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "textureblitter.h" - -#include <QtGui/QOpenGLShaderProgram> -#include <QtGui/QOpenGLContext> -#include <QtGui/QOpenGLFunctions> - -QT_BEGIN_NAMESPACE - -TextureBlitter::TextureBlitter() - : m_shaderProgram(new QOpenGLShaderProgram) -{ - static const char *textureVertexProgram = - "uniform highp mat4 matrix;\n" - "attribute highp vec3 vertexCoordEntry;\n" - "attribute highp vec2 textureCoordEntry;\n" - "varying highp vec2 textureCoord;\n" - "void main() {\n" - " textureCoord = textureCoordEntry;\n" - " gl_Position = matrix * vec4(vertexCoordEntry, 1);\n" - "}\n"; - - static const char *textureFragmentProgram = - "uniform sampler2D texture;\n" - "varying highp vec2 textureCoord;\n" - "void main() {\n" - " gl_FragColor = texture2D(texture, textureCoord);\n" - "}\n"; - - //Enable transparent windows - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); - m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); - m_shaderProgram->link(); -} - -TextureBlitter::~TextureBlitter() -{ - delete m_shaderProgram; -} - -void TextureBlitter::bind() -{ - - m_shaderProgram->bind(); - - m_vertexCoordEntry = m_shaderProgram->attributeLocation("vertexCoordEntry"); - m_textureCoordEntry = m_shaderProgram->attributeLocation("textureCoordEntry"); - m_matrixLocation = m_shaderProgram->uniformLocation("matrix"); -} - -void TextureBlitter::release() -{ - m_shaderProgram->release(); -} - -void TextureBlitter::drawTexture(int textureId, const QRectF &targetRect, const QSize &targetSize, int depth, bool targethasInvertedY, bool sourceHasInvertedY) -{ - - glViewport(0,0,targetSize.width(),targetSize.height()); - GLfloat zValue = depth / 1000.0f; - //Set Texture and Vertex coordinates - const GLfloat textureCoordinates[] = { - 0, 0, - 1, 0, - 1, 1, - 0, 1 - }; - - GLfloat x1 = targetRect.left(); - GLfloat x2 = targetRect.right(); - GLfloat y1, y2; - if (targethasInvertedY) { - if (sourceHasInvertedY) { - y1 = targetRect.top(); - y2 = targetRect.bottom(); - } else { - y1 = targetRect.bottom(); - y2 = targetRect.top(); - } - } else { - if (sourceHasInvertedY) { - y1 = targetSize.height() - targetRect.top(); - y2 = targetSize.height() - targetRect.bottom(); - } else { - y1 = targetSize.height() - targetRect.bottom(); - y2 = targetSize.height() - targetRect.top(); - } - } - - const GLfloat vertexCoordinates[] = { - GLfloat(x1), GLfloat(y1), zValue, - GLfloat(x2), GLfloat(y1), zValue, - GLfloat(x2), GLfloat(y2), zValue, - GLfloat(x1), GLfloat(y2), zValue - }; - - //Set matrix to transfrom geometry values into gl coordinate space. - m_transformMatrix.setToIdentity(); - m_transformMatrix.scale( 2.0f / targetSize.width(), 2.0f / targetSize.height() ); - m_transformMatrix.translate(-targetSize.width() / 2.0f, -targetSize.height() / 2.0f); - - //attach the data! - QOpenGLContext *currentContext = QOpenGLContext::currentContext(); - currentContext->functions()->glEnableVertexAttribArray(m_vertexCoordEntry); - currentContext->functions()->glEnableVertexAttribArray(m_textureCoordEntry); - - currentContext->functions()->glVertexAttribPointer(m_vertexCoordEntry, 3, GL_FLOAT, GL_FALSE, 0, vertexCoordinates); - currentContext->functions()->glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates); - m_shaderProgram->setUniformValue(m_matrixLocation, m_transformMatrix); - - glBindTexture(GL_TEXTURE_2D, textureId); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glBindTexture(GL_TEXTURE_2D, 0); - - currentContext->functions()->glDisableVertexAttribArray(m_vertexCoordEntry); - currentContext->functions()->glDisableVertexAttribArray(m_textureCoordEntry); -} - -QT_END_NAMESPACE diff --git a/examples/wayland/qwindow-compositor/windowcompositor.cpp b/examples/wayland/qwindow-compositor/windowcompositor.cpp new file mode 100644 index 00000000..ac637e62 --- /dev/null +++ b/examples/wayland/qwindow-compositor/windowcompositor.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 The Qt Company Ltd 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." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "windowcompositor.h" + +#include <QMouseEvent> +#include <QKeyEvent> +#include <QTouchEvent> + +#include <QtWaylandCompositor/QWaylandOutputSpace> +#include <QtWaylandCompositor/QWaylandShellSurface> +#include <QtWaylandCompositor/qwaylandinput.h> + +#include <QDebug> + +GLuint WindowCompositorView::getTexture() { + if (advance()) { + if (m_texture) + glDeleteTextures(1, &m_texture); + + glGenTextures(1, &m_texture); + glBindTexture(GL_TEXTURE_2D, m_texture); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + currentBuffer().bindToTexture(); + } + return m_texture; +} + +WindowCompositor::WindowCompositor(QWindow *window) + : QWaylandCompositor() + , m_window(window) + , m_shell(new QWaylandShell(this)) +{ + connect(m_shell, &QWaylandShell::createShellSurface, this, &WindowCompositor::onCreateShellSurface); +} + +WindowCompositor::~WindowCompositor() +{ +} + +void WindowCompositor::create() +{ + QWaylandCompositor::create(); + new QWaylandOutput(defaultOutputSpace(), m_window); + + connect(this, &QWaylandCompositor::surfaceCreated, this, &WindowCompositor::onSurfaceCreated); + connect(defaultInputDevice(), &QWaylandInputDevice::cursorSurfaceRequest, this, &WindowCompositor::adjustCursorSurface); +} + +void WindowCompositor::onSurfaceCreated(QWaylandSurface *surface) +{ + qDebug() << "onSurfaceCreated" << surface; + + connect(surface, &QWaylandSurface::surfaceDestroyed, this, &WindowCompositor::surfaceDestroyed); + connect(surface, &QWaylandSurface::mappedChanged, this, &WindowCompositor::surfaceMappedChanged); + connect(surface, &QWaylandSurface::redraw, this, &WindowCompositor::triggerRender); +} + +void WindowCompositor::surfaceMappedChanged() +{ + QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); + qDebug() << "surfaceMappedChanged()" << surface << surface->isMapped(); + if (surface->isMapped()) {\ + if (!surface->isCursorSurface()) + defaultInputDevice()->setKeyboardFocus(surface); + } + triggerRender(); +} + +void WindowCompositor::surfaceDestroyed() +{ + // QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); + qDebug() << "surfaceDestroyed()"; + // Q_FOREACH (QWaylandView *view, surface->views()) { + // int n = m_views.removeAll(static_cast<WindowCompositorView*>(view)); + // qDebug() << n << view; + // } + triggerRender(); +} + +void WindowCompositor::viewSurfaceDestroyed() +{ + WindowCompositorView *view = qobject_cast<WindowCompositorView*>(sender()); + int n = m_views.removeAll(view); + qDebug() << n << view; + delete view; +} + +void WindowCompositor::surfaceCommittedSlot() +{ + QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); + +// qDebug() << "surfaceCommittedSlot()" << surface; + triggerRender(); +} + +void WindowCompositor::onCreateShellSurface(QWaylandSurface *s, QWaylandClient *client, uint id) +{ + qDebug() << "onCreateShellSurface" << s << client << id; + QWaylandSurface *surface = s; + + WindowCompositorView *view = new WindowCompositorView; + view->setSurface(surface); + view->setOutput(output(m_window)); + m_views << view; + connect(view, &QWaylandView::surfaceDestroyed, this, &WindowCompositor::viewSurfaceDestroyed); + connect(view, &QWaylandView::requestedPositionChanged, this, &WindowCompositor::triggerRender); + + QWaylandShellSurface *shellSurface = new QWaylandShellSurface(m_shell, surface, view, client, id); +} + +void WindowCompositor::triggerRender() +{ + m_window->requestUpdate(); +} + +void WindowCompositor::startRender() +{ + defaultOutput()->frameStarted(); + cleanupGraphicsResources(); +} + +void WindowCompositor::endRender() +{ + defaultOutput()->sendFrameCallbacks(); +} + +void WindowCompositor::adjustCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY) +{ + //qDebug() << "adjustCursorSurface" << surface << hotspotY << hotspotY; +} + +void WindowCompositor::handleMouseEvent(QWaylandView *target, QMouseEvent *me) +{ + QWaylandInputDevice *input = defaultInputDevice(); + switch (me->type()) { + case QEvent::MouseButtonPress: + input->sendMousePressEvent(me->button()); + break; + case QEvent::MouseButtonRelease: + input->sendMouseReleaseEvent(me->button()); + break; + case QEvent::MouseMove: + input->sendMouseMoveEvent(target, me->localPos(), me->globalPos()); + default: + break; + } +} diff --git a/examples/wayland/qwindow-compositor/textureblitter.h b/examples/wayland/qwindow-compositor/windowcompositor.h index b46d354e..31ddf737 100644 --- a/examples/wayland/qwindow-compositor/textureblitter.h +++ b/examples/wayland/qwindow-compositor/windowcompositor.h @@ -3,7 +3,7 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the Qt Compositor. +** This file is part of the examples of the Qt Wayland module ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: @@ -38,34 +38,62 @@ ** ****************************************************************************/ -#ifndef TEXTUREBLITTER_H -#define TEXTUREBLITTER_H +#ifndef WINDOWCOMPOSITOR_H +#define WINDOWCOMPOSITOR_H -#include <QtGui/QMatrix4x4> +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandSurface> +#include <QtWaylandCompositor/QWaylandView> +#include <QTimer> QT_BEGIN_NAMESPACE -class QOpenGLShaderProgram; -class TextureBlitter +class QWaylandShell; + +class WindowCompositorView : public QWaylandView { + Q_OBJECT public: - TextureBlitter(); - ~TextureBlitter(); - void bind(); - void release(); - void drawTexture(int textureId, const QRectF &sourceGeometry, - const QSize &targetRect, int depth, - bool targethasInvertedY, bool sourceHasInvertedY); - + WindowCompositorView() : m_texture(0) {} + GLuint getTexture(); private: - QOpenGLShaderProgram *m_shaderProgram; - QMatrix4x4 m_transformMatrix; + GLuint m_texture; +}; + +class WindowCompositor : public QWaylandCompositor +{ + Q_OBJECT +public: + WindowCompositor(QWindow *window); + ~WindowCompositor(); + void create() Q_DECL_OVERRIDE; + + void startRender(); + void endRender(); - int m_matrixLocation; - int m_vertexCoordEntry; - int m_textureCoordEntry; + QList<WindowCompositorView*> views() const { return m_views; } + + void handleMouseEvent(QWaylandView *target, QMouseEvent *me); +protected: + void adjustCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY); + +private slots: + void surfaceMappedChanged(); + void surfaceDestroyed(); + void surfaceCommittedSlot(); + void viewSurfaceDestroyed(); + + void triggerRender(); + + void onSurfaceCreated(QWaylandSurface *surface); + void onCreateShellSurface(QWaylandSurface *s, QWaylandClient *client, uint id); +private: + QWindow *m_window; + QList<WindowCompositorView*> m_views; + QWaylandShell *m_shell; }; + QT_END_NAMESPACE -#endif // TEXTUREBLITTER_H +#endif // WINDOWCOMPOSITOR_H |