diff options
author | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-25 19:19:53 +0000 |
---|---|---|
committer | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-25 19:19:53 +0000 |
commit | 0bba72e1f8b3e5bad85a70bf8f20cb9334132413 (patch) | |
tree | a0d6be9925f1f0746e1480ec5bdd27186014a043 | |
parent | 7a888669e9c70cf9ac3b37132324bc31082bb1f2 (diff) | |
download | chromium_src-0bba72e1f8b3e5bad85a70bf8f20cb9334132413.zip chromium_src-0bba72e1f8b3e5bad85a70bf8f20cb9334132413.tar.gz chromium_src-0bba72e1f8b3e5bad85a70bf8f20cb9334132413.tar.bz2 |
Fixing WebKeyboardEvent.
Review URL: http://codereview.chromium.org/27056
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10360 0039d316-1c4b-4281-b951-d872f2087c98
20 files changed, 341 insertions, 303 deletions
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index edff720..2443918 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -1178,7 +1178,8 @@ void RenderViewHost::UnhandledInputEvent(const WebInputEvent& event) { // TODO(brettw) why do we have to filter these types of events here. Can't // the renderer just send us the ones we care abount, or maybe the view // should be able to decide which ones it wants or not? - if ((event.type == WebInputEvent::KEY_DOWN) || + if ((event.type == WebInputEvent::RAW_KEY_DOWN) || + (event.type == WebInputEvent::KEY_DOWN) || (event.type == WebInputEvent::CHAR)) { view->HandleKeyboardEvent( static_cast<const WebKeyboardEvent&>(event)); diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc index b27f835..49d7b3a 100644 --- a/chrome/browser/renderer_host/render_widget_host.cc +++ b/chrome/browser/renderer_host/render_widget_host.cc @@ -285,8 +285,8 @@ void RenderWidgetHost::ForwardWheelEvent( void RenderWidgetHost::ForwardKeyboardEvent(const WebKeyboardEvent& key_event) { if (key_event.type == WebKeyboardEvent::CHAR && - (key_event.key_code == base::VKEY_RETURN || - key_event.key_code == base::VKEY_SPACE)) { + (key_event.windows_key_code == base::VKEY_RETURN || + key_event.windows_key_code == base::VKEY_SPACE)) { OnEnterOrSpace(); } diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc index 1151152..9950a58 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc @@ -77,13 +77,6 @@ class RenderWidgetHostViewGtkWidget { RenderWidgetHostViewGtk* host_view) { WebKeyboardEvent wke(event); host_view->GetRenderWidgetHost()->ForwardKeyboardEvent(wke); - - // See note in webwidget_host_gtk.cc::HandleKeyPress(). - if (event->type == GDK_KEY_PRESS) { - wke.type = WebKeyboardEvent::CHAR; - host_view->GetRenderWidgetHost()->ForwardKeyboardEvent(wke); - } - return FALSE; } diff --git a/chrome/browser/tab_contents/web_contents_view_win.cc b/chrome/browser/tab_contents/web_contents_view_win.cc index 52989e4..8013ed1 100644 --- a/chrome/browser/tab_contents/web_contents_view_win.cc +++ b/chrome/browser/tab_contents/web_contents_view_win.cc @@ -237,13 +237,13 @@ void WebContentsViewWin::HandleKeyboardEvent(const WebKeyboardEvent& event) { // The renderer returned a keyboard event it did not process. This may be // a keyboard shortcut that we have to process. - if (event.type == WebInputEvent::KEY_DOWN) { + if (event.type == WebInputEvent::RAW_KEY_DOWN) { views::FocusManager* focus_manager = views::FocusManager::GetFocusManager(GetHWND()); // We may not have a focus_manager at this point (if the tab has been // switched by the time this message returned). if (focus_manager) { - views::Accelerator accelerator(event.key_code, + views::Accelerator accelerator(event.windows_key_code, (event.modifiers & WebInputEvent::SHIFT_KEY) == WebInputEvent::SHIFT_KEY, (event.modifiers & WebInputEvent::CTRL_KEY) == diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index e2a0aa0..b4a0acb 100755 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -495,6 +495,9 @@ struct ParamTraits<WebInputEvent::Type> { case WebInputEvent::MOUSE_WHEEL: type = L"MOUSE_WHEEL"; break; + case WebInputEvent::RAW_KEY_DOWN: + type = L"RAW_KEY_DOWN"; + break; case WebInputEvent::KEY_DOWN: type = L"KEY_DOWN"; break; diff --git a/webkit/glue/SConscript b/webkit/glue/SConscript index 3d9b3e6..a550d57 100644 --- a/webkit/glue/SConscript +++ b/webkit/glue/SConscript @@ -121,6 +121,7 @@ elif env.Bit('linux'): 'plugins/webplugin_delegate_impl_gtk.cc', 'webcursor_gtk.cc', 'webinputevent_linux.cc', + 'webinputevent_utils.cc', 'webkit_glue_gtk.cc', ]) elif env.Bit('mac'): diff --git a/webkit/glue/event_conversion.cc b/webkit/glue/event_conversion.cc index ea89652..7ceaa2e 100644 --- a/webkit/glue/event_conversion.cc +++ b/webkit/glue/event_conversion.cc @@ -20,6 +20,7 @@ MSVC_POP_WARNING(); #include "base/gfx/point.h" #include "base/logging.h" #include "webkit/glue/event_conversion.h" +#include "webkit/glue/glue_util.h" #include "webkit/glue/webinputevent.h" #include "webkit/glue/webkit_glue.h" @@ -139,6 +140,8 @@ static inline const PlatformKeyboardEvent::Type ToPlatformKeyboardEventType( return PlatformKeyboardEvent::KeyUp; case WebInputEvent::KEY_DOWN: return PlatformKeyboardEvent::KeyDown; + case WebInputEvent::RAW_KEY_DOWN: + return PlatformKeyboardEvent::RawKeyDown; case WebInputEvent::CHAR: return PlatformKeyboardEvent::Char; default: @@ -147,175 +150,22 @@ static inline const PlatformKeyboardEvent::Type ToPlatformKeyboardEventType( return PlatformKeyboardEvent::KeyDown; } -static inline String ToSingleCharacterString(UChar c) { - return String(&c, 1); -} - -#if !defined(OS_MACOSX) -// This function is not used on Mac OS X, and gcc complains. -static String GetKeyIdentifierForWindowsKeyCode(unsigned short keyCode) { - switch (keyCode) { - case VKEY_MENU: - return "Alt"; - case VKEY_CONTROL: - return "Control"; - case VKEY_SHIFT: - return "Shift"; - case VKEY_CAPITAL: - return "CapsLock"; - case VKEY_LWIN: - case VKEY_RWIN: - return "Win"; - case VKEY_CLEAR: - return "Clear"; - case VKEY_DOWN: - return "Down"; - // "End" - case VKEY_END: - return "End"; - // "Enter" - case VKEY_RETURN: - return "Enter"; - case VKEY_EXECUTE: - return "Execute"; - case VKEY_F1: - return "F1"; - case VKEY_F2: - return "F2"; - case VKEY_F3: - return "F3"; - case VKEY_F4: - return "F4"; - case VKEY_F5: - return "F5"; - case VKEY_F6: - return "F6"; - case VKEY_F7: - return "F7"; - case VKEY_F8: - return "F8"; - case VKEY_F9: - return "F9"; - case VKEY_F10: - return "F11"; - case VKEY_F12: - return "F12"; - case VKEY_F13: - return "F13"; - case VKEY_F14: - return "F14"; - case VKEY_F15: - return "F15"; - case VKEY_F16: - return "F16"; - case VKEY_F17: - return "F17"; - case VKEY_F18: - return "F18"; - case VKEY_F19: - return "F19"; - case VKEY_F20: - return "F20"; - case VKEY_F21: - return "F21"; - case VKEY_F22: - return "F22"; - case VKEY_F23: - return "F23"; - case VKEY_F24: - return "F24"; - case VKEY_HELP: - return "Help"; - case VKEY_HOME: - return "Home"; - case VKEY_INSERT: - return "Insert"; - case VKEY_LEFT: - return "Left"; - case VKEY_NEXT: - return "PageDown"; - case VKEY_PRIOR: - return "PageUp"; - case VKEY_PAUSE: - return "Pause"; - case VKEY_SNAPSHOT: - return "PrintScreen"; - case VKEY_RIGHT: - return "Right"; - case VKEY_SCROLL: - return "Scroll"; - case VKEY_SELECT: - return "Select"; - case VKEY_UP: - return "Up"; - // Standard says that DEL becomes U+007F. - case VKEY_DELETE: - return "U+007F"; - default: - return String::format("U+%04X", toupper(keyCode)); - } -} -#endif // !defined(OS_MACOSX) - -MakePlatformKeyboardEvent::MakePlatformKeyboardEvent(const WebKeyboardEvent& e) - { +MakePlatformKeyboardEvent::MakePlatformKeyboardEvent( + const WebKeyboardEvent& e) { m_type = ToPlatformKeyboardEventType(e.type); - if (m_type == Char || m_type == KeyDown) { -#if defined(OS_MACOSX) - m_text = &e.text[0]; - m_unmodifiedText = &e.unmodified_text[0]; - m_keyIdentifier = &e.key_identifier[0]; - - // Always use 13 for Enter/Return -- we don't want to use AppKit's - // different character for Enter. - if (m_windowsVirtualKeyCode == '\r') { - m_text = "\r"; - m_unmodifiedText = "\r"; - } - - // The adjustments below are only needed in backward compatibility mode, - // but we cannot tell what mode we are in from here. - - // Turn 0x7F into 8, because backspace needs to always be 8. - if (m_text == "\x7F") - m_text = "\x8"; - if (m_unmodifiedText == "\x7F") - m_unmodifiedText = "\x8"; - // Always use 9 for tab -- we don't want to use AppKit's different character for shift-tab. - if (m_windowsVirtualKeyCode == 9) { - m_text = "\x9"; - m_unmodifiedText = "\x9"; - } -#elif defined(OS_WIN) - m_text = m_unmodifiedText = ToSingleCharacterString(e.key_code); -#elif defined(OS_LINUX) - m_text = m_unmodifiedText = ToSingleCharacterString(e.text); -#endif - } -#if defined(OS_WIN) || defined(OS_LINUX) - if (m_type != Char) - m_keyIdentifier = GetKeyIdentifierForWindowsKeyCode(e.key_code); -#endif - if (m_type == Char || m_type == KeyDown || m_type == KeyUp || - m_type == RawKeyDown) { - m_windowsVirtualKeyCode = e.key_code; - } else { - m_windowsVirtualKeyCode = 0; - } + m_text = webkit_glue::String16ToString(string16(e.text)); + m_unmodifiedText = webkit_glue::String16ToString(string16(e.unmodified_text)); + m_keyIdentifier = + webkit_glue::StdStringToString(std::string(e.key_identifier)); m_autoRepeat = (e.modifiers & WebInputEvent::IS_AUTO_REPEAT) != 0; + m_windowsVirtualKeyCode = e.windows_key_code; + m_nativeVirtualKeyCode = e.native_key_code; m_isKeypad = (e.modifiers & WebInputEvent::IS_KEYPAD) != 0; m_shiftKey = (e.modifiers & WebInputEvent::SHIFT_KEY) != 0; m_ctrlKey = (e.modifiers & WebInputEvent::CTRL_KEY) != 0; m_altKey = (e.modifiers & WebInputEvent::ALT_KEY) != 0; m_metaKey = (e.modifiers & WebInputEvent::META_KEY) != 0; -#if defined(OS_WIN) m_isSystemKey = e.system_key; -// TODO(port): set this field properly for linux and mac. -#elif defined(OS_LINUX) - m_isSystemKey = m_altKey; -#else - m_isSystemKey = false; -#endif } void MakePlatformKeyboardEvent::SetKeyType(Type type) { diff --git a/webkit/glue/glue.vcproj b/webkit/glue/glue.vcproj index f31623c..7551ac4 100644 --- a/webkit/glue/glue.vcproj +++ b/webkit/glue/glue.vcproj @@ -605,6 +605,14 @@ >
</File>
<File
+ RelativePath=".\webinputevent_utils.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\webinputevent_utils.h"
+ >
+ </File>
+ <File
RelativePath=".\webkit_glue.cc"
>
</File>
diff --git a/webkit/glue/webinputevent.h b/webkit/glue/webinputevent.h index 9a1c84d..8f441e5 100644 --- a/webkit/glue/webinputevent.h +++ b/webkit/glue/webinputevent.h @@ -6,11 +6,11 @@ #define WEBKIT_GLUE_WEBINPUTEVENT_H_ #include "base/basictypes.h" +#include "base/string16.h" #if defined(OS_WIN) #include <windows.h> #elif defined(OS_MACOSX) -#include <vector> #ifdef __OBJC__ @class NSEvent; @class NSView; @@ -31,6 +31,10 @@ typedef struct _GdkEventKey GdkEventKey; // // The fields of these event classes roughly correspond to the fields required // by WebCore's platform event classes. +// +// WARNING! These classes must remain PODs (plain old data). They will be +// "serialized" by shipping their raw bytes across the wire, so they must not +// contain any non-bit-copyable member variables! // WebInputEvent -------------------------------------------------------------- @@ -38,6 +42,17 @@ class WebInputEvent { public: WebInputEvent() : modifiers(0) { } + // There are two schemes used for keyboard input. On Windows (and, + // interestingly enough, on Mac Carbon) there are two events for a keypress. + // One is a raw keydown, which provides the keycode only. If the app doesn't + // handle that, then the system runs key translation to create an event + // containing the generated character and pumps that event. In such a scheme, + // those two events are translated to RAW_KEY_DOWN and CHAR events + // respectively. In Cocoa and Gtk, key events contain both the keycode and any + // translation into actual text. In such a case, WebCore will eventually need + // to split the events (see disambiguateKeyDownEvent and its callers) but we + // don't worry about that here. We just use a different type (KEY_DOWN) to + // indicate this. enum Type { // WebMouseEvent MOUSE_DOWN, @@ -50,6 +65,7 @@ class WebInputEvent { MOUSE_WHEEL, // WebKeyboardEvent + RAW_KEY_DOWN, KEY_DOWN, KEY_UP, CHAR @@ -121,53 +137,68 @@ class WebMouseWheelEvent : public WebMouseEvent { // WebKeyboardEvent ----------------------------------------------------------- +// Caps on string lengths so we can make them static arrays and keep them PODs. +const size_t kTextLengthCap = 4; +// http://www.w3.org/TR/DOM-Level-3-Events/keyset.html lists the identifiers. +// The longest is 18 characters, so we'll round up to the next multiple of 4. +const size_t kIdentifierLengthCap = 20; + class WebKeyboardEvent : public WebInputEvent { public: - // The key_code field is the Windows key code associated with this key event. - // This sometimes matches the ASCII value of the key (for e.g. a-z) but - // officially ignores case, and has its own set of codes for control keys as - // well as other visible letters like punctuation. - // webkit/port/platform/chromium/KeyboardCodes* is an attempt at defining all - // of these keys, but it's not all the way there yet. (E.g., the Windows - // implementation there just passes through the code from the windows message - // directly.) - int key_code; - -#if defined(OS_MACOSX) - // text arrays extracted from the native event. On Mac, there may be - // multiple keys sent as a single event if the flags don't change. - std::vector<unsigned short> text; - std::vector<unsigned short> unmodified_text; - std::vector<unsigned short> key_identifier; -#elif defined(OS_WIN) - bool system_key; // Set if we receive a SYSKEYDOWN/WM_SYSKEYUP message. - MSG actual_message; // Set to the current keyboard message. -#elif defined(OS_LINUX) - // The unicode character, if available, corresponding to this key event. - // TODO(evanm): temporary hack for test_shell. Ideally we'd either manage - // to stuff everything into key_code, or make this field shared by all - // implementations, but this will have to do for now. - wchar_t text; + // |windows_key_code| is the Windows key code associated with this key event. + // Sometimes it's direct from the event (i.e. on Windows), sometimes it's via + // a mapping function. If you want a list, see + // webkit/port/platform/chromium/KeyboardCodes* . + int windows_key_code; + + // The actual key code genenerated by the platform. The DOM spec runs on + // Windows-equivalent codes (thus |windows_key_code| above) but it doesn't + // hurt to have this one around. + int native_key_code; + + // |text| is the text generated by this keystroke. |unmodified_text| is + // |text|, but unmodified by an concurrently-held modifiers (except shift). + // This is useful for working out shortcut keys. Linux and Windows guarantee + // one character per event. The Mac does not, but in reality that's all it + // ever gives. We're generous, and cap it a bit longer. + char16 text[kTextLengthCap]; + char16 unmodified_text[kTextLengthCap]; + + // This is a string identifying the key pressed. + char key_identifier[kIdentifierLengthCap]; + + // This identifies whether this event was tagged by the system as being a + // "system key" event (see + // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx for details). + // Other platforms don't have this concept, but it's just easier to leave it + // always false than ifdef. + + bool system_key; + + // References to the original event. +#if defined(OS_WIN) + MSG actual_message; // Set to the current keyboard message. TODO(avi): remove #endif - WebKeyboardEvent() - : key_code(0) + WebKeyboardEvent() : windows_key_code(0), + native_key_code(0), + system_key(false) { + memset(&text, 0, sizeof(text)); + memset(&unmodified_text, 0, sizeof(unmodified_text)); + memset(&key_identifier, 0, sizeof(key_identifier)); #if defined(OS_WIN) - , system_key(false) { memset(&actual_message, 0, sizeof(actual_message)); - } -#else - {} #endif + } #if defined(OS_WIN) - WebKeyboardEvent(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); + explicit WebKeyboardEvent(HWND hwnd, UINT message, WPARAM wparam, + LPARAM lparam); #elif defined(OS_MACOSX) - WebKeyboardEvent(NSEvent *event); + explicit WebKeyboardEvent(NSEvent *event); #elif defined(OS_LINUX) explicit WebKeyboardEvent(const GdkEventKey* event); #endif }; - #endif // WEBKIT_GLUE_WEBINPUTEVENT_H_ diff --git a/webkit/glue/webinputevent_linux.cc b/webkit/glue/webinputevent_linux.cc index 60659e3..ff19d8d 100644 --- a/webkit/glue/webinputevent_linux.cc +++ b/webkit/glue/webinputevent_linux.cc @@ -9,12 +9,9 @@ #include "KeyboardCodes.h" #include "KeyCodeConversion.h" -#include "webkit/glue/event_conversion.h" - -// This header is out of alphabetical order, but event_conversion.h pulls -// in more webkit headers that redefine LOG so I need to undef afterwards. -#undef LOG #include "base/logging.h" +#include "base/string_util.h" +#include "webkit/glue/webinputevent_utils.h" #include <gdk/gdk.h> #include <gdk/gdkkeysyms.h> @@ -66,7 +63,7 @@ WebMouseEvent::WebMouseEvent(const GdkEventButton* event) { break; default: - ASSERT_NOT_REACHED(); + NOTREACHED(); }; button = BUTTON_NONE; @@ -92,7 +89,7 @@ WebMouseEvent::WebMouseEvent(const GdkEventMotion* event) { type = MOUSE_MOVE; break; default: - ASSERT_NOT_REACHED(); + NOTREACHED(); } button = BUTTON_NONE; @@ -140,13 +137,9 @@ WebMouseWheelEvent::WebMouseWheelEvent(const GdkEventScroll* event) { } WebKeyboardEvent::WebKeyboardEvent(const GdkEventKey* event) { + system_key = false; modifiers = GdkStateToWebEventModifiers(event->state); - // GDK only exposes key press and release events. By contrast, - // WebKeyboardEvent matches Windows and wants key down/up events along with a - // separate CHAR event. - // We require the caller to simulate the CHAR event manually. See - // test_shell's webwidget_host for an example. switch (event->type) { case GDK_KEY_RELEASE: type = KEY_UP; @@ -162,7 +155,12 @@ WebKeyboardEvent::WebKeyboardEvent(const GdkEventKey* event) { // The key code tells us which physical key was pressed (for example, the // A key went down or up). It does not determine whether A should be lower // or upper case. This is what text does, which should be the keyval. - key_code = WebCore::windowsKeyCodeForKeyEvent(event->keyval); + windows_key_code = WebCore::windowsKeyCodeForKeyEvent(event->keyval); + native_key_code = event->hardware_keycode; + + memset(&text, 0, sizeof(text)); + memset(&unmodified_text, 0, sizeof(unmodified_text)); + memset(&key_identifier, 0, sizeof(key_identifier)); switch (event->keyval) { // We need to treat the enter key as a key press of character \r. This @@ -170,13 +168,20 @@ WebKeyboardEvent::WebKeyboardEvent(const GdkEventKey* event) { case GDK_ISO_Enter: case GDK_KP_Enter: case GDK_Return: - text = '\r'; + unmodified_text[0] = text[0] = static_cast<char16>('\r'); break; default: // This should set text to 0 when it's not a real character. - text = gdk_keyval_to_unicode(event->keyval); + // TODO(avi): fix for non BMP chars + unmodified_text[0] = text[0] = + static_cast<char16>(gdk_keyval_to_unicode(event->keyval)); break; } + std::string key_identifier_str = + GetKeyIdentifierForWindowsKeyCode(windows_key_code); + base::strlcpy(key_identifier, key_identifier_str.c_str(), + kIdentifierLengthCap); + // TODO(tc): Do we need to set IS_AUTO_REPEAT or IS_KEYPAD? } diff --git a/webkit/glue/webinputevent_mac.mm b/webkit/glue/webinputevent_mac.mm index 3090d96..1a324f8c 100644 --- a/webkit/glue/webinputevent_mac.mm +++ b/webkit/glue/webinputevent_mac.mm @@ -141,7 +141,7 @@ WebMouseWheelEvent::WebMouseWheelEvent(NSEvent *event, NSView* view) { // that. As a result we have to use NSString here exclusively and thus tweak // the code so it's not re-usable as-is. One possiblity would be to make the // upstream code only use NSString, but I'm not certain how far that change -// would propageage +// would propagate. namespace WebCore { @@ -923,18 +923,8 @@ static NSString* keyIdentifierForKeyEvent(NSEvent* event) // End Apple code. // --------------------------------------------------------------------- -// Helper that copies the unichar characters of a NSString into a suitably -// resized vector. The vector will be null terminated and thus even if the -// string is empty or nil, it array will have a NUL. -static void FillVectorFromNSString(std::vector<unsigned short>* v, - NSString* str) { - const unsigned int length = [str length]; - v->reserve(length + 1); - [str getCharacters:&(*v)[0]]; - (*v)[length] = '\0'; -} - WebKeyboardEvent::WebKeyboardEvent(NSEvent *event) { + system_key = false; type = WebCore::isKeyUpEvent(event) ? KEY_UP : KEY_DOWN; if ([event modifierFlags] & NSControlKeyMask) @@ -952,12 +942,50 @@ WebKeyboardEvent::WebKeyboardEvent(NSEvent *event) { if (([event type] != NSFlagsChanged) && [event isARepeat]) modifiers |= IS_AUTO_REPEAT; + windows_key_code = WebCore::windowsKeyCodeForKeyEvent(event); + native_key_code = [event keyCode]; + NSString* textString = WebCore::textFromEvent(event); NSString* unmodifiedStr = WebCore::unmodifiedTextFromEvent(event); NSString* identStr = WebCore::keyIdentifierForKeyEvent(event); - FillVectorFromNSString(&text, textString); - FillVectorFromNSString(&unmodified_text, unmodifiedStr); - FillVectorFromNSString(&key_identifier, identStr); - - key_code = WebCore::windowsKeyCodeForKeyEvent(event); + + // Begin Apple code, copied from KeyEventMac.mm + + // Always use 13 for Enter/Return -- we don't want to use AppKit's + // different character for Enter. + if (windows_key_code == '\r') { + textString = @"\r"; + unmodifiedStr = @"\r"; + } + + // The adjustments below are only needed in backward compatibility mode, + // but we cannot tell what mode we are in from here. + + // Turn 0x7F into 8, because backspace needs to always be 8. + if ([textString isEqualToString:@"\x7F"]) + textString = @"\x8"; + if ([unmodifiedStr isEqualToString:@"\x7F"]) + unmodifiedStr = @"\x8"; + // Always use 9 for tab -- we don't want to use AppKit's different character for shift-tab. + if (windows_key_code == 9) { + textString = @"\x9"; + unmodifiedStr = @"\x9"; + } + + // End Apple code. + + memset(&text, 0, sizeof(text)); + memset(&unmodified_text, 0, sizeof(unmodified_text)); + memset(&key_identifier, 0, sizeof(key_identifier)); + + if ([textString length] < kTextLengthCap && + [unmodifiedStr length] < kTextLengthCap) { + [textString getCharacters:&text[0]]; + [unmodifiedStr getCharacters:&unmodified_text[0]]; + } else { + LOG(ERROR) << "Event had text too long; dropped"; + } + [identStr getCString:&key_identifier[0] + maxLength:kIdentifierLengthCap + encoding:NSASCIIStringEncoding]; } diff --git a/webkit/glue/webinputevent_utils.cc b/webkit/glue/webinputevent_utils.cc new file mode 100644 index 0000000..e0ea547 --- /dev/null +++ b/webkit/glue/webinputevent_utils.cc @@ -0,0 +1,116 @@ +// Copyright (c) 2009 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 "config.h" + +#include "webkit/glue/webinputevent_utils.h" + +#include "KeyboardCodes.h" + +#include "base/string_util.h" + +using namespace WebCore; + +std::string GetKeyIdentifierForWindowsKeyCode(unsigned short key_code) { + switch (key_code) { + case VKEY_MENU: + return "Alt"; + case VKEY_CONTROL: + return "Control"; + case VKEY_SHIFT: + return "Shift"; + case VKEY_CAPITAL: + return "CapsLock"; + case VKEY_LWIN: + case VKEY_RWIN: + return "Win"; + case VKEY_CLEAR: + return "Clear"; + case VKEY_DOWN: + return "Down"; + // "End" + case VKEY_END: + return "End"; + // "Enter" + case VKEY_RETURN: + return "Enter"; + case VKEY_EXECUTE: + return "Execute"; + case VKEY_F1: + return "F1"; + case VKEY_F2: + return "F2"; + case VKEY_F3: + return "F3"; + case VKEY_F4: + return "F4"; + case VKEY_F5: + return "F5"; + case VKEY_F6: + return "F6"; + case VKEY_F7: + return "F7"; + case VKEY_F8: + return "F8"; + case VKEY_F9: + return "F9"; + case VKEY_F10: + return "F11"; + case VKEY_F12: + return "F12"; + case VKEY_F13: + return "F13"; + case VKEY_F14: + return "F14"; + case VKEY_F15: + return "F15"; + case VKEY_F16: + return "F16"; + case VKEY_F17: + return "F17"; + case VKEY_F18: + return "F18"; + case VKEY_F19: + return "F19"; + case VKEY_F20: + return "F20"; + case VKEY_F21: + return "F21"; + case VKEY_F22: + return "F22"; + case VKEY_F23: + return "F23"; + case VKEY_F24: + return "F24"; + case VKEY_HELP: + return "Help"; + case VKEY_HOME: + return "Home"; + case VKEY_INSERT: + return "Insert"; + case VKEY_LEFT: + return "Left"; + case VKEY_NEXT: + return "PageDown"; + case VKEY_PRIOR: + return "PageUp"; + case VKEY_PAUSE: + return "Pause"; + case VKEY_SNAPSHOT: + return "PrintScreen"; + case VKEY_RIGHT: + return "Right"; + case VKEY_SCROLL: + return "Scroll"; + case VKEY_SELECT: + return "Select"; + case VKEY_UP: + return "Up"; + // Standard says that DEL becomes U+007F. + case VKEY_DELETE: + return "U+007F"; + default: + return StringPrintf("U+%04X", toupper(key_code)); + } +} diff --git a/webkit/glue/webinputevent_utils.h b/webkit/glue/webinputevent_utils.h new file mode 100644 index 0000000..89edf23 --- /dev/null +++ b/webkit/glue/webinputevent_utils.h @@ -0,0 +1,14 @@ +// Copyright (c) 2009 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 WEBKIT_GLUE_WEBINPUTEVENT_UTILS_H_ +#define WEBKIT_GLUE_WEBINPUTEVENT_UTILS_H_ + +#include <string> + +// The shared Linux and Windows keyboard event code lives here. + +std::string GetKeyIdentifierForWindowsKeyCode(unsigned short key_code); + +#endif // WEBKIT_GLUE_WEBINPUTEVENT_UTILS_H_ diff --git a/webkit/glue/webinputevent_win.cc b/webkit/glue/webinputevent_win.cc index bcf573c..20d2e5b 100644 --- a/webkit/glue/webinputevent_win.cc +++ b/webkit/glue/webinputevent_win.cc @@ -6,7 +6,8 @@ #include "webkit/glue/webinputevent.h" -#include "webkit/glue/event_conversion.h" +#include "base/string_util.h" +#include "webkit/glue/webinputevent_utils.h" #undef LOG #include "base/logging.h" @@ -177,9 +178,9 @@ WebMouseWheelEvent::WebMouseWheelEvent(HWND hwnd, UINT message, WPARAM wparam, // message == WM_HSCROLL, wparam == SB_LINELEFT (== SB_LINEUP). // * Scrolling right // message == WM_HSCROLL, wparam == SB_LINERIGHT (== SB_LINEDOWN). - if (WM_HSCROLL == message) { - key_state |= MK_SHIFT; - wheel_delta = -wheel_delta; + if (WM_HSCROLL == message) { + key_state |= MK_SHIFT; + wheel_delta = -wheel_delta; } // Use GetAsyncKeyState for key state since we are synthesizing @@ -310,13 +311,13 @@ WebKeyboardEvent::WebKeyboardEvent(HWND hwnd, UINT message, WPARAM wparam, actual_message.wParam = wparam; actual_message.lParam = lparam; - key_code = static_cast<int>(wparam); + windows_key_code = native_key_code = static_cast<int>(wparam); switch (message) { case WM_SYSKEYDOWN: system_key = true; case WM_KEYDOWN: - type = KEY_DOWN; + type = RAW_KEY_DOWN; break; case WM_SYSKEYUP: system_key = true; @@ -336,6 +337,20 @@ WebKeyboardEvent::WebKeyboardEvent(HWND hwnd, UINT message, WPARAM wparam, NOTREACHED() << "unexpected native message: " << message; } + memset(&text, 0, sizeof(text)); + memset(&unmodified_text, 0, sizeof(unmodified_text)); + memset(&key_identifier, 0, sizeof(key_identifier)); + + if (type == CHAR || type == RAW_KEY_DOWN) + text[0] = windows_key_code; + unmodified_text[0] = windows_key_code; + if (type != CHAR) { + std::string key_identifier_str = + GetKeyIdentifierForWindowsKeyCode(windows_key_code); + base::strlcpy(key_identifier, key_identifier_str.c_str(), + kIdentifierLengthCap); + } + if (GetKeyState(VK_SHIFT) & 0x8000) modifiers |= SHIFT_KEY; if (GetKeyState(VK_CONTROL) & 0x8000) diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc index 2705168..99beb70 100644 --- a/webkit/glue/webview_impl.cc +++ b/webkit/glue/webview_impl.cc @@ -478,7 +478,8 @@ void WebViewImpl::MouseWheel(const WebMouseWheelEvent& event) { } bool WebViewImpl::KeyEvent(const WebKeyboardEvent& event) { - DCHECK((event.type == WebInputEvent::KEY_DOWN) || + DCHECK((event.type == WebInputEvent::RAW_KEY_DOWN) || + (event.type == WebInputEvent::KEY_DOWN) || (event.type == WebInputEvent::KEY_UP)); // Please refer to the comments explaining the suppress_next_keypress_event_ @@ -503,9 +504,9 @@ bool WebViewImpl::KeyEvent(const WebKeyboardEvent& event) { #if defined(OS_WIN) // TODO(pinkerton): figure out these keycodes on non-windows - if (((event.modifiers == 0) && (event.key_code == VK_APPS)) || + if (((event.modifiers == 0) && (event.windows_key_code == VK_APPS)) || ((event.modifiers == WebInputEvent::SHIFT_KEY) && - (event.key_code == VK_F10))) { + (event.windows_key_code == VK_F10))) { SendContextMenuEvent(event); return true; } @@ -513,10 +514,8 @@ bool WebViewImpl::KeyEvent(const WebKeyboardEvent& event) { MakePlatformKeyboardEvent evt(event); -#if !defined(OS_MACOSX) - if (WebInputEvent::KEY_DOWN == event.type) { + if (WebInputEvent::RAW_KEY_DOWN == event.type) { MakePlatformKeyboardEvent evt_rawkeydown = evt; - evt_rawkeydown.SetKeyType(WebCore::PlatformKeyboardEvent::RawKeyDown); if (handler->keyEvent(evt_rawkeydown) && !evt_rawkeydown.isSystemKey()) { suppress_next_keypress_event_ = true; return true; @@ -526,19 +525,6 @@ bool WebViewImpl::KeyEvent(const WebKeyboardEvent& event) { return true; } } -#else - // Windows and Cocoa handle events in rather different ways. On Windows, - // you get two events: WM_KEYDOWN/WM_KEYUP and WM_CHAR. In - // PlatformKeyboardEvent, RawKeyDown represents the raw messages. When - // processing them, we don't process text editing events, since we'll be - // getting the data soon enough. In Cocoa, we get one event with both the - // raw and processed data. Therefore we need to keep the type as KeyDown, so - // that we'll know that this is the only time we'll have the event and that - // we need to do our thing. - if (handler->keyEvent(evt)) { - return true; - } -#endif return KeyEventDefault(event); } @@ -546,18 +532,19 @@ bool WebViewImpl::KeyEvent(const WebKeyboardEvent& event) { bool WebViewImpl::AutocompleteHandleKeyEvent(const WebKeyboardEvent& event) { if (!autocomplete_popup_showing_ || // Home and End should be left to the text field to process. - event.key_code == base::VKEY_HOME || event.key_code == base::VKEY_END) { + event.windows_key_code == base::VKEY_HOME || + event.windows_key_code == base::VKEY_END) { return false; } - if (!autocomplete_popup_->isInterestedInEventForKey(event.key_code)) + if (!autocomplete_popup_->isInterestedInEventForKey(event.windows_key_code)) return false; if (autocomplete_popup_->handleKeyEvent(MakePlatformKeyboardEvent(event))) { #if defined(OS_WIN) // We need to ignore the next CHAR event after this otherwise pressing // enter when selecting an item in the menu will go to the page. - if (WebInputEvent::KEY_DOWN == event.type) + if (WebInputEvent::RAW_KEY_DOWN == event.type) suppress_next_keypress_event_ = true; #endif return true; @@ -691,7 +678,7 @@ bool WebViewImpl::KeyEventDefault(const WebKeyboardEvent& event) { case WebInputEvent::CHAR: { #if defined(OS_WIN) // TODO(pinkerton): hook this up for non-win32 - if (event.key_code == VK_SPACE) { + if (event.windows_key_code == VK_SPACE) { int key_code = ((event.modifiers & WebInputEvent::SHIFT_KEY) ? VK_PRIOR : VK_NEXT); return ScrollViewWithKeyboard(key_code); @@ -700,9 +687,9 @@ bool WebViewImpl::KeyEventDefault(const WebKeyboardEvent& event) { break; } - case WebInputEvent::KEY_DOWN: { + case WebInputEvent::RAW_KEY_DOWN: { if (event.modifiers == WebInputEvent::CTRL_KEY) { - switch (event.key_code) { + switch (event.windows_key_code) { case 'A': GetFocusedFrame()->SelectAll(); return true; @@ -727,7 +714,7 @@ bool WebViewImpl::KeyEventDefault(const WebKeyboardEvent& event) { } #if defined(OS_WIN) if (!event.system_key) { - return ScrollViewWithKeyboard(event.key_code); + return ScrollViewWithKeyboard(event.windows_key_code); } #endif break; @@ -972,6 +959,7 @@ bool WebViewImpl::HandleInputEvent(const WebInputEvent* input_event) { MouseUp(*static_cast<const WebMouseEvent*>(input_event)); break; + case WebInputEvent::RAW_KEY_DOWN: case WebInputEvent::KEY_DOWN: case WebInputEvent::KEY_UP: handled = KeyEvent(*static_cast<const WebKeyboardEvent*>(input_event)); @@ -1232,15 +1220,14 @@ void WebViewImpl::SetInitialFocus(bool reverse) { // Since we don't have a keyboard event, we'll create one. WebKeyboardEvent keyboard_event; - keyboard_event.type = WebInputEvent::KEY_DOWN; + keyboard_event.type = WebInputEvent::RAW_KEY_DOWN; if (reverse) keyboard_event.modifiers = WebInputEvent::SHIFT_KEY; // VK_TAB which is only defined on Windows. - keyboard_event.key_code = 0x09; + keyboard_event.windows_key_code = 0x09; MakePlatformKeyboardEvent platform_event(keyboard_event); // We have to set the key type explicitly to avoid an assert in the // KeyboardEvent constructor. - platform_event.SetKeyType(PlatformKeyboardEvent::RawKeyDown); RefPtr<KeyboardEvent> webkit_event = KeyboardEvent::create(platform_event, NULL); page()->focusController()->setInitialFocus( diff --git a/webkit/glue/webwidget_impl.cc b/webkit/glue/webwidget_impl.cc index 721bbd3..b745a66 100644 --- a/webkit/glue/webwidget_impl.cc +++ b/webkit/glue/webwidget_impl.cc @@ -172,6 +172,7 @@ bool WebWidgetImpl::HandleInputEvent(const WebInputEvent* input_event) { MouseUp(*static_cast<const WebMouseEvent*>(input_event)); return true; + case WebInputEvent::RAW_KEY_DOWN: case WebInputEvent::KEY_DOWN: case WebInputEvent::KEY_UP: return KeyEvent(*static_cast<const WebKeyboardEvent*>(input_event)); diff --git a/webkit/tools/test_shell/event_sending_controller.cc b/webkit/tools/test_shell/event_sending_controller.cc index 76e8a06..6409433 100644 --- a/webkit/tools/test_shell/event_sending_controller.cc +++ b/webkit/tools/test_shell/event_sending_controller.cc @@ -382,16 +382,20 @@ void EventSendingController::keyDown( // WebKit/WebKitTools/DumpRenderTree/win. We may also need // to generate a keyChar event in certain cases. WebKeyboardEvent event_down, event_up; +#if defined(OS_WIN) + event_down.type = WebInputEvent::RAW_KEY_DOWN; +#else event_down.type = WebInputEvent::KEY_DOWN; +#endif event_down.modifiers = 0; - event_down.key_code = code; -#if defined(OS_LINUX) + event_down.windows_key_code = code; +#if defined(OS_MAC) || defined(OS_LINUX) // TODO(deanm): This code is a confusing mix of different platform key // codes. Since we're not working with a GDK event, we can't use our // GDK -> WebKit converter, which means the Linux specific extra |text| // field goes uninitialized. I don't know how to correctly calculate this // field, but for now we will at least initialize it, even if it's wrong. - event_down.text = code; + event_down.text[0] = code; #endif if (args.size() >= 2 && (args[1].isObject() || args[1].isString())) diff --git a/webkit/tools/test_shell/keyboard_unittest.cc b/webkit/tools/test_shell/keyboard_unittest.cc index 673edd1..b23ccd1 100644 --- a/webkit/tools/test_shell/keyboard_unittest.cc +++ b/webkit/tools/test_shell/keyboard_unittest.cc @@ -46,14 +46,13 @@ class KeyboardTest : public testing::Test { void SetupKeyDownEvent(WebKeyboardEvent* keyboard_event, char key_code, int modifiers) { - keyboard_event->key_code = key_code; + keyboard_event->windows_key_code = key_code; keyboard_event->modifiers = modifiers; +#if defined(OS_WIN) + keyboard_event->type = WebInputEvent::RAW_KEY_DOWN; +#else keyboard_event->type = WebInputEvent::KEY_DOWN; -#if defined(OS_LINUX) - keyboard_event->text = key_code; -#elif defined(OS_MACOSX) - keyboard_event->text.clear(); - keyboard_event->text.push_back(key_code); + keyboard_event->text[0] = key_code; #endif } diff --git a/webkit/tools/test_shell/mac/webwidget_host.mm b/webkit/tools/test_shell/mac/webwidget_host.mm index dc1b6c6..b99aca7 100644 --- a/webkit/tools/test_shell/mac/webwidget_host.mm +++ b/webkit/tools/test_shell/mac/webwidget_host.mm @@ -221,15 +221,7 @@ void WebWidgetHost::MouseEvent(NSEvent *event) { case WebInputEvent::MOUSE_LEAVE: TrackMouseLeave(false); break; - case WebInputEvent::MOUSE_DOWN: - break; - case WebInputEvent::MOUSE_UP: - break; - case WebInputEvent::MOUSE_DOUBLE_CLICK: - case WebInputEvent::MOUSE_WHEEL: - case WebInputEvent::KEY_DOWN: - case WebInputEvent::KEY_UP: - case WebInputEvent::CHAR: + default: break; } webwidget_->HandleInputEvent(&web_event); diff --git a/webkit/tools/test_shell/webwidget_host_gtk.cc b/webkit/tools/test_shell/webwidget_host_gtk.cc index c3b5cb6..57d88d8 100644 --- a/webkit/tools/test_shell/webwidget_host_gtk.cc +++ b/webkit/tools/test_shell/webwidget_host_gtk.cc @@ -148,16 +148,6 @@ class WebWidgetHostGtkWidget { WebKeyboardEvent wke(event); host->webwidget()->HandleInputEvent(&wke); - // The WebKeyboardEvent model, when holding down a key, is: - // KEY_DOWN, CHAR, (repeated CHAR as key repeats,) KEY_UP - // The GDK model for the same sequence is just: - // KEY_PRESS, (repeated KEY_PRESS as key repeats,) KEY_RELEASE - // So we must simulate a CHAR event for every key press. - if (event->type == GDK_KEY_PRESS) { - wke.type = WebKeyboardEvent::CHAR; - host->webwidget()->HandleInputEvent(&wke); - } - return FALSE; } |