diff options
Diffstat (limited to 'tests/shared')
-rw-r--r-- | tests/shared/fakedirmodel.h | 29 | ||||
-rw-r--r-- | tests/shared/filesystem.h | 43 | ||||
-rw-r--r-- | tests/shared/localechange.h | 88 | ||||
-rw-r--r-- | tests/shared/nativewindow.h | 304 |
4 files changed, 406 insertions, 58 deletions
diff --git a/tests/shared/fakedirmodel.h b/tests/shared/fakedirmodel.h index d82ec21ee5..4e28aae431 100644 --- a/tests/shared/fakedirmodel.h +++ b/tests/shared/fakedirmodel.h @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** 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 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef FAKEDIRMODEL_H #define FAKEDIRMODEL_H diff --git a/tests/shared/filesystem.h b/tests/shared/filesystem.h index c043493ab4..23453054a3 100644 --- a/tests/shared/filesystem.h +++ b/tests/shared/filesystem.h @@ -1,43 +1,19 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** 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 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef QT_TESTS_SHARED_FILESYSTEM_H_INCLUDED #define QT_TESTS_SHARED_FILESYSTEM_H_INCLUDED +#include <QDir> +#include <QFile> +#include <QOperatingSystemVersion> +#include <QScopedPointer> #include <QString> #include <QStringList> #include <QTemporaryDir> -#include <QScopedPointer> -#include <QDir> -#include <QFile> #if defined(Q_OS_WIN) -#include <windows.h> +#include <qt_windows.h> #include <winioctl.h> #ifndef IO_REPARSE_TAG_MOUNT_POINT #define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) @@ -49,6 +25,11 @@ #ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE // MinGW #define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2) #endif +QT_BEGIN_NAMESPACE +namespace QTest { + static QString uncServerName() { return qgetenv("COMPUTERNAME"); } +} +QT_END_NAMESPACE #endif // QTemporaryDir-based helper class for creating file-system hierarchies and cleaning up. diff --git a/tests/shared/localechange.h b/tests/shared/localechange.h new file mode 100644 index 0000000000..74ed444ba6 --- /dev/null +++ b/tests/shared/localechange.h @@ -0,0 +1,88 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef QT_TESTS_SHARED_LOCALE_CHANGE_H +#define QT_TESTS_SHARED_LOCALE_CHANGE_H +#include <qglobal.h> +#include <QtCore/QByteArray> +#include <QtCore/QLocale> +#include <private/qlocale_p.h> + +#include <locale.h> + +namespace QTestLocaleChange { + + inline QLocale resetSystemLocale() + { +#ifndef QT_NO_SYSTEMLOCALE + { // Transient instance marks system locale data as stale: + QSystemLocale dummy; + } // Now we can reinitialize: +#endif + return QLocale::system(); + } + + class TransientLocale + { + const int m_category; + const QByteArray m_prior; + const bool m_didSet; +#if !defined(QT_NO_SYSTEMLOCALE) && defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) +#define TRANSIENT_ENV + // Unix system locale consults environment variables, so we need to set + // the appropriate one, too. + const QByteArray m_envVar, m_envPrior; + const bool m_envSet; + static QByteArray categoryToEnv(int category) + { + switch (category) { +#define CASE(cat) case cat: return #cat + CASE(LC_ALL); CASE(LC_NUMERIC); CASE(LC_TIME); CASE(LC_MONETARY); + CASE(LC_MESSAGES); CASE(LC_COLLATE); +#ifdef LC_MEASUREMENT + CASE(LC_MEASUREMENT); +#endif +#undef CASE + // Nothing in our code pays attention to any other LC_* + default: + Q_UNREACHABLE(); + qFatal("You need to add a case for this category"); + } + } +#endif // TRANSIENT_ENV + public: + TransientLocale(int category, const char *locale) + : m_category(category), + m_prior(setlocale(category, nullptr)), + // That return value may be stomped by this later call, so we copy + // it to a QByteArray for safe keeping. + m_didSet(setlocale(category, locale) != nullptr) +#ifdef TRANSIENT_ENV + , m_envVar(categoryToEnv(category)), + m_envPrior(qgetenv(m_envVar.constData())), + m_envSet(qputenv(m_envVar.constData(), locale)) +#endif + { + resetSystemLocale(); + } + ~TransientLocale() + { +#ifdef TRANSIENT_ENV + if (m_envSet) { + if (m_envPrior.isEmpty()) + qunsetenv(m_envVar.constData()); + else + qputenv(m_envVar.constData(), m_envPrior); + } +#endif + if (m_prior.size()) + setlocale(m_category, m_prior.constData()); + resetSystemLocale(); + } +#undef TRANSIENT_ENV + + bool isValid() const { return m_didSet; } + }; +} + +#endif // QT_TESTS_SHARED_LOCALE_CHANGE_H diff --git a/tests/shared/nativewindow.h b/tests/shared/nativewindow.h new file mode 100644 index 0000000000..163ca31634 --- /dev/null +++ b/tests/shared/nativewindow.h @@ -0,0 +1,304 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef NATIVEWINDOW_H +#define NATIVEWINDOW_H + +#if defined(Q_OS_MACOS) +# include <AppKit/AppKit.h> +# define VIEW_BASE NSView +#elif defined(Q_OS_IOS) +# include <UIKit/UIKit.h> +# define VIEW_BASE UIView +#elif defined(Q_OS_WIN) +# include <QtCore/qt_windows.h> +#elif QT_CONFIG(xcb) +# include <xcb/xcb.h> +#elif defined(ANDROID) +# include <QtCore/qjniobject.h> +# include <QtCore/qjnitypes.h> +# include <QtCore/qnativeinterface.h> +Q_DECLARE_JNI_CLASS(View, "android/view/View") +Q_DECLARE_JNI_CLASS(ViewParent, "android/view/ViewParent") +#endif + +class NativeWindow +{ + Q_DISABLE_COPY(NativeWindow) +public: +#if defined(Q_OS_MACOS) + using Handle = NSView*; +#elif defined(QT_PLATFORM_UIKIT) + using Handle = UIView*; +#elif defined(Q_OS_WIN) + using Handle = HWND; +#elif QT_CONFIG(xcb) + using Handle = xcb_window_t; +#elif defined(ANDROID) + using Handle = QtJniTypes::View; +#endif + + NativeWindow(); + ~NativeWindow(); + + operator WId() const; + WId parentWinId() const; + bool isParentOf(WId childWinId); + void setParent(WId parent); + + void setGeometry(const QRect &rect); + QRect geometry() const; + +private: + Handle m_handle = {}; +}; + +#if defined(Q_OS_MACOS) || defined(QT_PLATFORM_UIKIT) + +@interface View : VIEW_BASE +@end + +@implementation View +- (instancetype)init +{ + if ((self = [super init])) { +#if defined(Q_OS_MACOS) + self.wantsLayer = YES; +#endif + self.layer.backgroundColor = CGColorCreateGenericRGB(1.0, 0.5, 1.0, 1.0); + } + return self; +} + +- (void)dealloc +{ + [super dealloc]; +} +@end + +NativeWindow::NativeWindow() + : m_handle([View new]) +{ +} + +NativeWindow::~NativeWindow() +{ + [m_handle release]; +} + +void NativeWindow::setGeometry(const QRect &rect) +{ + m_handle.frame = QRectF(rect).toCGRect(); +} + +QRect NativeWindow::geometry() const +{ + return QRectF::fromCGRect(m_handle.frame).toRect(); +} + +NativeWindow::operator WId() const +{ + return reinterpret_cast<WId>(m_handle); +} + +WId NativeWindow::parentWinId() const +{ + return WId(m_handle.superview); +} + +bool NativeWindow::isParentOf(WId childWinId) +{ + auto *subview = reinterpret_cast<Handle>(childWinId); + return subview.superview == m_handle; +} + +void NativeWindow::setParent(WId parent) +{ + if (auto *superview = reinterpret_cast<Handle>(parent)) + [superview addSubview:m_handle]; + else + [m_handle removeFromSuperview]; +} + +#elif defined(Q_OS_WIN) + +NativeWindow::NativeWindow() +{ + static const LPCWSTR className = []{ + WNDCLASS wc = {}; + wc.lpfnWndProc = DefWindowProc; + wc.hInstance = GetModuleHandle(nullptr); + wc.lpszClassName = L"Native Window"; + wc.hbrBackground = CreateSolidBrush(RGB(255, 128, 255)); + RegisterClass(&wc); + return wc.lpszClassName; + }(); + m_handle = CreateWindowEx(0, className, nullptr, WS_POPUP, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + nullptr, nullptr, GetModuleHandle(nullptr), nullptr); +} + +NativeWindow::~NativeWindow() +{ + DestroyWindow(m_handle); +} + +void NativeWindow::setGeometry(const QRect &rect) +{ + MoveWindow(m_handle, rect.x(), rect.y(), rect.width(), rect.height(), false); +} + +QRect NativeWindow::geometry() const +{ + WINDOWPLACEMENT wp; + wp.length = sizeof(WINDOWPLACEMENT); + if (GetWindowPlacement(m_handle, &wp)) { + RECT r = wp.rcNormalPosition; + return QRect(r.left, r.top, r.right - r.left, r.bottom - r.top); + } + return {}; +} + +NativeWindow::operator WId() const +{ + return reinterpret_cast<WId>(m_handle); +} + +WId NativeWindow::parentWinId() const +{ + return WId(GetAncestor(m_handle, GA_PARENT)); +} + +bool NativeWindow::isParentOf(WId childWinId) +{ + return GetAncestor(Handle(childWinId), GA_PARENT) == m_handle; +} + +void NativeWindow::setParent(WId parent) +{ + SetParent(m_handle, Handle(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<const quint32*>(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 ? tree->parent : 0; +} + +bool NativeWindow::isParentOf(WId childWinId) +{ + xcb_query_tree_reply_t *tree = xcb_query_tree_reply( + connection, xcb_query_tree(connection, Handle(childWinId)), nullptr); + const auto cleanup = qScopeGuard([&]{ free(tree); }); + return tree->parent == m_handle; +} + +void NativeWindow::setParent(WId parent) +{ + xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data; + + xcb_reparent_window(connection, m_handle, + parent ? Handle(parent) : screen->root, 0, 0); +} + +#elif defined (ANDROID) +NativeWindow::NativeWindow() +{ + m_handle = QJniObject::construct<QtJniTypes::View, QtJniTypes::Context>( + QNativeInterface::QAndroidApplication::context()); + m_handle.callMethod<void>("setBackgroundColor", 0xffffaaff); +} + +NativeWindow::~NativeWindow() +{ +} + +NativeWindow::operator WId() const +{ + return reinterpret_cast<WId>(m_handle.object()); +} + +void NativeWindow::setGeometry(const QRect &rect) +{ + // No-op, the view geometry is handled by the QWindow constructed from it +} + +QRect NativeWindow::geometry() const +{ + int x = m_handle.callMethod<jint>("getX"); + int y = m_handle.callMethod<jint>("getY"); + int w = m_handle.callMethod<jint>("getWidth"); + int h = m_handle.callMethod<jint>("getHeight"); + return QRect(x, y, w, h); +} + +WId NativeWindow::parentWinId() const +{ + // TODO note, the returned object is a ViewParent, not necessarily + // a View - what is this used for? + using namespace QtJniTypes; + ViewParent parentView = m_handle.callMethod<ViewParent>("getParent"); + if (parentView.isValid()) + return reinterpret_cast<WId>(parentView.object()); + return 0L; +} + +#endif + +#endif // NATIVEWINDOW_H |