- Add new call to OnKeyEvent() to allow handling of keyboard events before they're passed to the renderer (issue #406).

- Windows: only scroll with middle mouse button when the cursor is over the view (issue #410).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@356 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt
2011-11-04 18:19:14 +00:00
parent 6d8e46fb63
commit 058e9ef2f2
17 changed files with 166 additions and 84 deletions

View File

@ -1393,21 +1393,26 @@ public:
typedef cef_handler_keyevent_type_t KeyEventType;
///
// Called when the browser component receives a keyboard event that has not
// been intercepted via JavaScript. |type| is the type of keyboard event,
// |code| is the windows scan-code for the event, |modifiers| is a set of bit-
// flags describing any pressed modifier keys and |isSystemKey| is true if
// Windows considers this a 'system key' message (see
// http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx). Return
// true if the keyboard event was handled or false to allow the browser
// component to handle the event.
// Called when the browser component receives a keyboard event. This method
// is called both before the event is passed to the renderer and after
// JavaScript in the page has had a chance to handle the event. |type| is the
// type of keyboard event, |code| is the windows scan-code for the event,
// |modifiers| is a set of bit- flags describing any pressed modifier keys and
// |isSystemKey| is true if Windows considers this a 'system key' message (see
// http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx). If
// |isAfterJavaScript| is true then JavaScript in the page has had a chance
// to handle the event and has chosen not to. Only RAWKEYDOWN, KEYDOWN and
// CHAR events will be sent with |isAfterJavaScript| set to true. Return
// true if the keyboard event was handled or false to allow continued handling
// of the event by the renderer.
///
/*--cef()--*/
virtual bool OnKeyEvent(CefRefPtr<CefBrowser> browser,
KeyEventType type,
int code,
int modifiers,
bool isSystemKey) { return false; }
bool isSystemKey,
bool isAfterJavaScript) { return false; }
};

View File

@ -1196,18 +1196,22 @@ typedef struct _cef_keyboard_handler_t
cef_base_t base;
///
// Called when the browser component receives a keyboard event that has not
// been intercepted via JavaScript. |type| is the type of keyboard event,
// |code| is the windows scan-code for the event, |modifiers| is a set of bit-
// flags describing any pressed modifier keys and |isSystemKey| is true (1) if
// Windows considers this a 'system key' message (see
// http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx). Return true
// (1) if the keyboard event was handled or false (0) to allow the browser
// component to handle the event.
// Called when the browser component receives a keyboard event. This function
// is called both before the event is passed to the renderer and after
// JavaScript in the page has had a chance to handle the event. |type| is the
// type of keyboard event, |code| is the windows scan-code for the event,
// |modifiers| is a set of bit- flags describing any pressed modifier keys and
// |isSystemKey| is true (1) if Windows considers this a 'system key' message
// (see http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx). If
// |isAfterJavaScript| is true (1) then JavaScript in the page has had a
// chance to handle the event and has chosen not to. Only RAWKEYDOWN, KEYDOWN
// and CHAR events will be sent with |isAfterJavaScript| set to true (1).
// Return true (1) if the keyboard event was handled or false (0) to allow
// continued handling of the event by the renderer.
///
int (CEF_CALLBACK *on_key_event)(struct _cef_keyboard_handler_t* self,
struct _cef_browser_t* browser, enum cef_handler_keyevent_type_t type,
int code, int modifiers, int isSystemKey);
int code, int modifiers, int isSystemKey, int isAfterJavaScript);
} cef_keyboard_handler_t;

View File

