summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorpaulg@google.com <paulg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-24 19:05:03 +0000
committerpaulg@google.com <paulg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-24 19:05:03 +0000
commit6b01318fe807d9a6dca2a31ce7f0242ef3c93453 (patch)
tree21d1c01eca0241e4b8526744b2dacb094967f2ac /webkit
parentc4848bad345fa487c5abc4645d1721d38aa28ac5 (diff)
downloadchromium_src-6b01318fe807d9a6dca2a31ce7f0242ef3c93453.zip
chromium_src-6b01318fe807d9a6dca2a31ce7f0242ef3c93453.tar.gz
chromium_src-6b01318fe807d9a6dca2a31ce7f0242ef3c93453.tar.bz2
First stage of implementing HTML select popup menus for
the Mac test_shell. Once the changes to WebKit/WebCore/platform/chromium/PopupMenuChromium* have been upstreamed (then landed in our tree), we can enable them in test_shell. The WebKit part is contained in this bug: https://bugs.webkit.org/show_bug.cgi?id=24692 BUG=5095 (http://crbug.com/5095) Review URL: http://codereview.chromium.org/48149 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12382 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/chrome_client_impl.cc217
-rw-r--r--webkit/glue/chrome_client_impl.h7
-rw-r--r--webkit/glue/webwidget_delegate.h38
-rw-r--r--webkit/glue/webwidget_impl.cc14
-rw-r--r--webkit/glue/webwidget_impl.h8
-rwxr-xr-xwebkit/tools/test_shell/mac/test_webview_delegate.mm145
-rw-r--r--webkit/tools/test_shell/test_shell_mac.mm3
-rw-r--r--webkit/tools/test_shell/test_webview_delegate.h5
-rwxr-xr-xwebkit/tools/test_shell/test_webview_delegate_gtk.cc8
-rwxr-xr-xwebkit/tools/test_shell/test_webview_delegate_win.cc8
10 files changed, 367 insertions, 86 deletions
diff --git a/webkit/glue/chrome_client_impl.cc b/webkit/glue/chrome_client_impl.cc
index 972a643..6b574d5 100644
--- a/webkit/glue/chrome_client_impl.cc
+++ b/webkit/glue/chrome_client_impl.cc
@@ -15,6 +15,7 @@ MSVC_PUSH_WARNING_LEVEL(0);
#include "HitTestResult.h"
#include "IntRect.h"
#include "Page.h"
+#include "PopupMenuChromium.h"
#include "ScriptController.h"
#include "WindowFeatures.h"
#if USE(V8)
@@ -86,11 +87,11 @@ void ChromeClientImpl::chromeDestroyed() {
}
void ChromeClientImpl::setWindowRect(const WebCore::FloatRect& r) {
- WebViewDelegate* d = webview_->delegate();
- if (d) {
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
WebCore::IntRect ir(r);
- d->SetWindowRect(webview_,
- gfx::Rect(ir.x(), ir.y(), ir.width(), ir.height()));
+ delegate->SetWindowRect(webview_,
+ gfx::Rect(ir.x(), ir.y(), ir.width(), ir.height()));
}
}
@@ -136,15 +137,15 @@ float ChromeClientImpl::scaleFactor() {
}
void ChromeClientImpl::focus() {
- WebViewDelegate* d = webview_->delegate();
- if (d)
- d->Focus(webview_);
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate)
+ delegate->Focus(webview_);
}
void ChromeClientImpl::unfocus() {
- WebViewDelegate* d = webview_->delegate();
- if (d)
- d->Blur(webview_);
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate)
+ delegate->Blur(webview_);
}
bool ChromeClientImpl::canTakeFocus(WebCore::FocusDirection) {
@@ -154,23 +155,23 @@ bool ChromeClientImpl::canTakeFocus(WebCore::FocusDirection) {
}
void ChromeClientImpl::takeFocus(WebCore::FocusDirection direction) {
- WebViewDelegate* d = webview_->delegate();
- if (d) {
- d->TakeFocus(webview_,
- direction == WebCore::FocusDirectionBackward);
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
+ delegate->TakeFocus(webview_,
+ direction == WebCore::FocusDirectionBackward);
}
}
WebCore::Page* ChromeClientImpl::createWindow(
WebCore::Frame* frame, const WebCore::FrameLoadRequest& r,
const WebCore::WindowFeatures& features) {
- WebViewDelegate* d = webview_->delegate();
- if (!d)
+ WebViewDelegate* delegate = webview_->delegate();
+ if (!delegate)
return NULL;
bool userGesture = frame->script()->processingUserGesture();
WebViewImpl* new_view = static_cast<WebViewImpl*>(
- d->CreateWebView(webview_, userGesture));
+ delegate->CreateWebView(webview_, userGesture));
if (!new_view)
return NULL;
@@ -198,8 +199,8 @@ static inline bool CurrentEventShouldCauseBackgroundTab(
}
void ChromeClientImpl::show() {
- WebViewDelegate* d = webview_->delegate();
- if (d) {
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
// If our default configuration was modified by a script or wasn't
// created by a user gesture, then show as a popup. Else, let this
// new window be opened as a toplevel window.
@@ -210,7 +211,7 @@ void ChromeClientImpl::show() {
!scrollbars_visible_ ||
!menubar_visible_ ||
!resizable_ ||
- !d->WasOpenedByUserGesture(webview_);
+ !delegate->WasOpenedByUserGesture(webview_);
WindowOpenDisposition disposition = NEW_FOREGROUND_TAB;
if (as_popup)
@@ -218,7 +219,7 @@ void ChromeClientImpl::show() {
if (CurrentEventShouldCauseBackgroundTab(WebViewImpl::current_input_event()))
disposition = NEW_BACKGROUND_TAB;
- d->Show(webview_, disposition);
+ delegate->Show(webview_, disposition);
}
}
@@ -227,9 +228,9 @@ bool ChromeClientImpl::canRunModal() {
}
void ChromeClientImpl::runModal() {
- WebViewDelegate* d = webview_->delegate();
- if (d)
- d->RunModal(webview_);
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate)
+ delegate->RunModal(webview_);
}
void ChromeClientImpl::setToolbarsVisible(bool value) {
@@ -275,11 +276,12 @@ void ChromeClientImpl::setResizable(bool value) {
void ChromeClientImpl::addMessageToConsole(const WebCore::String& message,
unsigned int line_no,
const WebCore::String& source_id) {
- WebViewDelegate* d = webview_->delegate();
- if (d) {
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
std::wstring wstr_message = webkit_glue::StringToStdWString(message);
std::wstring wstr_source_id = webkit_glue::StringToStdWString(source_id);
- d->AddMessageToConsole(webview_, wstr_message, line_no, wstr_source_id);
+ delegate->AddMessageToConsole(webview_, wstr_message,
+ line_no, wstr_source_id);
}
}
@@ -290,10 +292,11 @@ bool ChromeClientImpl::canRunBeforeUnloadConfirmPanel() {
bool ChromeClientImpl::runBeforeUnloadConfirmPanel(
const WebCore::String& message,
WebCore::Frame* frame) {
- WebViewDelegate* d = webview_->delegate();
- if (d) {
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
std::wstring wstr = webkit_glue::StringToStdWString(message);
- return d->RunBeforeUnloadConfirm(WebFrameImpl::FromFrame(frame), wstr);
+ return delegate->RunBeforeUnloadConfirm(WebFrameImpl::FromFrame(frame),
+ wstr);
}
return false;
}
@@ -305,9 +308,9 @@ void ChromeClientImpl::closeWindowSoon() {
// Make sure that all loading is stopped. Ensures that JS stops executing!
webview_->StopLoading();
- WebViewDelegate* d = webview_->delegate();
- if (d)
- d->CloseWidgetSoon(webview_);
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate)
+ delegate->CloseWidgetSoon(webview_);
}
// Although a WebCore::Frame is passed in, we don't actually use it, since we
@@ -315,8 +318,8 @@ void ChromeClientImpl::closeWindowSoon() {
void ChromeClientImpl::runJavaScriptAlert(WebCore::Frame* frame,
const WebCore::String& message) {
// Pass the request on to the WebView delegate, for more control.
- WebViewDelegate* d = webview_->delegate();
- if (d) {
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
#if USE(V8)
// Before showing the JavaScript dialog, we give the proxy implementation
// a chance to process any pending console messages.
@@ -324,17 +327,17 @@ void ChromeClientImpl::runJavaScriptAlert(WebCore::Frame* frame,
#endif
std::wstring wstr = webkit_glue::StringToStdWString(message);
- d->RunJavaScriptAlert(WebFrameImpl::FromFrame(frame), wstr);
+ delegate->RunJavaScriptAlert(WebFrameImpl::FromFrame(frame), wstr);
}
}
// See comments for runJavaScriptAlert().
bool ChromeClientImpl::runJavaScriptConfirm(WebCore::Frame* frame,
const WebCore::String& message) {
- WebViewDelegate* d = webview_->delegate();
- if (d) {
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
std::wstring wstr = webkit_glue::StringToStdWString(message);
- return d->RunJavaScriptConfirm(WebFrameImpl::FromFrame(frame), wstr);
+ return delegate->RunJavaScriptConfirm(WebFrameImpl::FromFrame(frame), wstr);
}
return false;
}
@@ -344,15 +347,15 @@ bool ChromeClientImpl::runJavaScriptPrompt(WebCore::Frame* frame,
const WebCore::String& message,
const WebCore::String& defaultValue,
WebCore::String& result) {
- WebViewDelegate* d = webview_->delegate();
- if (d) {
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
std::wstring wstr_message = webkit_glue::StringToStdWString(message);
std::wstring wstr_default = webkit_glue::StringToStdWString(defaultValue);
std::wstring wstr_result;
- bool ok = d->RunJavaScriptPrompt(WebFrameImpl::FromFrame(frame),
- wstr_message,
- wstr_default,
- &wstr_result);
+ bool ok = delegate->RunJavaScriptPrompt(WebFrameImpl::FromFrame(frame),
+ wstr_message,
+ wstr_default,
+ &wstr_result);
if (ok)
result = webkit_glue::StdWStringToString(wstr_result);
return ok;
@@ -361,10 +364,10 @@ bool ChromeClientImpl::runJavaScriptPrompt(WebCore::Frame* frame,
}
void ChromeClientImpl::setStatusbarText(const WebCore::String& message) {
- WebViewDelegate* d = webview_->delegate();
- if (d) {
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
std::wstring wstr = webkit_glue::StringToStdWString(message);
- d->SetStatusbarText(webview_, wstr);
+ delegate->SetStatusbarText(webview_, wstr);
}
}
@@ -400,19 +403,20 @@ void ChromeClientImpl::repaint(
// Ignore spurious calls.
if (!content_changed || paint_rect.isEmpty())
return;
- WebViewDelegate* d = webview_->delegate();
- if (d)
- d->DidInvalidateRect(webview_, webkit_glue::FromIntRect(paint_rect));
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate)
+ delegate->DidInvalidateRect(webview_, webkit_glue::FromIntRect(paint_rect));
}
void ChromeClientImpl::scroll(
const WebCore::IntSize& scroll_delta, const WebCore::IntRect& scroll_rect,
const WebCore::IntRect& clip_rect) {
- WebViewDelegate* d = webview_->delegate();
- if (d) {
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
int dx = scroll_delta.width();
int dy = scroll_delta.height();
- d->DidScrollRect(webview_, dx, dy, webkit_glue::FromIntRect(clip_rect));
+ delegate->DidScrollRect(webview_, dx, dy,
+ webkit_glue::FromIntRect(clip_rect));
}
}
@@ -426,10 +430,10 @@ WebCore::IntRect ChromeClientImpl::windowToScreen(
const WebCore::IntRect& rect) const {
WebCore::IntRect screen_rect(rect);
- WebViewDelegate* d = webview_->delegate();
- if (d) {
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
gfx::Rect window_rect;
- d->GetWindowRect(webview_, &window_rect);
+ delegate->GetWindowRect(webview_, &window_rect);
screen_rect.move(window_rect.x(), window_rect.y());
}
@@ -437,19 +441,20 @@ WebCore::IntRect ChromeClientImpl::windowToScreen(
}
PlatformWidget ChromeClientImpl::platformWindow() const {
- WebViewDelegate* d = webview_->delegate();
- return d ? d->GetContainingView(webview_) : NULL;
+ WebViewDelegate* delegate = webview_->delegate();
+ return delegate ? delegate->GetContainingView(webview_) : NULL;
}
void ChromeClientImpl::mouseDidMoveOverElement(
const WebCore::HitTestResult& result, unsigned modifierFlags) {
// Find out if the mouse is over a link, and if so, let our UI know... somehow
- WebViewDelegate* d = webview_->delegate();
- if (d) {
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
if (result.isLiveLink() && !result.absoluteLinkURL().string().isEmpty()) {
- d->UpdateTargetURL(webview_, webkit_glue::KURLToGURL(result.absoluteLinkURL()));
+ delegate->UpdateTargetURL(
+ webview_, webkit_glue::KURLToGURL(result.absoluteLinkURL()));
} else {
- d->UpdateTargetURL(webview_, GURL());
+ delegate->UpdateTargetURL(webview_, GURL());
}
}
}
@@ -463,9 +468,9 @@ void ChromeClientImpl::setToolTip(const WebCore::String& tooltip_text) {
}
void ChromeClientImpl::print(WebCore::Frame* frame) {
- WebViewDelegate* d = webview_->delegate();
- if (d) {
- d->ScriptedPrint(WebFrameImpl::FromFrame(frame));
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
+ delegate->ScriptedPrint(WebFrameImpl::FromFrame(frame));
}
}
@@ -494,24 +499,72 @@ void ChromeClientImpl::runOpenPanel(WebCore::Frame* frame,
void ChromeClientImpl::popupOpened(WebCore::FramelessScrollView* popup_view,
const WebCore::IntRect& bounds,
bool activatable) {
- WebViewDelegate* d = webview_->delegate();
- if (d) {
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate) {
WebWidgetImpl* webwidget =
- static_cast<WebWidgetImpl*>(d->CreatePopupWidget(webview_,
- activatable));
+ static_cast<WebWidgetImpl*>(delegate->CreatePopupWidget(webview_,
+ activatable));
webwidget->Init(popup_view, webkit_glue::FromIntRect(bounds));
}
}
+void ChromeClientImpl::popupOpenedWithItems(
+ WebCore::FramelessScrollView* popup_view,
+ const WebCore::IntRect& bounds,
+ bool activatable,
+ int item_height,
+ int selected_index,
+ const WTF::Vector<WebCore::PopupListData*>& items) {
+ /*
+ Uncomment this section once the changes to
+ WebKit/WebCore/platform/chromium/PopupMenuChromium* have landed in our tree.
+
+ WebViewDelegate* delegate = webview_->delegate();
+ if (!delegate)
+ return;
+
+ WebWidgetImpl* webwidget =
+ static_cast<WebWidgetImpl*>(delegate->CreatePopupWidget(webview_,
+ activatable));
+ // Convert WebKit types for Chromium.
+ std::vector<MenuItem> popup_items;
+ for (int i = 0; i < items.size(); ++i) {
+ MenuItem menu_item;
+ menu_item.label = webkit_glue::StringToString16(items[i]->label);
+ menu_item.enabled = items[i]->enabled;
+ switch (items[i]->type) {
+ case WebCore::PopupListData::TypeOption:
+ menu_item.type = MenuItem::OPTION;
+ break;
+ case WebCore::PopupListData::TypeGroup:
+ menu_item.type = MenuItem::GROUP;
+ break;
+ case WebCore::PopupListData::TypeSeparator:
+ menu_item.type = MenuItem::SEPARATOR;
+ break;
+ default:
+ NOTIMPLEMENTED();
+ }
+ popup_items.push_back(menu_item);
+ }
+
+ webwidget->InitWithItems(popup_view,
+ webkit_glue::FromIntRect(bounds),
+ item_height,
+ selected_index,
+ popup_items);
+ */
+}
+
void ChromeClientImpl::SetCursor(const WebCursor& cursor) {
if (ignore_next_set_cursor_) {
ignore_next_set_cursor_ = false;
return;
}
- WebViewDelegate* d = webview_->delegate();
- if (d)
- d->SetCursor(webview_, cursor);
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate)
+ delegate->SetCursor(webview_, cursor);
}
void ChromeClientImpl::SetCursorForPlugin(const WebCursor& cursor) {
@@ -523,19 +576,19 @@ void ChromeClientImpl::SetCursorForPlugin(const WebCursor& cursor) {
}
void ChromeClientImpl::enableSuddenTermination() {
- WebViewDelegate* d = webview_->delegate();
- if (d)
- d->EnableSuddenTermination();
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate)
+ delegate->EnableSuddenTermination();
}
void ChromeClientImpl::disableSuddenTermination() {
- WebViewDelegate* d = webview_->delegate();
- if (d)
- d->DisableSuddenTermination();
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate)
+ delegate->DisableSuddenTermination();
}
void ChromeClientImpl::formStateDidChange(const WebCore::Node*) {
- WebViewDelegate* d = webview_->delegate();
- if (d)
- d->OnNavStateChanged(webview_);
+ WebViewDelegate* delegate = webview_->delegate();
+ if (delegate)
+ delegate->OnNavStateChanged(webview_);
}
diff --git a/webkit/glue/chrome_client_impl.h b/webkit/glue/chrome_client_impl.h
index 2c6fc22..bf515d2 100644
--- a/webkit/glue/chrome_client_impl.h
+++ b/webkit/glue/chrome_client_impl.h
@@ -15,6 +15,7 @@ class WebCursor;
class WebViewImpl;
namespace WebCore {
+struct PopupListData;
class SecurityOrigin;
struct WindowFeatures;
}
@@ -118,6 +119,12 @@ class ChromeClientImpl : public WebCore::ChromeClientChromium {
virtual void popupOpened(WebCore::FramelessScrollView* popup_view,
const WebCore::IntRect& bounds,
bool activatable);
+ void popupOpenedWithItems(WebCore::FramelessScrollView* popupView,
+ const WebCore::IntRect& bounds,
+ bool activatable,
+ int item_height,
+ int selected_index,
+ const WTF::Vector<WebCore::PopupListData*>& items);
void SetCursor(const WebCursor& cursor);
void SetCursorForPlugin(const WebCursor& cursor);
diff --git a/webkit/glue/webwidget_delegate.h b/webkit/glue/webwidget_delegate.h
index 010a7d0..05ed760 100644
--- a/webkit/glue/webwidget_delegate.h
+++ b/webkit/glue/webwidget_delegate.h
@@ -5,7 +5,11 @@
#ifndef WEBKIT_GLUE_WEBWIDGET_DELEGATE_H__
#define WEBKIT_GLUE_WEBWIDGET_DELEGATE_H__
+#include <string>
+#include <vector>
+
#include "base/gfx/native_widget_types.h"
+#include "base/string16.h"
#include "webkit/glue/window_open_disposition.h"
namespace gfx {
@@ -17,6 +21,22 @@ class WebWidget;
class WebCursor;
struct WebPluginGeometry;
+struct MenuItem {
+ // Container for information about entries in an HTML select popup menu.
+ // Types must be kept in sync with PopupListBox::ListItemType in
+ // WebCore/platform/chromium/PopupMenuChromium.h. This won't change often
+ // (if ever).
+ enum Type {
+ OPTION = 0,
+ GROUP,
+ SEPARATOR
+ };
+
+ string16 label;
+ Type type;
+ bool enabled;
+};
+
class WebWidgetDelegate {
public:
// Returns the view in which the WebWidget is embedded.
@@ -36,6 +56,22 @@ class WebWidgetDelegate {
// window should be displayed, but generally only means something for WebViews.
virtual void Show(WebWidget* webwidget, WindowOpenDisposition disposition) = 0;
+ // Used for displaying HTML select elements as popup menus on Mac OS X (other
+ // platforms will use Show() above). |bounds| represents the positioning on
+ // the screen (in WebKit coordinates, origin at the top left corner) of the
+ // button that will display the menu. It will be used, along with
+ // |item_height| (which refers to the size of each entry in the menu), to
+ // position the menu on the screen. |selected_index| indicates the menu item
+ // that should be drawn as selected when the menu initially is displayed.
+ // |items| contains information about each of the entries in the popup menu,
+ // such as the type (separator, option, group), the text representation and
+ // the item's enabled status.
+ virtual void ShowWithItems(WebWidget* webwidget,
+ const gfx::Rect& bounds,
+ int item_height,
+ int selected_index,
+ const std::vector<MenuItem>& items) = 0;
+
// This method is called to instruct the window containing the WebWidget to
// close. Note: This method should just be the trigger that causes the
// WebWidget to eventually close. It should not actually be destroyed until
@@ -91,7 +127,7 @@ class WebWidgetDelegate {
virtual ~WebWidgetDelegate() { }
private:
- DISALLOW_EVIL_CONSTRUCTORS(WebWidgetDelegate);
+ DISALLOW_COPY_AND_ASSIGN(WebWidgetDelegate);
};
#endif // #ifndef WEBKIT_GLUE_WEBWIDGET_DELEGATE_H__
diff --git a/webkit/glue/webwidget_impl.cc b/webkit/glue/webwidget_impl.cc
index b745a66..5cf6bbe 100644
--- a/webkit/glue/webwidget_impl.cc
+++ b/webkit/glue/webwidget_impl.cc
@@ -62,6 +62,20 @@ void WebWidgetImpl::Init(WebCore::FramelessScrollView* widget,
}
}
+void WebWidgetImpl::InitWithItems(WebCore::FramelessScrollView* widget,
+ const gfx::Rect& bounds,
+ int item_height,
+ int selected_index,
+ const std::vector<MenuItem>& items) {
+ widget_ = widget;
+ widget_->setClient(this);
+
+ if (delegate_) {
+ delegate_->SetWindowRect(this, bounds);
+ delegate_->ShowWithItems(this, bounds, item_height, selected_index, items);
+ }
+}
+
void WebWidgetImpl::MouseMove(const WebMouseEvent& event) {
// don't send mouse move messages if the mouse hasn't moved.
if (event.x != last_mouse_position_.x() ||
diff --git a/webkit/glue/webwidget_impl.h b/webkit/glue/webwidget_impl.h
index efb1b65..e6decf4 100644
--- a/webkit/glue/webwidget_impl.h
+++ b/webkit/glue/webwidget_impl.h
@@ -25,6 +25,7 @@ namespace WebCore {
class Widget;
}
+struct MenuItem;
class WebKeyboardEvent;
class WebMouseEvent;
class WebMouseWheelEvent;
@@ -53,6 +54,11 @@ class WebWidgetImpl : public WebWidget,
// WebWidgetImpl
void Init(WebCore::FramelessScrollView* widget, const gfx::Rect& bounds);
+ void InitWithItems(WebCore::FramelessScrollView* widget,
+ const gfx::Rect& bounds,
+ int item_height,
+ int selected_index,
+ const std::vector<MenuItem>& items);
const gfx::Size& size() const { return size_; }
@@ -110,7 +116,7 @@ class WebWidgetImpl : public WebWidget,
WebCore::FramelessScrollView* widget_;
private:
- DISALLOW_EVIL_CONSTRUCTORS(WebWidgetImpl);
+ DISALLOW_COPY_AND_ASSIGN(WebWidgetImpl);
};
#endif // WEBKIT_GLUE_WEBWIDGET_IMPL_H__
diff --git a/webkit/tools/test_shell/mac/test_webview_delegate.mm b/webkit/tools/test_shell/mac/test_webview_delegate.mm
index e80f75a..039e34f3 100755
--- a/webkit/tools/test_shell/mac/test_webview_delegate.mm
+++ b/webkit/tools/test_shell/mac/test_webview_delegate.mm
@@ -5,6 +5,7 @@
#include "webkit/tools/test_shell/test_webview_delegate.h"
#import <Cocoa/Cocoa.h>
+#include "base/sys_string_conversions.h"
#include "base/string_util.h"
#include "webkit/glue/webcursor.h"
#include "webkit/glue/webview.h"
@@ -12,6 +13,63 @@
#include "webkit/glue/plugins/webplugin_delegate_impl.h"
#include "webkit/tools/test_shell/test_shell.h"
+// MenuDelegate ----------------------------------------------------------------
+// A class for determining whether an item was selected from an HTML select
+// control, or if the menu was dismissed without making a selection. If a menu
+// item is selected, MenuDelegate is informed and sets a flag which can be
+// queried after the menu has finished running.
+
+@interface MenuDelegate : NSObject {
+ @private
+ NSMenu* menu_; // Non-owning
+ BOOL menuItemWasChosen_;
+}
+- (id)initWithItems:(const std::vector<MenuItem>&)items forMenu:(NSMenu*)menu;
+- (void)addItem:(const MenuItem&)item;
+- (BOOL)menuItemWasChosen;
+- (void)menuItemSelected:(id)sender;
+@end
+
+@implementation MenuDelegate
+
+- (id)initWithItems:(const std::vector<MenuItem>&)items forMenu:(NSMenu*)menu {
+ if ((self = [super init])) {
+ menu_ = menu;
+ menuItemWasChosen_ = NO;
+ for (int i = 0; i < static_cast<int>(items.size()); ++i)
+ [self addItem:items[i]];
+ }
+ return self;
+}
+
+- (void)addItem:(const MenuItem&)item {
+ if (item.type == MenuItem::SEPARATOR) {
+ [menu_ addItem:[NSMenuItem separatorItem]];
+ return;
+ }
+
+ NSString* title = base::SysUTF16ToNSString(item.label);
+ NSMenuItem* menu_item = [menu_ addItemWithTitle:title
+ action:@selector(menuItemSelected:)
+ keyEquivalent:@""];
+ [menu_item setEnabled:(item.enabled && item.type != MenuItem::GROUP)];
+ [menu_item setTarget:self];
+}
+
+// Reflects the result of the user's interaction with the popup menu. If NO, the
+// menu was dismissed without the user choosing an item, which can happen if the
+// user clicked outside the menu region or hit the escape key. If YES, the user
+// selected an item from the menu.
+- (BOOL)menuItemWasChosen {
+ return menuItemWasChosen_;
+}
+
+- (void)menuItemSelected:(id)sender {
+ menuItemWasChosen_ = YES;
+}
+
+@end // MenuDelegate
+
// WebViewDelegate -----------------------------------------------------------
@@ -60,6 +118,93 @@ void TestWebViewDelegate::Show(WebWidget* webview,
WindowOpenDisposition disposition) {
}
+// Display a HTML select menu.
+void TestWebViewDelegate::ShowWithItems(
+ WebWidget* webview,
+ const gfx::Rect& bounds,
+ int item_height,
+ int selected_index,
+ const std::vector<MenuItem>& items) {
+ // Populate the menu.
+ NSMenu* menu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
+ [menu setAutoenablesItems:NO];
+ MenuDelegate* menu_delegate =
+ [[[MenuDelegate alloc] initWithItems:items forMenu:menu] autorelease];
+
+ // Set up the button cell, converting to NSView coordinates. The menu is
+ // positioned such that the currently selected menu item appears over the
+ // popup button, which is the expected Mac popup menu behavior.
+ NSPopUpButtonCell* button = [[NSPopUpButtonCell alloc] initTextCell:@""
+ pullsDown:NO];
+ [button autorelease];
+ [button setMenu:menu];
+ [button selectItemAtIndex:selected_index];
+ NSView* web_view = shell_->webViewWnd();
+ 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, and set a flag to determine if something was chosen. If
+ // nothing was chosen (i.e., the user dismissed the popup by the "ESC" key or
+ // clicking outside popup's region), send a dismiss message to WebKit.
+ [button performClickWithFrame:position inView:shell_->webViewWnd()];
+
+ // 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 = shell_->popupHost();
+ NSEvent* event = nil;
+ double event_time = (double)(AbsoluteToDuration(UpTime())) / 1000.0;
+ int window_num = [shell_->mainWnd() windowNumber];
+
+ if ([menu_delegate menuItemWasChosen]) {
+ // Construct a mouse up event to simulate the selection of an appropriate
+ // menu item.
+ NSPoint click_pos;
+ click_pos.x = position.size.width / 2;
+
+ // This is going to be hard to calculate since the button is painted by
+ // WebKit, the menu by Cocoa, and we have to translate the selected_item
+ // index to a coordinate that WebKit's PopupMenu expects which uses a
+ // different font *and* expects to draw the menu below the button like we do
+ // on Windows.
+ // The WebKit popup menu thinks it will draw just below the button, so
+ // create the click at the offset based on the selected item's index and
+ // account for the different coordinate system used by NSView.
+ int item_offset = [button indexOfSelectedItem] * item_height +
+ item_height / 2;
+ click_pos.y = view_rect.size.height - item_offset;
+ event = [NSEvent mouseEventWithType:NSLeftMouseUp
+ location:click_pos
+ modifierFlags:0
+ timestamp:event_time
+ windowNumber:window_num
+ context:nil
+ eventNumber:0
+ clickCount:1
+ pressure:1.0];
+ popup->MouseEvent(event);
+ } else {
+ // Fake an ESC key event (keyCode = 0x1B, from webinputevent_mac.mm) and
+ // forward that to WebKit.
+ NSPoint key_pos;
+ key_pos.x = 0;
+ key_pos.y = 0;
+ event = [NSEvent keyEventWithType:NSKeyUp
+ location:key_pos
+ modifierFlags:0
+ timestamp:event_time
+ windowNumber:window_num
+ context:nil
+ characters:@""
+ charactersIgnoringModifiers:@""
+ isARepeat:NO
+ keyCode:0x1B];
+ popup->KeyEvent(event);
+ }
+}
+
void TestWebViewDelegate::CloseWidgetSoon(WebWidget* webwidget) {
if (webwidget == shell_->webView()) {
NSWindow *win = shell_->mainWnd();
diff --git a/webkit/tools/test_shell/test_shell_mac.mm b/webkit/tools/test_shell/test_shell_mac.mm
index a3cd0f1..5df878e 100644
--- a/webkit/tools/test_shell/test_shell_mac.mm
+++ b/webkit/tools/test_shell/test_shell_mac.mm
@@ -460,8 +460,7 @@ void TestShell::DestroyWindow(gfx::NativeWindow windowHandle) {
WebWidget* TestShell::CreatePopupWidget(WebView* webview) {
DCHECK(!m_popupHost);
- m_popupHost = WebWidgetHost::Create(NULL, delegate_.get());
- // ShowWindow(popupWnd(), SW_SHOW);
+ m_popupHost = WebWidgetHost::Create(webViewWnd(), delegate_.get());
return m_popupHost->webwidget();
}
diff --git a/webkit/tools/test_shell/test_webview_delegate.h b/webkit/tools/test_shell/test_webview_delegate.h
index a0dcbf9..c24eccc 100644
--- a/webkit/tools/test_shell/test_webview_delegate.h
+++ b/webkit/tools/test_shell/test_webview_delegate.h
@@ -214,6 +214,11 @@ class TestWebViewDelegate : public base::RefCounted<TestWebViewDelegate>,
virtual void DidScrollRect(WebWidget* webwidget, int dx, int dy,
const gfx::Rect& clip_rect);
virtual void Show(WebWidget* webview, WindowOpenDisposition disposition);
+ virtual void ShowWithItems(WebWidget* webwidget,
+ const gfx::Rect& bounds,
+ int item_height,
+ int selected_index,
+ const std::vector<MenuItem>& items);
virtual void CloseWidgetSoon(WebWidget* webwidget);
virtual void Focus(WebWidget* webwidget);
virtual void Blur(WebWidget* webwidget);
diff --git a/webkit/tools/test_shell/test_webview_delegate_gtk.cc b/webkit/tools/test_shell/test_webview_delegate_gtk.cc
index 8c9399c..620de76 100755
--- a/webkit/tools/test_shell/test_webview_delegate_gtk.cc
+++ b/webkit/tools/test_shell/test_webview_delegate_gtk.cc
@@ -113,6 +113,14 @@ void TestWebViewDelegate::Show(WebWidget* webwidget,
gtk_widget_show_all(window);
}
+void TestWebViewDelegate::ShowWithItems(WebWidget* webwidget,
+ const gfx::Rect& bounds,
+ int item_height,
+ int selected_index,
+ const std::vector<MenuItem>& items) {
+ NOTIMPLEMENTED();
+}
+
void TestWebViewDelegate::CloseWidgetSoon(WebWidget* webwidget) {
if (webwidget == shell_->webView()) {
MessageLoop::current()->PostTask(FROM_HERE, NewRunnableFunction(
diff --git a/webkit/tools/test_shell/test_webview_delegate_win.cc b/webkit/tools/test_shell/test_webview_delegate_win.cc
index 6a10617..ff4a7e2 100755
--- a/webkit/tools/test_shell/test_webview_delegate_win.cc
+++ b/webkit/tools/test_shell/test_webview_delegate_win.cc
@@ -78,6 +78,14 @@ void TestWebViewDelegate::Show(WebWidget* webwidget, WindowOpenDisposition) {
}
}
+void TestWebViewDelegate::ShowWithItems(WebWidget* webwidget,
+ const gfx::Rect& bounds,
+ int item_height,
+ int selected_index,
+ const std::vector<MenuItem>& items) {
+ NOTIMPLEMENTED();
+}
+
void TestWebViewDelegate::CloseWidgetSoon(WebWidget* webwidget) {
if (webwidget == shell_->webView()) {
PostMessage(shell_->mainWnd(), WM_CLOSE, 0, 0);