Add window painting testcase to the QWasmWindow test

The test checks whether windows repaint correctly by sampling the
background after their backing stores have been flushed.

Change-Id: Ib544457074d7d477a4acdc5c331ef83e5ba471d2
Reviewed-by: Piotr Wierciński <piotr.wiercinski@qt.io>
Reviewed-by: Mikołaj Boc <Mikolaj.Boc@qt.io>
This commit is contained in:
Mikolaj Boc 2023-02-22 09:46:51 +01:00
parent 8393922e70
commit 7264f141cf
2 changed files with 102 additions and 4 deletions

View File

@ -24,6 +24,7 @@ class WidgetTestCase(unittest.TestCase):
self._test_sandbox_element = WebDriverWait(self._driver, 30).until(
presence_of_element_located((By.ID, 'test-sandbox'))
)
self.addTypeEqualityFunc(Color, assert_colors_equal)
self.addTypeEqualityFunc(Rect, assert_rects_equal)
def test_window_resizing(self):
@ -401,6 +402,33 @@ class WidgetTestCase(unittest.TestCase):
self.assertFalse(w4 in screen.query_windows())
def test_window_painting(self):
screen = Screen(self._driver, ScreenPosition.FIXED,
x=0, y=0, width=800, height=800)
bottom = Window(parent=screen, rect=Rect(x=0, y=0, width=400, height=400), title='root')
bottom.set_background_color(Color(r=255, g=0, b=0))
wait_for_animation_frame(self._driver)
self.assertEqual(bottom.color_at(0, 0), Color(r=255, g=0, b=0))
w1 = Window(parent=screen, rect=Rect(x=100, y=100, width=600, height=600), title='w1')
w1.set_background_color(Color(r=0, g=255, b=0))
wait_for_animation_frame(self._driver)
self.assertEqual(w1.color_at(0, 0), Color(r=0, g=255, b=0))
w1_w1 = Window(parent=w1, rect=Rect(x=100, y=100, width=400, height=400), title='w1_w1')
w1_w1.set_background_color(Color(r=0, g=0, b=255))
wait_for_animation_frame(self._driver)
self.assertEqual(w1_w1.color_at(0, 0), Color(r=0, g=0, b=255))
w1_w1_w1 = Window(parent=w1_w1, rect=Rect(x=100, y=100, width=200, height=200), title='w1_w1_w1')
w1_w1_w1.set_background_color(Color(r=255, g=255, b=0))
wait_for_animation_frame(self._driver)
self.assertEqual(w1_w1_w1.color_at(0, 0), Color(r=255, g=255, b=0))
def tearDown(self):
self._driver.quit()
@ -634,6 +662,22 @@ class Window:
'''
)
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 set_background_color(self, color):
return self.driver.execute_script(
f'''
return instance.setWindowBackgroundColor('{self.title}', {color.r}, {color.g}, {color.b});
'''
)
class TouchDragAction:
def __init__(self, origin, direction):
self.origin = origin
@ -745,6 +789,24 @@ def call_instance_function(driver, name):
instance.{name}();
return eval(result);''')
def wait_for_animation_frame(driver):
driver.execute_script(
'''
window.requestAnimationFrame(() => {
const sync = document.createElement('div');
sync.id = 'test-sync';
document.body.appendChild(sync);
});
'''
)
WebDriverWait(driver, 1).until(
presence_of_element_located((By.ID, 'test-sync'))
)
driver.execute_script(
'''
document.body.removeChild(document.body.querySelector('#test-sync'));
'''
)
class Direction:
def __init__(self):
@ -791,6 +853,11 @@ class Handle(Enum):
BOTTOM_RIGHT = auto()
TOP_WINDOW_BAR = auto()
class Color:
def __init__(self, r, g, b):
self.r = r
self.g = g
self.b = b
class Rect:
def __init__(self, x, y, width, height) -> None:
@ -806,6 +873,9 @@ class Rect:
def midpoint(self):
return self.x + self.width / 2, self.y + self.height / 2,
def assert_colors_equal(color1, color2, msg=None):
if color1.r != color2.r or color1.g != color2.g or color1.b != color2.b:
raise AssertionError(f'Colors not equal: \n{color1} \nvs \n{color2}')
def assert_rects_equal(geo1, geo2, msg=None):
if geo1.x != geo2.x or geo1.y != geo2.y or geo1.width != geo2.width or geo1.height != geo2.height:

View File

@ -6,6 +6,8 @@
#include <QtGui/qevent.h>
#include <QtCore/qobject.h>
#include <QtCore/qregularexpression.h>
#include <QtGui/qpainter.h>
#include <QtGui/qrasterwindow.h>
#include <QtGui/qscreen.h>
#include <QtGui/qwindow.h>
#include <QtGui/qguiapplication.h>
@ -18,10 +20,17 @@
#include <sstream>
#include <vector>
class DeleteOnCloseWindow : public QWindow
class TestWindow : public QRasterWindow
{
Q_OBJECT
public:
void setBackgroundColor(int r, int g, int b)
{
m_backgroundColor = QColor::fromRgb(r, g, b);
update();
}
private:
void closeEvent(QCloseEvent *ev) override
{
@ -48,16 +57,24 @@ private:
data.set("key", emscripten::val(event->text().toStdString()));
emscripten::val::global("window")["testSupport"].call<void>("reportEvent", std::move(data));
}
void paintEvent(QPaintEvent *e) final
{
QPainter painter(this);
painter.fillRect(e->rect(), m_backgroundColor);
}
QColor m_backgroundColor = Qt::white;
};
namespace {
DeleteOnCloseWindow *findWindowByTitle(const std::string &title)
TestWindow *findWindowByTitle(const std::string &title)
{
auto windows = qGuiApp->allWindows();
auto window_it = std::find_if(windows.begin(), windows.end(), [&title](QWindow *window) {
return window->title() == QString::fromLatin1(title);
});
return window_it == windows.end() ? nullptr : static_cast<DeleteOnCloseWindow *>(*window_it);
return window_it == windows.end() ? nullptr : static_cast<TestWindow *>(*window_it);
}
} // namespace
@ -175,7 +192,7 @@ void createWindow(int x, int y, int w, int h, std::string parentType, std::strin
return;
}
auto *window = new DeleteOnCloseWindow;
auto *window = new TestWindow;
window->setFlag(Qt::WindowTitleHint);
window->setFlag(Qt::WindowMaximizeButtonHint);
@ -185,6 +202,16 @@ void createWindow(int x, int y, int w, int h, std::string parentType, std::strin
window->setParent(parentWindow);
}
void setWindowBackgroundColor(std::string title, int r, int g, int b)
{
auto *window = findWindowByTitle(title);
if (!window) {
qWarning() << "No such window: " << title;
return;
}
window->setBackgroundColor(r, g, b);
}
void setWindowVisible(int windowId, bool visible) {
auto windows = qGuiApp->allWindows();
auto window_it = std::find_if(windows.begin(), windows.end(), [windowId](QWindow *window) {
@ -229,6 +256,7 @@ EMSCRIPTEN_BINDINGS(qwasmwindow)
emscripten::function("setWindowVisible", &setWindowVisible);
emscripten::function("setWindowParent", &setWindowParent);
emscripten::function("closeWindow", &closeWindow);
emscripten::function("setWindowBackgroundColor", &setWindowBackgroundColor);
}
int main(int argc, char **argv)