@ -268,40 +268,8 @@ bool BrowserWebViewDelegate::isSelectTrailingWhitespaceEnabled() {
}
bool BrowserWebViewDelegate::handleCurrentKeyboardEvent() {
bool handled = false;
CefRefPtr<CefClient> client = browser_->GetClient();
CefRefPtr<CefKeyboardHandler> handler;
if (client.get())
handler = client->GetKeyboardHandler();
if (handler.get()) {
WebWidgetHost* host = GetWidgetHost();
if (host) {
WebKeyboardEvent event = host->GetLastKeyEvent();
switch (event.type)
{
case WebKeyboardEvent::RawKeyDown:
handled = handler->OnKeyEvent(browser_,
KEYEVENT_RAWKEYDOWN, event.windowsKeyCode,
event.modifiers, event.isSystemKey?true:false);
break;
case WebKeyboardEvent::KeyUp:
handled = handler->OnKeyEvent(browser_,
KEYEVENT_KEYUP, event.windowsKeyCode,
event.modifiers, event.isSystemKey?true:false);
break;
case WebKeyboardEvent::Char:
handled = handler->OnKeyEvent(browser_,
KEYEVENT_CHAR, event.windowsKeyCode,
event.modifiers, event.isSystemKey?true:false);
break;
default:
break;
}
}
}
if (handled)
if (host && OnKeyboardEvent(host->GetLastKeyEvent(), true))
return true;
if (edit_command_name_.empty())
@ -1039,6 +1007,38 @@ void BrowserWebViewDelegate::WaitForPolicyDelegate() {
// Private methods -----------------------------------------------------------
bool BrowserWebViewDelegate::OnKeyboardEvent(
const WebKit::WebKeyboardEvent& event, bool isAfterJavaScript)
{
CefRefPtr<CefClient> client = browser_->GetClient();
CefRefPtr<CefKeyboardHandler> handler;
if (client.get())
handler = client->GetKeyboardHandler();
if (!handler.get())
return false;
CefKeyboardHandler::KeyEventType eventType;
switch (event.type) {
case WebKeyboardEvent::RawKeyDown:
eventType = KEYEVENT_RAWKEYDOWN;
break;
case WebKeyboardEvent::KeyDown:
eventType = KEYEVENT_KEYDOWN;
break;
case WebKeyboardEvent::KeyUp:
eventType = KEYEVENT_KEYUP;
break;
case WebKeyboardEvent::Char:
eventType = KEYEVENT_CHAR;
break;
default:
return false;
}
return handler->OnKeyEvent(browser_, eventType, event.windowsKeyCode,
event.modifiers, event.isSystemKey?true:false, isAfterJavaScript);
}
void BrowserWebViewDelegate::ShowStatus(const WebString& text,
cef_handler_statustype_t type)
{

View File

@ -263,6 +263,9 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient,
void HandleContextMenu(int selected_id);
#endif
bool OnKeyboardEvent(const WebKit::WebKeyboardEvent& event,
bool isAfterJavaScript);
protected:
// Default handling of JavaScript messages.
void ShowJavaScriptAlert(WebKit::WebFrame* webframe,

View File

@ -4,7 +4,8 @@
#include "webview_host.h"
WebViewHost::WebViewHost()
WebViewHost::WebViewHost(BrowserWebViewDelegate* delegate)
: delegate_(delegate)
{
}

View File

@ -48,24 +48,31 @@ class WebViewHost : public WebWidgetHost {
webkit::npapi::GtkPluginContainerManager* plugin_container_manager() {
return &plugin_container_manager_;
}
virtual void KeyEvent(GdkEventKey* event);
#elif defined(OS_MACOSX)
void SetIsActive(bool active);
virtual void MouseEvent(NSEvent *);
virtual void KeyEvent(NSEvent *);
virtual void SetFocus(bool enable);
#endif
protected:
WebViewHost();
WebViewHost(BrowserWebViewDelegate* delegate);
#if defined(OS_WIN)
virtual bool WndProc(UINT message, WPARAM wparam, LPARAM lparam);
virtual void MouseEvent(UINT message, WPARAM wparam, LPARAM lparam);
virtual void KeyEvent(UINT message, WPARAM wparam, LPARAM lparam);
#endif
#if defined(TOOLKIT_USES_GTK)
// Helper class that creates and moves plugin containers.
webkit::npapi::GtkPluginContainerManager plugin_container_manager_;
#endif
// The delegate pointer will always outlive the WebViewHost object.
BrowserWebViewDelegate* delegate_;
};
#endif // _WEBVIEW_HOST_H

View File

@ -8,6 +8,8 @@
#include "browser_webview_delegate.h"
#include "base/logging.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/gtk/WebInputEventFactory.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
@ -15,6 +17,9 @@
#include "webkit/plugins/npapi/gtk_plugin_container.h"
using WebKit::WebDevToolsAgentClient;
using WebKit::WebKeyboardEvent;
using WebKit::WebInputEvent;
using WebKit::WebInputEventFactory;
using WebKit::WebView;
// static
@ -24,7 +29,7 @@ WebViewHost* WebViewHost::Create(GtkWidget* parent_view,
PaintDelegate* paint_delegate,
WebDevToolsAgentClient* dev_tools_client,
const WebPreferences& prefs) {
WebViewHost* host = new WebViewHost();
WebViewHost* host = new WebViewHost(delegate);
host->view_ = WebWidgetHost::CreateWidget(parent_view, host);
host->plugin_container_manager_.set_host_widget(host->view_);
@ -53,3 +58,11 @@ void WebViewHost::CreatePluginContainer(gfx::PluginWindowHandle id) {
void WebViewHost::DestroyPluginContainer(gfx::PluginWindowHandle id) {
plugin_container_manager_.DestroyPluginContainer(id);
}
void WebViewHost::KeyEvent(GdkEventKey* event) {
WebKeyboardEvent keyboard_event(WebInputEventFactory::keyboardEvent(event));
if (delegate_->OnKeyboardEvent(keyboard_event, false))
return;
WebWidgetHost::KeyEvent(event);
}

View File

@ -10,6 +10,8 @@
#include "cef_context.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/mac/WebInputEventFactory.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "ui/gfx/rect.h"
@ -17,6 +19,9 @@
#include "webkit/glue/webpreferences.h"
using WebKit::WebDevToolsAgentClient;
using WebKit::WebKeyboardEvent;
using WebKit::WebInputEvent;
using WebKit::WebInputEventFactory;
using WebKit::WebSize;
using WebKit::WebView;
@ -27,7 +32,7 @@ WebViewHost* WebViewHost::Create(NSView* parent_view,
PaintDelegate* paint_delegate,
WebDevToolsAgentClient* dev_tools_client,
const WebPreferences& prefs) {
WebViewHost* host = new WebViewHost();
WebViewHost* host = new WebViewHost(delegate);
NSRect content_rect = {{rect.x(), rect.y()}, {rect.width(), rect.height()}};
host->view_ = [[BrowserWebView alloc] initWithFrame:content_rect];
@ -68,6 +73,14 @@ void WebViewHost::MouseEvent(NSEvent* event) {
WebWidgetHost::MouseEvent(event);
}
void WebViewHost::KeyEvent(NSEvent *event) {
WebKeyboardEvent keyboard_event(WebInputEventFactory::keyboardEvent(event));
if (delegate_->OnKeyboardEvent(keyboard_event, false))
return;
WebWidgetHost::KeyEvent(event);
}
void WebViewHost::SetFocus(bool enable) {
if (enable) {
// Set the current WebViewHost in case a drag action is started before mouse

View File

@ -6,13 +6,19 @@
#include "browser_webview_delegate.h"
#include "cef_context.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebInputEventFactory.h"
#include "ui/base/win/hwnd_util.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
#include "webkit/glue/webpreferences.h"
using namespace WebKit;
using WebKit::WebDevToolsAgentClient;
using WebKit::WebKeyboardEvent;
using WebKit::WebInputEvent;
using WebKit::WebInputEventFactory;
using WebKit::WebView;
static const wchar_t kWindowClassName[] = L"WebViewHost";
@ -23,7 +29,7 @@ WebViewHost* WebViewHost::Create(HWND parent_view,
PaintDelegate* paint_delegate,
WebDevToolsAgentClient* dev_tools_client,
const WebPreferences& prefs) {
WebViewHost* host = new WebViewHost();
WebViewHost* host = new WebViewHost(delegate);
if (!paint_delegate) {
static bool registered_class = false;
@ -79,3 +85,14 @@ void WebViewHost::MouseEvent(UINT message, WPARAM wparam, LPARAM lparam) {
_Context->set_current_webviewhost(this);
WebWidgetHost::MouseEvent(message, wparam, lparam);
}
void WebViewHost::KeyEvent(UINT message, WPARAM wparam, LPARAM lparam) {
// Give the client a chance to handle keyboard events before they're passed
// to WebKit.
const WebKeyboardEvent& event = WebInputEventFactory::keyboardEvent(
view_, message, wparam, lparam);
if (delegate_->OnKeyboardEvent(event, false))
return;
WebWidgetHost::KeyEvent(message, wparam, lparam);
}

View File

@ -24,6 +24,10 @@
#include "ui/base/win/ime_input.h"
#endif
#if defined(TOOLKIT_USES_GTK)
#include <gtk/gtk.h>
#endif
namespace gfx {
class Rect;
class Size;
@ -130,7 +134,7 @@ class WebWidgetHost {
void Resize(LPARAM lparam);
virtual void MouseEvent(UINT message, WPARAM wparam, LPARAM lparam);
void WheelEvent(WPARAM wparam, LPARAM lparam);
void KeyEvent(UINT message, WPARAM wparam, LPARAM lparam);
virtual void KeyEvent(UINT message, WPARAM wparam, LPARAM lparam);
void CaptureLostEvent();
void SetFocus(bool enable);
void OnNotify(WPARAM wparam, NMHDR* header);
@ -149,7 +153,7 @@ class WebWidgetHost {
void Resize(const gfx::Rect& rect);
virtual void MouseEvent(NSEvent *);
void WheelEvent(NSEvent *);
void KeyEvent(NSEvent *);
virtual void KeyEvent(NSEvent *);
virtual void SetFocus(bool enable);
protected:
#elif defined(TOOLKIT_USES_GTK)
@ -167,6 +171,7 @@ class WebWidgetHost {
WebWidgetHost* host);
void WindowDestroyed();
void Resize(const gfx::Size& size);
virtual void KeyEvent(GdkEventKey* event);
#endif
#if defined(OS_WIN)

View File

@ -168,21 +168,7 @@ class WebWidgetHostGtkWidget {
static gboolean HandleKeyPress(GtkWidget* widget,
GdkEventKey* event,
WebWidgetHost* host) {
host->webwidget()->handleInputEvent(
WebInputEventFactory::keyboardEvent(event));
// In the browser we do a ton of work with IMEs. This is some minimal
// code to make basic text work in test_shell, but doesn't cover IME.
// This is a copy of the logic in ProcessUnfilteredKeyPressEvent in
// render_widget_host_view_gtk.cc .
if (event->type == GDK_KEY_PRESS) {
WebKeyboardEvent wke = WebInputEventFactory::keyboardEvent(event);
if (wke.text[0]) {
wke.type = WebKit::WebInputEvent::Char;
host->webwidget()->handleInputEvent(wke);
}
}
host->KeyEvent(event);
return FALSE;
}
@ -523,3 +509,20 @@ void WebWidgetHost::ResetTooltip()
{
// TODO(port): Implement this method as part of tooltip support.
}
void WebWidgetHost::KeyEvent(GdkEventKey* event)
{
WebKeyboardEvent keyboard_event(WebInputEventFactory::keyboardEvent(event));
last_key_event_ = keyboard_event;
webwidget()->handleInputEvent(keyboard_event);
// In the browser we do a ton of work with IMEs. This is some minimal
// code to make basic text work in test_shell, but doesn't cover IME.
// This is a copy of the logic in ProcessUnfilteredKeyPressEvent in
// render_widget_host_view_gtk.cc .
if (event->type == GDK_KEY_PRESS && keyboard_event.text[0]) {
keyboard_event.type = WebKit::WebInputEvent::Char;
last_key_event_ = keyboard_event;
webwidget()->handleInputEvent(keyboard_event);
}
}

View File

@ -156,7 +156,14 @@ LRESULT CALLBACK WebWidgetHost::WndProc(HWND hwnd, UINT message, WPARAM wparam,
break;
case WM_MOUSEWHEEL:
{
// Only send mouse wheel events if the cursor is over the window.
POINT mousePt = { LOWORD(lparam), HIWORD(lparam) };
RECT wndRect;
GetWindowRect(hwnd, &wndRect);
if (PtInRect(&wndRect, mousePt))
host->WheelEvent(wparam, lparam);
}
break;
case WM_MOUSEACTIVATE:

View File

@ -19,7 +19,7 @@
int CEF_CALLBACK keyboard_handler_on_key_event(
struct _cef_keyboard_handler_t* self, cef_browser_t* browser,
enum cef_handler_keyevent_type_t type, int code, int modifiers,
int isSystemKey)
int isSystemKey, int isAfterJavaScript)
{
DCHECK(self);
DCHECK(browser);
@ -28,7 +28,7 @@ int CEF_CALLBACK keyboard_handler_on_key_event(
return CefKeyboardHandlerCppToC::Get(self)->OnKeyEvent(
CefBrowserCToCpp::Wrap(browser), type, code,
modifiers, isSystemKey?true:false);
modifiers, isSystemKey?true:false, isAfterJavaScript?true:false);
}

View File

@ -17,13 +17,14 @@
// VIRTUAL METHODS - Body may be edited by hand.
bool CefKeyboardHandlerCToCpp::OnKeyEvent(CefRefPtr<CefBrowser> browser,
KeyEventType type, int code, int modifiers, bool isSystemKey)
KeyEventType type, int code, int modifiers, bool isSystemKey,
bool isAfterJavaScript)
{
if (CEF_MEMBER_MISSING(struct_, on_key_event))
return false;
return struct_->on_key_event(struct_, CefBrowserCppToC::Wrap(browser),
type, code, modifiers, isSystemKey) ? true : false;
type, code, modifiers, isSystemKey, isAfterJavaScript) ? true : false;
}

View File

@ -34,7 +34,8 @@ public:
// CefKeyboardHandler methods
virtual bool OnKeyEvent(CefRefPtr<CefBrowser> browser, KeyEventType type,
int code, int modifiers, bool isSystemKey) OVERRIDE;
int code, int modifiers, bool isSystemKey,
bool isAfterJavaScript) OVERRIDE;
};
#endif // BUILDING_CEF_SHARED

View File

@ -216,11 +216,12 @@ bool ClientHandler::OnKeyEvent(CefRefPtr<CefBrowser> browser,
KeyEventType type,
int code,
int modifiers,
bool isSystemKey)
bool isSystemKey,
bool isAfterJavaScript)
{
REQUIRE_UI_THREAD();
if (!m_bFormElementHasFocus && code == 0x20) {
if (isAfterJavaScript && !m_bFormElementHasFocus && code == 0x20) {
// Special handling for the space character if a form element does not have
// focus.
if (type == KEYEVENT_RAWKEYDOWN) {

View File

@ -113,7 +113,8 @@ public:
KeyEventType type,
int code,
int modifiers,
bool isSystemKey) OVERRIDE;
bool isSystemKey,
bool isAfterJavaScript) OVERRIDE;
// CefPrintHandler methods.
virtual bool GetPrintHeaderFooter(CefRefPtr<CefBrowser> browser,