diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index b68f380fe7..74c5242394 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -149,11 +149,6 @@ void QWasmCompositor::initEventHandlers() emscripten::val(quintptr(reinterpret_cast(screen())))); } -void QWasmCompositor::startResize(Qt::Edges edges) -{ - m_windowManipulation.startResize(edges); -} - void QWasmCompositor::addWindow(QWasmWindow *window) { m_windowStack.pushWindow(window); @@ -317,33 +312,6 @@ void QWasmCompositor::frame(bool all, const QList &windows) } } -void QWasmCompositor::WindowManipulation::resizeWindow(const QPoint& amount) -{ - const auto& minShrink = std::get(m_state->operationSpecific).m_minShrink; - const auto& maxGrow = std::get(m_state->operationSpecific).m_maxGrow; - const auto &resizeEdges = std::get(m_state->operationSpecific).m_resizeEdges; - - const QPoint cappedGrowVector( - std::min(maxGrow.x(), - std::max(minShrink.x(), - (resizeEdges & Qt::Edge::LeftEdge) ? -amount.x() - : (resizeEdges & Qt::Edge::RightEdge) ? amount.x() - : 0)), - std::min(maxGrow.y(), - std::max(minShrink.y(), - (resizeEdges & Qt::Edge::TopEdge) ? -amount.y() - : (resizeEdges & Qt::Edge::BottomEdge) ? amount.y() - : 0))); - - const auto& initialBounds = - std::get(m_state->operationSpecific).m_initialWindowBounds; - m_state->window->setGeometry(initialBounds.adjusted( - (resizeEdges & Qt::Edge::LeftEdge) ? -cappedGrowVector.x() : 0, - (resizeEdges & Qt::Edge::TopEdge) ? -cappedGrowVector.y() : 0, - (resizeEdges & Qt::Edge::RightEdge) ? cappedGrowVector.x() : 0, - (resizeEdges & Qt::Edge::BottomEdge) ? cappedGrowVector.y() : 0)); -} - void QWasmCompositor::onTopWindowChanged() { constexpr int zOrderForElementInFrontOfScreen = 3; @@ -413,7 +381,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event) const QPoint pointInTargetWindowCoords = targetWindow->mapFromGlobal(event.point); const bool pointerIsWithinTargetWindowBounds = targetWindow->geometry().contains(event.point); - const bool isTargetWindowBlocked = QGuiApplicationPrivate::instance()->isWindowBlocked(targetWindow); if (m_mouseInScreen && m_windowUnderMouse != targetWindow && pointerIsWithinTargetWindowBounds) { @@ -422,10 +389,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event) m_windowUnderMouse = targetWindow; } - QWasmWindow *wasmTargetWindow = asWasmWindow(targetWindow); - Qt::WindowStates windowState = targetWindow->windowState(); - const bool isTargetWindowResizable = !windowState.testFlag(Qt::WindowMaximized) && !windowState.testFlag(Qt::WindowFullScreen); - switch (event.type) { case EventType::PointerDown: { @@ -444,25 +407,7 @@ bool QWasmCompositor::processPointer(const PointerEvent& event) m_windowManipulation.onPointerUp(event); break; } - case EventType::PointerMove: - { - if (wasmTargetWindow && event.mouseButtons.testFlag(Qt::NoButton)) { - const bool isOnResizeRegion = wasmTargetWindow->isPointOnResizeRegion(event.point); - - if (isTargetWindowResizable && isOnResizeRegion && !isTargetWindowBlocked) { - const QCursor resizingCursor = QWasmEventTranslator::cursorForEdges( - wasmTargetWindow->resizeEdgesAtPoint(event.point)); - - if (resizingCursor != targetWindow->cursor()) { - m_isResizeCursorDisplayed = true; - QWasmCursor::setOverrideWasmCursor(resizingCursor, targetWindow->screen()); - } - } else if (m_isResizeCursorDisplayed) { // off resizing area - m_isResizeCursorDisplayed = false; - QWasmCursor::clearOverrideWasmCursor(targetWindow->screen()); - } - } - + case EventType::PointerMove: { m_windowManipulation.onPointerMove(event); if (m_windowManipulation.operation() != WindowManipulation::Operation::None) requestUpdate(); @@ -538,9 +483,7 @@ QWasmCompositor::WindowManipulation::Operation QWasmCompositor::WindowManipulati { if (!m_state) return Operation::None; - - return std::holds_alternative(m_state->operationSpecific) - ? Operation::Move : Operation::Resize; + return Operation::Move; } void QWasmCompositor::WindowManipulation::onPointerDown( @@ -564,61 +507,30 @@ void QWasmCompositor::WindowManipulation::onPointerDown( if (isTargetWindowBlocked) return; - std::unique_ptr> operationSpecific; - if (asWasmWindow(windowAtPoint)->isPointOnTitle(event.point)) { - operationSpecific = std::make_unique>( - MoveState{ .m_lastPointInScreenCoords = event.point }); - } else if (asWasmWindow(windowAtPoint)->isPointOnResizeRegion(event.point)) { - operationSpecific = std::make_unique>(ResizeState{ - .m_resizeEdges = asWasmWindow(windowAtPoint)->resizeEdgesAtPoint(event.point), - .m_originInScreenCoords = event.point, - .m_initialWindowBounds = windowAtPoint->geometry(), - .m_minShrink = - QPoint(windowAtPoint->minimumWidth() - windowAtPoint->geometry().width(), - windowAtPoint->minimumHeight() - windowAtPoint->geometry().height()), - .m_maxGrow = - QPoint(windowAtPoint->maximumWidth() - windowAtPoint->geometry().width(), - windowAtPoint->maximumHeight() - windowAtPoint->geometry().height()), - }); - } else { + if (!asWasmWindow(windowAtPoint)->isPointOnTitle(event.point)) return; - } - m_state.reset(new OperationState{ - .pointerId = event.pointerId, - .window = windowAtPoint, - .operationSpecific = std::move(*operationSpecific), - }); + m_state.reset(new OperationState{ .pointerId = event.pointerId, + .window = windowAtPoint, + .lastPointInScreenCoords = event.point }); } void QWasmCompositor::WindowManipulation::onPointerMove( const PointerEvent& event) { - m_systemDragInitData = { - .lastMouseMovePoint = m_screen->clipPoint(event.point), - .lastMousePointerId = event.pointerId, - }; - if (operation() == Operation::None || event.pointerId != m_state->pointerId) return; switch (operation()) { case Operation::Move: { const QPoint targetPointClippedToScreen = m_screen->clipPoint(event.point); - const QPoint difference = targetPointClippedToScreen - - std::get(m_state->operationSpecific).m_lastPointInScreenCoords; + const QPoint difference = targetPointClippedToScreen - m_state->lastPointInScreenCoords; - std::get(m_state->operationSpecific).m_lastPointInScreenCoords = targetPointClippedToScreen; + m_state->lastPointInScreenCoords = targetPointClippedToScreen; m_state->window->setPosition(m_state->window->position() + difference); break; } - case Operation::Resize: { - const auto pointInScreenCoords = m_screen->geometry().topLeft() + event.point; - resizeWindow(pointInScreenCoords - - std::get(m_state->operationSpecific).m_originInScreenCoords); - break; - } case Operation::None: Q_ASSERT(0); break; @@ -633,34 +545,6 @@ void QWasmCompositor::WindowManipulation::onPointerUp(const PointerEvent& event) m_state.reset(); } -void QWasmCompositor::WindowManipulation::startResize(Qt::Edges edges) -{ - Q_ASSERT_X(operation() == Operation::None, Q_FUNC_INFO, - "Resize must not start anew when one is in progress"); - - auto *window = m_screen->compositor()->windowAt(m_systemDragInitData.lastMouseMovePoint); - if (Q_UNLIKELY(!window)) - return; - - m_state.reset(new OperationState{ - .pointerId = m_systemDragInitData.lastMousePointerId, - .window = window, - .operationSpecific = - ResizeState{ - .m_resizeEdges = edges, - .m_originInScreenCoords = m_systemDragInitData.lastMouseMovePoint, - .m_initialWindowBounds = window->geometry(), - .m_minShrink = - QPoint(window->minimumWidth() - window->geometry().width(), - window->minimumHeight() - window->geometry().height()), - .m_maxGrow = - QPoint(window->maximumWidth() - window->geometry().width(), - window->maximumHeight() - window->geometry().height()), - }, - }); - m_screen->element().call("setPointerCapture", m_systemDragInitData.lastMousePointerId); -} - bool QWasmCompositor::processKeyboard(int eventType, const EmscriptenKeyboardEvent *emKeyEvent) { constexpr bool ProceedToNativeEvent = false; diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h index c1fc62d380..17fb25bdd0 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.h +++ b/src/plugins/platforms/wasm/qwasmcompositor.h @@ -43,8 +43,6 @@ public: QPalette palette; }; - void startResize(Qt::Edges edges); - void addWindow(QWasmWindow *window); void removeWindow(QWasmWindow *window); @@ -72,47 +70,26 @@ private: enum class Operation { None, Move, - Resize, }; WindowManipulation(QWasmScreen* screen); void onPointerDown(const PointerEvent& event, QWindow* windowAtPoint); void onPointerMove(const PointerEvent& event); - void onPointerUp(const PointerEvent& event); - void startResize(Qt::Edges edges); + void onPointerUp(const PointerEvent &event); Operation operation() const; private: - struct ResizeState { - Qt::Edges m_resizeEdges; - QPoint m_originInScreenCoords; - QRect m_initialWindowBounds; - const QPoint m_minShrink; - const QPoint m_maxGrow; - }; - struct MoveState { - QPoint m_lastPointInScreenCoords; - }; struct OperationState { int pointerId; QPointer window; - std::variant operationSpecific; + QPoint lastPointInScreenCoords; }; - struct SystemDragInitData - { - QPoint lastMouseMovePoint; - int lastMousePointerId = -1; - }; - - void resizeWindow(const QPoint& amount); - ResizeState makeResizeState(Qt::Edges edges, const QPoint &startPoint, QWindow *window); QWasmScreen *m_screen; - SystemDragInitData m_systemDragInitData; std::unique_ptr m_state; }; diff --git a/src/plugins/platforms/wasm/qwasmcssstyle.cpp b/src/plugins/platforms/wasm/qwasmcssstyle.cpp index 0f31d8abde..f37124c834 100644 --- a/src/plugins/platforms/wasm/qwasmcssstyle.cpp +++ b/src/plugins/platforms/wasm/qwasmcssstyle.cpp @@ -12,6 +12,8 @@ namespace { const char *Style = R"css( .qt-screen { --border-width: 4px; + --resize-outline-width: 8px; + --resize-outline-half-width: var(--resize-outline-width) / 2; position: relative; border: none; @@ -35,6 +37,80 @@ const char *Style = R"css( caret-color: transparent; } +.resize-outline { + position: absolute; + pointer-events: all; + display: none; +} + +.qt-window.has-title-bar:not(.maximized) .resize-outline { + display: block; +} + +.resize-outline.nw { + left: calc(-1 * var(--resize-outline-half-width) - var(--border-width)); + top: calc(-1 * var(--resize-outline-half-width) - var(--border-width)); + width: var(--resize-outline-width); + height: var(--resize-outline-width); + cursor: nwse-resize; +} + +.resize-outline.n { + left: var(--resize-outline-half-width); + top: calc(-1 * var(--resize-outline-half-width) - var(--border-width)); + height: var(--resize-outline-width); + width: calc(100% + 2 * var(--border-width) - var(--resize-outline-width)); + cursor: ns-resize; +} + +.resize-outline.ne { + left: calc(100% + var(--border-width) - var(--resize-outline-half-width)); + top: calc(-1 * var(--resize-outline-half-width) - var(--border-width)); + width: var(--resize-outline-width); + height: var(--resize-outline-width); + cursor: nesw-resize; +} + +.resize-outline.w { + left: calc(-1 * var(--resize-outline-half-width) - var(--border-width)); + top: 0; + height: calc(100% + 2 * var(--border-width) - var(--resize-outline-width)); + width: var(--resize-outline-width); + cursor: ew-resize; +} + +.resize-outline.e { + left: calc(100% + var(--border-width) - var(--resize-outline-half-width)); + top: 0; + height: calc(100% + 2 * var(--border-width) - var(--resize-outline-width)); + width: var(--resize-outline-width); + cursor: ew-resize; +} + +.resize-outline.sw { + left: calc(-1 * var(--resize-outline-half-width) - var(--border-width)); + top: calc(100% + var(--border-width) - var(--resize-outline-half-width)); + width: var(--resize-outline-width); + height: var(--resize-outline-width); + cursor: nesw-resize; +} + +.resize-outline.s { + left: var(--resize-outline-half-width); + top: calc(100% + var(--border-width) - var(--resize-outline-half-width)); + height: var(--resize-outline-width); + width: calc(100% + 2 * var(--border-width) - var(--resize-outline-width)); + cursor: ns-resize; +} + +.resize-outline.se { + left: calc(100% + var(--border-width) - var(--resize-outline-half-width)); + top: calc(100% + var(--border-width) - var(--resize-outline-half-width)); + width: var(--resize-outline-width); + height: var(--resize-outline-width); + cursor: nwse-resize; +} + .title-bar { display: none; align-items: center; diff --git a/src/plugins/platforms/wasm/qwasmevent.cpp b/src/plugins/platforms/wasm/qwasmevent.cpp index f066d0041e..452a22ad5c 100644 --- a/src/plugins/platforms/wasm/qwasmevent.cpp +++ b/src/plugins/platforms/wasm/qwasmevent.cpp @@ -44,6 +44,7 @@ std::optional PointerEvent::fromWeb(emscripten::val event) ret.mouseButton = MouseEvent::buttonFromWeb(event["button"].as()); ret.mouseButtons = MouseEvent::buttonsFromWeb(event["buttons"].as()); ret.point = QPoint(event["offsetX"].as(), event["offsetY"].as()); + ret.pointInViewport = QPoint(event["x"].as(), event["y"].as()); ret.pointerId = event["pointerId"].as(); ret.modifiers = KeyboardModifier::getForEvent(event); diff --git a/src/plugins/platforms/wasm/qwasmevent.h b/src/plugins/platforms/wasm/qwasmevent.h index df9276b746..9f43b6a85f 100644 --- a/src/plugins/platforms/wasm/qwasmevent.h +++ b/src/plugins/platforms/wasm/qwasmevent.h @@ -115,6 +115,7 @@ struct Q_CORE_EXPORT Event struct Q_CORE_EXPORT MouseEvent : public Event { QPoint point; + QPoint pointInViewport; Qt::MouseButton mouseButton; Qt::MouseButtons mouseButtons; QFlags modifiers; diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp index 323a985454..36ba655d66 100644 --- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp @@ -283,29 +283,6 @@ QWasmEventTranslator::QWasmEventTranslator() = default; QWasmEventTranslator::~QWasmEventTranslator() = default; -QCursor QWasmEventTranslator::cursorForEdges(Qt::Edges edges) -{ - switch (edges) { - case Qt::Edge::LeftEdge | Qt::Edge::TopEdge: - case Qt::Edge::RightEdge | Qt::Edge::BottomEdge: - return Qt::SizeFDiagCursor; - case Qt::Edge::LeftEdge | Qt::Edge::BottomEdge: - case Qt::Edge::RightEdge | Qt::Edge::TopEdge: - return Qt::SizeBDiagCursor; - case Qt::Edge::TopEdge: - case Qt::Edge::BottomEdge: - return Qt::SizeVerCursor; - case Qt::Edge::LeftEdge: - case Qt::Edge::RightEdge: - return Qt::SizeHorCursor; - case Qt::Edge(0): - return Qt::ArrowCursor; - default: - Q_ASSERT(false); // Bad edges - } - return Qt::ArrowCursor; -} - QWasmEventTranslator::TranslatedEvent QWasmEventTranslator::translateKeyEvent(int emEventType, const EmscriptenKeyboardEvent *keyEvent) { diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.h b/src/plugins/platforms/wasm/qwasmeventtranslator.h index d89b543386..23299c294f 100644 --- a/src/plugins/platforms/wasm/qwasmeventtranslator.h +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.h @@ -33,8 +33,6 @@ public: explicit QWasmEventTranslator(); ~QWasmEventTranslator(); - static QCursor cursorForEdges(Qt::Edges edges); - TranslatedEvent translateKeyEvent(int emEventType, const EmscriptenKeyboardEvent *keyEvent); private: diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp index 842aaccc6e..c85142882e 100644 --- a/src/plugins/platforms/wasm/qwasmwindow.cpp +++ b/src/plugins/platforms/wasm/qwasmwindow.cpp @@ -45,8 +45,222 @@ void syncCSSClassWith(emscripten::val element, std::string cssClassName, bool fl element["classList"].call("remove", emscripten::val(std::move(cssClassName))); } + } // namespace +class QWasmWindow::Resizer +{ +public: + class ResizerElement + { + public: + static constexpr const char *cssClassNameForEdges(Qt::Edges edges) + { + switch (edges) { + case Qt::TopEdge | Qt::LeftEdge:; + return "nw"; + case Qt::TopEdge: + return "n"; + case Qt::TopEdge | Qt::RightEdge: + return "ne"; + case Qt::LeftEdge: + return "w"; + case Qt::RightEdge: + return "e"; + case Qt::BottomEdge | Qt::LeftEdge: + return "sw"; + case Qt::BottomEdge: + return "s"; + case Qt::BottomEdge | Qt::RightEdge: + return "se"; + default: + Q_ASSERT(false); // notreached + return ""; + } + } + + ResizerElement(emscripten::val parentElement, Qt::Edges edges, Resizer *resizer) + : m_element(emscripten::val::global("document") + .call("createElement", emscripten::val("div"))), + m_edges(edges), + m_resizer(resizer) + { + Q_ASSERT_X(m_resizer, Q_FUNC_INFO, "Resizer cannot be null"); + + m_element["classList"].call("add", emscripten::val("resize-outline")); + m_element["classList"].call("add", emscripten::val(cssClassNameForEdges(edges))); + + parentElement.call("appendChild", m_element); + + m_mouseDownEvent = std::make_unique( + m_element, "pointerdown", [this](emscripten::val event) { + if (!onPointerDown(*PointerEvent::fromWeb(event))) + return; + m_resizer->onInteraction(); + event.call("preventDefault"); + event.call("stopPropagation"); + }); + m_mouseDragEvent = std::make_unique( + m_element, "pointermove", [this](emscripten::val event) { + if (onPointerMove(*PointerEvent::fromWeb(event))) { + event.call("preventDefault"); + event.call("stopPropagation"); + } + }); + m_mouseUpEvent = std::make_unique( + m_element, "pointerup", [this](emscripten::val event) { + if (onPointerUp(*PointerEvent::fromWeb(event))) { + event.call("preventDefault"); + event.call("stopPropagation"); + } + }); + } + + ~ResizerElement() + { + m_element["parentElement"].call("removeChild", m_element); + } + ResizerElement(const ResizerElement &other) = delete; + ResizerElement(ResizerElement &&other) = default; + ResizerElement &operator=(const ResizerElement &other) = delete; + ResizerElement &operator=(ResizerElement &&other) = delete; + + bool onPointerDown(const PointerEvent &event) + { + if (event.pointerType != PointerType::Mouse) + return false; + + m_element.call("setPointerCapture", event.pointerId); + m_capturedPointerId = event.pointerId; + + m_resizer->startResize(m_edges, event.pointInViewport); + return true; + } + + bool onPointerMove(const PointerEvent &event) + { + if (m_capturedPointerId != event.pointerId) + return false; + + m_resizer->continueResize(event.pointInViewport); + return true; + } + + bool onPointerUp(const PointerEvent &event) + { + if (m_capturedPointerId != event.pointerId) + return false; + + m_resizer->finishResize(); + m_element.call("releasePointerCapture", event.pointerId); + m_capturedPointerId = -1; + return true; + } + + private: + emscripten::val m_element; + + int m_capturedPointerId = -1; + + const Qt::Edges m_edges; + + Resizer *m_resizer; + + std::unique_ptr m_mouseDownEvent; + std::unique_ptr m_mouseDragEvent; + std::unique_ptr m_mouseUpEvent; + }; + + using ClickCallback = std::function; + + Resizer(QWasmWindow *window, emscripten::val parentElement) : m_window(window) + { + Q_ASSERT_X(m_window, Q_FUNC_INFO, "Window must not be null"); + + constexpr std::array ResizeEdges = { Qt::TopEdge | Qt::LeftEdge, + Qt::TopEdge, + Qt::TopEdge | Qt::RightEdge, + Qt::LeftEdge, + Qt::RightEdge, + Qt::BottomEdge | Qt::LeftEdge, + Qt::BottomEdge, + Qt::BottomEdge | Qt::RightEdge }; + std::transform(std::begin(ResizeEdges), std::end(ResizeEdges), + std::back_inserter(m_elements), [parentElement, this](int edges) { + return std::make_unique(parentElement, + Qt::Edges::fromInt(edges), this); + }); + } + + ~Resizer() = default; + +private: + void onInteraction() { m_window->onInteraction(); } + + void startResize(Qt::Edges resizeEdges, const QPoint &origin) + { + Q_ASSERT_X(!m_currentResizeData, Q_FUNC_INFO, "Another resize in progress"); + + const QWindow *window = m_window->window(); + // TODO(mikolajboc): Implement system resize + // .m_originInScreenCoords = m_systemDragInitData.lastMouseMovePoint, + m_currentResizeData.reset(new ResizeData{ + .edges = resizeEdges, + .originInScreenCoords = origin, + .initialWindowBounds = window->geometry(), + .minShrink = QPoint(window->minimumWidth() - window->geometry().width(), + window->minimumHeight() - window->geometry().height()), + .maxGrow = QPoint(window->maximumWidth() - window->geometry().width(), + window->maximumHeight() - window->geometry().height()) }); + } + + void continueResize(const QPoint &point) + { + const auto amount = point - m_currentResizeData->originInScreenCoords; + const QPoint cappedGrowVector( + std::min(m_currentResizeData->maxGrow.x(), + std::max(m_currentResizeData->minShrink.x(), + (m_currentResizeData->edges & Qt::Edge::LeftEdge) ? -amount.x() + : (m_currentResizeData->edges & Qt::Edge::RightEdge) + ? amount.x() + : 0)), + std::min(m_currentResizeData->maxGrow.y(), + std::max(m_currentResizeData->minShrink.y(), + (m_currentResizeData->edges & Qt::Edge::TopEdge) ? -amount.y() + : (m_currentResizeData->edges & Qt::Edge::BottomEdge) + ? amount.y() + : 0))); + + auto bounds = m_currentResizeData->initialWindowBounds.adjusted( + (m_currentResizeData->edges & Qt::Edge::LeftEdge) ? -cappedGrowVector.x() : 0, + (m_currentResizeData->edges & Qt::Edge::TopEdge) ? -cappedGrowVector.y() : 0, + (m_currentResizeData->edges & Qt::Edge::RightEdge) ? cappedGrowVector.x() : 0, + (m_currentResizeData->edges & Qt::Edge::BottomEdge) ? cappedGrowVector.y() : 0); + bounds.setY(std::max(m_window->screen()->geometry().y() + m_window->frameMargins().top(), + bounds.y())); + m_window->setGeometry(std::move(bounds)); + } + + void finishResize() + { + Q_ASSERT_X(m_currentResizeData, Q_FUNC_INFO, "No resize in progress"); + m_currentResizeData.reset(); + } + + struct ResizeData + { + Qt::Edges edges = Qt::Edges::fromInt(0); + QPoint originInScreenCoords; + QRect initialWindowBounds; + QPoint minShrink; + QPoint maxGrow; + }; + std::unique_ptr m_currentResizeData; + + QWasmWindow *m_window; + std::vector> m_elements; +}; + class QWasmWindow::WebImageButton { public: @@ -181,6 +395,8 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingSt m_qtWindow.call("appendChild", m_windowContents); + m_resizer = std::make_unique(this, m_qtWindow); + m_icon = std::make_unique(); m_icon->setImage(IconType::QtLogo); @@ -411,11 +627,10 @@ void QWasmWindow::propagateSizeHints() } } -bool QWasmWindow::startSystemResize(Qt::Edges edges) +bool QWasmWindow::startSystemResize(Qt::Edges) { - m_compositor->startResize(edges); - - return true; + // TODO(mikolajboc): This can only be implemented if per-window events are up and running + return false; } void QWasmWindow::onRestoreClicked() @@ -450,51 +665,12 @@ QMarginsF QWasmWindow::borderMargins() const frameRect.bottom() - canvasRect.bottom()); } -QRegion QWasmWindow::resizeRegion() const -{ - QMargins margins = borderMargins().toMargins(); - QRegion result(window()->frameGeometry().marginsAdded(margins)); - result -= window()->frameGeometry().marginsRemoved(margins); - - return result; -} - bool QWasmWindow::isPointOnTitle(QPoint globalPoint) const { return QRectF::fromDOMRect(m_titleBar.call("getBoundingClientRect")) .contains(globalPoint); } -bool QWasmWindow::isPointOnResizeRegion(QPoint point) const -{ - // Certain windows, like undocked dock widgets, are both popups and dialogs. Those should be - // resizable. - if (windowIsPopupType(window()->flags())) - return false; - return (window()->maximumSize().isEmpty() || window()->minimumSize() != window()->maximumSize()) - && resizeRegion().contains(point); -} - -Qt::Edges QWasmWindow::resizeEdgesAtPoint(QPoint point) const -{ - const QPoint topLeft = window()->frameGeometry().topLeft() - QPoint(5, 5); - const QPoint bottomRight = window()->frameGeometry().bottomRight() + QPoint(5, 5); - const int gripAreaWidth = std::min(20, (bottomRight.y() - topLeft.y()) / 2); - - const QRect top(topLeft, QPoint(bottomRight.x(), topLeft.y() + gripAreaWidth)); - const QRect bottom(QPoint(topLeft.x(), bottomRight.y() - gripAreaWidth), bottomRight); - const QRect left(topLeft, QPoint(topLeft.x() + gripAreaWidth, bottomRight.y())); - const QRect right(QPoint(bottomRight.x() - gripAreaWidth, topLeft.y()), bottomRight); - - Q_ASSERT(!top.intersects(bottom)); - Q_ASSERT(!left.intersects(right)); - - Qt::Edges edges(top.contains(point) ? Qt::Edge::TopEdge : Qt::Edge(0)); - edges |= bottom.contains(point) ? Qt::Edge::BottomEdge : Qt::Edge(0); - edges |= left.contains(point) ? Qt::Edge::LeftEdge : Qt::Edge(0); - return edges | (right.contains(point) ? Qt::Edge::RightEdge : Qt::Edge(0)); -} - void QWasmWindow::invalidate() { m_compositor->requestUpdateWindow(this); @@ -565,6 +741,7 @@ void QWasmWindow::applyWindowState() newGeom = normalGeometry(); syncCSSClassWith(m_qtWindow, "has-title-bar", hasTitleBar()); + syncCSSClassWith(m_qtWindow, "maximized", isMaximized); m_restore->setVisible(isMaximized); m_maximize->setVisible(!isMaximized); diff --git a/src/plugins/platforms/wasm/qwasmwindow.h b/src/plugins/platforms/wasm/qwasmwindow.h index 183f68a311..8359391825 100644 --- a/src/plugins/platforms/wasm/qwasmwindow.h +++ b/src/plugins/platforms/wasm/qwasmwindow.h @@ -55,9 +55,6 @@ public: bool startSystemResize(Qt::Edges edges) final; bool isPointOnTitle(QPoint point) const; - bool isPointOnResizeRegion(QPoint point) const; - - Qt::Edges resizeEdgesAtPoint(QPoint point) const; void setWindowFlags(Qt::WindowFlags flags) override; void setWindowState(Qt::WindowStates state) override; @@ -74,10 +71,10 @@ public: private: friend class QWasmScreen; + class Resizer; class WebImageButton; QMarginsF borderMargins() const; - QRegion resizeRegion() const; void onRestoreClicked(); void onMaximizeClicked(); @@ -101,6 +98,8 @@ private: emscripten::val m_canvas; emscripten::val m_context2d = emscripten::val::undefined(); + std::unique_ptr m_resizer; + std::unique_ptr m_close; std::unique_ptr m_maximize; std::unique_ptr m_restore;