Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix native child widget #133

Merged
merged 2 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,17 +276,14 @@ See [examples](examples) for more demo use cases. The examples have no High DPI
- Once you have made the window frameless, it will not be able to switch back to the system frame again unless you destroy your window and recreate it with different settings.

#### Native Child Widget
- There **must not** be any internal child widget with `Qt::WA_NativeWindow` property enabled, otherwise the native features and display may be abnormal. Therefore, do not set any widget that has called `QWidget::winId()` or `QWidget::setAttribute(Qt::WA_NativeWindow)` as a descendant of a frameless window.
- If you really need to move widgets between different windows, make sure that the widget is not a top-level window and wrap it with a frameless container window.
- If you are about to add a widget with `Qt::WA_NativeWindow` property enabled as a descendent of the frameless window, you should enable `Qt::WA_DontCreateNativeAncestors` of it in advance.

#### Size Constrains
- If you want to disable window resizing, you can set a fixed size, which is officially supported by QWindowKit. If you use other special means to achieve this, QWK doesn't guarantee everything can still be fully functional.
- If you set a maximized width or height, the window should not be maximized because you cannot get the correct window size through Qt APIs. You may workaround this by using system APIs such as `GetWindowRect` or `GetClientRect`. The root cause lies deep in Qt QPA implementations and currently we don't know how to fix it without modifying Qt itself.

#### Windows 10

- Due to the inherent defects in the Windows 10 window system, the top border will disappear when the system title bar is removed. We have filtered Qt's event and perfectly reshown the system top border, thanks to the implementation of Windows Terminal for our reference. However, this workaround only works with QtWidgets and QtQuick (**only when rendering through D3D**) applications.

- In QtQuick applications that use OpenGL or other rendering backends, we use Qt's painting system to emulate this border. But since Windows 10 system border is translucent, the difference from the system border is more noticeable in a dark background.

## TODO
Expand Down
21 changes: 13 additions & 8 deletions src/core/contexts/win32windowcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -834,9 +834,7 @@ namespace QWK {
}

if (key == QStringLiteral("title-bar-height")) {
return m_windowId
? int(getTitleBarHeight(reinterpret_cast<HWND>(m_windowId)))
: 0;
return m_windowId ? int(getTitleBarHeight(reinterpret_cast<HWND>(m_windowId))) : 0;
}
return AbstractWindowContext::windowAttribute(key);
}
Expand Down Expand Up @@ -1695,7 +1693,8 @@ namespace QWK {
// outside the window, that is, the three transparent window resize area.
// Returning HTCLIENT will confuse Windows, we can't put our controls there
// anyway.
*result = HTNOWHERE; // Make sure we can know we don't set any value explicitly later.
*result = HTNOWHERE; // Make sure we can know we don't set any value
// explicitly later.
if (originalHitTestResult == HTCAPTION) {
} else if (isFixedSize || dontOverrideCursor) {
*result = HTBORDER;
Expand Down Expand Up @@ -1724,11 +1723,13 @@ namespace QWK {
} else {
*result = HTLEFT;
}
} else if (originalHitTestResult == HTLEFT || originalHitTestResult == HTRIGHT) {
} else if (originalHitTestResult == HTLEFT ||
originalHitTestResult == HTRIGHT) {
if (isFixedWidth) {
*result = HTBORDER;
}
} else if (originalHitTestResult == HTTOP || originalHitTestResult == HTBOTTOM) {
} else if (originalHitTestResult == HTTOP ||
originalHitTestResult == HTBOTTOM) {
if (isFixedHeight) {
*result = HTBORDER;
}
Expand Down Expand Up @@ -1757,7 +1758,8 @@ namespace QWK {
// inside our homemade title bar now, return HTCLIENT to let our
// title bar can still capture mouse events.
*result = [&]() {
if (isFixedSize || isFixedHeight || dontOverrideCursor || (isFixedWidth && (isInLeftBorder || isInRightBorder))) {
if (isFixedSize || isFixedHeight || dontOverrideCursor ||
(isFixedWidth && (isInLeftBorder || isInRightBorder))) {
if (isInTitleBar) {
return HTCAPTION;
} else {
Expand Down Expand Up @@ -2173,7 +2175,10 @@ namespace QWK {
// of the upper-left non-client area. It's confirmed that this issue exists
// from Windows 7 to Windows 10. Not tested on Windows 11 yet. Don't know
// whether it exists on Windows XP to Windows Vista or not.
*result = wParam ? WVR_REDRAW : FALSE;

// https://github.com/chromium/chromium/blob/5d297da3cf2a642e9ace2b23fed097370bc70814/ui/views/win/hwnd_message_handler.cc#L2330
// Do not return WVR_REDRAW otherwise child HWNDs will be mispositioned.
*result = FALSE;
return true;
}

Expand Down