如何在Linux系统中调整嵌入Qt的CEF浏览器的位置与大小
Let's break down why your current code isn't working and walk through the correct approach to adjust the CEF browser's position and size in your Qt application.
What's Wrong With Your Current Code?
The biggest issue in your resize logic is this line:
hwnd_ = parent_xwindow;
You're replacing the actual CEF browser window handle with the root X11 window (the entire screen), so all your XMoveResizeWindow calls are trying to resize the desktop instead of your CEF widget. Even if you removed that line, you'd still need to tell CEF internally that its window size changed—direct X11 calls alone won't trigger CEF's rendering layout updates.
Step-by-Step Solution
1. Fix the Window Handle & Use CEF Native Methods
Replace your invalid resize loop with code that targets the actual CEF browser window and uses CEF's built-in methods to handle size changes:
void CefWidget::updateCefBrowserGeometry() { // Get the Qt widget's client area (excludes borders/title bars) QRect client_rect = this->contentsRect(); CefRect cef_rect(client_rect.x(), client_rect.y(), client_rect.width(), client_rect.height()); for (auto browser : m_browserlist) { if (!browser || !browser->GetHost()) continue; CefWindowHandle cef_hwnd = browser->GetHost()->GetWindowHandle(); if (!cef_hwnd) continue; // Update CEF's internal bounds browser->GetHost()->SetBounds(cef_rect); // Tell CEF to refresh its rendering layout browser->GetHost()->WasResized(); // Optional: If you still need X11 calls (rarely necessary), use the actual CEF handle // Display* disp = cef_get_xdisplay(); // XMoveResizeWindow(disp, static_cast<Window>(cef_hwnd), client_rect.x(), client_rect.y(), client_rect.width(), client_rect.height()); // XSync(disp, false); } }
2. Sync CEF With Qt's Window Events
Qt widgets emit events when resized or moved—hook into these to automatically update CEF:
// Add these overrides to your CefWidget class void CefWidget::resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); updateCefBrowserGeometry(); } void CefWidget::moveEvent(QMoveEvent* event) { QWidget::moveEvent(event); updateCefBrowserGeometry(); } void CefWidget::showEvent(QShowEvent* event) { QWidget::showEvent(event); // Create CEF browser AFTER the Qt widget is shown (winId() is only valid post-show) if (!browser_) { CefWindowInfo window_info; WId qt_hwnd = winId(); QRect client_rect = contentsRect(); window_info.SetAsChild(static_cast<CefWindowHandle>(qt_hwnd), CefRect(client_rect.x(), client_rect.y(), client_rect.width(), client_rect.height())); CefBrowserSettings browser_settings; browser_settings.webgl = STATE_ENABLED; CefRefPtr<CefWidget> handler = this; browser_ = CefBrowserHost::CreateBrowserSync(window_info, handler, "https://your-url-here.com", browser_settings, nullptr, nullptr); m_browserlist.push_back(browser_); } }
3. Key Notes for Success
- Use
contentsRect()instead ofgeometry():geometry()includes the Qt widget's borders and title bar, whilecontentsRect()gives you the actual client area where CEF should render. - Always call
WasResized(): This tells CEF to recalculate its rendering viewport and refresh the content—without it, CEF will keep rendering at the old size even if the window is resized. - Create CEF after Qt widget is shown: The
winId()of a Qt widget is only valid once the widget is visible. Creating CEF inshowEvent()ensures you have a valid window handle to pass toSetAsChild.
Final Checks
- Verify your CEF command-line args don't interfere with window management: Your current args (like
--no-sandbox) are fine, but ensure you don't have any flags that disable window resizing. - Test with a simple layout: Start with a plain Qt widget (no complex layouts) to confirm CEF resizes correctly, then add back your layout logic.
内容的提问来源于stack exchange,提问作者Zoey

