diff options
Diffstat (limited to 'src/plugins/platforms/wasm/qwasmwindow.cpp')
-rw-r--r-- | src/plugins/platforms/wasm/qwasmwindow.cpp | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp new file mode 100644 index 0000000000..0489813929 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmwindow.cpp @@ -0,0 +1,398 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qpa/qwindowsysteminterface.h> +#include <private/qguiapplication_p.h> +#include <QtGui/private/qopenglcontext_p.h> +#include <QtGui/private/qwindow_p.h> +#include <QtGui/qopenglcontext.h> + +#include "qwasmwindow.h" +#include "qwasmscreen.h" +#include "qwasmcompositor.h" +#include "qwasmeventdispatcher.h" + +#include <iostream> + +Q_GUI_EXPORT int qt_defaultDpiX(); + +QT_BEGIN_NAMESPACE + +QWasmWindow::QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore) + : QPlatformWindow(w), + m_window(w), + m_compositor(compositor), + m_backingStore(backingStore) +{ + m_needsCompositor = w->surfaceType() != QSurface::OpenGLSurface; + static int serialNo = 0; + m_winid = ++serialNo; + qWarning("QWasmWindow %p: %p 0x%x\n", this, w, uint(m_winid)); + + m_compositor->addWindow(this); + + // Pure OpenGL windows draw directly using egl, disable the compositor. + m_compositor->setEnabled(w->surfaceType() != QSurface::OpenGLSurface); +} + +QWasmWindow::~QWasmWindow() +{ + m_compositor->removeWindow(this); +} + +void QWasmWindow::initialize() +{ + QRect rect = windowGeometry(); + + QPlatformWindow::setGeometry(rect); + + const QSize minimumSize = windowMinimumSize(); + if (rect.width() > 0 || rect.height() > 0) { + rect.setWidth(qBound(1, rect.width(), 2000)); + rect.setHeight(qBound(1, rect.height(), 2000)); + } else if (minimumSize.width() > 0 || minimumSize.height() > 0) { + rect.setSize(minimumSize); + } + + setWindowState(window()->windowStates()); + setWindowFlags(window()->flags()); + setWindowTitle(window()->title()); + m_hasTitle = window()->flags().testFlag(Qt::WindowTitleHint) && m_needsCompositor; + + if (window()->isTopLevel()) + setWindowIcon(window()->icon()); + m_normalGeometry = rect; +} + +QWasmScreen *QWasmWindow::platformScreen() const +{ + return static_cast<QWasmScreen *>(window()->screen()->handle()); +} + +void QWasmWindow::setGeometry(const QRect &rect) +{ + QRect r = rect; + if (m_needsCompositor) { + int yMin = window()->geometry().top() - window()->frameGeometry().top(); + + if (r.y() < yMin) + r.moveTop(yMin); + } + QWindowSystemInterface::handleGeometryChange(window(), r); + QPlatformWindow::setGeometry(r); + + QWindowSystemInterface::flushWindowSystemEvents(); + invalidate(); +} + +void QWasmWindow::setVisible(bool visible) +{ + QRect newGeom; + + if (visible) { + const bool forceFullScreen = !m_needsCompositor;//make gl apps fullscreen for now + + if (forceFullScreen || (m_windowState & Qt::WindowFullScreen)) + newGeom = platformScreen()->geometry(); + else if (m_windowState & Qt::WindowMaximized) + newGeom = platformScreen()->availableGeometry(); + } + QPlatformWindow::setVisible(visible); + + m_compositor->setVisible(this, visible); + + if (!newGeom.isEmpty()) + setGeometry(newGeom); // may or may not generate an expose + + invalidate(); +} + +QMargins QWasmWindow::frameMargins() const +{ + int border = m_hasTitle ? 4. * (qreal(qt_defaultDpiX()) / 96.0) : 0; + int titleBarHeight = m_hasTitle ? titleHeight() : 0; + + QMargins margins; + margins.setLeft(border); + margins.setRight(border); + margins.setTop(2*border + titleBarHeight); + margins.setBottom(border); + + return margins; +} + +void QWasmWindow::raise() +{ + m_compositor->raise(this); + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size())); + invalidate(); +} + +void QWasmWindow::lower() +{ + m_compositor->lower(this); + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size())); + invalidate(); +} + +WId QWasmWindow::winId() const +{ + return m_winid; +} + +void QWasmWindow::propagateSizeHints() +{ +// get rid of base class warning +} + +void QWasmWindow::injectMousePressed(const QPoint &local, const QPoint &global, + Qt::MouseButton button, Qt::KeyboardModifiers mods) +{ + Q_UNUSED(local); + Q_UNUSED(mods); + + if (!m_hasTitle || button != Qt::LeftButton) + return; + + if (maxButtonRect().contains(global)) + m_activeControl = QWasmCompositor::SC_TitleBarMaxButton; + else if (minButtonRect().contains(global)) + m_activeControl = QWasmCompositor::SC_TitleBarMinButton; + else if (closeButtonRect().contains(global)) + m_activeControl = QWasmCompositor::SC_TitleBarCloseButton; + else if (normButtonRect().contains(global)) + m_activeControl = QWasmCompositor::SC_TitleBarNormalButton; + + invalidate(); +} + +void QWasmWindow::injectMouseReleased(const QPoint &local, const QPoint &global, + Qt::MouseButton button, Qt::KeyboardModifiers mods) +{ + Q_UNUSED(local); + Q_UNUSED(mods); + + if (!m_hasTitle || button != Qt::LeftButton) + return; + + if (closeButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarCloseButton) + window()->close(); + + if (maxButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarMaxButton) { + window()->setWindowState(Qt::WindowMaximized); + platformScreen()->resizeMaximizedWindows(); + } + + if (normButtonRect().contains(global) && m_activeControl == QWasmCompositor::SC_TitleBarNormalButton) { + window()->setWindowState(Qt::WindowNoState); + setGeometry(normalGeometry()); + } + + m_activeControl = QWasmCompositor::SC_None; + + invalidate(); +} + +int QWasmWindow::titleHeight() const +{ + return 18. * (qreal(qt_defaultDpiX()) / 96.0);//dpiScaled(18.); +} + +int QWasmWindow::borderWidth() const +{ + return 4. * (qreal(qt_defaultDpiX()) / 96.0);// dpiScaled(4.); +} + +QRegion QWasmWindow::titleGeometry() const +{ + int border = borderWidth(); + + QRegion result(window()->frameGeometry().x() + border, + window()->frameGeometry().y() + border, + window()->frameGeometry().width() - 2*border, + titleHeight()); + + result -= titleControlRegion(); + + return result; +} + +QRegion QWasmWindow::resizeRegion() const +{ + int border = borderWidth(); + QRegion result(window()->frameGeometry().adjusted(-border, -border, border, border)); + result -= window()->frameGeometry().adjusted(border, border, -border, -border); + + return result; +} + +bool QWasmWindow::isPointOnTitle(QPoint point) const +{ + bool ok = titleGeometry().contains(point); + return ok; +} + +bool QWasmWindow::isPointOnResizeRegion(QPoint point) const +{ + return resizeRegion().contains(point); +} + +QWasmWindow::ResizeMode QWasmWindow::resizeModeAtPoint(QPoint point) const +{ + QPoint p1 = window()->frameGeometry().topLeft() - QPoint(5, 5); + QPoint p2 = window()->frameGeometry().bottomRight() + QPoint(5, 5); + int corner = 20; + + QRect top(p1, QPoint(p2.x(), p1.y() + corner)); + QRect middle(QPoint(p1.x(), p1.y() + corner), QPoint(p2.x(), p2.y() - corner)); + QRect bottom(QPoint(p1.x(), p2.y() - corner), p2); + + QRect left(p1, QPoint(p1.x() + corner, p2.y())); + QRect center(QPoint(p1.x() + corner, p1.y()), QPoint(p2.x() - corner, p2.y())); + QRect right(QPoint(p2.x() - corner, p1.y()), p2); + + if (top.contains(point)) { + // Top + if (left.contains(point)) + return ResizeTopLeft; + if (center.contains(point)) + return ResizeTop; + if (right.contains(point)) + return ResizeTopRight; + } else if (middle.contains(point)) { + // Middle + if (left.contains(point)) + return ResizeLeft; + if (right.contains(point)) + return ResizeRight; + } else if (bottom.contains(point)) { + // Bottom + if (left.contains(point)) + return ResizeBottomLeft; + if (center.contains(point)) + return ResizeBottom; + if (right.contains(point)) + return ResizeBottomRight; + } + + return ResizeNone; +} + +QRect getSubControlRect(const QWasmWindow *window, QWasmCompositor::SubControls subControl) +{ + QWasmCompositor::QWasmTitleBarOptions options = QWasmCompositor::makeTitleBarOptions(window); + + QRect r = QWasmCompositor::titlebarRect(options, subControl); + r.translate(window->window()->frameGeometry().x(), window->window()->frameGeometry().y()); + + return r; +} + +QRect QWasmWindow::maxButtonRect() const +{ + return getSubControlRect(this, QWasmCompositor::SC_TitleBarMaxButton); +} + +QRect QWasmWindow::minButtonRect() const +{ + return getSubControlRect(this, QWasmCompositor::SC_TitleBarMinButton); +} + +QRect QWasmWindow::closeButtonRect() const +{ + return getSubControlRect(this, QWasmCompositor::SC_TitleBarCloseButton); +} + +QRect QWasmWindow::normButtonRect() const +{ + return getSubControlRect(this, QWasmCompositor::SC_TitleBarNormalButton); +} + +QRect QWasmWindow::sysMenuRect() const +{ + return getSubControlRect(this, QWasmCompositor::SC_TitleBarSysMenu); +} + +QRegion QWasmWindow::titleControlRegion() const +{ + QRegion result; + result += closeButtonRect(); + result += minButtonRect(); + result += maxButtonRect(); + result += sysMenuRect(); + + return result; +} + +void QWasmWindow::invalidate() +{ + m_compositor->requestRedraw(); +} + +QWasmCompositor::SubControls QWasmWindow::activeSubControl() const +{ + return m_activeControl; +} + +void QWasmWindow::setWindowState(Qt::WindowStates states) +{ + m_windowState = Qt::WindowNoState; + if (states & Qt::WindowMinimized) + m_windowState = Qt::WindowMinimized; + else if (states & Qt::WindowFullScreen) + m_windowState = Qt::WindowFullScreen; + else if (states & Qt::WindowMaximized) + m_windowState = Qt::WindowMaximized; +} + +QRect QWasmWindow::normalGeometry() const +{ + return m_normalGeometry; +} + +qreal QWasmWindow::devicePixelRatio() const +{ + return screen()->devicePixelRatio(); +} + +void QWasmWindow::requestUpdate() +{ + QPointer<QWindow> windowPointer(window()); + bool registered = QWasmEventDispatcher::registerRequestUpdateCallback([=](){ + if (windowPointer.isNull()) + return; + + deliverUpdateRequest(); + }); + + if (!registered) + QPlatformWindow::requestUpdate(); +} + +QT_END_NAMESPACE |