| | |
| | | |
| | | namespace QWK { |
| | | |
| | | static inline bool isWindows1022H2OrGreater() { |
| | | RTL_OSVERSIONINFOW rovi = Private::GetRealOSVersion(); |
| | | return (rovi.dwMajorVersion > 10) || |
| | | (rovi.dwMajorVersion == 10 && |
| | | (rovi.dwMinorVersion > 0 || rovi.dwBuildNumber >= 19045)); |
| | | } |
| | | |
| | | #if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDERS) |
| | | |
| | | class BorderItem : public QQuickPaintedItem, public Windows10BorderHandler { |
| | |
| | | explicit BorderItem(QQuickItem *parent, AbstractWindowContext *context); |
| | | ~BorderItem() override; |
| | | |
| | | bool shouldEnableEmulatedPainter() const; |
| | | void updateGeometry() override; |
| | | |
| | | public: |
| | |
| | | |
| | | protected: |
| | | bool sharedEventFilter(QObject *obj, QEvent *event) override; |
| | | |
| | | # if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) |
| | | volatile bool needPaint = false; |
| | | bool nativeEventFilter(const QByteArray &eventType, void *message, |
| | | QT_NATIVE_EVENT_RESULT_TYPE *result) override; |
| | | |
| | | private: |
| | | volatile bool needPaint = false; |
| | | |
| | | void _q_afterSynchronizing(); |
| | | # endif |
| | | void _q_windowActivityChanged(); |
| | | }; |
| | | |
| | | bool BorderItem::shouldEnableEmulatedPainter() const { |
| | | # if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) |
| | | const QQuickWindow* win = window(); |
| | | if (!win) { |
| | | return true; |
| | | } |
| | | auto api = win->rendererInterface()->graphicsApi(); |
| | | switch (api) { |
| | | case QSGRendererInterface::OpenGL: |
| | | // FIXME: experimental, try to find the exact fixed version. |
| | | return !isWindows1022H2OrGreater(); |
| | | case QSGRendererInterface::Direct3D11: |
| | | # if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) |
| | | case QSGRendererInterface::Direct3D12: |
| | | # endif |
| | | return false; |
| | | default: |
| | | break; |
| | | } |
| | | # endif |
| | | return true; |
| | | } |
| | | |
| | | BorderItem::BorderItem(QQuickItem *parent, AbstractWindowContext *context) |
| | | : QQuickPaintedItem(parent), Windows10BorderHandler(context) { |
| | |
| | | connect(window(), &QQuickWindow::afterSynchronizing, this, |
| | | &BorderItem::_q_afterSynchronizing, Qt::DirectConnection); |
| | | # endif |
| | | connect(window(), &QQuickWindow::activeChanged, this, |
| | | &BorderItem::_q_windowActivityChanged); |
| | | |
| | | // First update |
| | | if (context->windowId()) { |
| | |
| | | BorderItem::~BorderItem() = default; |
| | | |
| | | void BorderItem::updateGeometry() { |
| | | setHeight(borderThickness()); |
| | | const QQuickWindow* win = window(); |
| | | if (!win) { |
| | | return; |
| | | } |
| | | setHeight(borderThickness() / win->effectiveDevicePixelRatio()); |
| | | setVisible(isNormalWindow()); |
| | | } |
| | | |
| | | void BorderItem::paint(QPainter *painter) { |
| | | Q_UNUSED(painter) |
| | | |
| | | # if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) |
| | | if (auto api = window()->rendererInterface()->graphicsApi(); |
| | | !(api == QSGRendererInterface::Direct3D11 || api == QSGRendererInterface::Direct3D12)) { |
| | | # endif |
| | | QRect rect(QPoint(0, 0), size().toSize()); |
| | | QRegion region(rect); |
| | | void *args[] = { |
| | | painter, |
| | | &rect, |
| | | ®ion, |
| | | }; |
| | | ctx->virtual_hook(AbstractWindowContext::DrawWindows10BorderHook, args); |
| | | # if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) |
| | | if (shouldEnableEmulatedPainter()) { |
| | | drawBorderEmulated(painter, QRect({0, 0}, size().toSize())); |
| | | } else { |
| | | needPaint = true; |
| | | } |
| | | # endif |
| | | } |
| | | |
| | | void BorderItem::itemChange(ItemChange change, const ItemChangeData &data) { |
| | |
| | | return Windows10BorderHandler::sharedEventFilter(obj, event); |
| | | } |
| | | |
| | | # if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) |
| | | bool BorderItem::nativeEventFilter(const QByteArray &eventType, void *message, |
| | | QT_NATIVE_EVENT_RESULT_TYPE *result) { |
| | | const auto msg = static_cast<const MSG *>(message); |
| | | switch (msg->message) { |
| | | case WM_THEMECHANGED: |
| | | case WM_SYSCOLORCHANGE: |
| | | case WM_DWMCOLORIZATIONCOLORCHANGED: { |
| | | update(); |
| | | break; |
| | | } |
| | | |
| | | case WM_SETTINGCHANGE: { |
| | | if (isImmersiveColorSetChange(msg->wParam, msg->lParam)) { |
| | | update(); |
| | | } |
| | | break; |
| | | } |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | return Windows10BorderHandler::nativeEventFilter(eventType, message, result); |
| | | } |
| | | |
| | | void BorderItem::_q_afterSynchronizing() { |
| | | if (needPaint) { |
| | | needPaint = false; |
| | | drawBorder(); |
| | | drawBorderNative(); |
| | | } |
| | | } |
| | | # endif |
| | | |
| | | void BorderItem::_q_windowActivityChanged() { |
| | | update(); |
| | | } |
| | | |
| | | void QuickWindowAgentPrivate::setupWindows10BorderWorkaround() { |
| | | // Install painting hook |