Commit b878d97c authored by spqchan's avatar spqchan Committed by Commit Bot

[MacViews] Use Views Context Menu for Web View

This CL refactors RenderViewContextMenuMac by moving
the logic to show a Cocoa menu into a
RenderViewContextMenuMacCocoa class.

To show the context menu using Views, this CL adds a
RenderViewContextMenuMacViews.

Bug: 837230
Change-Id: Id07f9e758278638c6fc47003de1055d9357ed1fa
Reviewed-on: https://chromium-review.googlesource.com/1056468Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarElly Fong-Jones <ellyjones@chromium.org>
Commit-Queue: Sarah Chan <spqchan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558726}
parent b67362ed
...@@ -2410,6 +2410,10 @@ split_static_library("ui") { ...@@ -2410,6 +2410,10 @@ split_static_library("ui") {
"cocoa/profiles/profile_menu_controller.mm", "cocoa/profiles/profile_menu_controller.mm",
"cocoa/renderer_context_menu/render_view_context_menu_mac.h", "cocoa/renderer_context_menu/render_view_context_menu_mac.h",
"cocoa/renderer_context_menu/render_view_context_menu_mac.mm", "cocoa/renderer_context_menu/render_view_context_menu_mac.mm",
"cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.h",
"cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm",
"cocoa/renderer_context_menu/render_view_context_menu_mac_views.h",
"cocoa/renderer_context_menu/render_view_context_menu_mac_views.mm",
"cocoa/scoped_menu_bar_lock.h", "cocoa/scoped_menu_bar_lock.h",
"cocoa/scoped_menu_bar_lock.mm", "cocoa/scoped_menu_bar_lock.mm",
"cocoa/share_menu_controller.h", "cocoa/share_menu_controller.h",
......
...@@ -7,13 +7,10 @@ ...@@ -7,13 +7,10 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h" #include "base/macros.h"
#include "chrome/browser/renderer_context_menu/render_view_context_menu.h" #include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
#include "ui/base/cocoa/text_services_context_menu.h" #include "ui/base/cocoa/text_services_context_menu.h"
@class MenuControllerCocoa;
// Mac implementation of the context menu display code. Uses a Cocoa NSMenu // Mac implementation of the context menu display code. Uses a Cocoa NSMenu
// to display the context menu. Internally uses an obj-c object as the // to display the context menu. Internally uses an obj-c object as the
// target of the NSMenu, bridging back to this C++ class. // target of the NSMenu, bridging back to this C++ class.
...@@ -21,8 +18,7 @@ class RenderViewContextMenuMac : public RenderViewContextMenu, ...@@ -21,8 +18,7 @@ class RenderViewContextMenuMac : public RenderViewContextMenu,
public ui::TextServicesContextMenu::Delegate { public ui::TextServicesContextMenu::Delegate {
public: public:
RenderViewContextMenuMac(content::RenderFrameHost* render_frame_host, RenderViewContextMenuMac(content::RenderFrameHost* render_frame_host,
const content::ContextMenuParams& params, const content::ContextMenuParams& params);
NSView* parent_view);
~RenderViewContextMenuMac() override; ~RenderViewContextMenuMac() override;
// SimpleMenuModel::Delegate: // SimpleMenuModel::Delegate:
...@@ -30,9 +26,6 @@ class RenderViewContextMenuMac : public RenderViewContextMenu, ...@@ -30,9 +26,6 @@ class RenderViewContextMenuMac : public RenderViewContextMenu,
bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdChecked(int command_id) const override;
bool IsCommandIdEnabled(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override;
// RenderViewContextMenuBase:
void Show() override;
// TextServicesContextMenu::Delegate: // TextServicesContextMenu::Delegate:
base::string16 GetSelectedText() const override; base::string16 GetSelectedText() const override;
bool IsTextDirectionEnabled( bool IsTextDirectionEnabled(
...@@ -42,47 +35,23 @@ class RenderViewContextMenuMac : public RenderViewContextMenu, ...@@ -42,47 +35,23 @@ class RenderViewContextMenuMac : public RenderViewContextMenu,
void UpdateTextDirection(base::i18n::TextDirection direction) override; void UpdateTextDirection(base::i18n::TextDirection direction) override;
protected: protected:
// RenderViewContextMenu:
void AppendPlatformEditableItems() override;
private:
friend class ToolkitDelegateMac;
// Adds menu to the platform's toolkit. // Adds menu to the platform's toolkit.
void InitToolkitMenu(); void InitToolkitMenu();
// Cancels the menu. // RenderViewContextMenu:
void CancelToolkitMenu(); void AppendPlatformEditableItems() override;
// Updates the status and text of the specified context-menu item.
void UpdateToolkitMenuItem(int command_id,
bool enabled,
bool hidden,
const base::string16& title);
private:
// Handler for the "Look Up" menu item. // Handler for the "Look Up" menu item.
void LookUpInDictionary(); void LookUpInDictionary();
// Returns the ContextMenuParams value associated with |direction|. // Returns the ContextMenuParams value associated with |direction|.
int ParamsForTextDirection(base::i18n::TextDirection direction) const; int ParamsForTextDirection(base::i18n::TextDirection direction) const;
// The Cocoa menu controller for this menu.
base::scoped_nsobject<MenuControllerCocoa> menu_controller_;
// The Cocoa parent view.
NSView* parent_view_;
// The context menu that adds and handles Speech and BiDi. // The context menu that adds and handles Speech and BiDi.
ui::TextServicesContextMenu text_services_context_menu_; ui::TextServicesContextMenu text_services_context_menu_;
DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenuMac); DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenuMac);
}; };
// The ChromeSwizzleServicesMenuUpdater filters Services menu items in the
// contextual menus and elsewhere using swizzling.
@interface ChromeSwizzleServicesMenuUpdater : NSObject
// Return filtered entries, for testing.
+ (void)storeFilteredEntriesForTestingInArray:(NSMutableArray*)array;
@end
#endif // CHROME_BROWSER_UI_COCOA_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_MAC_H_ #endif // CHROME_BROWSER_UI_COCOA_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_MAC_H_
// Copyright 2018 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 CHROME_BROWSER_UI_COCOA_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_MAC_COCOA_H_
#define CHROME_BROWSER_UI_COCOA_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_MAC_COCOA_H_
#import <Cocoa/Cocoa.h>
#include "base/mac/scoped_nsobject.h"
#include "chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.h"
@class MenuControllerCocoa;
// Mac Cocoa implementation of the renderer context menu display code. Uses a
// NSMenu to display the context menu. Internally uses an Obj-C object as the
// target of the NSMenu, bridging back to this C++ class.
class RenderViewContextMenuMacCocoa : public RenderViewContextMenuMac {
public:
RenderViewContextMenuMacCocoa(content::RenderFrameHost* render_frame_host,
const content::ContextMenuParams& params,
NSView* parent_view);
~RenderViewContextMenuMacCocoa() override;
// RenderViewContextMenuViewsMac:
void Show() override;
private:
friend class ToolkitDelegateMacCocoa;
// Cancels the menu.
void CancelToolkitMenu();
// Updates the status and text of the specified context-menu item.
void UpdateToolkitMenuItem(int command_id,
bool enabled,
bool hidden,
const base::string16& title);
// The Cocoa menu controller for this menu.
base::scoped_nsobject<MenuControllerCocoa> menu_controller_;
// The Cocoa parent view.
NSView* parent_view_;
DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenuMacCocoa);
};
// The ChromeSwizzleServicesMenuUpdater filters Services menu items in the
// contextual menus and elsewhere using swizzling.
@interface ChromeSwizzleServicesMenuUpdater : NSObject
// Return filtered entries, for testing.
+ (void)storeFilteredEntriesForTestingInArray:(NSMutableArray*)array;
@end
#endif // CHROME_BROWSER_UI_COCOA_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_MAC_COCOA_H_
\ No newline at end of file
// Copyright 2018 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 "chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.h"
#include <utility>
#include "base/compiler_specific.h"
#include "base/mac/mac_util.h"
#import "base/mac/scoped_objc_class_swizzler.h"
#import "base/mac/scoped_sending_event.h"
#include "base/macros.h"
#include "base/message_loop/message_loop_current.h"
#import "base/message_loop/message_pump_mac.h"
#include "base/strings/sys_string_conversions.h"
#import "chrome/browser/mac/nsprocessinfo_additions.h"
#import "ui/base/cocoa/menu_controller.h"
namespace {
IMP g_original_populatemenu_implementation = nullptr;
// |g_filtered_entries_array| is only set during testing (see
// +[ChromeSwizzleServicesMenuUpdater storeFilteredEntriesForTestingInArray:]).
// Otherwise it remains nil.
NSMutableArray* g_filtered_entries_array = nil;
// Retrieves an NSMenuItem which has the specified command_id. This function
// traverses the given |model| in the depth-first order. When this function
// finds an item whose command_id is the same as the given |command_id|, it
// returns the NSMenuItem associated with the item. This function emulates
// views::MenuItemViews::GetMenuItemByID() for Mac.
NSMenuItem* GetMenuItemByID(ui::MenuModel* model,
NSMenu* menu,
int command_id) {
for (int i = 0; i < model->GetItemCount(); ++i) {
NSMenuItem* item = [menu itemAtIndex:i];
if (model->GetCommandIdAt(i) == command_id)
return item;
ui::MenuModel* submenu = model->GetSubmenuModelAt(i);
if (submenu && [item hasSubmenu]) {
NSMenuItem* subitem =
GetMenuItemByID(submenu, [item submenu], command_id);
if (subitem)
return subitem;
}
}
return nil;
}
} // namespace
// An AppKit-private class that adds Services items to contextual menus and
// the application Services menu.
@interface _NSServicesMenuUpdater : NSObject
- (void)populateMenu:(NSMenu*)menu
withServiceEntries:(NSArray*)entries
forDisplay:(BOOL)display;
@end
// An AppKit-private class representing a Services menu entry.
@interface _NSServiceEntry : NSObject
- (NSString*)bundleIdentifier;
@end
@implementation ChromeSwizzleServicesMenuUpdater
- (void)populateMenu:(NSMenu*)menu
withServiceEntries:(NSArray*)entries
forDisplay:(BOOL)display {
// Create a new service entry array that does not include the redundant
// Services vended by Safari.
NSMutableArray* remainingEntries = [NSMutableArray array];
[g_filtered_entries_array removeAllObjects];
for (_NSServiceEntry* nextEntry in entries) {
if (![[nextEntry bundleIdentifier] isEqualToString:@"com.apple.Safari"]) {
[remainingEntries addObject:nextEntry];
} else {
[g_filtered_entries_array addObject:nextEntry];
}
}
// Pass the filtered array along to the _NSServicesMenuUpdater.
g_original_populatemenu_implementation(self, _cmd, menu, remainingEntries,
display);
}
+ (void)storeFilteredEntriesForTestingInArray:(NSMutableArray*)array {
[g_filtered_entries_array release];
g_filtered_entries_array = [array retain];
}
+ (void)load {
// Swizzling should not happen in renderer processes.
if (![[NSProcessInfo processInfo] cr_isMainBrowserOrTestProcess])
return;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// Confirm that the AppKit's private _NSServiceEntry class exists. This
// class cannot be accessed at link time and is not guaranteed to exist in
// past or future AppKits so use NSClassFromString() to locate it. Also
// check that the class implements the bundleIdentifier method. The browser
// test checks for all of this as well, but the checks here ensure that we
// don't crash out in the wild when running on some future version of OS X.
// Odds are a developer will be running a newer version of OS X sooner than
// the bots - NOTREACHED() will get them to tell us if compatibility breaks.
if (![NSClassFromString(@"_NSServiceEntry")
instancesRespondToSelector:@selector(bundleIdentifier)]) {
NOTREACHED();
return;
}
// Perform similar checks on the AppKit's private _NSServicesMenuUpdater
// class.
SEL targetSelector = @selector(populateMenu:withServiceEntries:forDisplay:);
Class targetClass = NSClassFromString(@"_NSServicesMenuUpdater");
if (![targetClass instancesRespondToSelector:targetSelector]) {
NOTREACHED();
return;
}
// Replace the populateMenu:withServiceEntries:forDisplay: method in
// _NSServicesMenuUpdater with an implementation that can filter Services
// menu entries from contextual menus and elsewhere. Place the swizzler into
// a static so that it never goes out of scope, because the scoper's
// destructor undoes the swizzling.
Class swizzleClass = [ChromeSwizzleServicesMenuUpdater class];
CR_DEFINE_STATIC_LOCAL(base::mac::ScopedObjCClassSwizzler,
servicesMenuFilter,
(targetClass, swizzleClass, targetSelector));
g_original_populatemenu_implementation =
servicesMenuFilter.GetOriginalImplementation();
});
}
@end
// OSX implemenation of the ToolkitDelegate.
// This simply (re)delegates calls to RVContextMenuMac because they do not
// have to be componentized.
class ToolkitDelegateMacCocoa : public RenderViewContextMenu::ToolkitDelegate {
public:
explicit ToolkitDelegateMacCocoa(RenderViewContextMenuMacCocoa* context_menu)
: context_menu_(context_menu) {}
~ToolkitDelegateMacCocoa() override {}
private:
// ToolkitDelegate:
void Init(ui::SimpleMenuModel* menu_model) override {
context_menu_->InitToolkitMenu();
}
void Cancel() override { context_menu_->CancelToolkitMenu(); }
void UpdateMenuItem(int command_id,
bool enabled,
bool hidden,
const base::string16& title) override {
context_menu_->UpdateToolkitMenuItem(command_id, enabled, hidden, title);
}
RenderViewContextMenuMacCocoa* context_menu_;
DISALLOW_COPY_AND_ASSIGN(ToolkitDelegateMacCocoa);
};
// Obj-C bridge class that is the target of all items in the context menu.
// Relies on the tag being set to the command id.
RenderViewContextMenuMacCocoa::RenderViewContextMenuMacCocoa(
content::RenderFrameHost* render_frame_host,
const content::ContextMenuParams& params,
NSView* parent_view)
: RenderViewContextMenuMac(render_frame_host, params),
parent_view_(parent_view) {
auto delegate = std::make_unique<ToolkitDelegateMacCocoa>(this);
set_toolkit_delegate(std::move(delegate));
}
RenderViewContextMenuMacCocoa::~RenderViewContextMenuMacCocoa() {}
void RenderViewContextMenuMacCocoa::Show() {
menu_controller_.reset([[MenuControllerCocoa alloc] initWithModel:&menu_model_
useWithPopUpButtonCell:NO]);
gfx::Point params_position(params_.x, params_.y);
// Synthesize an event for the click, as there is no certainty that
// [NSApp currentEvent] will return a valid event.
NSEvent* currentEvent = [NSApp currentEvent];
NSWindow* window = [parent_view_ window];
NSPoint position =
NSMakePoint(params_position.x(),
NSHeight([parent_view_ bounds]) - params_position.y());
position = [parent_view_ convertPoint:position toView:nil];
NSTimeInterval eventTime = [currentEvent timestamp];
NSEvent* clickEvent = [NSEvent mouseEventWithType:NSRightMouseDown
location:position
modifierFlags:NSRightMouseDownMask
timestamp:eventTime
windowNumber:[window windowNumber]
context:nil
eventNumber:0
clickCount:1
pressure:1.0];
{
// Make sure events can be pumped while the menu is up.
base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
// Ensure the UI can update while the menu is fading out.
base::ScopedPumpMessagesInPrivateModes pump_private;
// One of the events that could be pumped is |window.close()|.
// User-initiated event-tracking loops protect against this by
// setting flags in -[CrApplication sendEvent:], but since
// web-content menus are initiated by IPC message the setup has to
// be done manually.
base::mac::ScopedSendingEvent sendingEventScoper;
// Show the menu.
[NSMenu popUpContextMenu:[menu_controller_ menu]
withEvent:clickEvent
forView:parent_view_];
}
}
void RenderViewContextMenuMacCocoa::CancelToolkitMenu() {
[menu_controller_ cancel];
}
void RenderViewContextMenuMacCocoa::UpdateToolkitMenuItem(
int command_id,
bool enabled,
bool hidden,
const base::string16& title) {
NSMenuItem* item =
GetMenuItemByID(&menu_model_, [menu_controller_ menu], command_id);
if (!item)
return;
// Update the returned NSMenuItem directly so we can update it immediately.
[item setEnabled:enabled];
[item setTitle:base::SysUTF16ToNSString(title)];
[item setHidden:hidden];
[[item menu] itemChanged:item];
}
// Copyright 2016 The Chromium Authors. All rights reserved. // Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.h" #include "chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.h"
#include "base/mac/foundation_util.h" #include "base/mac/foundation_util.h"
#include "base/mac/mac_util.h" #include "base/mac/mac_util.h"
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
#include "content/public/test/test_utils.h" #include "content/public/test/test_utils.h"
#import "testing/gtest_mac.h" #import "testing/gtest_mac.h"
class RenderViewContextMenuMacBrowserTest : public InProcessBrowserTest { class RenderViewContextMenuMacCocoaBrowserTest : public InProcessBrowserTest {
public: public:
RenderViewContextMenuMacBrowserTest() {} RenderViewContextMenuMacCocoaBrowserTest() {}
protected: protected:
void SetUpOnMainThread() override { void SetUpOnMainThread() override {
...@@ -46,26 +46,27 @@ class RenderViewContextMenuMacBrowserTest : public InProcessBrowserTest { ...@@ -46,26 +46,27 @@ class RenderViewContextMenuMacBrowserTest : public InProcessBrowserTest {
base::scoped_nsobject<NSTextField> textField_; base::scoped_nsobject<NSTextField> textField_;
private: private:
DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenuMacBrowserTest); DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenuMacCocoaBrowserTest);
}; };
// Confirm that the private classes used to filter Safari's redundant Services // Confirm that the private classes used to filter Safari's redundant Services
// items exist and implement the expected methods, and that the filtering code // items exist and implement the expected methods, and that the filtering code
// successfully removes those Services items. // successfully removes those Services items.
IN_PROC_BROWSER_TEST_F(RenderViewContextMenuMacBrowserTest, ServicesFiltering) { IN_PROC_BROWSER_TEST_F(RenderViewContextMenuMacCocoaBrowserTest,
ServicesFiltering) {
// Confirm that the _NSServicesMenuUpdater class exists and implements the // Confirm that the _NSServicesMenuUpdater class exists and implements the
// method we expect it to. // method we expect it to.
Class menuUpdaterClass = NSClassFromString(@"_NSServicesMenuUpdater"); Class menuUpdaterClass = NSClassFromString(@"_NSServicesMenuUpdater");
EXPECT_TRUE(menuUpdaterClass); EXPECT_TRUE(menuUpdaterClass);
EXPECT_TRUE([menuUpdaterClass instancesRespondToSelector: EXPECT_TRUE([menuUpdaterClass instancesRespondToSelector:@selector
@selector(populateMenu:withServiceEntries:forDisplay:)]); (populateMenu:withServiceEntries:forDisplay:)]);
// Confirm that the _NSServiceEntry class exists and implements the // Confirm that the _NSServiceEntry class exists and implements the
// method we expect it to. // method we expect it to.
Class serviceEntryClass = NSClassFromString(@"_NSServiceEntry"); Class serviceEntryClass = NSClassFromString(@"_NSServiceEntry");
EXPECT_TRUE(serviceEntryClass); EXPECT_TRUE(serviceEntryClass);
EXPECT_TRUE([serviceEntryClass instancesRespondToSelector: EXPECT_TRUE([serviceEntryClass
@selector(bundleIdentifier)]); instancesRespondToSelector:@selector(bundleIdentifier)]);
// Make the testing textfield the browser window's first responder, in // Make the testing textfield the browser window's first responder, in
// preparation for the contextual menu we're about to display. Even though the // preparation for the contextual menu we're about to display. Even though the
......
// Copyright 2018 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 CHROME_BROWSER_UI_COCOA_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_MAC_VIEWS_H_
#define CHROME_BROWSER_UI_COCOA_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_MAC_VIEWS_H_
#import <Cocoa/Cocoa.h>
#include "chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.h"
// Mac Views implementation of the renderer context menu display code.
class RenderViewContextMenuMacViews : public RenderViewContextMenuMac {
public:
RenderViewContextMenuMacViews(content::RenderFrameHost* render_frame_host,
const content::ContextMenuParams& params,
NSView* parent_view);
~RenderViewContextMenuMacViews() override;
// RenderViewContextMenuMac:
void Show() override;
private:
friend class ToolkitDelegateViewsMac;
NSView* parent_view_;
DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenuMacViews);
};
#endif // CHROME_BROWSER_UI_COCOA_RENDERER_CONTEXT_MENU_RENDER_VIEW_CONTEXT_MENU_MAC_VIEWS_H_
\ No newline at end of file
// Copyright 2018 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 "chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_views.h"
#include "components/renderer_context_menu/views/toolkit_delegate_views.h"
#import "ui/base/cocoa/cocoa_base_utils.h"
#import "ui/gfx/mac/coordinate_conversion.h"
class ToolkitDelegateViewsMac : public ToolkitDelegateViews {
public:
explicit ToolkitDelegateViewsMac(RenderViewContextMenuMacViews* context_menu)
: context_menu_(context_menu) {}
~ToolkitDelegateViewsMac() override {}
private:
// ToolkitDelegateViews:
void Init(ui::SimpleMenuModel* menu_model) override {
context_menu_->InitToolkitMenu();
ToolkitDelegateViews::Init(menu_model);
}
RenderViewContextMenuMacViews* context_menu_;
DISALLOW_COPY_AND_ASSIGN(ToolkitDelegateViewsMac);
};
RenderViewContextMenuMacViews::RenderViewContextMenuMacViews(
content::RenderFrameHost* render_frame_host,
const content::ContextMenuParams& params,
NSView* parent_view)
: RenderViewContextMenuMac(render_frame_host, params),
parent_view_(parent_view) {
auto delegate = std::make_unique<ToolkitDelegateViewsMac>(this);
set_toolkit_delegate(std::move(delegate));
}
RenderViewContextMenuMacViews::~RenderViewContextMenuMacViews() {}
void RenderViewContextMenuMacViews::Show() {
NSPoint position =
NSMakePoint(params().x, NSHeight([parent_view_ bounds]) - params().y);
position = [parent_view_ convertPoint:position toView:nil];
gfx::Point menu_point = gfx::ScreenPointFromNSPoint(
ui::ConvertPointFromWindowToScreen([parent_view_ window], position));
static_cast<ToolkitDelegateViews*>(toolkit_delegate())
->RunMenuAt(nullptr, menu_point, params().source_type);
}
...@@ -58,6 +58,10 @@ class ChromeWebContentsViewDelegateMac ...@@ -58,6 +58,10 @@ class ChromeWebContentsViewDelegateMac
content::RenderWidgetHostView* GetActiveRenderWidgetHostView() const; content::RenderWidgetHostView* GetActiveRenderWidgetHostView() const;
NSWindow* GetNSWindowForFocusTracker() const; NSWindow* GetNSWindowForFocusTracker() const;
RenderViewContextMenuBase* CreateRenderViewContextMenu(
content::WebContents* web_contents,
const content::ContextMenuParams& params);
// The context menu. Callbacks are asynchronous so we need to keep it around. // The context menu. Callbacks are asynchronous so we need to keep it around.
std::unique_ptr<RenderViewContextMenuBase> context_menu_; std::unique_ptr<RenderViewContextMenuBase> context_menu_;
......
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.h" #include "chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.h"
#include "chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_views.h"
#include "chrome/browser/ui/cocoa/tab_contents/web_drag_bookmark_handler_mac.h" #include "chrome/browser/ui/cocoa/tab_contents/web_drag_bookmark_handler_mac.h"
#include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h" #include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h"
#include "chrome/browser/ui/views_mode_controller.h"
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#import "ui/base/cocoa/focus_tracker.h" #import "ui/base/cocoa/focus_tracker.h"
...@@ -106,22 +108,39 @@ ChromeWebContentsViewDelegateMac::BuildMenu( ...@@ -106,22 +108,39 @@ ChromeWebContentsViewDelegateMac::BuildMenu(
content::WebContents* web_contents, content::WebContents* web_contents,
const content::ContextMenuParams& params) { const content::ContextMenuParams& params) {
std::unique_ptr<RenderViewContextMenuBase> menu; std::unique_ptr<RenderViewContextMenuBase> menu;
content::RenderFrameHost* focused_frame = web_contents->GetFocusedFrame(); menu.reset(CreateRenderViewContextMenu(web_contents, params));
// If the frame tree does not have a focused frame at this point, do not
// bother creating RenderViewContextMenuMac. if (menu)
// This happens if the frame has navigated to a different page before
// ContextMenu message was received by the current RenderFrameHost.
if (focused_frame) {
content::RenderWidgetHostView* widget_view =
GetActiveRenderWidgetHostView();
menu.reset(new RenderViewContextMenuMac(
focused_frame, params, widget_view->GetNativeView()));
menu->Init(); menu->Init();
}
return menu; return menu;
} }
RenderViewContextMenuBase*
ChromeWebContentsViewDelegateMac::CreateRenderViewContextMenu(
content::WebContents* web_contents,
const content::ContextMenuParams& params) {
// If the frame tree does not have a focused frame at this point, do not
// bother creating RenderViewContextMenuBase. This happens if the frame has
// navigated to a different page before ContextMenu message was received by
// the current RenderFrameHost.
content::RenderFrameHost* focused_frame = web_contents->GetFocusedFrame();
if (!focused_frame)
return nullptr;
gfx::NativeView parent_view =
GetActiveRenderWidgetHostView()->GetNativeView();
#if BUILDFLAG(MAC_VIEWS_BROWSER)
if (!views_mode_controller::IsViewsBrowserCocoa()) {
return new RenderViewContextMenuMacViews(focused_frame, params,
parent_view);
}
#endif
return new RenderViewContextMenuMacCocoa(focused_frame, params, parent_view);
}
content::RenderWidgetHostView* content::RenderWidgetHostView*
ChromeWebContentsViewDelegateMac::GetActiveRenderWidgetHostView() const { ChromeWebContentsViewDelegateMac::GetActiveRenderWidgetHostView() const {
return web_contents_->GetFullscreenRenderWidgetHostView() ? return web_contents_->GetFullscreenRenderWidgetHostView() ?
......
...@@ -1894,7 +1894,7 @@ test("browser_tests") { ...@@ -1894,7 +1894,7 @@ test("browser_tests") {
"../browser/ui/cocoa/passwords/passwords_bubble_browsertest.mm", "../browser/ui/cocoa/passwords/passwords_bubble_browsertest.mm",
"../browser/ui/cocoa/permission_bubble/permission_bubble_views_cocoa_browsertest.mm", "../browser/ui/cocoa/permission_bubble/permission_bubble_views_cocoa_browsertest.mm",
"../browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller_browsertest.mm", "../browser/ui/cocoa/profiles/profile_signin_confirmation_view_controller_browsertest.mm",
"../browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_browsertest.mm", "../browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa_browsertest.mm",
"../browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm", "../browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm",
"../browser/ui/cocoa/task_manager_mac_browsertest.mm", "../browser/ui/cocoa/task_manager_mac_browsertest.mm",
"../browser/ui/cocoa/view_id_util_browsertest.mm", "../browser/ui/cocoa/view_id_util_browsertest.mm",
......
...@@ -35,9 +35,12 @@ class ToolkitDelegateViews : public RenderViewContextMenuBase::ToolkitDelegate { ...@@ -35,9 +35,12 @@ class ToolkitDelegateViews : public RenderViewContextMenuBase::ToolkitDelegate {
const gfx::Point& point, const gfx::Point& point,
ui::MenuSourceType type); ui::MenuSourceType type);
private: protected:
// ToolkitDelegate: // ToolkitDelegate:
void Init(ui::SimpleMenuModel* menu_model) override; void Init(ui::SimpleMenuModel* menu_model) override;
private:
// ToolkitDelegate:
void Cancel() override; void Cancel() override;
void UpdateMenuItem(int command_id, void UpdateMenuItem(int command_id,
bool enabled, bool enabled,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment