summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/platforms/wasm/qwasmbackingstore.cpp9
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp31
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.h9
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp10
-rw-r--r--tests/auto/wasm/selenium/qwasmwindow.py57
-rw-r--r--tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp43
6 files changed, 130 insertions, 29 deletions
diff --git a/src/plugins/platforms/wasm/qwasmbackingstore.cpp b/src/plugins/platforms/wasm/qwasmbackingstore.cpp
index a3c1ae8a502..c14d1f59e4e 100644
--- a/src/plugins/platforms/wasm/qwasmbackingstore.cpp
+++ b/src/plugins/platforms/wasm/qwasmbackingstore.cpp
@@ -39,11 +39,12 @@ QPaintDevice *QWasmBackingStore::paintDevice()
void QWasmBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
Q_UNUSED(window);
- Q_UNUSED(region);
- Q_UNUSED(offset);
-
m_dirty |= region;
- m_compositor->handleBackingStoreFlush(window);
+
+ QRect updateRect = region.boundingRect();
+ updateRect.translate(offset);
+
+ m_compositor->handleBackingStoreFlush(this->window(), updateRect);
}
void QWasmBackingStore::updateTexture(QWasmWindow *window)
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
index ef460f666ff..c534cce9ef5 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -55,16 +55,23 @@ bool QWasmCompositor::releaseRequestUpdateHold()
return wasEnabled;
}
-void QWasmCompositor::requestUpdateWindow(QWasmWindow *window, UpdateRequestDeliveryType updateType)
+void QWasmCompositor::requestUpdateWindow(QWasmWindow *window, const QRect &updateRect, UpdateRequestDeliveryType updateType)
{
auto it = m_requestUpdateWindows.find(window);
if (it == m_requestUpdateWindows.end()) {
- m_requestUpdateWindows.insert(window, updateType);
+ m_requestUpdateWindows.insert(window, std::make_tuple(updateRect, updateType));
} else {
// Already registered, but upgrade ExposeEventDeliveryType to UpdateRequestDeliveryType.
// if needed, to make sure QWindow::updateRequest's are matched.
- if (it.value() == ExposeEventDelivery && updateType == UpdateRequestDelivery)
- it.value() = UpdateRequestDelivery;
+ if (std::get<0>(it.value()) != updateRect) {
+ QRegion region;
+ region |= std::get<0>(it.value());
+ region |= updateRect;
+ std::get<0>(it.value()) = region.boundingRect();
+ }
+ if (std::get<1>(it.value()) == ExposeEventDelivery &&
+ updateType == UpdateRequestDelivery)
+ std::get<1>(it.value()) = UpdateRequestDelivery;
}
requestUpdate();
@@ -106,15 +113,20 @@ void QWasmCompositor::deliverUpdateRequests()
m_inDeliverUpdateRequest = true;
for (auto it = requestUpdateWindows.constBegin(); it != requestUpdateWindows.constEnd(); ++it) {
auto *window = it.key();
- UpdateRequestDeliveryType updateType = it.value();
- deliverUpdateRequest(window, updateType);
+
+ const QRect updateRect = std::get<0>(it.value());
+ const UpdateRequestDeliveryType updateType = std::get<1>(it.value());
+ deliverUpdateRequest(window, updateRect, updateType);
}
m_inDeliverUpdateRequest = false;
frame(requestUpdateWindows.keys());
}
-void QWasmCompositor::deliverUpdateRequest(QWasmWindow *window, UpdateRequestDeliveryType updateType)
+void QWasmCompositor::deliverUpdateRequest(
+ QWasmWindow *window,
+ const QRect &updateRect,
+ UpdateRequestDeliveryType updateType)
{
QWindow *qwindow = window->window();
@@ -126,7 +138,6 @@ void QWasmCompositor::deliverUpdateRequest(QWasmWindow *window, UpdateRequestDel
// type. If the window has not yet been exposed then we must expose it first regardless
// of update type. The deliverUpdateRequest must still be sent in this case in order
// to maintain correct window update state.
- QRect updateRect(QPoint(0, 0), qwindow->geometry().size());
if (updateType == UpdateRequestDelivery) {
if (qwindow->isExposed() == false)
QWindowSystemInterface::handleExposeEvent(qwindow, updateRect);
@@ -136,12 +147,12 @@ void QWasmCompositor::deliverUpdateRequest(QWasmWindow *window, UpdateRequestDel
}
}
-void QWasmCompositor::handleBackingStoreFlush(QWindow *window)
+void QWasmCompositor::handleBackingStoreFlush(QWindow *window, const QRect &updateRect)
{
// Request update to flush the updated backing store content, unless we are currently
// processing an update, in which case the new content will flushed as a part of that update.
if (!m_inDeliverUpdateRequest)
- requestUpdateWindow(static_cast<QWasmWindow *>(window->handle()));
+ requestUpdateWindow(static_cast<QWasmWindow *>(window->handle()), updateRect);
}
void QWasmCompositor::frame(const QList<QWasmWindow *> &windows)
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h
index 4953d652338..0f24a6690e7 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.h
+++ b/src/plugins/platforms/wasm/qwasmcompositor.h
@@ -9,6 +9,7 @@
#include <qpa/qplatformwindow.h>
#include <QMap>
+#include <tuple>
QT_BEGIN_NAMESPACE
@@ -35,9 +36,9 @@ public:
void requestUpdate();
enum UpdateRequestDeliveryType { ExposeEventDelivery, UpdateRequestDelivery };
- void requestUpdateWindow(QWasmWindow *window, UpdateRequestDeliveryType updateType = ExposeEventDelivery);
+ void requestUpdateWindow(QWasmWindow *window, const QRect &updateRect, UpdateRequestDeliveryType updateType = ExposeEventDelivery);
- void handleBackingStoreFlush(QWindow *window);
+ void handleBackingStoreFlush(QWindow *window, const QRect &updateRect);
void onWindowTreeChanged(QWasmWindowTreeNodeChangeType changeType, QWasmWindow *window);
private:
@@ -46,10 +47,10 @@ private:
void deregisterEventHandlers();
void deliverUpdateRequests();
- void deliverUpdateRequest(QWasmWindow *window, UpdateRequestDeliveryType updateType);
+ void deliverUpdateRequest(QWasmWindow *window, const QRect &updateRect, UpdateRequestDeliveryType updateType);
bool m_isEnabled = true;
- QMap<QWasmWindow *, UpdateRequestDeliveryType> m_requestUpdateWindows;
+ QMap<QWasmWindow *, std::tuple<QRect, UpdateRequestDeliveryType>> m_requestUpdateWindows;
int m_requestAnimationFrameId = -1;
bool m_inDeliverUpdateRequest = false;
static bool m_requestUpdateHoldEnabled;
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
index 99e9bb22f1b..6fa56f1d064 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -317,7 +317,7 @@ void QWasmWindow::setGeometry(const QRect &rect)
if (shouldInvalidate)
invalidate();
else
- m_compositor->requestUpdateWindow(this);
+ m_compositor->requestUpdateWindow(this, QRect(QPoint(0, 0), geometry().size()));
}
void QWasmWindow::setVisible(bool visible)
@@ -327,7 +327,7 @@ void QWasmWindow::setVisible(bool visible)
if (visible == nowVisible)
return;
- m_compositor->requestUpdateWindow(this, QWasmCompositor::ExposeEventDelivery);
+ m_compositor->requestUpdateWindow(this, QRect(QPoint(0, 0), geometry().size()), QWasmCompositor::ExposeEventDelivery);
m_qtWindow["style"].set("display", visible ? "block" : "none");
if (window()->isActive())
m_canvas.call<void>("focus");
@@ -385,7 +385,7 @@ void QWasmWindow::setOpacity(qreal level)
void QWasmWindow::invalidate()
{
- m_compositor->requestUpdateWindow(this);
+ m_compositor->requestUpdateWindow(this, QRect(QPoint(0, 0), geometry().size()));
}
void QWasmWindow::onActivationChanged(bool active)
@@ -401,7 +401,7 @@ void QWasmWindow::setWindowFlags(Qt::WindowFlags flags)
onPositionPreferenceChanged(positionPreferenceFromWindowFlags(flags));
}
m_flags = flags;
- dom::syncCSSClassWith(m_qtWindow, "frameless", !hasFrame());
+ dom::syncCSSClassWith(m_qtWindow, "frameless", !hasFrame() || !window()->isTopLevel());
dom::syncCSSClassWith(m_qtWindow, "has-border", hasBorder());
dom::syncCSSClassWith(m_qtWindow, "has-shadow", hasShadow());
dom::syncCSSClassWith(m_qtWindow, "has-title", hasTitleBar());
@@ -566,7 +566,7 @@ qreal QWasmWindow::devicePixelRatio() const
void QWasmWindow::requestUpdate()
{
- m_compositor->requestUpdateWindow(this, QWasmCompositor::UpdateRequestDelivery);
+ m_compositor->requestUpdateWindow(this, QRect(QPoint(0, 0), geometry().size()), QWasmCompositor::UpdateRequestDelivery);
}
bool QWasmWindow::hasFrame() const
diff --git a/tests/auto/wasm/selenium/qwasmwindow.py b/tests/auto/wasm/selenium/qwasmwindow.py
index 260e9d2d24a..df2d39f5167 100644
--- a/tests/auto/wasm/selenium/qwasmwindow.py
+++ b/tests/auto/wasm/selenium/qwasmwindow.py
@@ -28,6 +28,24 @@ class WidgetTestCase(unittest.TestCase):
self.addTypeEqualityFunc(Color, assert_colors_equal)
self.addTypeEqualityFunc(Rect, assert_rects_equal)
+ #
+ # This is a manual test
+ # The reason is that the color readback works
+ # even if the display is incorrect
+ #
+ def test_native_widgets(self):
+ screen = Screen(self._driver, ScreenPosition.FIXED,
+ x=0, y=0, width=600, height=1200)
+
+ w0 = Widget(self._driver, "w0", 1)
+ w0.show()
+ #time.sleep(3600)
+ color = w0.color_at(100, 150)
+ self.assertEqual(color.r, 255)
+ self.assertEqual(color.g, 255)
+ self.assertEqual(color.b, 255)
+ self.assertEqual(w0.hasFocus(), True)
+
def test_hasFocus_returnsFalse_whenSetNoFocusShowWasCalled(self):
screen = Screen(self._driver, ScreenPosition.FIXED,
x=0, y=0, width=600, height=1200)
@@ -607,15 +625,30 @@ def clearWidgets(driver):
)
class Widget:
- def __init__(self, driver, name):
+ def __init__(self, driver, name, isNative=0):
self.name=name
self.driver=driver
- self.driver.execute_script(
- f'''
- instance.createWidget('{self.name}');
- '''
- )
+ if isNative == 0:
+ self.driver.execute_script(
+ f'''
+ instance.createWidget('{self.name}');
+ '''
+ )
+ if isNative == 1:
+ self.driver.execute_script(
+ f'''
+ instance.createNativeWidget('{self.name}');
+ '''
+ )
+
+ if isNative == 1:
+ information = self.__window_information()
+ self.screen = Screen(self.driver, screen_name=information['screen']['name'])
+
+ self._window_id = self.__window_information()['id']
+ self.element = self.screen.find_element(
+ By.CSS_SELECTOR, f'#qt-window-{self._window_id}')
def setNoFocusShow(self):
self.driver.execute_script(
@@ -641,6 +674,18 @@ class Widget:
'''
)
+ def color_at(self, x, y):
+ raw = self.driver.execute_script(
+ f'''
+ return arguments[0].querySelector('canvas')
+ .getContext('2d').getImageData({x}, {y}, 1, 1).data;
+ ''', self.element)
+ return Color(r=raw[0], g=raw[1], b=raw[2])
+
+ def __window_information(self):
+ information = call_instance_function(self.driver, 'windowInformation')
+ return next(filter(lambda e: e['title'] == "Dialog", information))
+
class Window:
def __init__(self, parent=None, rect=None, title=None, element=None, visible=True, opengl=0):
diff --git a/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp b/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp
index 365fc74a34e..75e23cecdaf 100644
--- a/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp
+++ b/tests/auto/wasm/selenium/tst_qwasmwindow_harness.cpp
@@ -16,6 +16,10 @@
#include <QApplication>
#include <QDialog>
#include <QSysInfo>
+#include <QTreeView>
+#include <QFileSystemModel>
+#include <QScrollArea>
+#include <QVBoxLayout>
#include <QOpenGLWindow>
#include <QOpenGLFunctions>
@@ -389,6 +393,7 @@ public:
void make(const std::string &name)
{
auto widget = std::make_shared<TestWidget>();
+ widget->setWindowTitle("Dialog");
auto *lineEdit = new QLineEdit(widget.get());
widget->setMinimumSize(200, 200);
@@ -401,6 +406,38 @@ public:
m_widgets[name] = widget;
m_lineEdits[name] = lineEdit;
}
+ void makeNative(const std::string &name)
+ {
+ auto widget = std::make_shared<TestWidget>();
+ widget->setWindowTitle("Dialog");
+ auto *lineEdit = new QLineEdit();
+
+ widget->setMinimumSize(200, 200);
+ widget->setMaximumSize(200, 200);
+ widget->setGeometry(0, m_widgetY, 200, 200);
+ m_widgetY += 200;
+
+ lineEdit->setText("Hello world");
+
+ m_widgets[name] = widget;
+ m_lineEdits[name] = lineEdit;
+
+ QFileSystemModel *model = new QFileSystemModel;
+ model->setRootPath(QDir::currentPath());
+
+ auto *scrollArea = new QScrollArea();
+ auto *layout = new QVBoxLayout(widget.get());
+ auto *treeView = new QTreeView(scrollArea);
+ treeView->setModel(model);
+
+ layout->addWidget(lineEdit);
+ layout->addWidget(scrollArea);
+
+ treeView->setAttribute(Qt::WA_NativeWindow);
+ scrollArea->setAttribute(Qt::WA_NativeWindow);
+ lineEdit->setAttribute(Qt::WA_NativeWindow);
+ widget->setAttribute(Qt::WA_NativeWindow);
+ }
private:
using TestWidgetPtr = std::shared_ptr<TestWidget>;
@@ -503,6 +540,11 @@ void createWidget(const std::string &name)
WidgetStorage::getInstance()->make(name);
}
+void createNativeWidget(const std::string &name)
+{
+ WidgetStorage::getInstance()->makeNative(name);
+}
+
void setWidgetNoFocusShow(const std::string &name)
{
auto w = WidgetStorage::getInstance()->findWidget(name);
@@ -678,6 +720,7 @@ EMSCRIPTEN_BINDINGS(qwasmwindow)
emscripten::function("getOpenGLColorAt_0_0", &getOpenGLColorAt_0_0);
emscripten::function("createWidget", &createWidget);
+ emscripten::function("createNativeWidget", &createNativeWidget);
emscripten::function("setWidgetNoFocusShow", &setWidgetNoFocusShow);
emscripten::function("showWidget", &showWidget);
emscripten::function("activateWidget", &activateWidget);