diff options
author | Paul Olav Tvete <paul.tvete@qt.io> | 2018-08-15 13:31:21 +0200 |
---|---|---|
committer | Paul Olav Tvete <paul.tvete@qt.io> | 2018-08-16 12:56:52 +0000 |
commit | bc9fc09caf4f638005977281dc57e7d9c99cfddf (patch) | |
tree | 1ab1396a264c28afcc5b260cdc9445c44bb87a27 /examples | |
parent | 70f0f02568e3d577452e45b49deee47cf7d465b3 (diff) | |
download | qtwayland-bc9fc09caf4f638005977281dc57e7d9c99cfddf.tar.gz |
Add mouse and keyboard handling to minimal-cpp example
...and do some other minor cleanups.
Change-Id: I7fe2c70d8b2de37cee5cc114cc0148d31821e10f
Reviewed-by: Johan Helsing <johan.helsing@qt.io>
Diffstat (limited to 'examples')
-rw-r--r-- | examples/wayland/minimal-cpp/compositor.cpp | 105 | ||||
-rw-r--r-- | examples/wayland/minimal-cpp/compositor.h | 25 | ||||
-rw-r--r-- | examples/wayland/minimal-cpp/main.cpp | 3 | ||||
-rw-r--r-- | examples/wayland/minimal-cpp/window.cpp | 46 | ||||
-rw-r--r-- | examples/wayland/minimal-cpp/window.h | 7 |
5 files changed, 168 insertions, 18 deletions
diff --git a/examples/wayland/minimal-cpp/compositor.cpp b/examples/wayland/minimal-cpp/compositor.cpp index e19fb0d6..81b1be26 100644 --- a/examples/wayland/minimal-cpp/compositor.cpp +++ b/examples/wayland/minimal-cpp/compositor.cpp @@ -51,9 +51,12 @@ #include "compositor.h" #include "window.h" -#include <QtWaylandCompositor/qwaylandoutput.h> -#include <QtWaylandCompositor/qwaylandiviapplication.h> -#include <QtWaylandCompositor/qwaylandivisurface.h> +#include <QtWaylandCompositor/QWaylandOutput> +#include <QtWaylandCompositor/QWaylandIviApplication> +#include <QtWaylandCompositor/QWaylandIviSurface> +#include <QtWaylandCompositor/QWaylandSeat> + +#include <QRandomGenerator> #include <QOpenGLFunctions> QOpenGLTexture *View::getTexture() { @@ -62,9 +65,29 @@ QOpenGLTexture *View::getTexture() { return m_texture; } +QPoint View::mapToLocal(const QPoint &globalPos) const +{ + return globalPos - globalPosition(); +} + + +// Normally, an IVI based compositor would have a design where each window has +// a defined position, based on the id. In this example, we just assign a random position. + +void View::initPosition(const QSize &screenSize, const QSize &surfaceSize) +{ + if (m_positionSet) + return; + QRandomGenerator rand(iviId()); + int xrange = qMax(screenSize.width() - surfaceSize.width(), 1); + int yrange = qMax(screenSize.height() - surfaceSize.height(), 1); + setGlobalPosition(QPoint(rand.bounded(xrange), rand.bounded(yrange))); +} + Compositor::Compositor(Window *window) : m_window(window) { + window->setCompositor(this); } Compositor::~Compositor() @@ -74,7 +97,7 @@ Compositor::~Compositor() void Compositor::create() { QWaylandOutput *output = new QWaylandOutput(this, m_window); - QWaylandOutputMode mode(QSize(800, 600), 60000); + QWaylandOutputMode mode(m_window->size(), 60000); output->addMode(mode, true); QWaylandCompositor::create(); output->setCurrentMode(mode); @@ -83,11 +106,84 @@ void Compositor::create() connect(m_iviApplication, &QWaylandIviApplication::iviSurfaceCreated, this, &Compositor::onIviSurfaceCreated); } +View *Compositor::viewAt(const QPoint &position) +{ + // Since views are stored in painting order (back to front), we have to iterate backwards + // to find the topmost view at a given point. + for (auto it = m_views.crbegin(); it != m_views.crend(); ++it) { + View *view = *it; + if (view->globalGeometry().contains(position)) + return view; + } + return nullptr; +} + +void Compositor::raise(View *view) +{ + m_views.removeAll(view); + m_views.append(view); + defaultSeat()->setKeyboardFocus(view->surface()); + triggerRender(); +} + +static inline QPoint mapToView(const View *view, const QPoint &position) +{ + return view ? view->mapToLocal(position) : position; +} + +void Compositor::handleMousePress(const QPoint &position, Qt::MouseButton button) +{ + if (!m_mouseView) { + if (m_mouseView = viewAt(position)) + raise(m_mouseView); + } + auto *seat = defaultSeat(); + seat->sendMouseMoveEvent(m_mouseView, mapToView(m_mouseView, position)); + seat->sendMousePressEvent(button); +} + +void Compositor::handleMouseRelease(const QPoint &position, Qt::MouseButton button, Qt::MouseButtons buttons) +{ + auto *seat = defaultSeat(); + seat->sendMouseMoveEvent(m_mouseView, mapToView(m_mouseView, position)); + seat->sendMouseReleaseEvent(button); + + if (buttons == Qt::NoButton) { + View *newView = viewAt(position); + if (newView != m_mouseView) + seat->sendMouseMoveEvent(newView, mapToView(newView, position)); + m_mouseView = nullptr; + } +} + +void Compositor::handleMouseMove(const QPoint &position) +{ + View *view = m_mouseView ? m_mouseView.data() : viewAt(position); + defaultSeat()->sendMouseMoveEvent(view, mapToView(view, position)); +} + +void Compositor::handleMouseWheel(Qt::Orientation orientation, int delta) +{ + defaultSeat()->sendMouseWheelEvent(orientation, delta); +} + +void Compositor::handleKeyPress(quint32 nativeScanCode) +{ + defaultSeat()->sendKeyPressEvent(nativeScanCode); +} + +void Compositor::handleKeyRelease(quint32 nativeScanCode) +{ + defaultSeat()->sendKeyReleaseEvent(nativeScanCode); +} + + void Compositor::onIviSurfaceCreated(QWaylandIviSurface *iviSurface) { View *view = new View(iviSurface->iviId()); view->setSurface(iviSurface->surface()); view->setOutput(outputFor(m_window)); + m_views << view; connect(view, &QWaylandView::surfaceDestroyed, this, &Compositor::viewSurfaceDestroyed); connect(iviSurface->surface(), &QWaylandSurface::redraw, this, &Compositor::triggerRender); @@ -103,6 +199,7 @@ void Compositor::viewSurfaceDestroyed() View *view = qobject_cast<View*>(sender()); m_views.removeAll(view); delete view; + triggerRender(); } void Compositor::triggerRender() diff --git a/examples/wayland/minimal-cpp/compositor.h b/examples/wayland/minimal-cpp/compositor.h index e804ac02..f0642132 100644 --- a/examples/wayland/minimal-cpp/compositor.h +++ b/examples/wayland/minimal-cpp/compositor.h @@ -54,6 +54,7 @@ #include <QtWaylandCompositor/QWaylandCompositor> #include <QtWaylandCompositor/QWaylandSurface> #include <QtWaylandCompositor/QWaylandView> +#include <QtCore/QPointer> QT_BEGIN_NAMESPACE @@ -66,12 +67,23 @@ class View : public QWaylandView { Q_OBJECT public: - View(int iviId) : m_iviId(iviId) {} + explicit View(int iviId) : m_iviId(iviId) {} QOpenGLTexture *getTexture(); int iviId() const { return m_iviId; } + + QRect globalGeometry() const { return QRect(globalPosition(), surface()->size()); } + void setGlobalPosition(const QPoint &globalPos) { m_pos = globalPos; m_positionSet = true; } + QPoint globalPosition() const { return m_pos; } + QPoint mapToLocal(const QPoint &globalPos) const; + QSize size() const { return surface() ? surface()->size() : QSize(); } + + void initPosition(const QSize &screenSize, const QSize &surfaceSize); + private: friend class Compositor; QOpenGLTexture *m_texture = nullptr; + bool m_positionSet = false; + QPoint m_pos; int m_iviId; }; @@ -84,6 +96,16 @@ public: void create() override; QList<View*> views() const { return m_views; } + View *viewAt(const QPoint &position); + void raise(View *view); + + void handleMousePress(const QPoint &position, Qt::MouseButton button); + void handleMouseRelease(const QPoint &position, Qt::MouseButton button, Qt::MouseButtons buttons); + void handleMouseMove(const QPoint &position); + void handleMouseWheel(Qt::Orientation orientation, int delta); + + void handleKeyPress(quint32 nativeScanCode); + void handleKeyRelease(quint32 nativeScanCode); void startRender(); void endRender(); @@ -98,6 +120,7 @@ private: Window *m_window = nullptr; QWaylandIviApplication *m_iviApplication = nullptr; QList<View*> m_views; + QPointer<View> m_mouseView; }; QT_END_NAMESPACE diff --git a/examples/wayland/minimal-cpp/main.cpp b/examples/wayland/minimal-cpp/main.cpp index f2b00e88..0b0b4b9d 100644 --- a/examples/wayland/minimal-cpp/main.cpp +++ b/examples/wayland/minimal-cpp/main.cpp @@ -57,10 +57,9 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); Window window; + window.resize(800,600); Compositor compositor(&window); - window.setCompositor(&compositor); compositor.create(); - window.resize(800,600); window.show(); return app.exec(); diff --git a/examples/wayland/minimal-cpp/window.cpp b/examples/wayland/minimal-cpp/window.cpp index c43255df..673e15fd 100644 --- a/examples/wayland/minimal-cpp/window.cpp +++ b/examples/wayland/minimal-cpp/window.cpp @@ -55,7 +55,7 @@ #include <QMatrix4x4> #include <QOpenGLFunctions> #include <QOpenGLTexture> -#include <QRandomGenerator> +#include <QMouseEvent> Window::Window() { @@ -70,14 +70,6 @@ void Window::initializeGL() m_textureBlitter.create(); } -static QPoint sillyrandom(int seed, QSize screenSize, QSize surfaceSize) -{ - QRandomGenerator rand(seed); - int xrange = qMax(screenSize.width() - surfaceSize.width(), 200); - int yrange = qMax(screenSize.height() - surfaceSize.height(), 200); - return QPoint(rand.bounded(xrange), rand.bounded(yrange)); -} - void Window::paintGL() { m_compositor->startRender(); @@ -91,7 +83,8 @@ void Window::paintGL() functions->glEnable(GL_BLEND); functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Q_FOREACH (View *view, m_compositor->views()) { + const auto views = m_compositor->views(); + for (View *view : views) { auto texture = view->getTexture(); if (!texture) continue; @@ -103,7 +96,8 @@ void Window::paintGL() QWaylandSurface *surface = view->surface(); if (surface && surface->hasContent()) { QSize s = surface->size(); - QPointF pos = sillyrandom(view->iviId(), size(), s); + view->initPosition(size(), s); + QPointF pos = view->globalPosition(); QRectF surfaceGeometry(pos, s); QOpenGLTextureBlitter::Origin surfaceOrigin = view->currentBuffer().origin() == QWaylandSurface::OriginTopLeft @@ -116,3 +110,33 @@ void Window::paintGL() m_textureBlitter.release(); m_compositor->endRender(); } + +void Window::mousePressEvent(QMouseEvent *event) +{ + m_compositor->handleMousePress(event->localPos().toPoint(), event->button()); +} + +void Window::mouseReleaseEvent(QMouseEvent *event) +{ + m_compositor->handleMouseRelease(event->localPos().toPoint(), event->button(), event->buttons()); +} + +void Window::mouseMoveEvent(QMouseEvent *event) +{ + m_compositor->handleMouseMove(event->localPos().toPoint()); +} + +void Window::wheelEvent(QWheelEvent *event) +{ + m_compositor->handleMouseWheel(event->orientation(), event->delta()); +} + +void Window::keyPressEvent(QKeyEvent *e) +{ + m_compositor->handleKeyPress(e->nativeScanCode()); +} + +void Window::keyReleaseEvent(QKeyEvent *e) +{ + m_compositor->handleKeyRelease(e->nativeScanCode()); +} diff --git a/examples/wayland/minimal-cpp/window.h b/examples/wayland/minimal-cpp/window.h index 2a7a1109..1a106da9 100644 --- a/examples/wayland/minimal-cpp/window.h +++ b/examples/wayland/minimal-cpp/window.h @@ -67,6 +67,13 @@ public: protected: void initializeGL() override; void paintGL() override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void wheelEvent(QWheelEvent *) override; + + void keyPressEvent(QKeyEvent *e) override; + void keyReleaseEvent(QKeyEvent *e) override; private: QOpenGLTextureBlitter m_textureBlitter; |