From 2240e6c4c1d69189e1369aaf1999a86d13513537 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Tue, 29 Nov 2016 13:27:22 +0100 Subject: Add animations to the C++ example Show how to use setBufferLocked() from C++. Change-Id: I43be7dcf8f44fd80dd0d4977e38a0d8ff3339432 Reviewed-by: Johan Helsing --- examples/wayland/qwindow-compositor/compositor.cpp | 79 ++++++++++++++++++++-- examples/wayland/qwindow-compositor/compositor.h | 31 ++++++++- examples/wayland/qwindow-compositor/window.cpp | 19 +++--- 3 files changed, 110 insertions(+), 19 deletions(-) diff --git a/examples/wayland/qwindow-compositor/compositor.cpp b/examples/wayland/qwindow-compositor/compositor.cpp index 4878c373e..8d0db5258 100644 --- a/examples/wayland/qwindow-compositor/compositor.cpp +++ b/examples/wayland/qwindow-compositor/compositor.cpp @@ -56,13 +56,15 @@ #define GL_TEXTURE_EXTERNAL_OES 0x8D65 #endif -View::View() - : m_textureTarget(GL_TEXTURE_2D) +View::View(Compositor *compositor) + : m_compositor(compositor) + , m_textureTarget(GL_TEXTURE_2D) , m_texture(0) , m_wlShellSurface(nullptr) , m_xdgSurface(nullptr) , m_xdgPopup(nullptr) , m_parentView(nullptr) + , m_animationFactor(1.0) {} QOpenGLTexture *View::getTexture() @@ -70,16 +72,33 @@ QOpenGLTexture *View::getTexture() if (advance()) { QWaylandBufferRef buf = currentBuffer(); m_texture = buf.toOpenGLTexture(); + if (surface()) { + m_size = surface()->size(); + m_origin = buf.origin() == QWaylandSurface::OriginTopLeft + ? QOpenGLTextureBlitter::OriginTopLeft + : QOpenGLTextureBlitter::OriginBottomLeft; + } } return m_texture; } +QOpenGLTextureBlitter::Origin View::textureOrigin() const +{ + return m_origin; +} + +QSize View::size() const +{ + return surface() ? surface()->size() : m_size; +} + bool View::isCursor() const { - return surface()->isCursorSurface(); + return surface() && surface()->isCursorSurface(); } + void View::onXdgSetMaximized() { m_xdgSurface->sendMaximized(output()->geometry().size()); @@ -117,6 +136,44 @@ void View::onOffsetForNextFrame(const QPoint &offset) setPosition(position() + offset); } + +void View::timerEvent(QTimerEvent *event) +{ + if (event->timerId() != m_animationTimer.timerId()) + return; + + m_compositor->triggerRender(); + + if (m_animationCountUp) { + m_animationFactor += .08; + if (m_animationFactor > 1.0) { + m_animationFactor = 1.0; + m_animationTimer.stop(); + emit animationDone(); + } + } else { + m_animationFactor -= .08; + if (m_animationFactor < 0.01) { + m_animationFactor = 0.01; + m_animationTimer.stop(); + emit animationDone(); + } + } +} + +void View::startAnimation(bool countUp) +{ + m_animationCountUp = countUp; + m_animationFactor = countUp ? .1 : 1.0; + m_animationTimer.start(20, this); +} + +void View::cancelAnimation() +{ + m_animationFactor = 1.0; + m_animationTimer.stop(); +} + void View::onXdgUnsetFullscreen() { onXdgUnsetMaximized(); @@ -159,8 +216,7 @@ void Compositor::onSurfaceCreated(QWaylandSurface *surface) connect(surface, &QWaylandSurface::redraw, this, &Compositor::triggerRender); connect(surface, &QWaylandSurface::subsurfacePositionChanged, this, &Compositor::onSubsurfacePositionChanged); - - View *view = new View; + View *view = new View(this); view->setSurface(surface); view->setOutput(outputFor(m_window)); m_views << view; @@ -187,12 +243,22 @@ void Compositor::surfaceDestroyed() } void Compositor::viewSurfaceDestroyed() +{ + View *view = qobject_cast(sender()); + view->setBufferLocked(true); + view->startAnimation(false); + connect(view, &View::animationDone, this, &Compositor::viewAnimationDone); +} + + +void Compositor::viewAnimationDone() { View *view = qobject_cast(sender()); m_views.removeAll(view); delete view; } + View * Compositor::findView(const QWaylandSurface *s) const { Q_FOREACH (View* view, m_views) { @@ -212,6 +278,7 @@ void Compositor::onWlShellSurfaceCreated(QWaylandWlShellSurface *wlShellSurface) View *view = findView(wlShellSurface->surface()); Q_ASSERT(view); view->m_wlShellSurface = wlShellSurface; + view->startAnimation(true); } void Compositor::onXdgSurfaceCreated(QWaylandXdgSurfaceV5 *xdgSurface) @@ -227,6 +294,7 @@ void Compositor::onXdgSurfaceCreated(QWaylandXdgSurfaceV5 *xdgSurface) connect(xdgSurface, &QWaylandXdgSurfaceV5::setFullscreen, view, &View::onXdgSetFullscreen); connect(xdgSurface, &QWaylandXdgSurfaceV5::unsetMaximized, view, &View::onXdgUnsetMaximized); connect(xdgSurface, &QWaylandXdgSurfaceV5::unsetFullscreen, view, &View::onXdgUnsetFullscreen); + view->startAnimation(true); } void Compositor::onXdgPopupRequested(QWaylandSurface *surface, QWaylandSurface *parent, @@ -291,6 +359,7 @@ void Compositor::onSetPopup(QWaylandSeat *seat, QWaylandSurface *parent, const Q View *parentView = findView(parent); if (parentView) view->setPosition(parentView->position() + relativeToParent); + view->cancelAnimation(); } } diff --git a/examples/wayland/qwindow-compositor/compositor.h b/examples/wayland/qwindow-compositor/compositor.h index bf52c8c7e..83a76b80a 100644 --- a/examples/wayland/qwindow-compositor/compositor.h +++ b/examples/wayland/qwindow-compositor/compositor.h @@ -47,6 +47,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -54,33 +55,51 @@ class QWaylandWlShell; class QWaylandWlShellSurface; class QWaylandXdgShellV5; class QOpenGLTexture; +class Compositor; class View : public QWaylandView { Q_OBJECT public: - View(); + View(Compositor *compositor); QOpenGLTexture *getTexture(); + QOpenGLTextureBlitter::Origin textureOrigin() const; QPointF position() const { return m_position; } void setPosition(const QPointF &pos) { m_position = pos; } + QSize size() const; bool isCursor() const; bool hasShell() const { return m_wlShellSurface; } void setParentView(View *parent) { m_parentView = parent; } View *parentView() const { return m_parentView; } QPointF parentPosition() const { return m_parentView ? (m_parentView->position() + m_parentView->parentPosition()) : QPointF(); } - QSize windowSize() { return m_xdgSurface ? m_xdgSurface->windowGeometry().size() : surface()->size(); } + QSize windowSize() { return m_xdgSurface ? m_xdgSurface->windowGeometry().size() : surface() ? surface()->size() : m_size; } QPoint offset() const { return m_offset; } + qreal animationFactor() const {return m_animationFactor; } + void setAnimationFactor(qreal f) {m_animationFactor = f; } + +signals: + void animationDone(); + +protected: + void timerEvent(QTimerEvent *event); + private: friend class Compositor; + Compositor *m_compositor; GLenum m_textureTarget; QOpenGLTexture *m_texture; + QOpenGLTextureBlitter::Origin m_origin; QPointF m_position; + QSize m_size; QWaylandWlShellSurface *m_wlShellSurface; QWaylandXdgSurfaceV5 *m_xdgSurface; QWaylandXdgPopupV5 *m_xdgPopup; View *m_parentView; QPoint m_offset; + qreal m_animationFactor; + QBasicTimer m_animationTimer; + bool m_animationCountUp; public slots: void onXdgSetMaximized(); @@ -88,6 +107,9 @@ public slots: void onXdgSetFullscreen(QWaylandOutput *output); void onXdgUnsetFullscreen(); void onOffsetForNextFrame(const QPoint &offset); + + void startAnimation(bool countUp); + void cancelAnimation(); }; class Compositor : public QWaylandCompositor @@ -119,6 +141,9 @@ signals: void dragStarted(View *dragIcon); void frameOffset(const QPoint &offset); +public slots: + void triggerRender(); + private slots: void surfaceHasContentChanged(); void surfaceDestroyed(); @@ -129,7 +154,6 @@ private slots: void startDrag(); - void triggerRender(); void onSurfaceCreated(QWaylandSurface *surface); void onWlShellSurfaceCreated(QWaylandWlShellSurface *wlShellSurface); @@ -143,6 +167,7 @@ private slots: void onSubsurfacePositionChanged(const QPoint &position); void updateCursor(); + void viewAnimationDone(); private: View *findView(const QWaylandSurface *s) const; QWindow *m_window; diff --git a/examples/wayland/qwindow-compositor/window.cpp b/examples/wayland/qwindow-compositor/window.cpp index 59ef1d56a..fcb5fd474 100644 --- a/examples/wayland/qwindow-compositor/window.cpp +++ b/examples/wayland/qwindow-compositor/window.cpp @@ -129,18 +129,17 @@ void Window::paintGL() m_textureBlitter.bind(currentTarget); } QWaylandSurface *surface = view->surface(); - if (surface && surface->hasContent()) { - QSize s = surface->size(); + if ((surface && surface->hasContent()) || view->isBufferLocked()) { + QSize s = view->size(); if (!s.isEmpty()) { if (m_mouseView == view && m_grabState == ResizeGrab && m_resizeAnchored) view->setPosition(getAnchoredPosition(m_resizeAnchorPosition, m_resizeEdge, s)); QPointF pos = view->position() + view->parentPosition(); QRectF surfaceGeometry(pos, s); - QOpenGLTextureBlitter::Origin surfaceOrigin = - view->currentBuffer().origin() == QWaylandSurface::OriginTopLeft - ? QOpenGLTextureBlitter::OriginTopLeft - : QOpenGLTextureBlitter::OriginBottomLeft; - QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(surfaceGeometry, QRect(QPoint(), size())); + auto surfaceOrigin = view->textureOrigin(); + auto sf = view->animationFactor(); + QRectF targetRect(surfaceGeometry.topLeft() * sf, surfaceGeometry.size() * sf); + QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(targetRect, QRect(QPoint(), size())); m_textureBlitter.blit(texture->textureId(), targetTransform, surfaceOrigin); } } @@ -157,10 +156,8 @@ View *Window::viewAt(const QPointF &point) Q_FOREACH (View *view, m_compositor->views()) { if (view == m_dragIconView) continue; - QPointF topLeft = view->position(); - QWaylandSurface *surface = view->surface(); - QRectF geo(topLeft, surface->size()); - if (geo.contains(point)) + QRectF geom(view->position(), view->size()); + if (geom.contains(point)) ret = view; } return ret; -- cgit v1.2.3