From fd4f105f9e5c197eb9413486ebed5beda02cf648 Mon Sep 17 00:00:00 2001 From: amrbashir Date: Wed, 19 Aug 2026 06:12:57 +0300 Subject: [PATCH 1/2] Support transparency in Views framework and native embedding --- cef_paths2.gypi | 1 + include/internal/cef_types.h | 8 +++-- libcef/browser/browser_host_base.cc | 3 +- .../browser_platform_delegate_create.cc | 14 ++++---- libcef/browser/context.cc | 36 +++++++++---------- libcef/browser/context.h | 9 ++--- .../browser/native/native_widget_delegate.cc | 4 ++- libcef/browser/views/window_view.cc | 21 +++++++++++ tests/cefclient/browser/main_context_impl.cc | 2 ++ tests/cefclient/browser/resource.h | 13 +++---- .../browser/resource_util_win_idmap.cc | 1 + tests/cefclient/browser/views_window.cc | 6 ++++ .../resources/transparency_demo.html | 30 ++++++++++++++++ tests/cefclient/win/cefclient.rc | 1 + tests/shared/common/client_switches.cc | 1 + tests/shared/common/client_switches.h | 1 + 16 files changed, 112 insertions(+), 39 deletions(-) create mode 100644 tests/cefclient/resources/transparency_demo.html diff --git a/cef_paths2.gypi b/cef_paths2.gypi index 299c1cea9c..d821bc34ae 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -358,6 +358,7 @@ 'tests/cefclient/resources/server.html', 'tests/cefclient/resources/task_manager.html', 'tests/cefclient/resources/transparency.html', + 'tests/cefclient/resources/transparency_demo.html', 'tests/cefclient/resources/urlrequest.html', 'tests/cefclient/resources/websocket.html', 'tests/cefclient/resources/window.html', diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h index 7e00f3d6fa..50d4d9d50d 100644 --- a/include/internal/cef_types.h +++ b/include/internal/cef_types.h @@ -443,8 +443,9 @@ typedef struct _cef_settings_t { /// opaque then the RGB components will be used as the background color. If /// the alpha component is fully transparent for a windowed browser then the /// default value of opaque white be used. If the alpha component is fully - /// transparent for a windowless (off-screen) browser then transparent - /// painting will be enabled. + /// transparent for a windowless (off-screen) browser, a frameless window + /// using Views framework or a Alloy-style browser then transparent painting + /// will be enabled. /// cef_color_t background_color; @@ -704,7 +705,8 @@ typedef struct _cef_browser_settings_t { /// opaque then the RGB components will be used as the background color. If /// the alpha component is fully transparent for a windowed browser then the /// CefSettings.background_color value will be used. If the alpha component is - /// fully transparent for a windowless (off-screen) browser then transparent + /// fully transparent for a windowless (off-screen) browser, a frameless + /// window using Views framework or a Alloy-style browser then transparent /// painting will be enabled. /// cef_color_t background_color; diff --git a/libcef/browser/browser_host_base.cc b/libcef/browser/browser_host_base.cc index c9f84e5039..b666a4f457 100644 --- a/libcef/browser/browser_host_base.cc +++ b/libcef/browser/browser_host_base.cc @@ -1535,7 +1535,8 @@ int CefBrowserHostBase::browser_id() const { SkColor CefBrowserHostBase::GetBackgroundColor() const { // Don't use |platform_delegate_| because it's not thread-safe. return CefContext::Get()->GetBackgroundColor( - &settings_, IsWindowless() ? STATE_ENABLED : STATE_DISABLED); + &settings_, + IsWindowless() || is_views_hosted() ? STATE_ENABLED : STATE_DISABLED); } content::WebContents* CefBrowserHostBase::GetWebContents() const { diff --git a/libcef/browser/browser_platform_delegate_create.cc b/libcef/browser/browser_platform_delegate_create.cc index b2f30ae0a0..7cd3f745b6 100644 --- a/libcef/browser/browser_platform_delegate_create.cc +++ b/libcef/browser/browser_platform_delegate_create.cc @@ -67,10 +67,14 @@ std::unique_ptr CreateOSRDelegate( std::unique_ptr CefBrowserPlatformDelegate::Create( const CefBrowserCreateParams& create_params) { const bool is_windowless = create_params.IsWindowless(); + const bool is_chrome = create_params.IsChromeStyle(); + const bool is_views_hosted = create_params.browser_view || + create_params.popup_with_views_hosted_opener; + const bool is_transparent = is_windowless || is_views_hosted || !is_chrome; const SkColor background_color = CefContext::Get()->GetBackgroundColor( - &create_params.settings, is_windowless ? STATE_ENABLED : STATE_DISABLED); + &create_params.settings, is_transparent ? STATE_ENABLED : STATE_DISABLED); - if (create_params.IsChromeStyle()) { + if (is_chrome) { CefWindowInfo window_info; if (create_params.window_info) { window_info = *create_params.window_info; @@ -85,8 +89,7 @@ std::unique_ptr CefBrowserPlatformDelegate::Create( return std::make_unique( std::move(native_delegate), static_cast(create_params.browser_view.get())); - } else if (create_params.browser_view || - create_params.popup_with_views_hosted_opener) { + } else if (is_views_hosted) { // CefWindowInfo is not used in this case. return std::make_unique( std::move(native_delegate), @@ -97,8 +100,7 @@ std::unique_ptr CefBrowserPlatformDelegate::Create( std::move(native_delegate)); } - if (create_params.browser_view || - create_params.popup_with_views_hosted_opener) { + if (is_views_hosted) { // CefWindowInfo is not used in this case. std::unique_ptr native_delegate = CreateNativeDelegate(CefWindowInfo(), background_color); diff --git a/libcef/browser/context.cc b/libcef/browser/context.cc index 53abc8dba7..0910958c3e 100644 --- a/libcef/browser/context.cc +++ b/libcef/browser/context.cc @@ -74,14 +74,14 @@ void InitCrashReporter() { #endif // BUILDFLAG(IS_WIN) -bool GetColor(const cef_color_t cef_in, bool is_windowless, SkColor* sk_out) { - // Windowed browser colors must be fully opaque. - if (!is_windowless && CefColorGetA(cef_in) != SK_AlphaOPAQUE) { +bool GetColor(const cef_color_t cef_in, bool is_transparent, SkColor* sk_out) { + // Transparent unsupported browser colors must be fully opaque. + if (!is_transparent && CefColorGetA(cef_in) != SK_AlphaOPAQUE) { return false; } - // Windowless browser colors may be fully transparent. - if (is_windowless && CefColorGetA(cef_in) == SK_AlphaTRANSPARENT) { + // Transparent supported browser colors may be fully transparent. + if (is_transparent && CefColorGetA(cef_in) == SK_AlphaTRANSPARENT) { *sk_out = SK_ColorTRANSPARENT; return true; } @@ -444,19 +444,19 @@ bool CefContext::OnInitThread() { SkColor CefContext::GetBackgroundColor( const CefBrowserSettings* browser_settings, - cef_state_t windowless_state) const { - bool is_windowless = windowless_state == STATE_ENABLED - ? true - : (windowless_state == STATE_DISABLED - ? false - : !!settings_.windowless_rendering_enabled); - - // Default to opaque white if no acceptable color values are found. - SkColor sk_color = SK_ColorWHITE; - - if (!browser_settings || - !GetColor(browser_settings->background_color, is_windowless, &sk_color)) { - GetColor(settings_.background_color, is_windowless, &sk_color); + cef_state_t transparent_state) const { + bool is_transparent = transparent_state == STATE_ENABLED + ? true + : (transparent_state == STATE_DISABLED + ? false + : !!settings_.windowless_rendering_enabled); + + // Default to transparent if no acceptable color values are found. + SkColor sk_color = SK_AlphaTRANSPARENT; + + if (!browser_settings || !GetColor(browser_settings->background_color, + is_transparent, &sk_color)) { + GetColor(settings_.background_color, is_transparent, &sk_color); } return sk_color; } diff --git a/libcef/browser/context.h b/libcef/browser/context.h index b73fc32f52..db024a46cc 100644 --- a/libcef/browser/context.h +++ b/libcef/browser/context.h @@ -70,13 +70,14 @@ class CefContext { // Returns the background color for the browser. If |browser_settings| is // nullptr or does not specify a color then the global settings will be used. // The alpha component will be either SK_AlphaTRANSPARENT or SK_AlphaOPAQUE - // (e.g. fully transparent or fully opaque). If |is_windowless| is + // (e.g. fully transparent or fully opaque). If |transparent_state| is // STATE_DISABLED then SK_AlphaTRANSPARENT will always be returned. If - // |is_windowless| is STATE_ENABLED then SK_ColorTRANSPARENT may be returned - // to enable transparency for windowless browsers. See additional comments on + // |transparent_state| is STATE_ENABLED then SK_ColorTRANSPARENT may be + // returned to enable transparency for windowless browsers, a frameless + // window in Views or a Alloy-style browser. See additional comments on // CefSettings.background_color and CefBrowserSettings.background_color. SkColor GetBackgroundColor(const CefBrowserSettings* browser_settings, - cef_state_t windowless_state) const; + cef_state_t transparent_state) const; CefTraceSubscriber* GetTraceSubscriber(); pref_helper::Registrar* GetPrefRegistrar(); diff --git a/libcef/browser/native/native_widget_delegate.cc b/libcef/browser/native/native_widget_delegate.cc index 281a3c1eaa..5d8e7f89d3 100644 --- a/libcef/browser/native/native_widget_delegate.cc +++ b/libcef/browser/native/native_widget_delegate.cc @@ -88,7 +88,9 @@ void CefNativeWidgetDelegate::Init(gfx::AcceleratedWidget parent_widget, // Set the WS_VISIBLE flag. params.type = views::Widget::InitParams::TYPE_CONTROL; // Don't set the WS_EX_COMPOSITED flag. - params.opacity = views::Widget::InitParams::WindowOpacity::kOpaque; + params.opacity = background_color_ == SK_ColorTRANSPARENT + ? views::Widget::InitParams::WindowOpacity::kTranslucent + : views::Widget::InitParams::WindowOpacity::kOpaque; // Tell Aura not to draw the window frame on resize. params.remove_standard_frame = true; // Cause WidgetDelegate::CanActivate to return true. See comments in diff --git a/libcef/browser/views/window_view.cc b/libcef/browser/views/window_view.cc index 47ff9bf786..7f30ffbae7 100644 --- a/libcef/browser/views/window_view.cc +++ b/libcef/browser/views/window_view.cc @@ -17,6 +17,9 @@ #endif #endif +#include + +#include "cef/libcef/browser/context.h" #include "cef/libcef/browser/geometry_util.h" #include "cef/libcef/browser/image_impl.h" #include "cef/libcef/browser/views/widget.h" @@ -521,6 +524,9 @@ void CefWindowView::CreateWidget(gfx::AcceleratedWidget parent_widget) { bool can_activate = true; bool can_resize = true; + auto color = CefContext::Get()->GetBackgroundColor(nullptr, STATE_ENABLED); + bool is_transparent = color == SK_ColorTRANSPARENT; + const bool has_native_parent = parent_widget != gfx::kNullAcceleratedWidget; if (has_native_parent) { params.parent_widget = parent_widget; @@ -539,6 +545,12 @@ void CefWindowView::CreateWidget(gfx::AcceleratedWidget parent_widget) { params.opacity = views::Widget::InitParams::WindowOpacity::kOpaque; } else { params.type = views::Widget::InitParams::TYPE_WINDOW; + +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + if (is_transparent) { + params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent; + } +#endif } if (cef_delegate()) { @@ -562,6 +574,15 @@ void CefWindowView::CreateWidget(gfx::AcceleratedWidget parent_widget) { } else { is_frameless_ = cef_delegate()->IsFrameless(cef_window); +#if BUILDFLAG(IS_WIN) + // Only set transparency on Windows if the window is frameless. + // because setting kTranslucent removes the window frames and that's + // not what we want for framed windows. + if (is_frameless_ && is_transparent) { + params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent; + } +#endif + params.native_widget = view_util::CreateNativeWidget(widget, cef_window, cef_delegate()); diff --git a/tests/cefclient/browser/main_context_impl.cc b/tests/cefclient/browser/main_context_impl.cc index f93a81583d..1d6e401152 100644 --- a/tests/cefclient/browser/main_context_impl.cc +++ b/tests/cefclient/browser/main_context_impl.cc @@ -157,6 +157,8 @@ std::string MainContextImpl::GetMainURL( std::string main_url = kDefaultUrl; if (command_line->HasSwitch(switches::kUrl)) { main_url = command_line->GetSwitchValue(switches::kUrl); + } else if (command_line->HasSwitch(switches::kTransparencyDemo)) { + main_url = test_runner::GetTestURL("transparency_demo"); } else if (use_views_ && command_line->HasSwitch(switches::kHideFrame)) { // Use the draggable regions test as the default URL for frameless windows. main_url = test_runner::GetTestURL("draggable"); diff --git a/tests/cefclient/browser/resource.h b/tests/cefclient/browser/resource.h index 37c561d055..24735df2c0 100644 --- a/tests/cefclient/browser/resource.h +++ b/tests/cefclient/browser/resource.h @@ -69,12 +69,13 @@ #define IDS_SERVER_HTML 1022 #define IDS_TASK_MANAGER_HTML 1023 #define IDS_TRANSPARENCY_HTML 1024 -#define IDS_URLREQUEST_HTML 1025 -#define IDS_WEBSOCKET_HTML 1026 -#define IDS_WINDOW_HTML 1027 -#define IDS_WINDOW_ICON_1X_PNG 1028 -#define IDS_WINDOW_ICON_2X_PNG 1029 -#define IDS_XMLHTTPREQUEST_HTML 1030 +#define IDS_TRANSPARENCY_DEMO_HTML 1025 +#define IDS_URLREQUEST_HTML 1026 +#define IDS_WEBSOCKET_HTML 1027 +#define IDS_WINDOW_HTML 1028 +#define IDS_WINDOW_ICON_1X_PNG 1029 +#define IDS_WINDOW_ICON_2X_PNG 1030 +#define IDS_XMLHTTPREQUEST_HTML 1031 // Next default values for new objects // diff --git a/tests/cefclient/browser/resource_util_win_idmap.cc b/tests/cefclient/browser/resource_util_win_idmap.cc index f22ac4e4e1..46075f9689 100644 --- a/tests/cefclient/browser/resource_util_win_idmap.cc +++ b/tests/cefclient/browser/resource_util_win_idmap.cc @@ -38,6 +38,7 @@ int GetResourceId(const char* resource_name) { {"server.html", IDS_SERVER_HTML}, {"task_manager.html", IDS_TASK_MANAGER_HTML}, {"transparency.html", IDS_TRANSPARENCY_HTML}, + {"transparency_demo.html", IDS_TRANSPARENCY_DEMO_HTML}, {"urlrequest.html", IDS_URLREQUEST_HTML}, {"websocket.html", IDS_WEBSOCKET_HTML}, {"window.html", IDS_WINDOW_HTML}, diff --git a/tests/cefclient/browser/views_window.cc b/tests/cefclient/browser/views_window.cc index 22abfde4cb..604418ae08 100644 --- a/tests/cefclient/browser/views_window.cc +++ b/tests/cefclient/browser/views_window.cc @@ -1103,6 +1103,12 @@ void ViewsWindow::OnLayoutChanged(CefRefPtr view, void ViewsWindow::OnThemeChanged(CefRefPtr view) { // Apply colors when the theme changes. views_style::OnThemeChanged(view); + + if (command_line_->HasSwitch(switches::kTransparencyDemo)) { + // Make the Window and BrowserView fully transparent so the page's + // semi-transparent background blends with whatever is behind the window. + view->SetBackgroundColor(0x00000000); + } } void ViewsWindow::MenuBarExecuteCommand(CefRefPtr menu_model, diff --git a/tests/cefclient/resources/transparency_demo.html b/tests/cefclient/resources/transparency_demo.html new file mode 100644 index 0000000000..72c60f646f --- /dev/null +++ b/tests/cefclient/resources/transparency_demo.html @@ -0,0 +1,30 @@ + + + +Transparency Demo + + + +
+

Transparency Demo

+

The page background is rgba(128, 128, 128, 0.5).

+

The desktop should be visible behind this window.

+
+ + diff --git a/tests/cefclient/win/cefclient.rc b/tests/cefclient/win/cefclient.rc index 476e5c695a..a89a5251a4 100644 --- a/tests/cefclient/win/cefclient.rc +++ b/tests/cefclient/win/cefclient.rc @@ -54,6 +54,7 @@ IDS_RESPONSE_FILTER_HTML BINARY "tests\\cefclient\\resources\\response_filter.ht IDS_SERVER_HTML BINARY "tests\\cefclient\\resources\\server.html" IDS_TASK_MANAGER_HTML BINARY "tests\\cefclient\\resources\\task_manager.html" IDS_TRANSPARENCY_HTML BINARY "tests\\cefclient\\resources\\transparency.html" +IDS_TRANSPARENCY_DEMO_HTML BINARY "tests\\cefclient\\resources\\transparency_demo.html" IDS_URLREQUEST_HTML BINARY "tests\\cefclient\\resources\\urlrequest.html" IDS_WEBSOCKET_HTML BINARY "tests\\cefclient\\resources\\websocket.html" IDS_WINDOW_HTML BINARY "tests\\cefclient\\resources\\window.html" diff --git a/tests/shared/common/client_switches.cc b/tests/shared/common/client_switches.cc index 9d8088d9f9..90155d6d19 100644 --- a/tests/shared/common/client_switches.cc +++ b/tests/shared/common/client_switches.cc @@ -66,5 +66,6 @@ const char kShowOverlayBrowser[] = "show-overlay-browser"; const char kUseAngle[] = "use-angle"; const char kOzonePlatform[] = "ozone-platform"; const char kAxViewportCollapse[] = "ax-viewport-collapse"; +const char kTransparencyDemo[] = "transparency-demo"; } // namespace client::switches diff --git a/tests/shared/common/client_switches.h b/tests/shared/common/client_switches.h index 936833abcd..b65362239a 100644 --- a/tests/shared/common/client_switches.h +++ b/tests/shared/common/client_switches.h @@ -60,6 +60,7 @@ extern const char kShowOverlayBrowser[]; extern const char kUseAngle[]; extern const char kOzonePlatform[]; extern const char kAxViewportCollapse[]; +extern const char kTransparencyDemo[]; } // namespace client::switches From 99a35b2c170678f12bb5a04a1d2c4b5e4df77b65 Mon Sep 17 00:00:00 2001 From: amrbashir Date: Wed, 19 Aug 2026 07:50:09 +0300 Subject: [PATCH 2/2] Fix type casting in ParseCommandLineArgs for num_args --- libcef_dll/wrapper/cef_util_win.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcef_dll/wrapper/cef_util_win.cc b/libcef_dll/wrapper/cef_util_win.cc index b66012db22..7892264959 100644 --- a/libcef_dll/wrapper/cef_util_win.cc +++ b/libcef_dll/wrapper/cef_util_win.cc @@ -106,7 +106,7 @@ std::vector ParseCommandLineArgs(const wchar_t* str) { std::vector result; result.reserve(num_args); - for (std::wstring arg : std::span{args, num_args}) { + for (std::wstring arg : std::span{args, static_cast(num_args)}) { TrimWhitespace(arg); if (!arg.empty()) { result.push_back(std::move(arg));