From c45f88643aacc94440131ceaeb98b48365f8b7d0 Mon Sep 17 00:00:00 2001 From: Nik Pavlov Date: Fri, 12 Apr 2024 15:49:31 +0000 Subject: [PATCH] mac: views: Add customization point for acceptsFirstMouse (fixes #3680) --- include/capi/views/cef_window_delegate_capi.h | 16 ++++++++- include/cef_api_hash.h | 8 ++--- include/views/cef_window_delegate.h | 15 +++++++++ libcef/browser/views/native_widget_mac.mm | 6 ++-- libcef/browser/views/ns_window.h | 9 ++++- libcef/browser/views/ns_window.mm | 9 ++++- .../cpptoc/views/window_delegate_cpptoc.cc | 28 +++++++++++++++- .../ctocpp/views/window_delegate_ctocpp.cc | 28 +++++++++++++++- .../ctocpp/views/window_delegate_ctocpp.h | 3 +- patch/patch.cfg | 5 +++ patch/patches/mac_render_widget_3680.patch | 33 +++++++++++++++++++ tests/cefclient/browser/views_window.cc | 8 +++++ tests/cefclient/browser/views_window.h | 2 ++ tests/shared/common/client_switches.cc | 1 + tests/shared/common/client_switches.h | 1 + 15 files changed, 160 insertions(+), 12 deletions(-) create mode 100644 patch/patches/mac_render_widget_3680.patch diff --git a/include/capi/views/cef_window_delegate_capi.h b/include/capi/views/cef_window_delegate_capi.h index 041f44ee9..7196ed72a 100644 --- a/include/capi/views/cef_window_delegate_capi.h +++ b/include/capi/views/cef_window_delegate_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=b292cdf6e293dfd42c30ea9189b2a8a2ed77ba7a$ +// $hash=e6bbc33db1b5ed3832982f8799e14557204f4028$ // #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_WINDOW_DELEGATE_CAPI_H_ @@ -182,6 +182,20 @@ typedef struct _cef_window_delegate_t { struct _cef_window_t* window, float* titlebar_height); + /// + /// Return whether the view should accept the initial mouse-down event, + /// allowing it to respond to click-through behavior. If STATE_ENABLED is + /// returned, the view will be sent a mouseDown: message for an initial mouse- + /// down event, activating the view with one click, instead of clicking first + /// to make the window active and then clicking the view. + /// + /// This function is only supported on macOS. For more details, refer to the + /// documentation of acceptsFirstMouse. + /// + cef_state_t(CEF_CALLBACK* accepts_first_mouse)( + struct _cef_window_delegate_t* self, + struct _cef_window_t* window); + /// /// Return true (1) if |window| can be resized. /// diff --git a/include/cef_api_hash.h b/include/cef_api_hash.h index 033077fd6..1ff10a15b 100644 --- a/include/cef_api_hash.h +++ b/include/cef_api_hash.h @@ -42,13 +42,13 @@ // way that may cause binary incompatibility with other builds. The universal // hash value will change if any platform is affected whereas the platform hash // values will change only if that particular platform is affected. -#define CEF_API_HASH_UNIVERSAL "ed9b17c85e769cb4d087390a77bed6613fed9166" +#define CEF_API_HASH_UNIVERSAL "de72aee0623e568ded52b7075c7fda576844e8b3" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "5f47de7bf681782160a81ee201cef71f82ac9d69" +#define CEF_API_HASH_PLATFORM "46bb69fe7038d7e9f8d4ee86e4a0825bb2d289b7" #elif defined(OS_MAC) -#define CEF_API_HASH_PLATFORM "d4ca78dc9bc6357c4a05679b2da0863b543f96fa" +#define CEF_API_HASH_PLATFORM "e3ef47d5541f5260eba70030386d692138315900" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "2dfd768af8ca7aa0474a2014b05cec33f64d83b0" +#define CEF_API_HASH_PLATFORM "579ef9c5282456c7de906cf055aed0ff4ba0a5a3" #endif #ifdef __cplusplus diff --git a/include/views/cef_window_delegate.h b/include/views/cef_window_delegate.h index 3231c45ab..d2f7a33ad 100644 --- a/include/views/cef_window_delegate.h +++ b/include/views/cef_window_delegate.h @@ -176,6 +176,21 @@ class CefWindowDelegate : public CefPanelDelegate { return false; } + /// + /// Return whether the view should accept the initial mouse-down event, + /// allowing it to respond to click-through behavior. If STATE_ENABLED is + /// returned, the view will be sent a mouseDown: message for an initial + /// mouse-down event, activating the view with one click, instead of clicking + /// first to make the window active and then clicking the view. + /// + /// This method is only supported on macOS. For more details, refer to the + /// documentation of acceptsFirstMouse. + /// + /*--cef(default_retval=STATE_DEFAULT)--*/ + virtual cef_state_t AcceptsFirstMouse(CefRefPtr window) { + return STATE_DEFAULT; + } + /// /// Return true if |window| can be resized. /// diff --git a/libcef/browser/views/native_widget_mac.mm b/libcef/browser/views/native_widget_mac.mm index 9367f3133..6fe00ed86 100644 --- a/libcef/browser/views/native_widget_mac.mm +++ b/libcef/browser/views/native_widget_mac.mm @@ -87,10 +87,12 @@ NativeWidgetMacNSWindow* CefNativeWidgetMac::CreateNSWindow( NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | NSWindowStyleMaskTexturedBackground; - bool is_frameless = window_delegate_->IsFrameless(window_); + const bool is_frameless = window_delegate_->IsFrameless(window_); + const auto accepts_first_mouse = window_delegate_->AcceptsFirstMouse(window_); auto window = [[CefNSWindow alloc] initWithStyle:style_mask - isFrameless:is_frameless]; + isFrameless:is_frameless + acceptsFirstMouse:accepts_first_mouse]; if (is_frameless) { [window setTitlebarAppearsTransparent:YES]; diff --git a/libcef/browser/views/ns_window.h b/libcef/browser/views/ns_window.h index 2ed159c3e..6b292279e 100644 --- a/libcef/browser/views/ns_window.h +++ b/libcef/browser/views/ns_window.h @@ -6,15 +6,22 @@ #define CEF_LIBCEF_BROWSER_VIEWS_NS_WINDOW_H_ #pragma once +#include "include/internal/cef_types.h" + #include "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h" @interface CefNSWindow : NativeWidgetMacNSWindow { @private bool is_frameless_; + cef_state_t accepts_first_mouse_; } -- (id)initWithStyle:(NSUInteger)style_mask isFrameless:(bool)is_frameless; + +- (id)initWithStyle:(NSUInteger)style_mask + isFrameless:(bool)is_frameless + acceptsFirstMouse:(cef_state_t)accepts_first_mouse; - (BOOL)shouldCenterTrafficLights; +- (int)acceptsFirstMouse; @end #endif // CEF_LIBCEF_BROWSER_VIEWS_NS_WINDOW_H_ diff --git a/libcef/browser/views/ns_window.mm b/libcef/browser/views/ns_window.mm index 5327db157..aaaf63096 100644 --- a/libcef/browser/views/ns_window.mm +++ b/libcef/browser/views/ns_window.mm @@ -64,12 +64,15 @@ @implementation CefNSWindow -- (id)initWithStyle:(NSUInteger)style_mask isFrameless:(bool)is_frameless { +- (id)initWithStyle:(NSUInteger)style_mask + isFrameless:(bool)is_frameless + acceptsFirstMouse:(cef_state_t)accepts_first_mouse { if ((self = [super initWithContentRect:ui::kWindowSizeDeterminedLater styleMask:style_mask backing:NSBackingStoreBuffered defer:NO])) { is_frameless_ = is_frameless; + accepts_first_mouse_ = accepts_first_mouse; } return self; } @@ -102,4 +105,8 @@ return [super frameViewClassForStyleMask:windowStyle]; } +- (int)acceptsFirstMouse { + return accepts_first_mouse_; +} + @end diff --git a/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc b/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc index 8a63d1f88..9e6419d38 100644 --- a/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc +++ b/libcef_dll/cpptoc/views/window_delegate_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=4350cb3f26c9b2a56bac5a0368eab19dff8659ae$ +// $hash=4d171663d78dd204b321d77248f44ed7f0d752b8$ // #include "libcef_dll/cpptoc/views/window_delegate_cpptoc.h" @@ -374,6 +374,31 @@ window_delegate_get_titlebar_height(struct _cef_window_delegate_t* self, return _retval; } +cef_state_t CEF_CALLBACK +window_delegate_accepts_first_mouse(struct _cef_window_delegate_t* self, + cef_window_t* window) { + shutdown_checker::AssertNotShutdown(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) { + return STATE_DEFAULT; + } + // Verify param: window; type: refptr_diff + DCHECK(window); + if (!window) { + return STATE_DEFAULT; + } + + // Execute + cef_state_t _retval = CefWindowDelegateCppToC::Get(self)->AcceptsFirstMouse( + CefWindowCToCpp::Wrap(window)); + + // Return type: simple + return _retval; +} + int CEF_CALLBACK window_delegate_can_resize(struct _cef_window_delegate_t* self, cef_window_t* window) { shutdown_checker::AssertNotShutdown(); @@ -860,6 +885,7 @@ CefWindowDelegateCppToC::CefWindowDelegateCppToC() { GetStruct()->with_standard_window_buttons = window_delegate_with_standard_window_buttons; GetStruct()->get_titlebar_height = window_delegate_get_titlebar_height; + GetStruct()->accepts_first_mouse = window_delegate_accepts_first_mouse; GetStruct()->can_resize = window_delegate_can_resize; GetStruct()->can_maximize = window_delegate_can_maximize; GetStruct()->can_minimize = window_delegate_can_minimize; diff --git a/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc b/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc index 45a35e8b0..3e6c52b85 100644 --- a/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc +++ b/libcef_dll/ctocpp/views/window_delegate_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=18fd259f012c67956bda267a62d0e30971c696ca$ +// $hash=e7548cf2202aa3827f45c56a706f735606db1f83$ // #include "libcef_dll/ctocpp/views/window_delegate_ctocpp.h" @@ -363,6 +363,32 @@ bool CefWindowDelegateCToCpp::GetTitlebarHeight(CefRefPtr window, return _retval ? true : false; } +NO_SANITIZE("cfi-icall") +cef_state_t CefWindowDelegateCToCpp::AcceptsFirstMouse( + CefRefPtr window) { + shutdown_checker::AssertNotShutdown(); + + cef_window_delegate_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, accepts_first_mouse)) { + return STATE_DEFAULT; + } + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: window; type: refptr_diff + DCHECK(window.get()); + if (!window.get()) { + return STATE_DEFAULT; + } + + // Execute + cef_state_t _retval = + _struct->accepts_first_mouse(_struct, CefWindowCppToC::Wrap(window)); + + // Return type: simple + return _retval; +} + NO_SANITIZE("cfi-icall") bool CefWindowDelegateCToCpp::CanResize(CefRefPtr window) { shutdown_checker::AssertNotShutdown(); diff --git a/libcef_dll/ctocpp/views/window_delegate_ctocpp.h b/libcef_dll/ctocpp/views/window_delegate_ctocpp.h index b538cf7b1..48f3aeb79 100644 --- a/libcef_dll/ctocpp/views/window_delegate_ctocpp.h +++ b/libcef_dll/ctocpp/views/window_delegate_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=a67a7b010e34bdda6ad0ecdf8da9bd6402689a6b$ +// $hash=c829c66e21b16f72c4af8421de518eaa89b5e8eb$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_WINDOW_DELEGATE_CTOCPP_H_ @@ -56,6 +56,7 @@ class CefWindowDelegateCToCpp bool WithStandardWindowButtons(CefRefPtr window) override; bool GetTitlebarHeight(CefRefPtr window, float* titlebar_height) override; + cef_state_t AcceptsFirstMouse(CefRefPtr window) override; bool CanResize(CefRefPtr window) override; bool CanMaximize(CefRefPtr window) override; bool CanMinimize(CefRefPtr window) override; diff --git a/patch/patch.cfg b/patch/patch.cfg index 844c939c8..ae424e3fc 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -752,5 +752,10 @@ patches = [ # https://github.com/chromiumembedded/cef/issues/3610 # https://issues.chromium.org/issues/40280130#comment7 'name': 'linux_gtk_theme_3610' + }, + { + # views: mac: Add customization point to acceptsFirstMouse. + # https://github.com/chromiumembedded/cef/issues/3680 + 'name': 'mac_render_widget_3680' } ] diff --git a/patch/patches/mac_render_widget_3680.patch b/patch/patches/mac_render_widget_3680.patch new file mode 100644 index 000000000..91fa4802d --- /dev/null +++ b/patch/patches/mac_render_widget_3680.patch @@ -0,0 +1,33 @@ +diff --git content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm +index 5649f120ccefa..c6c1a676a24cf 100644 +--- content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm ++++ content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm +@@ -164,6 +164,13 @@ void ExtractUnderlines(NSAttributedString* string, + + // RenderWidgetHostViewCocoa --------------------------------------------------- + ++@interface NSWindow (CefCustomMethods) ++- (int)acceptsFirstMouse; ++@end ++ ++constexpr int kStateEnabled = 1; ++constexpr int kStateDisabled = 2; ++ + // Private methods: + @interface RenderWidgetHostViewCocoa () + +@@ -744,6 +751,14 @@ void ExtractUnderlines(NSAttributedString* string, + } + + - (BOOL)acceptsFirstMouse:(NSEvent*)theEvent { ++ if ([self.window respondsToSelector:@selector(acceptsFirstMouse)]) { ++ const auto mode = [self.window acceptsFirstMouse]; ++ if (mode == kStateEnabled) { ++ return YES; ++ } else if (mode == kStateDisabled) { ++ return NO; ++ } ++ } + return [self acceptsMouseEventsWhenInactive]; + } + diff --git a/tests/cefclient/browser/views_window.cc b/tests/cefclient/browser/views_window.cc index 90c4c8812..151a43638 100644 --- a/tests/cefclient/browser/views_window.cc +++ b/tests/cefclient/browser/views_window.cc @@ -905,6 +905,13 @@ bool ViewsWindow::GetTitlebarHeight(CefRefPtr window, return false; } +cef_state_t ViewsWindow::AcceptsFirstMouse(CefRefPtr window) { + if (accepts_first_mouse_) { + return STATE_ENABLED; + } + return STATE_DEFAULT; +} + bool ViewsWindow::CanResize(CefRefPtr window) { CEF_REQUIRE_UI_THREAD(); // Only allow resize of normal and DevTools windows. @@ -1110,6 +1117,7 @@ ViewsWindow::ViewsWindow(WindowType type, const bool hide_toolbar = hide_overlays && !with_controls_; const bool show_window_buttons = command_line->HasSwitch(switches::kShowWindowButtons); + accepts_first_mouse_ = command_line->HasSwitch(switches::kAcceptsFirstMouse); // Without a window frame. frameless_ = hide_frame || type_ == WindowType::EXTENSION; diff --git a/tests/cefclient/browser/views_window.h b/tests/cefclient/browser/views_window.h index 5e1e0601d..a4c9993fb 100644 --- a/tests/cefclient/browser/views_window.h +++ b/tests/cefclient/browser/views_window.h @@ -184,6 +184,7 @@ class ViewsWindow : public CefBrowserViewDelegate, bool WithStandardWindowButtons(CefRefPtr window) override; bool GetTitlebarHeight(CefRefPtr window, float* titlebar_height) override; + cef_state_t AcceptsFirstMouse(CefRefPtr window) override; bool CanResize(CefRefPtr window) override; bool CanMaximize(CefRefPtr window) override; bool CanMinimize(CefRefPtr window) override; @@ -268,6 +269,7 @@ class ViewsWindow : public CefBrowserViewDelegate, bool use_window_modal_dialog_; bool use_bottom_controls_; bool hide_pip_frame_; + bool accepts_first_mouse_; CefRefPtr window_; CefRefPtr button_menu_model_; diff --git a/tests/shared/common/client_switches.cc b/tests/shared/common/client_switches.cc index 5e599f21b..89324b423 100644 --- a/tests/shared/common/client_switches.cc +++ b/tests/shared/common/client_switches.cc @@ -57,5 +57,6 @@ const char kUseBottomControls[] = "use-bottom-controls"; const char kHidePipFrame[] = "hide-pip-frame"; const char kHideChromeBubbles[] = "hide-chrome-bubbles"; const char kHideWindowOnClose[] = "hide-window-on-close"; +const char kAcceptsFirstMouse[] = "accepts-first-mouse"; } // namespace client::switches diff --git a/tests/shared/common/client_switches.h b/tests/shared/common/client_switches.h index 3c232a1d9..d1b174e36 100644 --- a/tests/shared/common/client_switches.h +++ b/tests/shared/common/client_switches.h @@ -51,6 +51,7 @@ extern const char kUseBottomControls[]; extern const char kHidePipFrame[]; extern const char kHideChromeBubbles[]; extern const char kHideWindowOnClose[]; +extern const char kAcceptsFirstMouse[]; } // namespace client::switches