From 8efaa9f8306be981f9942816a151c895bb197539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 15 Aug 2023 21:04:46 +0200 Subject: [PATCH] xcb: Implement native window helper for embeddedwindows/foreign window test Change-Id: I73720f8f49a5d7e5df7c95bf4b17ef910180e01c Reviewed-by: Liang Qi (cherry picked from commit 3cb3c1d9a8e5cfe262be8d6e9800f604d4d48c97) Reviewed-by: Qt Cherry-pick Bot --- tests/auto/gui/kernel/qwindow/CMakeLists.txt | 6 +- .../gui/kernel/qwindow/tst_foreignwindow.cpp | 5 +- tests/manual/embeddedwindows/CMakeLists.txt | 4 + tests/manual/embeddedwindows/main.cpp | 2 +- tests/shared/nativewindow.h | 78 ++++++++++++++++++- 5 files changed, 91 insertions(+), 4 deletions(-) diff --git a/tests/auto/gui/kernel/qwindow/CMakeLists.txt b/tests/auto/gui/kernel/qwindow/CMakeLists.txt index 5117526b9c6..0b4486559cd 100644 --- a/tests/auto/gui/kernel/qwindow/CMakeLists.txt +++ b/tests/auto/gui/kernel/qwindow/CMakeLists.txt @@ -14,7 +14,7 @@ qt_internal_add_test(tst_qwindow Qt::GuiPrivate ) -if(APPLE OR WIN32) +if(APPLE OR WIN32 OR QT_FEATURE_xcb) qt_internal_add_test(tst_foreignwindow LOWDPI SOURCES @@ -29,6 +29,10 @@ if(APPLE OR WIN32) set_source_files_properties(tst_foreignwindow.cpp PROPERTIES LANGUAGE OBJCXX) set_property(TARGET tst_foreignwindow PROPERTY PROPERTY MACOSX_BUNDLE TRUE) endif() + + if(QT_FEATURE_xcb) + target_link_libraries(tst_foreignwindow PRIVATE XCB::XCB) + endif() endif() ## Scopes: diff --git a/tests/auto/gui/kernel/qwindow/tst_foreignwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_foreignwindow.cpp index 04c70e5feec..ce4d9f28c88 100644 --- a/tests/auto/gui/kernel/qwindow/tst_foreignwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_foreignwindow.cpp @@ -60,12 +60,15 @@ void tst_ForeignWindow::initialState() const QRect initialGeometry(123, 456, 321, 654); nativeWindow.setGeometry(initialGeometry); + QTRY_COMPARE(nativeWindow.geometry(), initialGeometry); std::unique_ptr foreignWindow(QWindow::fromWinId(nativeWindow)); QCOMPARE(nativeWindow.geometry(), initialGeometry); // For extra bonus points, the foreign window should actually // reflect the state of the native window. + if (!QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive)) + QEXPECT_FAIL("", "QXcbWindow does not pick up foreign window geometry", Continue); QCOMPARE(foreignWindow->geometry(), initialGeometry); } @@ -83,7 +86,7 @@ void tst_ForeignWindow::embedForeignWindow() // As a prerequisite to that, we must be able to reparent the foreign window std::unique_ptr foreignWindow(QWindow::fromWinId(nativeWindow)); foreignWindow.release()->setParent(&parentWindow); - QCOMPARE(nativeWindow.parentWinId(), parentWindow.winId()); + QTRY_COMPARE(nativeWindow.parentWinId(), parentWindow.winId()); } #include diff --git a/tests/manual/embeddedwindows/CMakeLists.txt b/tests/manual/embeddedwindows/CMakeLists.txt index e25f14206e8..814398631ec 100644 --- a/tests/manual/embeddedwindows/CMakeLists.txt +++ b/tests/manual/embeddedwindows/CMakeLists.txt @@ -8,6 +8,10 @@ qt_internal_add_manual_test(embeddedwindows Qt::Gui ) +if(QT_FEATURE_xcb) + target_link_libraries(embeddedwindows PRIVATE XCB::XCB) +endif() + if(APPLE) enable_language(OBJCXX) set_source_files_properties(main.cpp PROPERTIES LANGUAGE OBJCXX) diff --git a/tests/manual/embeddedwindows/main.cpp b/tests/manual/embeddedwindows/main.cpp index 0bc2901d69c..db91d90387a 100644 --- a/tests/manual/embeddedwindows/main.cpp +++ b/tests/manual/embeddedwindows/main.cpp @@ -3,7 +3,7 @@ #include -#if defined(Q_OS_MACOS) || defined(Q_OS_IOS) || defined(Q_OS_WIN) +#if defined(Q_OS_MACOS) || defined(Q_OS_IOS) || defined(Q_OS_WIN) || QT_CONFIG(xcb) #include "../../shared/nativewindow.h" #define HAVE_NATIVE_WINDOW #endif diff --git a/tests/shared/nativewindow.h b/tests/shared/nativewindow.h index 1ab5fc40ced..087b7da0fc6 100644 --- a/tests/shared/nativewindow.h +++ b/tests/shared/nativewindow.h @@ -12,6 +12,8 @@ # define VIEW_BASE UIView #elif defined(Q_OS_WIN) # include +#elif QT_CONFIG(xcb) +# include #endif class NativeWindow @@ -21,7 +23,7 @@ public: NativeWindow(); ~NativeWindow(); - operator WId() const { return reinterpret_cast(m_handle); } + operator WId() const; WId parentWinId() const; void setGeometry(const QRect &rect); @@ -32,6 +34,8 @@ private: VIEW_BASE *m_handle = nullptr; #elif defined(Q_OS_WIN) HWND m_handle = nullptr; +#elif QT_CONFIG(xcb) + xcb_window_t m_handle = 0; #endif }; @@ -78,6 +82,11 @@ QRect NativeWindow::geometry() const return QRectF::fromCGRect(m_handle.frame).toRect(); } +NativeWindow::operator WId() const +{ + return reinterpret_cast(m_handle); +} + WId NativeWindow::parentWinId() const { return WId(m_handle.superview); @@ -122,11 +131,78 @@ QRect NativeWindow::geometry() const return {}; } +NativeWindow::operator WId() const +{ + return reinterpret_cast(m_handle); +} + WId NativeWindow::parentWinId() const { return WId(GetAncestor(m_handle, GA_PARENT)); } +#elif QT_CONFIG(xcb) + +struct Connection +{ + Connection() : m_connection(xcb_connect(nullptr, nullptr)) {} + ~Connection() { xcb_disconnect(m_connection); } + operator xcb_connection_t*() const { return m_connection; } + xcb_connection_t *m_connection = nullptr; +}; + +static Connection connection; + +NativeWindow::NativeWindow() +{ + m_handle = xcb_generate_id(connection); + + xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data; + + xcb_create_window(connection, XCB_COPY_FROM_PARENT, m_handle, + screen->root, 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, XCB_CW_BACK_PIXEL, + (const uint32_t []){ 0xffffaaff }); + + xcb_flush(connection); +} + +NativeWindow::~NativeWindow() +{ + xcb_destroy_window(connection, m_handle); +} + +void NativeWindow::setGeometry(const QRect &rect) +{ + const quint32 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y + | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; + const qint32 values[] = { rect.x(), rect.y(), rect.width(), rect.height() }; + xcb_configure_window(connection, m_handle, mask, + reinterpret_cast(values)); + xcb_flush(connection); +} + +QRect NativeWindow::geometry() const +{ + xcb_get_geometry_reply_t *geometry = xcb_get_geometry_reply( + connection, xcb_get_geometry(connection, m_handle), nullptr); + const auto cleanup = qScopeGuard([&]{ free(geometry); }); + return QRect(geometry->x, geometry->y, geometry->width, geometry->height); +} + +NativeWindow::operator WId() const +{ + return m_handle; +} + +WId NativeWindow::parentWinId() const +{ + xcb_query_tree_reply_t *tree = xcb_query_tree_reply( + connection, xcb_query_tree(connection, m_handle), nullptr); + const auto cleanup = qScopeGuard([&]{ free(tree); }); + return tree->parent; +} + #endif #endif // NATIVEWINDOW_H