- Implement the WebExternalPopupMenu interface to fix select popup menu display.
- Remove the kCFRunLoopBeforeTimers option from CFRunLoopObserverCreate to reduce CPU usage (issue #211).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@218 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2011-04-09 16:54:59 +00:00
parent a66c733ab6
commit 1f7a4b4566
7 changed files with 138 additions and 78 deletions

View File

@ -686,6 +686,8 @@
'libcef/browser_webview_mac.h',
'libcef/browser_webview_mac.mm',
'libcef/cef_process_ui_thread_mac.mm',
'libcef/external_popup_menu_mac.h',
'libcef/external_popup_menu_mac.mm',
'libcef/external_protocol_handler_mac.mm',
'libcef/webview_host_mac.mm',
'libcef/webwidget_host_mac.mm',

View File

@ -29,6 +29,7 @@
#if defined(OS_MACOSX)
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenuInfo.h"
#include "external_popup_menu_mac.h"
#endif
#if defined(OS_WIN)
@ -55,8 +56,9 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient,
WebKit::WebFrame* creator, const WebKit::WebURLRequest& request,
const WebKit::WebWindowFeatures& features, const WebKit::WebString& name);
virtual WebKit::WebWidget* createPopupMenu(WebKit::WebPopupType popup_type);
virtual WebKit::WebWidget* createPopupMenu(
const WebKit::WebPopupMenuInfo& info);
virtual WebKit::WebExternalPopupMenu* createExternalPopupMenu(
const WebKit::WebPopupMenuInfo& info,
WebKit::WebExternalPopupMenuClient* client);
virtual WebKit::WebStorageNamespace* createSessionStorageNamespace(
unsigned quota);
virtual void didAddMessageToConsole(
@ -247,7 +249,8 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient,
CefBrowserImpl* GetBrowser() { return browser_; }
#if defined(OS_MACOSX)
void SetPopupMenuInfo(const WebKit::WebPopupMenuInfo& info);
// Called after the external popup menu has been dismissed.
void ClosePopupMenu();
#endif
// Called after dragging has finished.
@ -322,8 +325,8 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient,
#endif
#if defined(OS_MACOSX)
scoped_ptr<WebKit::WebPopupMenuInfo> popup_menu_info_;
WebKit::WebRect popup_bounds_;
// The external popup menu for the currently showing select popup.
scoped_ptr<ExternalPopupMenu> external_popup_menu_;
#endif
// true if we want to enable smart insert/delete.

View File

@ -17,19 +17,29 @@
#include "webkit/glue/webmenurunner_mac.h"
using WebKit::WebCursorInfo;
using WebKit::WebExternalPopupMenu;
using WebKit::WebExternalPopupMenuClient;
using WebKit::WebNavigationPolicy;
using WebKit::WebPopupMenu;
using WebKit::WebPopupMenuInfo;
using WebKit::WebRect;
using WebKit::WebWidget;
// WebViewClient --------------------------------------------------------------
WebWidget* BrowserWebViewDelegate::createPopupMenu(
const WebPopupMenuInfo& info) {
WebWidget* webwidget = browser_->UIT_CreatePopupWidget();
browser_->UIT_GetPopupDelegate()->SetPopupMenuInfo(info);
return webwidget;
WebExternalPopupMenu* BrowserWebViewDelegate::createExternalPopupMenu(
const WebPopupMenuInfo& info,
WebExternalPopupMenuClient* client) {
DCHECK(!external_popup_menu_.get());
external_popup_menu_.reset(new ExternalPopupMenu(this, info, client));
return external_popup_menu_.get();
}
void BrowserWebViewDelegate::ClosePopupMenu() {
if (external_popup_menu_ == NULL) {
NOTREACHED();
return;
}
external_popup_menu_.reset();
}
void BrowserWebViewDelegate::showContextMenu(
@ -40,64 +50,6 @@ void BrowserWebViewDelegate::showContextMenu(
// WebWidgetClient ------------------------------------------------------------
void BrowserWebViewDelegate::show(WebNavigationPolicy policy) {
if (!popup_menu_info_.get())
return;
if (this != browser_->UIT_GetPopupDelegate())
return;
// Display a HTML select menu.
std::vector<WebMenuItem> items;
for (size_t i = 0; i < popup_menu_info_->items.size(); ++i)
items.push_back(popup_menu_info_->items[i]);
int item_height = popup_menu_info_->itemHeight;
double font_size = popup_menu_info_->itemFontSize;
int selected_index = popup_menu_info_->selectedIndex;
bool right_aligned = popup_menu_info_->rightAligned;
popup_menu_info_.reset(); // No longer needed.
const WebRect& bounds = popup_bounds_;
// Set up the menu position.
NSView* web_view = browser_->UIT_GetWebViewWndHandle();
NSRect view_rect = [web_view bounds];
int y_offset = bounds.y + bounds.height;
NSRect position = NSMakeRect(bounds.x, view_rect.size.height - y_offset,
bounds.width, bounds.height);
// Display the menu.
scoped_nsobject<WebMenuRunner> menu_runner;
menu_runner.reset([[WebMenuRunner alloc] initWithItems:items
fontSize:font_size
rightAligned:right_aligned]);
[menu_runner runMenuInView:browser_->UIT_GetWebViewWndHandle()
withBounds:position
initialIndex:selected_index];
// Get the selected item and forward to WebKit. WebKit expects an input event
// (mouse down, keyboard activity) for this, so we calculate the proper
// position based on the selected index and provided bounds.
WebWidgetHost* popup = browser_->UIT_GetPopupHost();
NSWindow* window = [browser_->UIT_GetMainWndHandle() window];
int window_num = [window windowNumber];
NSEvent* event =
webkit_glue::EventWithMenuAction([menu_runner menuItemWasChosen],
window_num, item_height,
[menu_runner indexOfSelectedItem],
position, view_rect);
if ([menu_runner menuItemWasChosen]) {
// Construct a mouse up event to simulate the selection of an appropriate
// menu item.
popup->MouseEvent(event);
} else {
// Fake an ESC key event (keyCode = 0x1B, from webinputevent_mac.mm) and
// forward that to WebKit.
popup->KeyEvent(event);
}
browser_->UIT_ClosePopupWidget();
}
void BrowserWebViewDelegate::didChangeCursor(const WebCursorInfo& cursor_info) {
@ -117,8 +69,6 @@ WebRect BrowserWebViewDelegate::windowRect() {
void BrowserWebViewDelegate::setWindowRect(const WebRect& rect) {
if (this == browser_->UIT_GetWebViewDelegate()) {
// TODO(port): Set the window rectangle.
} else if (this == browser_->UIT_GetPopupDelegate()) {
popup_bounds_ = rect; // The initial position of the popup.
}
}
@ -189,10 +139,6 @@ void BrowserWebViewDelegate::DidMovePlugin(
// Protected methods ----------------------------------------------------------
void BrowserWebViewDelegate::SetPopupMenuInfo(const WebPopupMenuInfo& info) {
popup_menu_info_.reset(new WebPopupMenuInfo(info));
}
void BrowserWebViewDelegate::ShowJavaScriptAlert(
WebKit::WebFrame* webframe, const CefString& message) {
std::string messageStr(message);

View File

@ -38,6 +38,8 @@
using webkit::npapi::WebPluginDelegateImpl;
using WebKit::WebContextMenuData;
using WebKit::WebCursorInfo;
using WebKit::WebExternalPopupMenu;
using WebKit::WebExternalPopupMenuClient;
using WebKit::WebFrame;
using WebKit::WebNavigationPolicy;
using WebKit::WebPopupMenuInfo;
@ -48,8 +50,9 @@ static const wchar_t kPluginWindowClassName[] = L"WebPluginHost";
// WebViewClient --------------------------------------------------------------
WebWidget* BrowserWebViewDelegate::createPopupMenu(
const WebPopupMenuInfo& info) {
WebExternalPopupMenu* BrowserWebViewDelegate::createExternalPopupMenu(
const WebPopupMenuInfo& info,
WebExternalPopupMenuClient* client) {
NOTREACHED();
return NULL;
}

View File

@ -7,6 +7,7 @@
#include "cef_process_ui_thread.h"
#include "browser_webkit_glue.h"
#include "base/message_pump_mac.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Source/WebKit/mac/WebCoreSupport/WebSystemInterface.h"
// CrAppProtocol implementation.
@ -53,7 +54,7 @@ void CefProcessUIThread::PlatformInit() {
// Register the run loop observer.
CFRunLoopObserverRef observer =
CFRunLoopObserverCreate(NULL,
kCFRunLoopBeforeTimers | kCFRunLoopBeforeWaiting,
kCFRunLoopBeforeWaiting,
YES, /* repeat */
0,
&RunLoopObserver,
@ -64,6 +65,9 @@ void CefProcessUIThread::PlatformInit() {
}
webkit_glue::InitializeDataPak();
// On Mac, the select popup menus are rendered by the browser.
WebKit::WebView::setUseExternalPopupMenus(true);
}
void CefProcessUIThread::PlatformCleanUp() {

View File

@ -0,0 +1,36 @@
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2010 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 _EXTERNAL_POPUP_MENU_MAC_H
#define _EXTERNAL_POPUP_MENU_MAC_H
#include "base/basictypes.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebExternalPopupMenu.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenuInfo.h"
class BrowserWebViewDelegate;
namespace WebKit {
class WebExternalPopupMenuClient;
}
class ExternalPopupMenu : public WebKit::WebExternalPopupMenu {
public:
ExternalPopupMenu(BrowserWebViewDelegate* delegate,
const WebKit::WebPopupMenuInfo& popup_menu_info,
WebKit::WebExternalPopupMenuClient* popup_menu_client);
// WebKit::WebExternalPopupMenu implementation:
virtual void show(const WebKit::WebRect& bounds);
virtual void close();
private:
BrowserWebViewDelegate* delegate_;
WebKit::WebPopupMenuInfo popup_menu_info_;
WebKit::WebExternalPopupMenuClient* popup_menu_client_;
DISALLOW_COPY_AND_ASSIGN(ExternalPopupMenu);
};
#endif // _EXTERNAL_POPUP_MENU_MAC_H

View File

@ -0,0 +1,66 @@
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2010 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 "external_popup_menu_mac.h"
#include "browser_impl.h"
#include "content/common/view_messages.h"
#include "content/renderer/render_view.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebExternalPopupMenuClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenuInfo.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
#include "webkit/glue/webmenurunner_mac.h"
ExternalPopupMenu::ExternalPopupMenu(
BrowserWebViewDelegate* delegate,
const WebKit::WebPopupMenuInfo& popup_menu_info,
WebKit::WebExternalPopupMenuClient* popup_menu_client)
: delegate_(delegate),
popup_menu_info_(popup_menu_info),
popup_menu_client_(popup_menu_client) {
}
void ExternalPopupMenu::show(const WebKit::WebRect& bounds) {
// Display a HTML select menu.
std::vector<WebMenuItem> items;
for (size_t i = 0; i < popup_menu_info_.items.size(); ++i)
items.push_back(popup_menu_info_.items[i]);
double font_size = popup_menu_info_.itemFontSize;
int selected_index = popup_menu_info_.selectedIndex;
bool right_aligned = popup_menu_info_.rightAligned;
CefBrowserImpl* browser = delegate_->GetBrowser();
// Set up the menu position.
NSView* web_view = browser->UIT_GetWebViewWndHandle();
NSRect view_rect = [web_view bounds];
int y_offset = bounds.y + bounds.height;
NSRect position = NSMakeRect(bounds.x, view_rect.size.height - y_offset,
bounds.width, bounds.height);
// Display the menu.
scoped_nsobject<WebMenuRunner> menu_runner;
menu_runner.reset([[WebMenuRunner alloc] initWithItems:items
fontSize:font_size
rightAligned:right_aligned]);
[menu_runner runMenuInView:browser->UIT_GetWebViewWndHandle()
withBounds:position
initialIndex:selected_index];
if ([menu_runner menuItemWasChosen])
popup_menu_client_->didAcceptIndex([menu_runner indexOfSelectedItem]);
else
popup_menu_client_->didCancel();
delegate_->ClosePopupMenu();
}
void ExternalPopupMenu::close() {
popup_menu_client_ = NULL;
delegate_ = NULL;
}