diff --git a/BUILD.gn b/BUILD.gn index 6726b8f0a..d914d6dea 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1020,13 +1020,6 @@ static_library("libcef_static") { "libcef/browser/native/cursor_util_win.cc", "libcef/browser/native/javascript_dialog_runner_win.cc", "libcef/browser/native/javascript_dialog_runner_win.h", - "libcef/browser/native/menu_2.cc", - "libcef/browser/native/menu_2.h", - "libcef/browser/native/menu_runner_win.cc", - "libcef/browser/native/menu_runner_win.h", - "libcef/browser/native/menu_wrapper.h", - "libcef/browser/native/native_menu_win.cc", - "libcef/browser/native/native_menu_win.h", "libcef/browser/osr/browser_platform_delegate_osr_win.cc", "libcef/browser/osr/browser_platform_delegate_osr_win.h", ] @@ -1056,8 +1049,6 @@ static_library("libcef_static") { "libcef/browser/native/browser_platform_delegate_native_linux.cc", "libcef/browser/native/browser_platform_delegate_native_linux.h", "libcef/browser/native/cursor_util_linux.cc", - "libcef/browser/native/menu_runner_linux.cc", - "libcef/browser/native/menu_runner_linux.h", "libcef/browser/osr/browser_platform_delegate_osr_linux.cc", "libcef/browser/osr/browser_platform_delegate_osr_linux.h", "libcef/browser/printing/print_dialog_linux.cc", @@ -1127,6 +1118,8 @@ static_library("libcef_static") { sources += [ "libcef/browser/native/browser_platform_delegate_native_aura.cc", "libcef/browser/native/browser_platform_delegate_native_aura.h", + "libcef/browser/native/menu_runner_views_aura.cc", + "libcef/browser/native/menu_runner_views_aura.h", "libcef/browser/views/view_util_aura.cc", # Part of //ui/views:test_support which is testingonly. diff --git a/include/capi/cef_render_handler_capi.h b/include/capi/cef_render_handler_capi.h index e9a84ef23..98d343b9d 100644 --- a/include/capi/cef_render_handler_capi.h +++ b/include/capi/cef_render_handler_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=79fba8a1a86cc65251dd7251e0863dd20205bb3b$ +// $hash=7fc75c41ce47a5e715471b9bb82c848d6cf25472$ // #ifndef CEF_INCLUDE_CAPI_CEF_RENDER_HANDLER_CAPI_H_ @@ -67,25 +67,27 @@ typedef struct _cef_render_handler_t { struct _cef_render_handler_t* self); /// - // Called to retrieve the root window rectangle in screen coordinates. Return - // true (1) if the rectangle was provided. If this function returns false (0) - // the rectangle from GetViewRect will be used. + // Called to retrieve the root window rectangle in screen DIP coordinates. + // Return true (1) if the rectangle was provided. If this function returns + // false (0) the rectangle from GetViewRect will be used. /// int(CEF_CALLBACK* get_root_screen_rect)(struct _cef_render_handler_t* self, struct _cef_browser_t* browser, cef_rect_t* rect); /// - // Called to retrieve the view rectangle which is relative to screen - // coordinates. This function must always provide a non-NULL rectangle. + // Called to retrieve the view rectangle in screen DIP coordinates. This + // function must always provide a non-NULL rectangle. /// void(CEF_CALLBACK* get_view_rect)(struct _cef_render_handler_t* self, struct _cef_browser_t* browser, cef_rect_t* rect); /// - // Called to retrieve the translation from view coordinates to actual screen - // coordinates. Return true (1) if the screen coordinates were provided. + // Called to retrieve the translation from view DIP coordinates to screen + // coordinates. Windows/Linux should provide screen device (pixel) coordinates + // and MacOS should provide screen DIP coordinates. Return true (1) if the + // requested coordinates were provided. /// int(CEF_CALLBACK* get_screen_point)(struct _cef_render_handler_t* self, struct _cef_browser_t* browser, diff --git a/include/cef_render_handler.h b/include/cef_render_handler.h index f101083a7..7eb24cb99 100644 --- a/include/cef_render_handler.h +++ b/include/cef_render_handler.h @@ -68,8 +68,8 @@ class CefRenderHandler : public virtual CefBaseRefCounted { } /// - // Called to retrieve the root window rectangle in screen coordinates. Return - // true if the rectangle was provided. If this method returns false the + // Called to retrieve the root window rectangle in screen DIP coordinates. + // Return true if the rectangle was provided. If this method returns false the // rectangle from GetViewRect will be used. /// /*--cef()--*/ @@ -78,15 +78,17 @@ class CefRenderHandler : public virtual CefBaseRefCounted { } /// - // Called to retrieve the view rectangle which is relative to screen - // coordinates. This method must always provide a non-empty rectangle. + // Called to retrieve the view rectangle in screen DIP coordinates. This + // method must always provide a non-empty rectangle. /// /*--cef()--*/ virtual void GetViewRect(CefRefPtr browser, CefRect& rect) = 0; /// - // Called to retrieve the translation from view coordinates to actual screen - // coordinates. Return true if the screen coordinates were provided. + // Called to retrieve the translation from view DIP coordinates to screen + // coordinates. Windows/Linux should provide screen device (pixel) coordinates + // and MacOS should provide screen DIP coordinates. Return true if the + // requested coordinates were provided. /// /*--cef()--*/ virtual bool GetScreenPoint(CefRefPtr browser, diff --git a/libcef/browser/alloy/alloy_browser_host_impl.cc b/libcef/browser/alloy/alloy_browser_host_impl.cc index 9b8f76d55..9852116d1 100644 --- a/libcef/browser/alloy/alloy_browser_host_impl.cc +++ b/libcef/browser/alloy/alloy_browser_host_impl.cc @@ -1522,10 +1522,11 @@ bool AlloyBrowserHostImpl::CreateHostWindow() { return success; } -gfx::Point AlloyBrowserHostImpl::GetScreenPoint(const gfx::Point& view) const { +gfx::Point AlloyBrowserHostImpl::GetScreenPoint(const gfx::Point& view, + bool want_dip_coords) const { CEF_REQUIRE_UIT(); if (platform_delegate_) - return platform_delegate_->GetScreenPoint(view); + return platform_delegate_->GetScreenPoint(view, want_dip_coords); return gfx::Point(); } diff --git a/libcef/browser/alloy/alloy_browser_host_impl.h b/libcef/browser/alloy/alloy_browser_host_impl.h index ae25cd990..24f9a2524 100644 --- a/libcef/browser/alloy/alloy_browser_host_impl.h +++ b/libcef/browser/alloy/alloy_browser_host_impl.h @@ -154,9 +154,10 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase, bool is_guest_view, const content::OpenURLParams& params) override; - // Convert from view coordinates to screen coordinates. Potential display - // scaling will be applied to the result. - gfx::Point GetScreenPoint(const gfx::Point& view) const; + // Convert from view DIP coordinates to screen coordinates. If + // |want_dip_coords| is true return DIP instead of device (pixel) coordinates + // on Windows/Linux. + gfx::Point GetScreenPoint(const gfx::Point& view, bool want_dip_coords) const; void StartDragging(const content::DropData& drop_data, blink::DragOperationsMask allowed_ops, diff --git a/libcef/browser/browser_platform_delegate.cc b/libcef/browser/browser_platform_delegate.cc index 103117636..06432603c 100644 --- a/libcef/browser/browser_platform_delegate.cc +++ b/libcef/browser/browser_platform_delegate.cc @@ -191,7 +191,8 @@ void CefBrowserPlatformDelegate::SizeTo(int width, int height) {} #endif gfx::Point CefBrowserPlatformDelegate::GetScreenPoint( - const gfx::Point& view) const { + const gfx::Point& view, + bool want_dip_coords) const { NOTREACHED(); return gfx::Point(); } diff --git a/libcef/browser/browser_platform_delegate.h b/libcef/browser/browser_platform_delegate.h index 6ff01e656..09b09e4c4 100644 --- a/libcef/browser/browser_platform_delegate.h +++ b/libcef/browser/browser_platform_delegate.h @@ -239,9 +239,11 @@ class CefBrowserPlatformDelegate { virtual void SizeTo(int width, int height); #endif - // Convert from view coordinates to screen coordinates. Potential display - // scaling will be applied to the result. - virtual gfx::Point GetScreenPoint(const gfx::Point& view) const; + // Convert from view DIP coordinates to screen coordinates. If + // |want_dip_coords| is true return DIP instead of device (pixel) coordinates + // on Windows/Linux. + virtual gfx::Point GetScreenPoint(const gfx::Point& view, + bool want_dip_coords) const; // Open the specified text in the default text editor. virtual void ViewText(const std::string& text); diff --git a/libcef/browser/chrome/browser_platform_delegate_chrome.cc b/libcef/browser/chrome/browser_platform_delegate_chrome.cc index b94c06ea8..a3fc15ed0 100644 --- a/libcef/browser/chrome/browser_platform_delegate_chrome.cc +++ b/libcef/browser/chrome/browser_platform_delegate_chrome.cc @@ -8,6 +8,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" +#include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/gfx/geometry/point.h" @@ -76,13 +77,24 @@ void CefBrowserPlatformDelegateChrome::SendMouseWheelEvent( } gfx::Point CefBrowserPlatformDelegateChrome::GetScreenPoint( - const gfx::Point& view) const { + const gfx::Point& view, + bool want_dip_coords) const { auto screen = display::Screen::GetScreen(); - // Returns screen pixel coordinates. + // Get device (pixel) coordinates. auto screen_rect = screen->DIPToScreenRectInWindow( GetNativeWindow(), gfx::Rect(view, gfx::Size(0, 0))); - return screen_rect.origin(); + auto screen_point = screen_rect.origin(); + + if (want_dip_coords) { + // Convert to DIP coordinates. + const auto& display = view_util::GetDisplayNearestPoint( + screen_point, /*input_pixel_coords=*/true); + view_util::ConvertPointFromPixels(&screen_point, + display.device_scale_factor()); + } + + return screen_point; } void CefBrowserPlatformDelegateChrome::ViewText(const std::string& text) { @@ -100,8 +112,9 @@ CefWindowHandle CefBrowserPlatformDelegateChrome::GetParentWindowHandle() } gfx::Point CefBrowserPlatformDelegateChrome::GetParentScreenPoint( - const gfx::Point& view) const { - return GetScreenPoint(view); + const gfx::Point& view, + bool want_dip_coords) const { + return GetScreenPoint(view, want_dip_coords); } void CefBrowserPlatformDelegateChrome::set_chrome_browser(Browser* browser) { diff --git a/libcef/browser/chrome/browser_platform_delegate_chrome.h b/libcef/browser/chrome/browser_platform_delegate_chrome.h index c1e839f16..e237db82e 100644 --- a/libcef/browser/chrome/browser_platform_delegate_chrome.h +++ b/libcef/browser/chrome/browser_platform_delegate_chrome.h @@ -35,14 +35,16 @@ class CefBrowserPlatformDelegateChrome void SendMouseWheelEvent(const CefMouseEvent& event, int deltaX, int deltaY) override; - gfx::Point GetScreenPoint(const gfx::Point& view) const override; + gfx::Point GetScreenPoint(const gfx::Point& view, + bool want_dip_coords) const override; void ViewText(const std::string& text) override; CefEventHandle GetEventHandle( const content::NativeWebKeyboardEvent& event) const override; // CefBrowserPlatformDelegateNative::WindowlessHandler methods: CefWindowHandle GetParentWindowHandle() const override; - gfx::Point GetParentScreenPoint(const gfx::Point& view) const override; + gfx::Point GetParentScreenPoint(const gfx::Point& view, + bool want_dip_coords) const override; void set_chrome_browser(Browser* browser); diff --git a/libcef/browser/extensions/browser_platform_delegate_background.cc b/libcef/browser/extensions/browser_platform_delegate_background.cc index 57e301972..198dca0b5 100644 --- a/libcef/browser/extensions/browser_platform_delegate_background.cc +++ b/libcef/browser/extensions/browser_platform_delegate_background.cc @@ -82,7 +82,8 @@ void CefBrowserPlatformDelegateBackground::SetFocus(bool setFocus) { } gfx::Point CefBrowserPlatformDelegateBackground::GetScreenPoint( - const gfx::Point& view_pt) const { + const gfx::Point& view_pt, + bool want_dip_coords) const { // Nothing to do here. return view_pt; } @@ -119,6 +120,7 @@ CefWindowHandle CefBrowserPlatformDelegateBackground::GetParentWindowHandle() } gfx::Point CefBrowserPlatformDelegateBackground::GetParentScreenPoint( - const gfx::Point& view) const { - return GetScreenPoint(view); + const gfx::Point& view, + bool want_dip_coords) const { + return GetScreenPoint(view, want_dip_coords); } diff --git a/libcef/browser/extensions/browser_platform_delegate_background.h b/libcef/browser/extensions/browser_platform_delegate_background.h index 608b16141..ab44eb544 100644 --- a/libcef/browser/extensions/browser_platform_delegate_background.h +++ b/libcef/browser/extensions/browser_platform_delegate_background.h @@ -34,7 +34,8 @@ class CefBrowserPlatformDelegateBackground int deltaY) override; void SendTouchEvent(const CefTouchEvent& event) override; void SetFocus(bool setFocus) override; - gfx::Point GetScreenPoint(const gfx::Point& view) const override; + gfx::Point GetScreenPoint(const gfx::Point& view, + bool want_dip_coords) const override; void ViewText(const std::string& text) override; bool HandleKeyboardEvent( const content::NativeWebKeyboardEvent& event) override; @@ -46,7 +47,8 @@ class CefBrowserPlatformDelegateBackground // CefBrowserPlatformDelegateNative::WindowlessHandler methods: CefWindowHandle GetParentWindowHandle() const override; - gfx::Point GetParentScreenPoint(const gfx::Point& view) const override; + gfx::Point GetParentScreenPoint(const gfx::Point& view, + bool want_dip_coords) const override; private: std::unique_ptr native_delegate_; diff --git a/libcef/browser/menu_manager.cc b/libcef/browser/menu_manager.cc index 4b3b7dca9..7ba539424 100644 --- a/libcef/browser/menu_manager.cc +++ b/libcef/browser/menu_manager.cc @@ -188,9 +188,15 @@ bool CefMenuManager::CreateContextMenu( } } - if (custom_menu || !runner_) + if (custom_menu) return true; - return runner_->RunContextMenu(browser_, model_.get(), params_); + + if (!runner_ || !runner_->RunContextMenu(browser_, model_.get(), params_)) { + LOG(ERROR) << "Default context menu implementation is not available; " + "canceling the menu"; + return false; + } + return true; } void CefMenuManager::CancelContextMenu() { diff --git a/libcef/browser/native/browser_platform_delegate_native.h b/libcef/browser/native/browser_platform_delegate_native.h index d3b47b1ec..704da0d1a 100644 --- a/libcef/browser/native/browser_platform_delegate_native.h +++ b/libcef/browser/native/browser_platform_delegate_native.h @@ -18,8 +18,11 @@ class CefBrowserPlatformDelegateNative // Returns the parent window handle. virtual CefWindowHandle GetParentWindowHandle() const = 0; - // Convert from view coordinates to screen coordinates. - virtual gfx::Point GetParentScreenPoint(const gfx::Point& view) const = 0; + // Convert from view DIP coordinates to screen coordinates. If + // |want_dip_coords| is true return DIP instead of device (pixel) + // coordinates on Windows/Linux. + virtual gfx::Point GetParentScreenPoint(const gfx::Point& view, + bool want_dip_coords) const = 0; protected: virtual ~WindowlessHandler() {} diff --git a/libcef/browser/native/browser_platform_delegate_native_aura.cc b/libcef/browser/native/browser_platform_delegate_native_aura.cc index 32f567c92..468f49b00 100644 --- a/libcef/browser/native/browser_platform_delegate_native_aura.cc +++ b/libcef/browser/native/browser_platform_delegate_native_aura.cc @@ -4,12 +4,16 @@ #include "libcef/browser/native/browser_platform_delegate_native_aura.h" +#include "libcef/browser/native/menu_runner_views_aura.h" +#include "libcef/browser/views/view_util.h" + #include "content/browser/renderer_host/render_widget_host_view_aura.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" #include "ui/events/blink/blink_event_util.h" #include "ui/events/blink/web_input_event.h" #include "ui/gfx/geometry/vector2d.h" +#include "ui/views/widget/widget.h" CefBrowserPlatformDelegateNativeAura::CefBrowserPlatformDelegateNativeAura( const CefWindowInfo& window_info, @@ -68,6 +72,30 @@ void CefBrowserPlatformDelegateNativeAura::SendTouchEvent( NOTIMPLEMENTED(); } +std::unique_ptr +CefBrowserPlatformDelegateNativeAura::CreateMenuRunner() { + return base::WrapUnique(new CefMenuRunnerViewsAura); +} + +gfx::Point CefBrowserPlatformDelegateNativeAura::GetScreenPoint( + const gfx::Point& view, + bool want_dip_coords) const { + if (windowless_handler_) + return windowless_handler_->GetParentScreenPoint(view, want_dip_coords); + + if (!window_widget_) + return view; + + gfx::Point screen_pt(view); + if (!view_util::ConvertPointToScreen( + window_widget_->GetRootView(), &screen_pt, + /*output_pixel_coords=*/!want_dip_coords)) { + return view; + } + + return screen_pt; +} + content::NativeWebKeyboardEvent CefBrowserPlatformDelegateNativeAura::TranslateWebKeyEvent( const CefKeyEvent& key_event) const { @@ -110,8 +138,8 @@ ui::MouseEvent CefBrowserPlatformDelegateNativeAura::TranslateUiClickEvent( ui::EventType event_type = mouseUp ? ui::ET_MOUSE_RELEASED : ui::ET_MOUSE_PRESSED; gfx::PointF location(mouse_event.x, mouse_event.y); - gfx::PointF root_location( - GetScreenPoint(gfx::Point(mouse_event.x, mouse_event.y))); + gfx::PointF root_location(GetScreenPoint( + gfx::Point(mouse_event.x, mouse_event.y), /*want_dip_coords=*/false)); base::TimeTicks time_stamp = GetEventTimeStamp(); int flags = TranslateUiEventModifiers(mouse_event.modifiers); @@ -142,8 +170,8 @@ ui::MouseEvent CefBrowserPlatformDelegateNativeAura::TranslateUiMoveEvent( ui::EventType event_type = mouseLeave ? ui::ET_MOUSE_EXITED : ui::ET_MOUSE_MOVED; gfx::PointF location(mouse_event.x, mouse_event.y); - gfx::PointF root_location( - GetScreenPoint(gfx::Point(mouse_event.x, mouse_event.y))); + gfx::PointF root_location(GetScreenPoint( + gfx::Point(mouse_event.x, mouse_event.y), /*want_dip_coords=*/false)); base::TimeTicks time_stamp = GetEventTimeStamp(); int flags = TranslateUiEventModifiers(mouse_event.modifiers); @@ -164,8 +192,8 @@ ui::MouseWheelEvent CefBrowserPlatformDelegateNativeAura::TranslateUiWheelEvent( DCHECK(!offset.IsZero()); gfx::PointF location(mouse_event.x, mouse_event.y); - gfx::PointF root_location( - GetScreenPoint(gfx::Point(mouse_event.x, mouse_event.y))); + gfx::PointF root_location(GetScreenPoint( + gfx::Point(mouse_event.x, mouse_event.y), /*want_dip_coords=*/false)); base::TimeTicks time_stamp = GetEventTimeStamp(); int flags = TranslateUiEventModifiers(mouse_event.modifiers); int changed_button_flags = diff --git a/libcef/browser/native/browser_platform_delegate_native_aura.h b/libcef/browser/native/browser_platform_delegate_native_aura.h index 0e7d7efdb..525d41687 100644 --- a/libcef/browser/native/browser_platform_delegate_native_aura.h +++ b/libcef/browser/native/browser_platform_delegate_native_aura.h @@ -35,6 +35,9 @@ class CefBrowserPlatformDelegateNativeAura int deltaX, int deltaY) override; void SendTouchEvent(const CefTouchEvent& event) override; + std::unique_ptr CreateMenuRunner() override; + gfx::Point GetScreenPoint(const gfx::Point& view, + bool want_dip_coords) const override; // CefBrowserPlatformDelegateNative methods: content::NativeWebKeyboardEvent TranslateWebKeyEvent( @@ -72,6 +75,10 @@ class CefBrowserPlatformDelegateNativeAura static int TranslateUiEventModifiers(uint32 cef_modifiers); static int TranslateUiChangedButtonFlags(uint32 cef_modifiers); + // Widget hosting the web contents. It will be deleted automatically when the + // associated root window is destroyed. + views::Widget* window_widget_ = nullptr; + private: content::RenderWidgetHostViewAura* GetHostView() const; }; diff --git a/libcef/browser/native/browser_platform_delegate_native_linux.cc b/libcef/browser/native/browser_platform_delegate_native_linux.cc index 3716d9d18..238302a69 100644 --- a/libcef/browser/native/browser_platform_delegate_native_linux.cc +++ b/libcef/browser/native/browser_platform_delegate_native_linux.cc @@ -6,7 +6,6 @@ #include "libcef/browser/browser_host_base.h" #include "libcef/browser/context.h" -#include "libcef/browser/native/menu_runner_linux.h" #include "libcef/browser/native/window_delegate_view.h" #include "libcef/browser/thread_util.h" @@ -31,9 +30,7 @@ CefBrowserPlatformDelegateNativeLinux::CefBrowserPlatformDelegateNativeLinux( const CefWindowInfo& window_info, SkColor background_color) - : CefBrowserPlatformDelegateNativeAura(window_info, background_color), - host_window_created_(false), - window_widget_(nullptr) {} + : CefBrowserPlatformDelegateNativeAura(window_info, background_color) {} void CefBrowserPlatformDelegateNativeLinux::BrowserDestroyed( CefBrowserHostBase* browser) { @@ -190,26 +187,6 @@ void CefBrowserPlatformDelegateNativeLinux::SizeTo(int width, int height) { #endif // BUILDFLAG(OZONE_PLATFORM_X11) } -gfx::Point CefBrowserPlatformDelegateNativeLinux::GetScreenPoint( - const gfx::Point& view) const { - if (windowless_handler_) - return windowless_handler_->GetParentScreenPoint(view); - -#if BUILDFLAG(OZONE_PLATFORM_X11) - if (!window_x11_) - return view; - - // We can't use aura::Window::GetBoundsInScreen on Linux because it will - // return bounds from DesktopWindowTreeHostLinux which in our case is relative - // to the parent window instead of the root window (screen). - const gfx::Rect& bounds_in_screen = window_x11_->GetBoundsInScreen(); - return gfx::Point(bounds_in_screen.x() + view.x(), - bounds_in_screen.y() + view.y()); -#else // !BUILDFLAG(OZONE_PLATFORM_X11) - return gfx::Point(); -#endif -} - void CefBrowserPlatformDelegateNativeLinux::ViewText(const std::string& text) { char buff[] = "/tmp/CEFSourceXXXXXX"; int fd = mkstemp(buff); @@ -256,11 +233,6 @@ CefEventHandle CefBrowserPlatformDelegateNativeLinux::GetEventHandle( return nullptr; } -std::unique_ptr -CefBrowserPlatformDelegateNativeLinux::CreateMenuRunner() { - return base::WrapUnique(new CefMenuRunnerLinux); -} - gfx::Point CefBrowserPlatformDelegateNativeLinux::GetDialogPosition( const gfx::Size& size) { const gfx::Size& max_size = GetMaximumDialogSize(); diff --git a/libcef/browser/native/browser_platform_delegate_native_linux.h b/libcef/browser/native/browser_platform_delegate_native_linux.h index de661e6ec..05be1f4cb 100644 --- a/libcef/browser/native/browser_platform_delegate_native_linux.h +++ b/libcef/browser/native/browser_platform_delegate_native_linux.h @@ -29,13 +29,11 @@ class CefBrowserPlatformDelegateNativeLinux void SetFocus(bool setFocus) override; void NotifyMoveOrResizeStarted() override; void SizeTo(int width, int height) override; - gfx::Point GetScreenPoint(const gfx::Point& view) const override; void ViewText(const std::string& text) override; bool HandleKeyboardEvent( const content::NativeWebKeyboardEvent& event) override; CefEventHandle GetEventHandle( const content::NativeWebKeyboardEvent& event) const override; - std::unique_ptr CreateMenuRunner() override; gfx::Point GetDialogPosition(const gfx::Size& size) override; gfx::Size GetMaximumDialogSize() override; @@ -46,11 +44,7 @@ class CefBrowserPlatformDelegateNativeLinux private: // True if the host window has been created. - bool host_window_created_; - - // Widget hosting the web contents. It will be deleted automatically when the - // associated root window is destroyed. - views::Widget* window_widget_; + bool host_window_created_ = false; #if BUILDFLAG(OZONE_PLATFORM_X11) CefWindowX11* window_x11_ = nullptr; diff --git a/libcef/browser/native/browser_platform_delegate_native_mac.h b/libcef/browser/native/browser_platform_delegate_native_mac.h index a1a1bef17..55c529bf0 100644 --- a/libcef/browser/native/browser_platform_delegate_native_mac.h +++ b/libcef/browser/native/browser_platform_delegate_native_mac.h @@ -34,7 +34,8 @@ class CefBrowserPlatformDelegateNativeMac int deltaY) override; void SendTouchEvent(const CefTouchEvent& event) override; void SetFocus(bool setFocus) override; - gfx::Point GetScreenPoint(const gfx::Point& view) const override; + gfx::Point GetScreenPoint(const gfx::Point& view, + bool want_dip_coords) const override; void ViewText(const std::string& text) override; bool HandleKeyboardEvent( const content::NativeWebKeyboardEvent& event) override; diff --git a/libcef/browser/native/browser_platform_delegate_native_mac.mm b/libcef/browser/native/browser_platform_delegate_native_mac.mm index 48f13aa41..d8ff19987 100644 --- a/libcef/browser/native/browser_platform_delegate_native_mac.mm +++ b/libcef/browser/native/browser_platform_delegate_native_mac.mm @@ -324,9 +324,11 @@ void CefBrowserPlatformDelegateNativeMac::SetFocus(bool setFocus) { } gfx::Point CefBrowserPlatformDelegateNativeMac::GetScreenPoint( - const gfx::Point& view) const { + const gfx::Point& view, + bool want_dip_coords) const { + // Mac always operates in DIP coordinates so |want_dip_coords| is ignored. if (windowless_handler_) - return windowless_handler_->GetParentScreenPoint(view); + return windowless_handler_->GetParentScreenPoint(view, want_dip_coords); NSView* nsview = CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(window_info_.parent_view); if (nsview) { @@ -543,8 +545,8 @@ void CefBrowserPlatformDelegateNativeMac::TranslateWebMouseEvent( // position result.SetPositionInWidget(mouse_event.x, mouse_event.y); - const gfx::Point& screen_pt = - GetScreenPoint(gfx::Point(mouse_event.x, mouse_event.y)); + const gfx::Point& screen_pt = GetScreenPoint( + gfx::Point(mouse_event.x, mouse_event.y), /*want_dip_coords=*/true); result.SetPositionInScreen(screen_pt.x(), screen_pt.y()); // modifiers diff --git a/libcef/browser/native/browser_platform_delegate_native_win.cc b/libcef/browser/native/browser_platform_delegate_native_win.cc index 9e8ffeb5f..a345a6afe 100644 --- a/libcef/browser/native/browser_platform_delegate_native_win.cc +++ b/libcef/browser/native/browser_platform_delegate_native_win.cc @@ -11,7 +11,6 @@ #include "libcef/browser/alloy/alloy_browser_host_impl.h" #include "libcef/browser/context.h" #include "libcef/browser/native/javascript_dialog_runner_win.h" -#include "libcef/browser/native/menu_runner_win.h" #include "libcef/browser/native/window_delegate_view.h" #include "libcef/browser/thread_util.h" @@ -365,26 +364,6 @@ void CefBrowserPlatformDelegateNativeWin::SizeTo(int width, int height) { SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); } -gfx::Point CefBrowserPlatformDelegateNativeWin::GetScreenPoint( - const gfx::Point& view) const { - if (windowless_handler_) - return windowless_handler_->GetParentScreenPoint(view); - - if (!window_info_.window) - return view; - - // Convert from logical coordinates to device coordinates. - const float scale = GetWindowScaleFactor(window_info_.window); - const gfx::Point& device_pt = - gfx::ToFlooredPoint(gfx::ScalePoint(gfx::PointF(view), scale)); - - // Convert from client coordinates to screen coordinates. - POINT screen_pt = {device_pt.x(), device_pt.y()}; - ClientToScreen(window_info_.window, &screen_pt); - - return gfx::Point(screen_pt.x, screen_pt.y); -} - void CefBrowserPlatformDelegateNativeWin::ViewText(const std::string& text) { std::string str = text; scoped_refptr str_ref = @@ -451,11 +430,6 @@ CefBrowserPlatformDelegateNativeWin::CreateJavaScriptDialogRunner() { return base::WrapUnique(new CefJavaScriptDialogRunnerWin); } -std::unique_ptr -CefBrowserPlatformDelegateNativeWin::CreateMenuRunner() { - return base::WrapUnique(new CefMenuRunnerWin); -} - gfx::Point CefBrowserPlatformDelegateNativeWin::GetDialogPosition( const gfx::Size& size) { const gfx::Size& max_size = GetMaximumDialogSize(); diff --git a/libcef/browser/native/browser_platform_delegate_native_win.h b/libcef/browser/native/browser_platform_delegate_native_win.h index 2fbefab72..fd1ccc7dd 100644 --- a/libcef/browser/native/browser_platform_delegate_native_win.h +++ b/libcef/browser/native/browser_platform_delegate_native_win.h @@ -28,7 +28,6 @@ class CefBrowserPlatformDelegateNativeWin void SetFocus(bool setFocus) override; void NotifyMoveOrResizeStarted() override; void SizeTo(int width, int height) override; - gfx::Point GetScreenPoint(const gfx::Point& view) const override; void ViewText(const std::string& text) override; bool HandleKeyboardEvent( const content::NativeWebKeyboardEvent& event) override; @@ -36,7 +35,6 @@ class CefBrowserPlatformDelegateNativeWin const content::NativeWebKeyboardEvent& event) const override; std::unique_ptr CreateJavaScriptDialogRunner() override; - std::unique_ptr CreateMenuRunner() override; gfx::Point GetDialogPosition(const gfx::Size& size) override; gfx::Size GetMaximumDialogSize() override; @@ -55,10 +53,6 @@ class CefBrowserPlatformDelegateNativeWin // True if the host window has been created. bool host_window_created_ = false; - // Widget hosting the web contents. It will be deleted automatically when the - // associated root window is destroyed. - views::Widget* window_widget_ = nullptr; - bool has_frame_ = false; bool called_enable_non_client_dpi_scaling_ = false; }; diff --git a/libcef/browser/native/menu_2.cc b/libcef/browser/native/menu_2.cc deleted file mode 100644 index f3ea808fc..000000000 --- a/libcef/browser/native/menu_2.cc +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "libcef/browser/native/menu_2.h" - -#include "ui/base/models/menu_model.h" - -namespace views { - -Menu2::Menu2(ui::MenuModel* model) - : model_(model), wrapper_(MenuWrapper::CreateWrapper(model)) { - Rebuild(); -} - -Menu2::~Menu2() {} - -HMENU Menu2::GetNativeMenu() const { - return wrapper_->GetNativeMenu(); -} - -void Menu2::RunMenuAt(const gfx::Point& point, Alignment alignment) { - wrapper_->RunMenuAt(point, alignment); -} - -void Menu2::RunContextMenuAt(const gfx::Point& point) { - RunMenuAt(point, ALIGN_TOPLEFT); -} - -void Menu2::CancelMenu() { - wrapper_->CancelMenu(); -} - -void Menu2::Rebuild() { - wrapper_->Rebuild(nullptr); -} - -void Menu2::UpdateStates() { - wrapper_->UpdateStates(); -} - -MenuWrapper::MenuAction Menu2::GetMenuAction() const { - return wrapper_->GetMenuAction(); -} - -void Menu2::SetMinimumWidth(int width) { - wrapper_->SetMinimumWidth(width); -} - -} // namespace views diff --git a/libcef/browser/native/menu_2.h b/libcef/browser/native/menu_2.h deleted file mode 100644 index b2d0fcbf6..000000000 --- a/libcef/browser/native/menu_2.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CEF_LIBCEF_BROWSER_NATIVE_MENU_2_H_ -#define CEF_LIBCEF_BROWSER_NATIVE_MENU_2_H_ - -#include - -#include "libcef/browser/native/menu_wrapper.h" - -#include "ui/gfx/native_widget_types.h" - -namespace gfx { -class Point; -} - -namespace ui { -class MenuModel; -} - -namespace views { - -// A menu. Populated from a model, and relies on a delegate to execute commands. -// -// WARNING: do NOT create and use Menu2 on the stack. Menu2 notifies the model -// of selection AFTER a delay. This means that if use a Menu2 on the stack -// ActivatedAt is never invoked. -class Menu2 { - public: - // How the menu is aligned relative to the point it is shown at. - // The alignment is reversed by menu if text direction is right to left. - enum Alignment { ALIGN_TOPLEFT, ALIGN_TOPRIGHT }; - - // Creates a new menu populated with the contents of |model|. - // WARNING: this populates the menu on construction by invoking methods on - // the model. As such, it is typically not safe to use this as the model - // from the constructor. EG: - // MyClass : menu_(this) {} - // is likely to have problems. - explicit Menu2(ui::MenuModel* model); - - Menu2(const Menu2&) = delete; - Menu2& operator=(const Menu2&) = delete; - - virtual ~Menu2(); - - // Runs the menu at the specified point. This method blocks until done. - // RunContextMenuAt is the same, but the alignment is the default for a - // context menu. - void RunMenuAt(const gfx::Point& point, Alignment alignment); - void RunContextMenuAt(const gfx::Point& point); - - // Cancels the active menu. - void CancelMenu(); - - // Called when the model supplying data to this menu has changed, and the menu - // must be rebuilt. - void Rebuild(); - - // Called when the states of the menu items in the menu should be refreshed - // from the model. - void UpdateStates(); - - // For submenus. - HMENU GetNativeMenu() const; - - // Get the result of the last call to RunMenuAt to determine whether an - // item was selected, the user navigated to a next or previous menu, or - // nothing. - MenuWrapper::MenuAction GetMenuAction() const; - - // Accessors. - ui::MenuModel* model() const { return model_; } - - // Sets the minimum width of the menu. - void SetMinimumWidth(int width); - - private: - ui::MenuModel* model_; - - // The object that actually implements the menu. - std::unique_ptr wrapper_; -}; - -} // namespace views - -#endif // CEF_LIBCEF_BROWSER_NATIVE_MENU_2_H_ diff --git a/libcef/browser/native/menu_runner_linux.cc b/libcef/browser/native/menu_runner_linux.cc deleted file mode 100644 index c0f62aca3..000000000 --- a/libcef/browser/native/menu_runner_linux.cc +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2014 The Chromium Embedded Framework Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be found -// in the LICENSE file. - -#include "libcef/browser/native/menu_runner_linux.h" - -#include "libcef/browser/alloy/alloy_browser_host_impl.h" - -#include "base/strings/string_util.h" -#include "ui/gfx/geometry/point.h" - -CefMenuRunnerLinux::CefMenuRunnerLinux() {} - -bool CefMenuRunnerLinux::RunContextMenu( - AlloyBrowserHostImpl* browser, - CefMenuModelImpl* model, - const content::ContextMenuParams& params) { - menu_.reset( - new views::MenuRunner(model->model(), views::MenuRunner::CONTEXT_MENU)); - - const gfx::Point& screen_point = - browser->GetScreenPoint(gfx::Point(params.x, params.y)); - - views::Widget* parent_widget = nullptr; - if (!browser->IsWindowless()) - parent_widget = browser->GetWindowWidget(); - - menu_->RunMenuAt(parent_widget, nullptr, gfx::Rect(screen_point, gfx::Size()), - views::MenuAnchorPosition::kTopRight, ui::MENU_SOURCE_NONE); - - return true; -} - -void CefMenuRunnerLinux::CancelContextMenu() { - if (menu_) - menu_->Cancel(); -} - -bool CefMenuRunnerLinux::FormatLabel(std::u16string& label) { - // Remove the accelerator indicator (&) from label strings. - const std::u16string::value_type replace[] = {u'&', 0}; - return base::ReplaceChars(label, replace, std::u16string(), &label); -} diff --git a/libcef/browser/native/menu_runner_mac.mm b/libcef/browser/native/menu_runner_mac.mm index d7e319e9e..11f12fd6c 100644 --- a/libcef/browser/native/menu_runner_mac.mm +++ b/libcef/browser/native/menu_runner_mac.mm @@ -48,8 +48,8 @@ bool CefMenuRunnerMac::RunContextMenu( if (!browser->GetWindowHandle()) return false; - const gfx::Point& screen_point = - browser->GetScreenPoint(gfx::Point(params.x, params.y)); + const gfx::Point& screen_point = browser->GetScreenPoint( + gfx::Point(params.x, params.y), /*want_dip_coords=*/true); NSPoint screen_position = NSPointFromCGPoint(screen_point.ToCGPoint()); [[menu_controller_ menu] popUpMenuPositioningItem:nil atLocation:screen_position diff --git a/libcef/browser/native/menu_runner_views_aura.cc b/libcef/browser/native/menu_runner_views_aura.cc new file mode 100644 index 000000000..bf8dd8294 --- /dev/null +++ b/libcef/browser/native/menu_runner_views_aura.cc @@ -0,0 +1,52 @@ +// Copyright 2014 The Chromium Embedded Framework Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be found +// in the LICENSE file. + +#include "libcef/browser/native/menu_runner_views_aura.h" + +#include "libcef/browser/alloy/alloy_browser_host_impl.h" + +#include "base/strings/string_util.h" +#include "ui/gfx/geometry/point.h" + +CefMenuRunnerViewsAura::CefMenuRunnerViewsAura() {} + +bool CefMenuRunnerViewsAura::RunContextMenu( + AlloyBrowserHostImpl* browser, + CefMenuModelImpl* model, + const content::ContextMenuParams& params) { + views::Widget* widget = nullptr; + gfx::AcceleratedWidget parent_widget = gfx::kNullAcceleratedWidget; + if (browser->IsWindowless()) { + parent_widget = browser->GetWindowHandle(); + if (!parent_widget) { + LOG(ERROR) << "Window handle is required for default OSR context menu."; + return false; + } + } else { + widget = browser->GetWindowWidget(); + } + + menu_.reset( + new views::MenuRunner(model->model(), views::MenuRunner::CONTEXT_MENU)); + + gfx::Point screen_point = browser->GetScreenPoint( + gfx::Point(params.x, params.y), /*want_dip_coords=*/true); + + menu_->RunMenuAt(widget, nullptr, gfx::Rect(screen_point, gfx::Size()), + views::MenuAnchorPosition::kTopRight, ui::MENU_SOURCE_NONE, + /*native_view_for_gestures=*/nullptr, parent_widget); + + return true; +} + +void CefMenuRunnerViewsAura::CancelContextMenu() { + if (menu_) + menu_->Cancel(); +} + +bool CefMenuRunnerViewsAura::FormatLabel(std::u16string& label) { + // Remove the accelerator indicator (&) from label strings. + const std::u16string::value_type replace[] = {u'&', 0}; + return base::ReplaceChars(label, replace, std::u16string(), &label); +} diff --git a/libcef/browser/native/menu_runner_linux.h b/libcef/browser/native/menu_runner_views_aura.h similarity index 71% rename from libcef/browser/native/menu_runner_linux.h rename to libcef/browser/native/menu_runner_views_aura.h index 503461370..c930441b3 100644 --- a/libcef/browser/native/menu_runner_linux.h +++ b/libcef/browser/native/menu_runner_views_aura.h @@ -2,17 +2,17 @@ // reserved. Use of this source code is governed by a BSD-style license that can // be found in the LICENSE file. -#ifndef CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_LINUX_H_ -#define CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_LINUX_H_ +#ifndef CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_VIEWS_AURA_H_ +#define CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_VIEWS_AURA_H_ #pragma once #include "libcef/browser/menu_runner.h" #include "ui/views/controls/menu/menu_runner.h" -class CefMenuRunnerLinux : public CefMenuRunner { +class CefMenuRunnerViewsAura : public CefMenuRunner { public: - CefMenuRunnerLinux(); + CefMenuRunnerViewsAura(); // CefMenuRunner methods. bool RunContextMenu(AlloyBrowserHostImpl* browser, @@ -25,4 +25,4 @@ class CefMenuRunnerLinux : public CefMenuRunner { std::unique_ptr menu_; }; -#endif // CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_LINUX_H_ +#endif // CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_VIEWS_AURA_H_ diff --git a/libcef/browser/native/menu_runner_win.cc b/libcef/browser/native/menu_runner_win.cc deleted file mode 100644 index dbc6dc66e..000000000 --- a/libcef/browser/native/menu_runner_win.cc +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that can -// be found in the LICENSE file. - -#include "libcef/browser/native/menu_runner_win.h" - -#include "libcef/browser/alloy/alloy_browser_host_impl.h" -#include "libcef/browser/native/menu_2.h" - -#include "base/task/current_thread.h" -#include "ui/gfx/geometry/point.h" - -CefMenuRunnerWin::CefMenuRunnerWin() {} - -bool CefMenuRunnerWin::RunContextMenu( - AlloyBrowserHostImpl* browser, - CefMenuModelImpl* model, - const content::ContextMenuParams& params) { - // Create a menu based on the model. - menu_.reset(new views::CefNativeMenuWin(model->model(), nullptr)); - menu_->Rebuild(nullptr); - - // Make sure events can be pumped while the menu is up. - base::CurrentThread::ScopedNestableTaskAllower allow; - - const gfx::Point& screen_point = - browser->GetScreenPoint(gfx::Point(params.x, params.y)); - - // Show the menu. Blocks until the menu is dismissed. - menu_->RunMenuAt(screen_point, views::Menu2::ALIGN_TOPLEFT); - - return true; -} diff --git a/libcef/browser/native/menu_runner_win.h b/libcef/browser/native/menu_runner_win.h deleted file mode 100644 index 7a098705d..000000000 --- a/libcef/browser/native/menu_runner_win.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that can -// be found in the LICENSE file. - -#ifndef CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_WIN_H_ -#define CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_WIN_H_ -#pragma once - -#include "libcef/browser/menu_runner.h" - -#include "libcef/browser/native/native_menu_win.h" - -class CefMenuRunnerWin : public CefMenuRunner { - public: - CefMenuRunnerWin(); - - // CefMenuRunner methods. - bool RunContextMenu(AlloyBrowserHostImpl* browser, - CefMenuModelImpl* model, - const content::ContextMenuParams& params) override; - - private: - std::unique_ptr menu_; -}; - -#endif // CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_WIN_H_ diff --git a/libcef/browser/native/menu_wrapper.h b/libcef/browser/native/menu_wrapper.h deleted file mode 100644 index 0f4f0e342..000000000 --- a/libcef/browser/native/menu_wrapper.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CEF_LIBCEF_BROWSER_NATIVE_MENU_WRAPPER_H_ -#define CEF_LIBCEF_BROWSER_NATIVE_MENU_WRAPPER_H_ - -#include "ui/gfx/native_widget_types.h" - -namespace gfx { -class Point; -} - -namespace ui { -class MenuModel; -} - -namespace views { - -class MenuInsertionDelegateWin; - -// An interface that wraps an object that implements a menu. -class MenuWrapper { - public: - // All of the possible actions that can result from RunMenuAt. - enum MenuAction { - MENU_ACTION_NONE, // Menu cancelled, or never opened. - MENU_ACTION_SELECTED, // An item was selected. - MENU_ACTION_PREVIOUS, // User wants to navigate to the previous menu. - MENU_ACTION_NEXT, // User wants to navigate to the next menu. - }; - - virtual ~MenuWrapper() {} - - // Creates the appropriate instance of this wrapper for the current platform. - static MenuWrapper* CreateWrapper(ui::MenuModel* model); - - // Runs the menu at the specified point. This blocks until done. - virtual void RunMenuAt(const gfx::Point& point, int alignment) = 0; - - // Cancels the active menu. - virtual void CancelMenu() = 0; - - // Called when the model supplying data to this menu has changed, and the menu - // must be rebuilt. - virtual void Rebuild(MenuInsertionDelegateWin* delegate) = 0; - - // Called when the states of the items in the menu must be updated from the - // model. - virtual void UpdateStates() = 0; - - // Retrieve a native menu handle. - virtual HMENU GetNativeMenu() const = 0; - - // Get the result of the last call to RunMenuAt to determine whether an - // item was selected, the user navigated to a next or previous menu, or - // nothing. - virtual MenuAction GetMenuAction() const = 0; - - // Sets the minimum width of the menu. - virtual void SetMinimumWidth(int width) = 0; -}; - -} // namespace views - -#endif // CEF_LIBCEF_BROWSER_NATIVE_MENU_WRAPPER_H_ diff --git a/libcef/browser/native/native_menu_win.cc b/libcef/browser/native/native_menu_win.cc deleted file mode 100644 index b20e4b5e4..000000000 --- a/libcef/browser/native/native_menu_win.cc +++ /dev/null @@ -1,793 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "libcef/browser/native/native_menu_win.h" - -#include "libcef/browser/native/menu_2.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/memory/ptr_util.h" -#include "base/stl_util.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/win/wrapped_window_proc.h" -#include "skia/ext/platform_canvas.h" -#include "skia/ext/skia_utils_win.h" -#include "ui/base/accelerators/accelerator.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/l10n/l10n_util_win.h" -#include "ui/base/models/image_model.h" -#include "ui/base/models/menu_model.h" -#include "ui/base/themed_vector_icon.h" -#include "ui/color/color_provider_manager.h" -#include "ui/events/keycodes/keyboard_codes.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/font_list.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/image/image_skia.h" -#include "ui/gfx/text_utils.h" -#include "ui/gfx/win/hwnd_util.h" -#include "ui/native_theme/native_theme.h" -#include "ui/views/controls/menu/menu_config.h" -#include "ui/views/controls/menu/menu_insertion_delegate_win.h" - -using ui::NativeTheme; - -namespace views { - -// The width of an icon, including the pixels between the icon and -// the item label. -static const int kIconWidth = 23; -// Margins between the top of the item and the label. -static const int kItemTopMargin = 3; -// Margins between the bottom of the item and the label. -static const int kItemBottomMargin = 4; -// Margins between the left of the item and the icon. -static const int kItemLeftMargin = 4; -// The width for displaying the sub-menu arrow. -static const int kArrowWidth = 10; - -// Horizontal spacing between the end of an item (i.e. an icon or a checkbox) -// and the start of its corresponding text. -constexpr int kItemLabelSpacing = 10; - -namespace { - -// Draws the top layer of the canvas into the specified HDC. Only works -// with a SkCanvas with a BitmapPlatformDevice. Will create a temporary -// HDC to back the canvas if one doesn't already exist, tearing it down -// before returning. If |src_rect| is null, copies the entire canvas. -// Deleted from skia/ext/platform_canvas.h in https://crbug.com/675977#c13 -void DrawToNativeContext(SkCanvas* canvas, - HDC destination_hdc, - int x, - int y, - const RECT* src_rect) { - RECT temp_rect; - if (!src_rect) { - temp_rect.left = 0; - temp_rect.right = canvas->imageInfo().width(); - temp_rect.top = 0; - temp_rect.bottom = canvas->imageInfo().height(); - src_rect = &temp_rect; - } - skia::CopyHDC(skia::GetNativeDrawingContext(canvas), destination_hdc, x, y, - canvas->imageInfo().isOpaque(), *src_rect, - canvas->getTotalMatrix()); -} - -HFONT CreateNativeFont(const gfx::Font& font) { - // Extracts |fonts| properties. - const DWORD italic = (font.GetStyle() & gfx::Font::ITALIC) ? TRUE : FALSE; - const DWORD underline = - (font.GetStyle() & gfx::Font::UNDERLINE) ? TRUE : FALSE; - // The font mapper matches its absolute value against the character height of - // the available fonts. - const int height = -font.GetFontSize(); - - // Select the primary font which forces a mapping to a physical font. - return ::CreateFont(height, 0, 0, 0, static_cast(font.GetWeight()), - italic, underline, FALSE, DEFAULT_CHARSET, - OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, - DEFAULT_PITCH | FF_DONTCARE, - base::UTF8ToWide(font.GetFontName()).c_str()); -} - -} // namespace - -struct CefNativeMenuWin::ItemData { - // The Windows API requires that whoever creates the menus must own the - // strings used for labels, and keep them around for the lifetime of the - // created menu. So be it. - std::wstring label; - - // Someone needs to own submenus, it may as well be us. - std::unique_ptr submenu; - - // We need a pointer back to the containing menu in various circumstances. - CefNativeMenuWin* native_menu_win; - - // The index of the item within the menu's model. - int model_index; -}; - -// Returns the CefNativeMenuWin for a particular HMENU. -static CefNativeMenuWin* GetCefNativeMenuWinFromHMENU(HMENU hmenu) { - MENUINFO mi = {0}; - mi.cbSize = sizeof(mi); - mi.fMask = MIM_MENUDATA | MIM_STYLE; - GetMenuInfo(hmenu, &mi); - return reinterpret_cast(mi.dwMenuData); -} - -// A window that receives messages from Windows relevant to the native menu -// structure we have constructed in CefNativeMenuWin. -class CefNativeMenuWin::MenuHostWindow { - public: - MenuHostWindow() { - RegisterClass(); - hwnd_ = CreateWindowEx(l10n_util::GetExtendedStyles(), kWindowClassName, - L"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); - gfx::CheckWindowCreated(hwnd_, ::GetLastError()); - gfx::SetWindowUserData(hwnd_, this); - } - - MenuHostWindow(const MenuHostWindow&) = delete; - MenuHostWindow& operator=(const MenuHostWindow&) = delete; - - ~MenuHostWindow() { DestroyWindow(hwnd_); } - - HWND hwnd() const { return hwnd_; } - - private: - static const wchar_t* kWindowClassName; - - void RegisterClass() { - static bool registered = false; - if (registered) - return; - - WNDCLASSEX window_class; - base::win::InitializeWindowClass( - kWindowClassName, &base::win::WrappedWindowProc, - CS_DBLCLKS, 0, 0, NULL, reinterpret_cast(COLOR_WINDOW + 1), - NULL, NULL, NULL, &window_class); - ATOM clazz = RegisterClassEx(&window_class); - CHECK(clazz); - registered = true; - } - - // Converts the WPARAM value passed to WM_MENUSELECT into an index - // corresponding to the menu item that was selected. - int GetMenuItemIndexFromWPARAM(HMENU menu, WPARAM w_param) const { - int count = GetMenuItemCount(menu); - // For normal command menu items, Windows passes a command id as the LOWORD - // of WPARAM for WM_MENUSELECT. We need to walk forward through the menu - // items to find an item with a matching ID. Ugh! - for (int i = 0; i < count; ++i) { - MENUITEMINFO mii = {0}; - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_ID; - GetMenuItemInfo(menu, i, MF_BYPOSITION, &mii); - if (mii.wID == w_param) - return i; - } - // If we didn't find a matching command ID, this means a submenu has been - // selected instead, and rather than passing a command ID in - // LOWORD(w_param), Windows has actually passed us a position, so we just - // return it. - return w_param; - } - - CefNativeMenuWin::ItemData* GetItemData(ULONG_PTR item_data) { - return reinterpret_cast(item_data); - } - - // Called when the user selects a specific item. - void OnMenuCommand(int position, HMENU menu) { - CefNativeMenuWin* menu_win = GetCefNativeMenuWinFromHMENU(menu); - ui::MenuModel* model = menu_win->model_; - CefNativeMenuWin* root_menu = menu_win; - while (root_menu->parent_) - root_menu = root_menu->parent_; - - // Only notify the model if it didn't already send out notification. - // See comment in MenuMessageHook for details. - if (root_menu->menu_action_ == MenuWrapper::MENU_ACTION_NONE) - model->ActivatedAt(position); - } - - // Called by Windows to measure the size of an owner-drawn menu item. - void OnMeasureItem(WPARAM w_param, MEASUREITEMSTRUCT* measure_item_struct) { - CefNativeMenuWin::ItemData* data = - GetItemData(measure_item_struct->itemData); - if (data) { - gfx::FontList font_list; - measure_item_struct->itemWidth = - gfx::GetStringWidth(base::WideToUTF16(data->label), font_list) + - kIconWidth + kItemLeftMargin + kItemLabelSpacing - - GetSystemMetrics(SM_CXMENUCHECK); - if (data->submenu.get()) - measure_item_struct->itemWidth += kArrowWidth; - // If the label contains an accelerator, make room for tab. - if (data->label.find(L'\t') != std::wstring::npos) - measure_item_struct->itemWidth += gfx::GetStringWidth(u" ", font_list); - measure_item_struct->itemHeight = - font_list.GetHeight() + kItemBottomMargin + kItemTopMargin; - } else { - // Measure separator size. - measure_item_struct->itemHeight = GetSystemMetrics(SM_CYMENU) / 2; - measure_item_struct->itemWidth = 0; - } - } - - // Called by Windows to paint an owner-drawn menu item. - void OnDrawItem(UINT w_param, DRAWITEMSTRUCT* draw_item_struct) { - HDC dc = draw_item_struct->hDC; - COLORREF prev_bg_color, prev_text_color; - - // Set background color and text color - if (draw_item_struct->itemState & ODS_SELECTED) { - prev_bg_color = SetBkColor(dc, GetSysColor(COLOR_HIGHLIGHT)); - prev_text_color = SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT)); - } else { - prev_bg_color = SetBkColor(dc, GetSysColor(COLOR_MENU)); - if (draw_item_struct->itemState & ODS_DISABLED) - prev_text_color = SetTextColor(dc, GetSysColor(COLOR_GRAYTEXT)); - else - prev_text_color = SetTextColor(dc, GetSysColor(COLOR_MENUTEXT)); - } - - if (draw_item_struct->itemData) { - CefNativeMenuWin::ItemData* data = - GetItemData(draw_item_struct->itemData); - // Draw the background. - HBRUSH hbr = CreateSolidBrush(GetBkColor(dc)); - FillRect(dc, &draw_item_struct->rcItem, hbr); - DeleteObject(hbr); - - // Draw the label. - RECT rect = draw_item_struct->rcItem; - rect.top += kItemTopMargin; - // Should we add kIconWidth only when icon.width() != 0 ? - rect.left += kItemLeftMargin + kIconWidth; - rect.right -= kItemLabelSpacing; - UINT format = DT_TOP | DT_SINGLELINE; - // Check whether the mnemonics should be underlined. - BOOL underline_mnemonics; - SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &underline_mnemonics, 0); - if (!underline_mnemonics) - format |= DT_HIDEPREFIX; - gfx::FontList font_list; - HFONT new_font = CreateNativeFont(font_list.GetPrimaryFont()); - HGDIOBJ old_font = SelectObject(dc, new_font); - - // If an accelerator is specified (with a tab delimiting the rest of the - // label from the accelerator), we have to justify the fist part on the - // left and the accelerator on the right. - // TODO(jungshik): This will break in RTL UI. Currently, he/ar use the - // window system UI font and will not hit here. - std::wstring label = data->label; - std::wstring accel; - std::wstring::size_type tab_pos = label.find(L'\t'); - if (tab_pos != std::wstring::npos) { - accel = label.substr(tab_pos); - label = label.substr(0, tab_pos); - } - DrawTextEx(dc, const_cast(label.data()), - static_cast(label.size()), &rect, format | DT_LEFT, NULL); - if (!accel.empty()) { - DrawTextEx(dc, const_cast(accel.data()), - static_cast(accel.size()), &rect, format | DT_RIGHT, - NULL); - } - SelectObject(dc, old_font); - DeleteObject(new_font); - - ui::MenuModel::ItemType type = - data->native_menu_win->model_->GetTypeAt(data->model_index); - - // Draw the icon after the label, otherwise it would be covered - // by the label. - ui::ImageModel icon = - data->native_menu_win->model_->GetIconAt(data->model_index); - if (icon.IsImage() || icon.IsVectorIcon()) { - ui::NativeTheme* native_theme = - ui::NativeTheme::GetInstanceForNativeUi(); - - auto* color_provider = - ui::ColorProviderManager::Get().GetColorProviderFor( - native_theme->GetColorProviderKey(nullptr)); - - // We currently don't support items with both icons and checkboxes. - const gfx::ImageSkia skia_icon = - icon.IsImage() ? icon.GetImage().AsImageSkia() - : ui::ThemedVectorIcon(icon.GetVectorIcon()) - .GetImageSkia(color_provider, 16); - - DCHECK(type != ui::MenuModel::TYPE_CHECK); - std::unique_ptr canvas = skia::CreatePlatformCanvas( - skia_icon.width(), skia_icon.height(), false); - canvas->drawImage(skia_icon.bitmap()->asImage(), 0, 0); - DrawToNativeContext( - canvas.get(), dc, draw_item_struct->rcItem.left + kItemLeftMargin, - draw_item_struct->rcItem.top + - (draw_item_struct->rcItem.bottom - - draw_item_struct->rcItem.top - skia_icon.height()) / - 2, - NULL); - } else if (type == ui::MenuModel::TYPE_CHECK && - data->native_menu_win->model_->IsItemCheckedAt( - data->model_index)) { - // Manually render a checkbox. - const MenuConfig& config = MenuConfig::instance(); - NativeTheme::State state; - if (draw_item_struct->itemState & ODS_DISABLED) { - state = NativeTheme::kDisabled; - } else { - state = draw_item_struct->itemState & ODS_SELECTED - ? NativeTheme::kHovered - : NativeTheme::kNormal; - } - - std::unique_ptr canvas = skia::CreatePlatformCanvas( - config.check_width, config.check_height, false); - cc::SkiaPaintCanvas paint_canvas(canvas.get()); - - NativeTheme::ExtraParams extra; - extra.menu_check.is_radio = false; - gfx::Rect bounds(0, 0, config.check_width, config.check_height); - - // Draw the background and the check. - ui::NativeTheme* native_theme = - ui::NativeTheme::GetInstanceForNativeUi(); - auto* color_provider = - ui::ColorProviderManager::Get().GetColorProviderFor( - native_theme->GetColorProviderKey(nullptr)); - - native_theme->Paint(&paint_canvas, color_provider, - NativeTheme::kMenuCheckBackground, state, bounds, - extra); - native_theme->Paint(&paint_canvas, color_provider, - NativeTheme::kMenuCheck, state, bounds, extra); - - // Draw checkbox to menu. - DrawToNativeContext( - canvas.get(), dc, draw_item_struct->rcItem.left + kItemLeftMargin, - draw_item_struct->rcItem.top + - (draw_item_struct->rcItem.bottom - - draw_item_struct->rcItem.top - config.check_height) / - 2, - NULL); - } - } else { - // Draw the separator - draw_item_struct->rcItem.top += - (draw_item_struct->rcItem.bottom - draw_item_struct->rcItem.top) / 3; - DrawEdge(dc, &draw_item_struct->rcItem, EDGE_ETCHED, BF_TOP); - } - - SetBkColor(dc, prev_bg_color); - SetTextColor(dc, prev_text_color); - } - - bool ProcessWindowMessage(HWND window, - UINT message, - WPARAM w_param, - LPARAM l_param, - LRESULT* l_result) { - switch (message) { - case WM_MENUCOMMAND: - OnMenuCommand(w_param, reinterpret_cast(l_param)); - *l_result = 0; - return true; - case WM_MENUSELECT: - *l_result = 0; - return true; - case WM_MEASUREITEM: - OnMeasureItem(w_param, reinterpret_cast(l_param)); - *l_result = 0; - return true; - case WM_DRAWITEM: - OnDrawItem(w_param, reinterpret_cast(l_param)); - *l_result = 0; - return true; - // TODO(beng): bring over owner draw from old menu system. - } - return false; - } - - static LRESULT CALLBACK MenuHostWindowProc(HWND window, - UINT message, - WPARAM w_param, - LPARAM l_param) { - MenuHostWindow* host = - reinterpret_cast(gfx::GetWindowUserData(window)); - // host is null during initial construction. - LRESULT l_result = 0; - if (!host || !host->ProcessWindowMessage(window, message, w_param, l_param, - &l_result)) { - return DefWindowProc(window, message, w_param, l_param); - } - return l_result; - } - - HWND hwnd_; -}; - -struct CefNativeMenuWin::HighlightedMenuItemInfo { - HighlightedMenuItemInfo() - : has_parent(false), has_submenu(false), menu(nullptr), position(-1) {} - - bool has_parent; - bool has_submenu; - - // The menu and position. These are only set for non-disabled menu items. - CefNativeMenuWin* menu; - int position; -}; - -// static -const wchar_t* CefNativeMenuWin::MenuHostWindow::kWindowClassName = - L"ViewsMenuHostWindow"; - -//////////////////////////////////////////////////////////////////////////////// -// CefNativeMenuWin, public: - -CefNativeMenuWin::CefNativeMenuWin(ui::MenuModel* model, HWND system_menu_for) - : model_(model), - menu_(nullptr), - owner_draw_(l10n_util::NeedOverrideDefaultUIFont(NULL, NULL) && - !system_menu_for), - system_menu_for_(system_menu_for), - first_item_index_(0), - menu_action_(MENU_ACTION_NONE), - menu_to_select_(nullptr), - position_to_select_(-1), - parent_(nullptr), - destroyed_flag_(nullptr), - menu_to_select_factory_(this) {} - -CefNativeMenuWin::~CefNativeMenuWin() { - if (destroyed_flag_) - *destroyed_flag_ = true; - DestroyMenu(menu_); -} - -//////////////////////////////////////////////////////////////////////////////// -// CefNativeMenuWin, MenuWrapper implementation: - -void CefNativeMenuWin::RunMenuAt(const gfx::Point& point, int alignment) { - CreateHostWindow(); - UpdateStates(); - UINT flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RECURSE; - flags |= GetAlignmentFlags(alignment); - menu_action_ = MENU_ACTION_NONE; - - // Set a hook function so we can listen for keyboard events while the - // menu is open, and store a pointer to this object in a static - // variable so the hook has access to it (ugly, but it's the - // only way). - open_native_menu_win_ = this; - HHOOK hhook = SetWindowsHookEx(WH_MSGFILTER, MenuMessageHook, - GetModuleHandle(NULL), ::GetCurrentThreadId()); - - // Command dispatch is done through WM_MENUCOMMAND, handled by the host - // window. - menu_to_select_ = nullptr; - position_to_select_ = -1; - menu_to_select_factory_.InvalidateWeakPtrs(); - bool destroyed = false; - destroyed_flag_ = &destroyed; - model_->MenuWillShow(); - TrackPopupMenu(menu_, flags, point.x(), point.y(), 0, host_window_->hwnd(), - NULL); - UnhookWindowsHookEx(hhook); - open_native_menu_win_ = nullptr; - if (destroyed) - return; - destroyed_flag_ = nullptr; - if (menu_to_select_) { - // Folks aren't too happy if we notify immediately. In particular, notifying - // the delegate can cause destruction leaving the stack in a weird - // state. Instead post a task, then notify. This mirrors what WM_MENUCOMMAND - // does. - menu_to_select_factory_.InvalidateWeakPtrs(); - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&CefNativeMenuWin::DelayedSelect, - menu_to_select_factory_.GetWeakPtr())); - menu_action_ = MENU_ACTION_SELECTED; - } - // Send MenuWillClose after we schedule the select, otherwise MenuWillClose is - // processed after the select (MenuWillClose posts a delayed task too). - model_->MenuWillClose(); -} - -void CefNativeMenuWin::CancelMenu() { - EndMenu(); -} - -void CefNativeMenuWin::Rebuild(MenuInsertionDelegateWin* delegate) { - ResetNativeMenu(); - items_.clear(); - - owner_draw_ = model_->HasIcons() || owner_draw_; - first_item_index_ = delegate ? delegate->GetInsertionIndex(menu_) : 0; - for (int menu_index = first_item_index_; - menu_index < first_item_index_ + model_->GetItemCount(); ++menu_index) { - int model_index = menu_index - first_item_index_; - if (model_->GetTypeAt(model_index) == ui::MenuModel::TYPE_SEPARATOR) - AddSeparatorItemAt(menu_index, model_index); - else - AddMenuItemAt(menu_index, model_index); - } -} - -void CefNativeMenuWin::UpdateStates() { - // A depth-first walk of the menu items, updating states. - int model_index = 0; - ItemDataList::const_iterator it; - for (it = items_.begin(); it != items_.end(); ++it, ++model_index) { - int menu_index = model_index + first_item_index_; - SetMenuItemState(menu_index, model_->IsEnabledAt(model_index), - model_->IsItemCheckedAt(model_index), false); - if (model_->IsItemDynamicAt(model_index)) { - // TODO(atwilson): Update the icon as well (http://crbug.com/66508). - SetMenuItemLabel(menu_index, model_index, - base::UTF16ToWide(model_->GetLabelAt(model_index))); - } - Menu2* submenu = (*it)->submenu.get(); - if (submenu) - submenu->UpdateStates(); - } -} - -HMENU CefNativeMenuWin::GetNativeMenu() const { - return menu_; -} - -CefNativeMenuWin::MenuAction CefNativeMenuWin::GetMenuAction() const { - return menu_action_; -} - -void CefNativeMenuWin::SetMinimumWidth(int width) { - NOTIMPLEMENTED(); -} - -//////////////////////////////////////////////////////////////////////////////// -// CefNativeMenuWin, private: - -// static -CefNativeMenuWin* CefNativeMenuWin::open_native_menu_win_ = nullptr; - -void CefNativeMenuWin::DelayedSelect() { - if (menu_to_select_) - menu_to_select_->model_->ActivatedAt(position_to_select_); -} - -// static -bool CefNativeMenuWin::GetHighlightedMenuItemInfo( - HMENU menu, - HighlightedMenuItemInfo* info) { - for (int i = 0; i < ::GetMenuItemCount(menu); i++) { - UINT state = ::GetMenuState(menu, i, MF_BYPOSITION); - if (state & MF_HILITE) { - if (state & MF_POPUP) { - HMENU submenu = GetSubMenu(menu, i); - if (GetHighlightedMenuItemInfo(submenu, info)) - info->has_parent = true; - else - info->has_submenu = true; - } else if (!(state & MF_SEPARATOR) && !(state & MF_DISABLED)) { - info->menu = GetCefNativeMenuWinFromHMENU(menu); - info->position = i; - } - return true; - } - } - return false; -} - -// static -LRESULT CALLBACK CefNativeMenuWin::MenuMessageHook(int n_code, - WPARAM w_param, - LPARAM l_param) { - LRESULT result = CallNextHookEx(NULL, n_code, w_param, l_param); - - CefNativeMenuWin* this_ptr = open_native_menu_win_; - if (!this_ptr) - return result; - - MSG* msg = reinterpret_cast(l_param); - if (msg->message == WM_LBUTTONUP || msg->message == WM_RBUTTONUP) { - HighlightedMenuItemInfo info; - if (GetHighlightedMenuItemInfo(this_ptr->menu_, &info) && info.menu) { - // It appears that when running a menu by way of TrackPopupMenu(Ex) win32 - // gets confused if the underlying window paints itself. As its very easy - // for the underlying window to repaint itself (especially since some menu - // items trigger painting of the tabstrip on mouse over) we have this - // workaround. When the mouse is released on a menu item we remember the - // menu item and end the menu. When the nested message loop returns we - // schedule a task to notify the model. It's still possible to get a - // WM_MENUCOMMAND, so we have to be careful that we don't notify the model - // twice. - this_ptr->menu_to_select_ = info.menu; - this_ptr->position_to_select_ = info.position; - EndMenu(); - } - } else if (msg->message == WM_KEYDOWN) { - HighlightedMenuItemInfo info; - if (GetHighlightedMenuItemInfo(this_ptr->menu_, &info)) { - if (msg->wParam == VK_LEFT && !info.has_parent) { - this_ptr->menu_action_ = MENU_ACTION_PREVIOUS; - ::EndMenu(); - } else if (msg->wParam == VK_RIGHT && !info.has_parent && - !info.has_submenu) { - this_ptr->menu_action_ = MENU_ACTION_NEXT; - ::EndMenu(); - } - } - } - - return result; -} - -bool CefNativeMenuWin::IsSeparatorItemAt(int menu_index) const { - MENUITEMINFO mii = {0}; - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_FTYPE; - GetMenuItemInfo(menu_, menu_index, MF_BYPOSITION, &mii); - return !!(mii.fType & MF_SEPARATOR); -} - -void CefNativeMenuWin::AddMenuItemAt(int menu_index, int model_index) { - MENUITEMINFO mii = {0}; - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_FTYPE | MIIM_ID | MIIM_DATA; - if (!owner_draw_) - mii.fType = MFT_STRING; - else - mii.fType = MFT_OWNERDRAW; - - std::unique_ptr item_data = std::make_unique(); - item_data->label = std::wstring(); - ui::MenuModel::ItemType type = model_->GetTypeAt(model_index); - if (type == ui::MenuModel::TYPE_SUBMENU) { - item_data->submenu.reset(new Menu2(model_->GetSubmenuModelAt(model_index))); - mii.fMask |= MIIM_SUBMENU; - mii.hSubMenu = item_data->submenu->GetNativeMenu(); - GetCefNativeMenuWinFromHMENU(mii.hSubMenu)->parent_ = this; - } else { - if (type == ui::MenuModel::TYPE_RADIO) - mii.fType |= MFT_RADIOCHECK; - mii.wID = model_->GetCommandIdAt(model_index); - } - item_data->native_menu_win = this; - item_data->model_index = model_index; - mii.dwItemData = reinterpret_cast(item_data.get()); - items_.insert(items_.begin() + model_index, std::move(item_data)); - UpdateMenuItemInfoForString( - &mii, model_index, base::UTF16ToWide(model_->GetLabelAt(model_index))); - InsertMenuItem(menu_, menu_index, TRUE, &mii); -} - -void CefNativeMenuWin::AddSeparatorItemAt(int menu_index, int model_index) { - MENUITEMINFO mii = {0}; - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_FTYPE; - mii.fType = MFT_SEPARATOR; - // Insert a dummy entry into our label list so we can index directly into it - // using item indices if need be. - items_.insert(items_.begin() + model_index, std::make_unique()); - InsertMenuItem(menu_, menu_index, TRUE, &mii); -} - -void CefNativeMenuWin::SetMenuItemState(int menu_index, - bool enabled, - bool checked, - bool is_default) { - if (IsSeparatorItemAt(menu_index)) - return; - - UINT state = enabled ? MFS_ENABLED : MFS_DISABLED; - if (checked) - state |= MFS_CHECKED; - if (is_default) - state |= MFS_DEFAULT; - - MENUITEMINFO mii = {0}; - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STATE; - mii.fState = state; - SetMenuItemInfo(menu_, menu_index, MF_BYPOSITION, &mii); -} - -void CefNativeMenuWin::SetMenuItemLabel(int menu_index, - int model_index, - const std::wstring& label) { - if (IsSeparatorItemAt(menu_index)) - return; - - MENUITEMINFO mii = {0}; - mii.cbSize = sizeof(mii); - UpdateMenuItemInfoForString(&mii, model_index, label); - SetMenuItemInfo(menu_, menu_index, MF_BYPOSITION, &mii); -} - -void CefNativeMenuWin::UpdateMenuItemInfoForString(MENUITEMINFO* mii, - int model_index, - const std::wstring& label) { - std::wstring formatted = label; - ui::MenuModel::ItemType type = model_->GetTypeAt(model_index); - // Strip out any tabs, otherwise they get interpreted as accelerators and can - // lead to weird behavior. - base::ReplaceSubstringsAfterOffset(&formatted, 0, L"\t", L" "); - if (type != ui::MenuModel::TYPE_SUBMENU) { - // Add accelerator details to the label if provided. - ui::Accelerator accelerator(ui::VKEY_UNKNOWN, ui::EF_NONE); - if (model_->GetAcceleratorAt(model_index, &accelerator)) { - formatted += L"\t"; - formatted += base::UTF16ToWide(accelerator.GetShortcutText()); - } - } - - // Update the owned string, since Windows will want us to keep this new - // version around. - items_[model_index]->label = formatted; - - // Give Windows a pointer to the label string. - mii->fMask |= MIIM_STRING; - mii->dwTypeData = const_cast(items_[model_index]->label.c_str()); -} - -UINT CefNativeMenuWin::GetAlignmentFlags(int alignment) const { - UINT alignment_flags = TPM_TOPALIGN; - if (alignment == Menu2::ALIGN_TOPLEFT) - alignment_flags |= TPM_LEFTALIGN; - else if (alignment == Menu2::ALIGN_TOPRIGHT) - alignment_flags |= TPM_RIGHTALIGN; - return alignment_flags; -} - -void CefNativeMenuWin::ResetNativeMenu() { - if (IsWindow(system_menu_for_)) { - if (menu_) - GetSystemMenu(system_menu_for_, TRUE); - menu_ = GetSystemMenu(system_menu_for_, FALSE); - } else { - if (menu_) - DestroyMenu(menu_); - menu_ = CreatePopupMenu(); - // Rather than relying on the return value of TrackPopupMenuEx, which is - // always a command identifier, instead we tell the menu to notify us via - // our host window and the WM_MENUCOMMAND message. - MENUINFO mi = {0}; - mi.cbSize = sizeof(mi); - mi.fMask = MIM_STYLE | MIM_MENUDATA; - mi.dwStyle = MNS_NOTIFYBYPOS; - mi.dwMenuData = reinterpret_cast(this); - SetMenuInfo(menu_, &mi); - } -} - -void CefNativeMenuWin::CreateHostWindow() { - // This only gets called from RunMenuAt, and as such there is only ever one - // host window per menu hierarchy, no matter how many CefNativeMenuWin objects - // exist wrapping submenus. - if (!host_window_.get()) - host_window_.reset(new MenuHostWindow()); -} - -//////////////////////////////////////////////////////////////////////////////// -// MenuWrapper, public: - -// static -MenuWrapper* MenuWrapper::CreateWrapper(ui::MenuModel* model) { - return new CefNativeMenuWin(model, NULL); -} - -} // namespace views diff --git a/libcef/browser/native/native_menu_win.h b/libcef/browser/native/native_menu_win.h deleted file mode 100644 index 491997236..000000000 --- a/libcef/browser/native/native_menu_win.h +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CEF_LIBCEF_BROWSER_NATIVE_NATIVE_MENU_WIN_H_ -#define CEF_LIBCEF_BROWSER_NATIVE_NATIVE_MENU_WIN_H_ - -#include -#include - -#include "libcef/browser/native/menu_wrapper.h" - -#include "base/memory/weak_ptr.h" -#include "base/observer_list.h" - -namespace ui { -class MenuModel; -} - -namespace views { - -// A Windows implementation of MenuWrapper. -// TODO(beng): rename to MenuWin once the old class is dead. -class CefNativeMenuWin : public MenuWrapper { - public: - // Construct a CefNativeMenuWin, with a model and delegate. If - // |system_menu_for| is non-NULL, the CefNativeMenuWin wraps the system menu - // for that window. - // The caller owns the model and the delegate. - CefNativeMenuWin(ui::MenuModel* model, HWND system_menu_for); - - CefNativeMenuWin(const CefNativeMenuWin&) = delete; - CefNativeMenuWin& operator=(const CefNativeMenuWin&) = delete; - - ~CefNativeMenuWin() override; - - // Overridden from MenuWrapper: - void RunMenuAt(const gfx::Point& point, int alignment) override; - void CancelMenu() override; - void Rebuild(MenuInsertionDelegateWin* delegate) override; - void UpdateStates() override; - HMENU GetNativeMenu() const override; - MenuAction GetMenuAction() const override; - void SetMinimumWidth(int width) override; - - private: - // IMPORTANT: Note about indices. - // Functions in this class deal in two index spaces: - // 1. menu_index - the index of an item within the actual Windows - // native menu. - // 2. model_index - the index of the item within our model. - // These two are most often but not always the same value! The - // notable exception is when this object is used to wrap the - // Windows System Menu. In this instance, the model indices start - // at 0, but the insertion index into the existing menu is not. - // It is important to take this into consideration when editing the - // code in the functions in this class. - - struct HighlightedMenuItemInfo; - - // Returns true if the item at the specified index is a separator. - bool IsSeparatorItemAt(int menu_index) const; - - // Add items. See note above about indices. - void AddMenuItemAt(int menu_index, int model_index); - void AddSeparatorItemAt(int menu_index, int model_index); - - // Sets the state of the item at the specified index. - void SetMenuItemState(int menu_index, - bool enabled, - bool checked, - bool is_default); - - // Sets the label of the item at the specified index. - void SetMenuItemLabel(int menu_index, - int model_index, - const std::wstring& label); - - // Updates the local data structure with the correctly formatted version of - // |label| at the specified model_index, and adds string data to |mii| if - // the menu is not owner-draw. That's a mouthful. This function exists because - // of the peculiarities of the Windows menu API. - void UpdateMenuItemInfoForString(MENUITEMINFO* mii, - int model_index, - const std::wstring& label); - - // Returns the alignment flags to be passed to TrackPopupMenuEx, based on the - // supplied alignment and the UI text direction. - UINT GetAlignmentFlags(int alignment) const; - - // Resets the native menu stored in |menu_| by destroying any old menu then - // creating a new empty one. - void ResetNativeMenu(); - - // Creates the host window that receives notifications from the menu. - void CreateHostWindow(); - - // Callback from task to notify menu it was selected. - void DelayedSelect(); - - // Given a menu that's currently popped-up, find the currently highlighted - // item. Returns true if a highlighted item was found. - static bool GetHighlightedMenuItemInfo(HMENU menu, - HighlightedMenuItemInfo* info); - - // Hook to receive keyboard events while the menu is open. - static LRESULT CALLBACK MenuMessageHook(int n_code, - WPARAM w_param, - LPARAM l_param); - - // Our attached model and delegate. - ui::MenuModel* model_; - - HMENU menu_; - - // True if the contents of menu items in this menu are drawn by the menu host - // window, rather than Windows. - bool owner_draw_; - - // An object that collects all of the data associated with an individual menu - // item. - struct ItemData; - using ItemDataList = std::vector>; - ItemDataList items_; - - // The window that receives notifications from the menu. - class MenuHostWindow; - friend MenuHostWindow; - std::unique_ptr host_window_; - - // The HWND this menu is the system menu for, or NULL if the menu is not a - // system menu. - HWND system_menu_for_; - - // The index of the first item in the model in the menu. - int first_item_index_; - - // The action that took place during the call to RunMenuAt. - MenuAction menu_action_; - - // See comment in MenuMessageHook for details on these. - CefNativeMenuWin* menu_to_select_; - int position_to_select_; - - // If we're a submenu, this is our parent. - CefNativeMenuWin* parent_; - - // If non-null the destructor sets this to true. This is set to non-null while - // the menu is showing. It is used to detect if the menu was deleted while - // running. - bool* destroyed_flag_; - - base::WeakPtrFactory menu_to_select_factory_; - - // Ugly: a static pointer to the instance of this class that currently - // has a menu open, because our hook function that receives keyboard - // events doesn't have a mechanism to get a user data pointer. - static CefNativeMenuWin* open_native_menu_win_; -}; - -} // namespace views - -#endif // CEF_LIBCEF_BROWSER_NATIVE_NATIVE_MENU_WIN_H_ diff --git a/libcef/browser/osr/browser_platform_delegate_osr.cc b/libcef/browser/osr/browser_platform_delegate_osr.cc index 0fd5b4770..1b3708065 100644 --- a/libcef/browser/osr/browser_platform_delegate_osr.cc +++ b/libcef/browser/osr/browser_platform_delegate_osr.cc @@ -10,12 +10,14 @@ #include "libcef/browser/osr/osr_accessibility_util.h" #include "libcef/browser/osr/render_widget_host_view_osr.h" #include "libcef/browser/osr/web_contents_view_osr.h" +#include "libcef/browser/views/view_util.h" #include "libcef/common/drag_data_impl.h" #include "base/task/current_thread.h" #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/render_view_host.h" +#include "ui/display/screen.h" #include "ui/events/base_event_utils.h" CefBrowserPlatformDelegateOsr::CefBrowserPlatformDelegateOsr( @@ -168,13 +170,25 @@ void CefBrowserPlatformDelegateOsr::SetFocus(bool setFocus) { } gfx::Point CefBrowserPlatformDelegateOsr::GetScreenPoint( - const gfx::Point& view) const { + const gfx::Point& view, + bool want_dip_coords) const { CefRefPtr handler = browser_->client()->GetRenderHandler(); if (handler.get()) { int screenX = 0, screenY = 0; if (handler->GetScreenPoint(browser_, view.x(), view.y(), screenX, screenY)) { - return gfx::Point(screenX, screenY); + gfx::Point screen_point(screenX, screenY); +#if !BUILDFLAG(IS_MAC) + // Mac always operates in DIP coordinates so |want_dip_coords| is ignored. + if (want_dip_coords) { + // Convert to DIP coordinates. + const auto& display = view_util::GetDisplayNearestPoint( + screen_point, /*input_pixel_coords=*/true); + view_util::ConvertPointFromPixels(&screen_point, + display.device_scale_factor()); + } +#endif + return screen_point; } } return view; @@ -306,7 +320,8 @@ void CefBrowserPlatformDelegateOsr::DragTargetDragEnter( CefDragDataImpl* data_impl = static_cast(drag_data.get()); base::AutoLock lock_scope(data_impl->lock()); content::DropData* drop_data = data_impl->drop_data(); - const gfx::Point& screen_pt = GetScreenPoint(client_pt); + const gfx::Point& screen_pt = + GetScreenPoint(client_pt, /*want_dip_coords=*/false); blink::DragOperationsMask ops = static_cast(allowed_ops); int modifiers = TranslateWebEventModifiers(event.modifiers); @@ -337,7 +352,8 @@ void CefBrowserPlatformDelegateOsr::DragTargetDragOver( return; const gfx::Point client_pt(event.x, event.y); - const gfx::Point& screen_pt = GetScreenPoint(client_pt); + const gfx::Point& screen_pt = + GetScreenPoint(client_pt, /*want_dip_coords=*/false); gfx::PointF transformed_pt; content::RenderWidgetHostImpl* target_rwh = @@ -404,7 +420,8 @@ void CefBrowserPlatformDelegateOsr::DragTargetDrop(const CefMouseEvent& event) { return; gfx::Point client_pt(event.x, event.y); - const gfx::Point& screen_pt = GetScreenPoint(client_pt); + const gfx::Point& screen_pt = + GetScreenPoint(client_pt, /*want_dip_coords=*/false); gfx::PointF transformed_pt; content::RenderWidgetHostImpl* target_rwh = @@ -508,7 +525,8 @@ void CefBrowserPlatformDelegateOsr::DragSourceEndedAt( content::RenderWidgetHostImpl* source_rwh = drag_start_rwh_.get(); const gfx::Point client_loc(gfx::Point(x, y)); - const gfx::Point& screen_loc = GetScreenPoint(client_loc); + const gfx::Point& screen_loc = + GetScreenPoint(client_loc, /*want_dip_coords=*/false); ui::mojom::DragOperation drag_op = static_cast(op); // |client_loc| and |screen_loc| are in the root coordinate space, for @@ -585,8 +603,9 @@ CefWindowHandle CefBrowserPlatformDelegateOsr::GetParentWindowHandle() const { } gfx::Point CefBrowserPlatformDelegateOsr::GetParentScreenPoint( - const gfx::Point& view) const { - return GetScreenPoint(view); + const gfx::Point& view, + bool want_dip_coords) const { + return GetScreenPoint(view, want_dip_coords); } CefRenderWidgetHostViewOSR* CefBrowserPlatformDelegateOsr::GetOSRHostView() diff --git a/libcef/browser/osr/browser_platform_delegate_osr.h b/libcef/browser/osr/browser_platform_delegate_osr.h index a8c08a9da..669251102 100644 --- a/libcef/browser/osr/browser_platform_delegate_osr.h +++ b/libcef/browser/osr/browser_platform_delegate_osr.h @@ -43,7 +43,8 @@ class CefBrowserPlatformDelegateOsr int deltaY) override; void SendTouchEvent(const CefTouchEvent& event) override; void SetFocus(bool setFocus) override; - gfx::Point GetScreenPoint(const gfx::Point& view) const override; + gfx::Point GetScreenPoint(const gfx::Point& view, + bool want_dip_coords) const override; void ViewText(const std::string& text) override; bool HandleKeyboardEvent( const content::NativeWebKeyboardEvent& event) override; @@ -91,7 +92,8 @@ class CefBrowserPlatformDelegateOsr // CefBrowserPlatformDelegateNative::WindowlessHandler methods: CefWindowHandle GetParentWindowHandle() const override; - gfx::Point GetParentScreenPoint(const gfx::Point& view) const override; + gfx::Point GetParentScreenPoint(const gfx::Point& view, + bool want_dip_coords) const override; protected: // Platform-specific behaviors will be delegated to |native_delegate|. diff --git a/libcef/browser/osr/render_widget_host_view_osr.cc b/libcef/browser/osr/render_widget_host_view_osr.cc index 1c9f8cc83..ba4d420d5 100644 --- a/libcef/browser/osr/render_widget_host_view_osr.cc +++ b/libcef/browser/osr/render_widget_host_view_osr.cc @@ -1116,7 +1116,8 @@ void CefRenderWidgetHostViewOSR::SendMouseEvent( TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::SendMouseEvent"); if (!IsPopupWidget()) { if (browser_impl_.get() && - event.GetType() == blink::WebMouseEvent::Type::kMouseDown) { + event.GetType() == blink::WebMouseEvent::Type::kMouseDown && + event.button != blink::WebPointerProperties::Button::kRight) { browser_impl_->CancelContextMenu(); } diff --git a/libcef/browser/views/browser_platform_delegate_views.cc b/libcef/browser/views/browser_platform_delegate_views.cc index 10659232a..9f9a2accd 100644 --- a/libcef/browser/views/browser_platform_delegate_views.cc +++ b/libcef/browser/views/browser_platform_delegate_views.cc @@ -232,13 +232,14 @@ void CefBrowserPlatformDelegateViews::SetFocus(bool setFocus) { } gfx::Point CefBrowserPlatformDelegateViews::GetScreenPoint( - const gfx::Point& view_pt) const { + const gfx::Point& view_pt, + bool want_dip_coords) const { if (!browser_view_->root_view()) return view_pt; gfx::Point screen_point = view_pt; view_util::ConvertPointToScreen(browser_view_->root_view(), &screen_point, - true); + /*output_pixel_coords=*/!want_dip_coords); return screen_point; } @@ -293,6 +294,7 @@ CefWindowHandle CefBrowserPlatformDelegateViews::GetParentWindowHandle() const { } gfx::Point CefBrowserPlatformDelegateViews::GetParentScreenPoint( - const gfx::Point& view) const { - return GetScreenPoint(view); + const gfx::Point& view, + bool want_dip_coords) const { + return GetScreenPoint(view, want_dip_coords); } diff --git a/libcef/browser/views/browser_platform_delegate_views.h b/libcef/browser/views/browser_platform_delegate_views.h index c18b0cbe9..dd27f6903 100644 --- a/libcef/browser/views/browser_platform_delegate_views.h +++ b/libcef/browser/views/browser_platform_delegate_views.h @@ -54,7 +54,8 @@ class CefBrowserPlatformDelegateViews int deltaY) override; void SendTouchEvent(const CefTouchEvent& event) override; void SetFocus(bool setFocus) override; - gfx::Point GetScreenPoint(const gfx::Point& view) const override; + gfx::Point GetScreenPoint(const gfx::Point& view, + bool want_dip_coords) const override; void ViewText(const std::string& text) override; bool HandleKeyboardEvent( const content::NativeWebKeyboardEvent& event) override; @@ -69,7 +70,8 @@ class CefBrowserPlatformDelegateViews // CefBrowserPlatformDelegateNative::WindowlessHandler methods: CefWindowHandle GetParentWindowHandle() const override; - gfx::Point GetParentScreenPoint(const gfx::Point& view) const override; + gfx::Point GetParentScreenPoint(const gfx::Point& view, + bool want_dip_coords) const override; private: void SetBrowserView(CefRefPtr browser_view); diff --git a/patch/patch.cfg b/patch/patch.cfg index a628654cd..55b8bc4ff 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -177,7 +177,10 @@ patches = [ # Expose callbacks for mouse/keyboard events that trigger menu switching. # Add accelerator display support to Label. # https://bitbucket.org/chromiumembedded/cef/issues/2102 - 'name': 'views_1749_2102', + # + # Route |parent_widget| to MenuHost for OSR context menu Widget creation. + # https://bitbucket.org/chromiumembedded/cef/issues/3330 + 'name': 'views_1749_2102_3330', }, { # Support CEF changes in chrome/browser. diff --git a/patch/patches/views_1749_2102.patch b/patch/patches/views_1749_2102_3330.patch similarity index 62% rename from patch/patches/views_1749_2102.patch rename to patch/patches/views_1749_2102_3330.patch index 3c6dfacc4..bbb183c84 100644 --- a/patch/patches/views_1749_2102.patch +++ b/patch/patches/views_1749_2102_3330.patch @@ -238,10 +238,36 @@ index 8132b9b9a1c75..4f78f6f41c77f 100644 std::unique_ptr selection_controller_; diff --git ui/views/controls/menu/menu_controller.cc ui/views/controls/menu/menu_controller.cc -index 2dbf14bc018d2..ec38c00234980 100644 +index 2dbf14bc018d2..ea1d0153a9b64 100644 --- ui/views/controls/menu/menu_controller.cc +++ ui/views/controls/menu/menu_controller.cc -@@ -2879,8 +2879,13 @@ MenuItemView* MenuController::FindNextSelectableMenuItem( +@@ -473,7 +473,8 @@ void MenuController::Run(Widget* parent, + MenuAnchorPosition position, + bool context_menu, + bool is_nested_drag, +- gfx::NativeView native_view_for_gestures) { ++ gfx::NativeView native_view_for_gestures, ++ gfx::AcceleratedWidget parent_widget) { + exit_type_ = ExitType::kNone; + possible_drag_ = false; + drag_in_progress_ = false; +@@ -520,6 +521,7 @@ void MenuController::Run(Widget* parent, + owner_->AddObserver(this); + + native_view_for_gestures_ = native_view_for_gestures; ++ parent_widget_ = parent_widget; + + // Only create a MenuPreTargetHandler for non-nested menus. Nested menus + // will use the existing one. +@@ -2177,6 +2179,7 @@ void MenuController::OpenMenuImpl(MenuItemView* item, bool show) { + params.do_capture = do_capture; + params.native_view_for_gestures = native_view_for_gestures_; + params.owned_window_anchor = anchor; ++ params.parent_widget = parent_widget_; + + if (item->GetParentMenuItem()) { + params.context = state_.item->GetWidget(); +@@ -2879,8 +2882,13 @@ MenuItemView* MenuController::FindNextSelectableMenuItem( void MenuController::OpenSubmenuChangeSelectionIfCan() { MenuItemView* item = pending_state_.item; @@ -256,7 +282,7 @@ index 2dbf14bc018d2..ec38c00234980 100644 MenuItemView* to_select = nullptr; if (!item->GetSubmenu()->GetMenuItems().empty()) to_select = FindInitialSelectableMenuItem(item, INCREMENT_SELECTION_DOWN); -@@ -2899,8 +2904,10 @@ void MenuController::OpenSubmenuChangeSelectionIfCan() { +@@ -2899,8 +2907,10 @@ void MenuController::OpenSubmenuChangeSelectionIfCan() { void MenuController::CloseSubmenu() { MenuItemView* item = state_.item; DCHECK(item); @@ -268,6 +294,30 @@ index 2dbf14bc018d2..ec38c00234980 100644 if (item->SubmenuIsShowing()) SetSelection(item, SELECTION_UPDATE_IMMEDIATELY); else if (item->GetParentMenuItem()->GetParentMenuItem()) +diff --git ui/views/controls/menu/menu_controller.h ui/views/controls/menu/menu_controller.h +index a4958eb424441..0e1ebb20af2da 100644 +--- ui/views/controls/menu/menu_controller.h ++++ ui/views/controls/menu/menu_controller.h +@@ -105,7 +105,9 @@ class VIEWS_EXPORT MenuController + MenuAnchorPosition position, + bool context_menu, + bool is_nested_drag, +- gfx::NativeView native_view_for_gestures = nullptr); ++ gfx::NativeView native_view_for_gestures = nullptr, ++ gfx::AcceleratedWidget parent_widget = ++ gfx::kNullAcceleratedWidget); + + bool for_drop() const { return for_drop_; } + +@@ -720,6 +722,8 @@ class VIEWS_EXPORT MenuController + // RunType::SEND_GESTURE_EVENTS_TO_OWNER is set. + gfx::NativeView native_view_for_gestures_ = nullptr; + ++ gfx::AcceleratedWidget parent_widget_ = gfx::kNullAcceleratedWidget; ++ + // Indicates a possible drag operation. + bool possible_drag_ = false; + diff --git ui/views/controls/menu/menu_delegate.h ui/views/controls/menu/menu_delegate.h index 7101143c63803..058da34d3499e 100644 --- ui/views/controls/menu/menu_delegate.h @@ -307,6 +357,42 @@ index 7101143c63803..058da34d3499e 100644 // Returns the max width menus can grow to be. virtual int GetMaxWidthForMenu(MenuItemView* menu); +diff --git ui/views/controls/menu/menu_host.cc ui/views/controls/menu/menu_host.cc +index 702391702c399..cc669d448fc20 100644 +--- ui/views/controls/menu/menu_host.cc ++++ ui/views/controls/menu/menu_host.cc +@@ -144,6 +144,8 @@ void MenuHost::InitMenuHost(const InitParams& init_params) { + : gfx::kNullNativeWindow; + params.bounds = init_params.bounds; + ++ params.parent_widget = init_params.parent_widget; ++ + #if defined(USE_AURA) + // TODO(msisov): remove kMenutype once positioning of anchored windows + // finally migrates to a new path. +@@ -155,7 +157,8 @@ void MenuHost::InitMenuHost(const InitParams& init_params) { + // If MenuHost has no parent widget, it needs to be marked + // Activatable, so that calling Show in ShowMenuHost will + // get keyboard focus. +- if (init_params.parent == nullptr) ++ if (init_params.parent == nullptr && ++ init_params.parent_widget == gfx::kNullAcceleratedWidget) + params.activatable = Widget::InitParams::Activatable::kYes; + + #if BUILDFLAG(IS_WIN) +diff --git ui/views/controls/menu/menu_host.h ui/views/controls/menu/menu_host.h +index 9c8c5de34d064..b054688cca148 100644 +--- ui/views/controls/menu/menu_host.h ++++ ui/views/controls/menu/menu_host.h +@@ -54,6 +54,8 @@ class MenuHost : public Widget, public WidgetObserver { + // Additional information that helps to position anchored windows in such + // backends as Wayland. + ui::OwnedWindowAnchor owned_window_anchor; ++ ++ gfx::AcceleratedWidget parent_widget = gfx::kNullAcceleratedWidget; + }; + + explicit MenuHost(SubmenuView* submenu); diff --git ui/views/controls/menu/menu_item_view.cc ui/views/controls/menu/menu_item_view.cc index 6da48e9716bcd..98f0d4d217f9e 100644 --- ui/views/controls/menu/menu_item_view.cc @@ -448,6 +534,155 @@ index b7c7474fb5910..ce3e14071f0c6 100644 void WillShowMenu(MenuItemView* menu) override; void WillHideMenu(MenuItemView* menu) override; void OnMenuClosed(MenuItemView* menu) override; +diff --git ui/views/controls/menu/menu_runner.cc ui/views/controls/menu/menu_runner.cc +index 31716d454d1cd..f778a989ad663 100644 +--- ui/views/controls/menu/menu_runner.cc ++++ ui/views/controls/menu/menu_runner.cc +@@ -34,7 +34,8 @@ void MenuRunner::RunMenuAt(Widget* parent, + const gfx::Rect& bounds, + MenuAnchorPosition anchor, + ui::MenuSourceType source_type, +- gfx::NativeView native_view_for_gestures) { ++ gfx::NativeView native_view_for_gestures, ++ gfx::AcceleratedWidget parent_widget) { + // Do not attempt to show the menu if the application is currently shutting + // down. MenuDelegate::OnMenuClosed would not be called. + if (ViewsDelegate::GetInstance() && +@@ -80,7 +81,7 @@ void MenuRunner::RunMenuAt(Widget* parent, + } + + impl_->RunMenuAt(parent, button_controller, bounds, anchor, run_types_, +- native_view_for_gestures); ++ native_view_for_gestures, parent_widget); + } + + bool MenuRunner::IsRunning() const { +diff --git ui/views/controls/menu/menu_runner.h ui/views/controls/menu/menu_runner.h +index 17c074cbd7dc9..53921c55671cf 100644 +--- ui/views/controls/menu/menu_runner.h ++++ ui/views/controls/menu/menu_runner.h +@@ -146,7 +146,9 @@ class VIEWS_EXPORT MenuRunner { + const gfx::Rect& bounds, + MenuAnchorPosition anchor, + ui::MenuSourceType source_type, +- gfx::NativeView native_view_for_gestures = nullptr); ++ gfx::NativeView native_view_for_gestures = nullptr, ++ gfx::AcceleratedWidget parent_widget = ++ gfx::kNullAcceleratedWidget); + + // Returns true if we're in a nested run loop running the menu. + bool IsRunning() const; +diff --git ui/views/controls/menu/menu_runner_impl.cc ui/views/controls/menu/menu_runner_impl.cc +index 4311a517b1179..7eed89badd038 100644 +--- ui/views/controls/menu/menu_runner_impl.cc ++++ ui/views/controls/menu/menu_runner_impl.cc +@@ -119,7 +119,8 @@ void MenuRunnerImpl::RunMenuAt(Widget* parent, + const gfx::Rect& bounds, + MenuAnchorPosition anchor, + int32_t run_types, +- gfx::NativeView native_view_for_gestures) { ++ gfx::NativeView native_view_for_gestures, ++ gfx::AcceleratedWidget parent_widget) { + closing_event_time_ = base::TimeTicks(); + if (running_) { + // Ignore requests to show the menu while it's already showing. MenuItemView +@@ -184,7 +185,7 @@ void MenuRunnerImpl::RunMenuAt(Widget* parent, + controller->Run(parent, button_controller, menu_, bounds, anchor, + (run_types & MenuRunner::CONTEXT_MENU) != 0, + (run_types & MenuRunner::NESTED_DRAG) != 0, +- native_view_for_gestures); ++ native_view_for_gestures, parent_widget); + } + + void MenuRunnerImpl::Cancel() { +diff --git ui/views/controls/menu/menu_runner_impl.h ui/views/controls/menu/menu_runner_impl.h +index c99ef21736a5b..f24375fed0f48 100644 +--- ui/views/controls/menu/menu_runner_impl.h ++++ ui/views/controls/menu/menu_runner_impl.h +@@ -47,7 +47,8 @@ class VIEWS_EXPORT MenuRunnerImpl : public MenuRunnerImplInterface, + const gfx::Rect& bounds, + MenuAnchorPosition anchor, + int32_t run_types, +- gfx::NativeView native_view_for_gestures) override; ++ gfx::NativeView native_view_for_gestures, ++ gfx::AcceleratedWidget parent_widget) override; + void Cancel() override; + base::TimeTicks GetClosingEventTime() const override; + +diff --git ui/views/controls/menu/menu_runner_impl_adapter.cc ui/views/controls/menu/menu_runner_impl_adapter.cc +index fbc9166e188a8..48f87d01e61f4 100644 +--- ui/views/controls/menu/menu_runner_impl_adapter.cc ++++ ui/views/controls/menu/menu_runner_impl_adapter.cc +@@ -34,9 +34,10 @@ void MenuRunnerImplAdapter::RunMenuAt( + const gfx::Rect& bounds, + MenuAnchorPosition anchor, + int32_t types, +- gfx::NativeView native_view_for_gestures) { ++ gfx::NativeView native_view_for_gestures, ++ gfx::AcceleratedWidget parent_widget) { + impl_->RunMenuAt(parent, button_controller, bounds, anchor, types, +- native_view_for_gestures); ++ native_view_for_gestures, parent_widget); + } + + void MenuRunnerImplAdapter::Cancel() { +diff --git ui/views/controls/menu/menu_runner_impl_adapter.h ui/views/controls/menu/menu_runner_impl_adapter.h +index 4bec3df3f3d32..0ebb3b2ac73df 100644 +--- ui/views/controls/menu/menu_runner_impl_adapter.h ++++ ui/views/controls/menu/menu_runner_impl_adapter.h +@@ -38,7 +38,8 @@ class VIEWS_EXPORT MenuRunnerImplAdapter : public MenuRunnerImplInterface { + const gfx::Rect& bounds, + MenuAnchorPosition anchor, + int32_t types, +- gfx::NativeView native_view_for_gestures) override; ++ gfx::NativeView native_view_for_gestures, ++ gfx::AcceleratedWidget parent_widget) override; + void Cancel() override; + base::TimeTicks GetClosingEventTime() const override; + +diff --git ui/views/controls/menu/menu_runner_impl_cocoa.h ui/views/controls/menu/menu_runner_impl_cocoa.h +index b24b07fb16b86..50859104e909c 100644 +--- ui/views/controls/menu/menu_runner_impl_cocoa.h ++++ ui/views/controls/menu/menu_runner_impl_cocoa.h +@@ -37,7 +37,8 @@ class VIEWS_EXPORT MenuRunnerImplCocoa : public MenuRunnerImplInterface { + const gfx::Rect& bounds, + MenuAnchorPosition anchor, + int32_t run_types, +- gfx::NativeView native_view_for_gestures) override; ++ gfx::NativeView native_view_for_gestures, ++ gfx::AcceleratedWidget parent_widget) override; + void Cancel() override; + base::TimeTicks GetClosingEventTime() const override; + +diff --git ui/views/controls/menu/menu_runner_impl_cocoa.mm ui/views/controls/menu/menu_runner_impl_cocoa.mm +index 4ac619cfdb725..8c6979e80d2dc 100644 +--- ui/views/controls/menu/menu_runner_impl_cocoa.mm ++++ ui/views/controls/menu/menu_runner_impl_cocoa.mm +@@ -533,7 +533,8 @@ - (void)controllerWillAddMenu:(NSMenu*)menu fromModel:(ui::MenuModel*)model { + const gfx::Rect& bounds, + MenuAnchorPosition anchor, + int32_t run_types, +- gfx::NativeView native_view_for_gestures) { ++ gfx::NativeView native_view_for_gestures, ++ gfx::AcceleratedWidget /*parent_widget*/) { + DCHECK(!IsRunning()); + DCHECK(parent); + closing_event_time_ = base::TimeTicks(); +diff --git ui/views/controls/menu/menu_runner_impl_interface.h ui/views/controls/menu/menu_runner_impl_interface.h +index 54c95d830233e..408f090b55698 100644 +--- ui/views/controls/menu/menu_runner_impl_interface.h ++++ ui/views/controls/menu/menu_runner_impl_interface.h +@@ -40,7 +40,9 @@ class MenuRunnerImplInterface { + const gfx::Rect& bounds, + MenuAnchorPosition anchor, + int32_t run_types, +- gfx::NativeView native_view_for_gestures) = 0; ++ gfx::NativeView native_view_for_gestures, ++ gfx::AcceleratedWidget parent_widget = ++ gfx::kNullAcceleratedWidget) = 0; + + // Hides and cancels the menu. + virtual void Cancel() = 0; diff --git ui/views/controls/menu/menu_scroll_view_container.cc ui/views/controls/menu/menu_scroll_view_container.cc index 25d368664566d..870bf405c6c80 100644 --- ui/views/controls/menu/menu_scroll_view_container.cc diff --git a/tests/cefclient/browser/browser_window_osr_gtk.cc b/tests/cefclient/browser/browser_window_osr_gtk.cc index 155f7b72c..94ea62248 100644 --- a/tests/cefclient/browser/browser_window_osr_gtk.cc +++ b/tests/cefclient/browser/browser_window_osr_gtk.cc @@ -1175,6 +1175,7 @@ bool BrowserWindowOsrGtk::GetScreenPoint(CefRefPtr browser, device_scale_factor = device_scale_factor_; } + // Convert from view DIP coordinates to screen device (pixel) coordinates. GdkRectangle screen_rect; GetWidgetRectInScreen(glarea_, &screen_rect); screenX = screen_rect.x + LogicalToDevice(viewX, device_scale_factor); diff --git a/tests/cefclient/browser/osr_window_win.cc b/tests/cefclient/browser/osr_window_win.cc index ad3da12fc..cf2404574 100644 --- a/tests/cefclient/browser/osr_window_win.cc +++ b/tests/cefclient/browser/osr_window_win.cc @@ -969,7 +969,7 @@ bool OsrWindowWin::GetScreenPoint(CefRefPtr browser, if (!::IsWindow(hwnd_)) return false; - // Convert the point from view coordinates to actual screen coordinates. + // Convert from view DIP coordinates to screen device (pixel) coordinates. POINT screen_pt = {LogicalToDevice(viewX, device_scale_factor_), LogicalToDevice(viewY, device_scale_factor_)}; ClientToScreen(hwnd_, &screen_pt);