I am writing a cross-platform web browser in Qt because it has built-in WebKit support through QWebView or the more modern QWebEngineView. To get compact window chrome, I want to disable my own window title bar and border through Qt :: FramelessWindowHint, but still get my own behavior, such as resizing and Windows Aero Snap.
First I trimmed the PKE BorderlessWindow demo. This worked fine: on Windows 8.1 x64, the window can be resized, the custom title bar can be dragged or double-clicked, and Aero Snap will work.
Then I tried replacing the central QLabel with a QWebEngineView. This led to the appearance of gray borders of my own size around my window. When I have interactive widgets at the top of the window (for example, menus or toolbars), the ghost title bar with QWebEngineView repels them, but accepts cursor clicks in their place.
Here is a screenshot comparing two windows. (Look at the dark background to better see the light gray frame on the right.)

Is QWebEngineView generally compatible with a frameless window, or should I deal with the lost chrome built-in space?
Edit: Replacing QWebEngineView with QWebView fixes this problem:

However, WebView is deprecated, and WebEngine has more useful features:
- Renders with Chromium Blink instead of Safari WebKit
- Multiprocessor, so you can run Javascript without blocking the user interface
- Do not leak information about browser plug-ins in Panopticlick (try QWebView populates navigator.plugins in Javascript, but QWebEngineView doesn't)
However, I would prefer not to waste space on the native title, so if QWebEngineView can be made to work with a frameless window, I would like to know how to do it.
mainwindow.h:
#include <QtWidgets> #include <QToolBar> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(); protected: void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; bool nativeEvent(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE; private: QToolBar *titleBar; };
mainwindow.cpp:
#include <QtWidgets> #include <QLabel> #include <QWebEngineView> #include <windows.h> #include <windowsx.h> #include "mainwindow.h" MainWindow::MainWindow() : QMainWindow() { setWindowFlags(windowFlags() | Qt::FramelessWindowHint); titleBar = addToolBar(tr("Title Bar")); titleBar->setIconSize(QSize(16, 16)); titleBar->setFloatable(false); titleBar->setMovable(false); titleBar->setStyleSheet("QToolBar { background: red; border: 0; padding: 0; }"); titleBar->addWidget(new QLabel("Title Bar", titleBar)); // Try QLabel... QLabel *central = new QLabel("Hello World"); // ...or QWebEngineView //QWebEngineView *central = new QWebEngineView(this); //central->load(QUrl("http://www.google.com")); setCentralWidget(central); resize(320, 240); } bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result) { Q_UNUSED(eventType); MSG *msg = (MSG *)message; HWND hwnd = isVisible() ? (HWND)winId() : NULL; LPARAM lparam = msg->lParam; const LONG border_width = 4; RECT winrect; long x, y; switch (msg->message) { case WM_NCCALCSIZE: result = 0; return true; case WM_NCHITTEST: GetWindowRect(hwnd, &winrect); x = GET_X_LPARAM(lparam); y = GET_Y_LPARAM(lparam); if (x >= winrect.left && x < winrect.left + border_width && y < winrect.bottom && y >= winrect.bottom - border_width) *result = HTBOTTOMLEFT; else if (x < winrect.right && x >= winrect.right - border_width && y < winrect.bottom && y >= winrect.bottom - border_width) *result = HTBOTTOMRIGHT; else if (x >= winrect.left && x < winrect.left + border_width && y >= winrect.top && y < winrect.top + border_width) *result = HTTOPLEFT; else if (x < winrect.right && x >= winrect.right - border_width && y >= winrect.top && y < winrect.top + border_width) *result = HTTOPRIGHT; else if (x >= winrect.left && x < winrect.left + border_width) *result = HTLEFT; else if (x < winrect.right && x >= winrect.right - border_width) *result = HTRIGHT; else if (y < winrect.bottom && y >= winrect.bottom - border_width) *result = HTBOTTOM; else if (y >= winrect.top && y < winrect.top + border_width) *result = HTTOP; else if (titleBar->underMouse()) *result = HTCAPTION; else break; return true; } return QMainWindow::nativeEvent(eventType, message, result); } void MainWindow::showEvent(QShowEvent *event) { Q_UNUSED(event); HWND hwnd = (HWND)winId(); DWORD newStyle = WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; SetWindowLongPtr(hwnd, GWL_STYLE, static_cast<LONG>(newStyle)); SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); ShowWindow(hwnd, SW_SHOW); }
main.cpp:
#include <QtWidgets> #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow *window = new MainWindow(); window->show(); return app.exec(); }
example.pro:
QT += core gui widgets webenginewidgets msvc:LIBS += -luser32 TEMPLATE = app SOURCES += main.cpp \ mainwindow.cpp HEADERS += mainwindow.h