diff options
Diffstat (limited to 'examples/wayland/qwindow-compositor/compositorwindow.cpp')
-rw-r--r-- | examples/wayland/qwindow-compositor/compositorwindow.cpp | 220 |
1 files changed, 206 insertions, 14 deletions
diff --git a/examples/wayland/qwindow-compositor/compositorwindow.cpp b/examples/wayland/qwindow-compositor/compositorwindow.cpp index 7d855016f..a902a7d0d 100644 --- a/examples/wayland/qwindow-compositor/compositorwindow.cpp +++ b/examples/wayland/qwindow-compositor/compositorwindow.cpp @@ -39,23 +39,215 @@ ****************************************************************************/ #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> + +CompositorWindow::CompositorWindow() + : m_backgroundTexture(0) + , m_compositor(0) + , m_grabState(NoGrab) + , m_dragIconView(0) +{ +} + +void CompositorWindow::setCompositor(WindowCompositor *comp) { + m_compositor = comp; + connect(m_compositor, &WindowCompositor::startMove, this, &CompositorWindow::startMove); + connect(m_compositor, &WindowCompositor::startResize, this, &CompositorWindow::startResize); + connect(m_compositor, &WindowCompositor::dragStarted, this, &CompositorWindow::startDrag); + connect(m_compositor, &WindowCompositor::frameOffset, this, &CompositorWindow::setFrameOffset); +} + +void CompositorWindow::initializeGL() +{ + QImage backgroundImage = QImage(QLatin1String(":/background.jpg")); + m_backgroundTexture = new QOpenGLTexture(backgroundImage, QOpenGLTexture::DontGenerateMipMaps); + m_backgroundTexture->setMinificationFilter(QOpenGLTexture::Nearest); + 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()) { + if (view->isCursor()) + continue; + GLuint textureId = view->getTexture(); + QWaylandSurface *surface = view->surface(); + if (surface && surface->isMapped()) { + QSize s = surface->size(); + if (!s.isEmpty()) { + QRectF surfaceGeometry(view->position(), 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(); +} + +WindowCompositorView *CompositorWindow::viewAt(const QPointF &point) +{ + WindowCompositorView *ret = 0; + Q_FOREACH (WindowCompositorView *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)) + ret = view; + } + return ret; +} + +void CompositorWindow::startMove() +{ + m_grabState = MoveGrab; +} + +void CompositorWindow::startResize(int edge) +{ + m_initialSize = m_mouseView->surface()->size(); + m_grabState = ResizeGrab; + m_resizeEdge = edge; +} + +void CompositorWindow::startDrag(WindowCompositorView *dragIcon) +{ + m_grabState = DragGrab; + m_dragIconView = dragIcon; + m_compositor->raise(dragIcon); +} + +void CompositorWindow::setFrameOffset(const QPoint &offset) +{ + if (m_mouseView) + m_mouseView->setPosition(m_mouseView->position() + offset); +} + +void CompositorWindow::mousePressEvent(QMouseEvent *e) +{ + if (mouseGrab()) + return; + if (m_mouseView.isNull()) { + m_mouseView = viewAt(e->localPos()); + if (!m_mouseView) { + m_compositor->closePopups(); + return; + } + if (e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::MetaModifier) + m_grabState = MoveGrab; //start move + else + m_compositor->raise(m_mouseView); + m_initialMousePos = e->localPos(); + m_mouseOffset = e->localPos() - m_mouseView->position(); + + 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) +{ + if (!mouseGrab()) + sendMouseEvent(e, m_mouseView); + if (e->buttons() == Qt::NoButton) { + if (m_grabState == DragGrab) { + WindowCompositorView *view = viewAt(e->localPos()); + m_compositor->handleDrag(view, e); + } + m_mouseView = 0; + m_grabState = NoGrab; + } +} + +void CompositorWindow::mouseMoveEvent(QMouseEvent *e) +{ + switch (m_grabState) { + case NoGrab: { + WindowCompositorView *view = m_mouseView ? m_mouseView.data() : viewAt(e->localPos()); + sendMouseEvent(e, view); + if (!view) + setCursor(Qt::ArrowCursor); + } + break; + case MoveGrab: { + m_mouseView->setPosition(e->localPos() - m_mouseOffset); + update(); + } + break; + case ResizeGrab: { + QPoint delta = (e->localPos() - m_initialMousePos).toPoint(); + m_compositor->handleResize(m_mouseView, m_initialSize, delta, m_resizeEdge); + } + break; + case DragGrab: { + WindowCompositorView *view = viewAt(e->localPos()); + m_compositor->handleDrag(view, e); + if (m_dragIconView) { + m_dragIconView->setPosition(e->localPos()); + update(); + } + } + break; + } +} + +void CompositorWindow::sendMouseEvent(QMouseEvent *e, WindowCompositorView *target) +{ + if (!target) + return; + + QPointF mappedPos = e->localPos() - target->position(); + 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()); } |