diff options
32 files changed, 442 insertions, 177 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc index 889d682..fb04276 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc @@ -51,6 +51,7 @@ #include "ui/gfx/canvas_skia.h" #include "views/controls/textfield/native_textfield_win.h" #include "views/drag_utils.h" +#include "views/events/event_utils_win.h" #include "views/focus/focus_util_win.h" #include "views/widget/widget.h" @@ -973,7 +974,7 @@ bool AutocompleteEditViewWin::SkipDefaultKeyEventProcessing( // We don't process ALT + numpad digit as accelerators, they are used for // entering special characters. We do translate alt-home. if (e.IsAltDown() && (key != ui::VKEY_HOME) && - views::NativeTextfieldWin::IsNumPadDigit(key, e.IsExtendedKey())) + views::NativeTextfieldWin::IsNumPadDigit(key, views::IsExtendedKey(e))) return true; // Skip accelerators for key combinations omnibox wants to crack. This list diff --git a/chrome/browser/chromeos/login/screen_locker.cc b/chrome/browser/chromeos/login/screen_locker.cc index 9314efc..de04c8f 100644 --- a/chrome/browser/chromeos/login/screen_locker.cc +++ b/chrome/browser/chromeos/login/screen_locker.cc @@ -326,7 +326,7 @@ class GrabWidget : public views::WidgetGtk { } virtual gboolean OnKeyEvent(GtkWidget* widget, GdkEventKey* event) { - views::KeyEvent key_event(event); + views::KeyEvent key_event(reinterpret_cast<GdkEvent*>(event)); // This is a hack to workaround the issue crosbug.com/10655 due to // the limitation that a focus manager cannot handle views in // TYPE_CHILD WidgetGtk correctly. diff --git a/chrome/browser/chromeos/login/screen_locker_tester.cc b/chrome/browser/chromeos/login/screen_locker_tester.cc index 75907f6..209f7db 100644 --- a/chrome/browser/chromeos/login/screen_locker_tester.cc +++ b/chrome/browser/chromeos/login/screen_locker_tester.cc @@ -55,7 +55,7 @@ void ScreenLockerTester::EnterPassword(const std::string& password) { views::Textfield* pass = GetPasswordField(); GdkEvent* event = gdk_event_new(GDK_KEY_PRESS); event->key.keyval = GDK_Return; - views::KeyEvent key_event(&event->key); + views::KeyEvent key_event(event); ScreenLocker::screen_locker_->screen_lock_view_->HandleKeyEvent( pass, key_event); gdk_event_free(event); diff --git a/chrome/browser/extensions/extension_input_api.cc b/chrome/browser/extensions/extension_input_api.cc index b062fd4..84dba8e 100644 --- a/chrome/browser/extensions/extension_input_api.cc +++ b/chrome/browser/extensions/extension_input_api.cc @@ -119,7 +119,7 @@ bool SendKeyboardEventInputFunction::RunImpl() { return false; } - views::KeyEvent event(type, prototype_event.key_code(), flags, 0, 0); + views::KeyEvent event(type, prototype_event.key_code(), flags); if (!root_view->ProcessKeyEvent(event)) { error_ = kKeyEventUnprocessedError; return false; diff --git a/chrome/browser/extensions/key_identifier_conversion_views.cc b/chrome/browser/extensions/key_identifier_conversion_views.cc index de11ad7..a9829be 100644 --- a/chrome/browser/extensions/key_identifier_conversion_views.cc +++ b/chrome/browser/extensions/key_identifier_conversion_views.cc @@ -294,7 +294,7 @@ static void InitializeMaps() { return; kUnknownKeyEvent = new views::KeyEvent( - ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, 0, 0, 0); + ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, 0); for (int i = 0; i < kNumIdentifierTypes; ++i) identifierMaps[i] = new IdentifierMap; @@ -303,7 +303,7 @@ static void InitializeMaps() { const KeyIdentifier& key = kKeyIdentifiers[i]; views::KeyEvent* event = new views::KeyEvent( - ui::ET_KEY_PRESSED, key.key_code, key.event_flags, 0, 0); + ui::ET_KEY_PRESSED, key.key_code, key.event_flags); for (int j = 0; j < kNumIdentifierTypes; ++j) { if (key.identifiers[j][0] != '\0') { diff --git a/chrome/browser/ui/views/dropdown_bar_host_gtk.cc b/chrome/browser/ui/views/dropdown_bar_host_gtk.cc index 00a03f1c..61f53f8 100644 --- a/chrome/browser/ui/views/dropdown_bar_host_gtk.cc +++ b/chrome/browser/ui/views/dropdown_bar_host_gtk.cc @@ -46,6 +46,6 @@ NativeWebKeyboardEvent DropdownBarHost::GetKeyboardEvent( key_event.IsShiftDown() ^ key_event.IsCapsLockDown()))); return wke; #else - return NativeWebKeyboardEvent(key_event.native_event()); + return NativeWebKeyboardEvent(&key_event.native_event()->key); #endif } diff --git a/chrome/browser/ui/views/dropdown_bar_host_win.cc b/chrome/browser/ui/views/dropdown_bar_host_win.cc index 0f0ce6a..ef25f14 100644 --- a/chrome/browser/ui/views/dropdown_bar_host_win.cc +++ b/chrome/browser/ui/views/dropdown_bar_host_win.cc @@ -19,7 +19,7 @@ NativeWebKeyboardEvent DropdownBarHost::GetKeyboardEvent( HWND hwnd = contents->GetContentNativeView(); WORD key = WindowsKeyCodeForKeyboardCode(key_event.key_code()); - return NativeWebKeyboardEvent(hwnd, key_event.message(), key, 0); + return NativeWebKeyboardEvent(hwnd, key_event.native_event().message, key, 0); } views::Widget* DropdownBarHost::CreateHost() { diff --git a/chrome/browser/ui/views/find_bar_host_win.cc b/chrome/browser/ui/views/find_bar_host_win.cc index 051f54c..ee0a980 100644 --- a/chrome/browser/ui/views/find_bar_host_win.cc +++ b/chrome/browser/ui/views/find_bar_host_win.cc @@ -31,5 +31,6 @@ void FindBarHost::GetWidgetPositionNative(gfx::Rect* avoid_overlapping_rect) { bool FindBarHost::ShouldForwardKeyEventToWebpageNative( const views::KeyEvent& key_event) { // We specifically ignore WM_CHAR. See http://crbug.com/10509. - return key_event.message() == WM_KEYDOWN || key_event.message() == WM_KEYUP; + return key_event.native_event().message == WM_KEYDOWN || + key_event.native_event().message == WM_KEYUP; } diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 3f34a24..ea9acb0 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -1257,7 +1257,7 @@ bool BrowserView::PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event, // TODO(suzhe): We need to check if Windows code also has this issue, and // it'll be best if we can unify these conversion tables. // See http://crbug.com/54315 - views::KeyEvent views_event(event.os_event); + views::KeyEvent views_event(reinterpret_cast<GdkEvent*>(event.os_event)); views::Accelerator accelerator(views_event.key_code(), views_event.IsShiftDown(), views_event.IsControlDown(), diff --git a/views/controls/button/custom_button.cc b/views/controls/button/custom_button.cc index cf2f752..08a7e22 100644 --- a/views/controls/button/custom_button.cc +++ b/views/controls/button/custom_button.cc @@ -137,7 +137,7 @@ bool CustomButton::AcceleratorPressed(const Accelerator& accelerator) { SetState(BS_NORMAL); KeyEvent key_event(ui::ET_KEY_RELEASED, accelerator.GetKeyCode(), - accelerator.modifiers(), 0, 0); + accelerator.modifiers()); NotifyClick(key_event); return true; } diff --git a/views/controls/textfield/native_textfield_gtk.cc b/views/controls/textfield/native_textfield_gtk.cc index 0b7cba1..cbe7a2c 100644 --- a/views/controls/textfield/native_textfield_gtk.cc +++ b/views/controls/textfield/native_textfield_gtk.cc @@ -384,7 +384,7 @@ gboolean NativeTextfieldGtk::OnKeyPressEventHandler( gboolean NativeTextfieldGtk::OnKeyPressEvent(GdkEventKey* event) { Textfield::Controller* controller = textfield_->GetController(); if (controller) { - KeyEvent key_event(event); + KeyEvent key_event(reinterpret_cast<GdkEvent*>(event)); return controller->HandleKeyEvent(textfield_, key_event); } return false; @@ -407,7 +407,7 @@ gboolean NativeTextfieldGtk::OnActivate() { Textfield::Controller* controller = textfield_->GetController(); if (controller) { - KeyEvent views_key_event(key_event); + KeyEvent views_key_event(event); handled = controller->HandleKeyEvent(textfield_, views_key_event); } diff --git a/views/controls/textfield/native_textfield_views_unittest.cc b/views/controls/textfield/native_textfield_views_unittest.cc index 3c35e59..d8e8d1f 100644 --- a/views/controls/textfield/native_textfield_views_unittest.cc +++ b/views/controls/textfield/native_textfield_views_unittest.cc @@ -116,7 +116,7 @@ class NativeTextfieldViewsTest : public ViewsTestBase, int flags = (shift ? ui::EF_SHIFT_DOWN : 0) | (control ? ui::EF_CONTROL_DOWN : 0) | (capslock ? ui::EF_CAPS_LOCK_DOWN : 0); - KeyEvent event(ui::ET_KEY_PRESSED, key_code, flags, 1, 0); + KeyEvent event(ui::ET_KEY_PRESSED, key_code, flags); return textfield_->OnKeyPressed(event); } diff --git a/views/controls/textfield/native_textfield_win.cc b/views/controls/textfield/native_textfield_win.cc index c229eb90..5ceb2a4d 100644 --- a/views/controls/textfield/native_textfield_win.cc +++ b/views/controls/textfield/native_textfield_win.cc @@ -488,7 +488,7 @@ void NativeTextfieldWin::UpdateAccessibleValue(const std::wstring& value) { // NativeTextfieldWin, private: void NativeTextfieldWin::OnChar(TCHAR ch, UINT repeat_count, UINT flags) { - HandleKeystroke(GetCurrentMessage()->message, ch, repeat_count, flags); + HandleKeystroke(); } void NativeTextfieldWin::OnContextMenu(HWND window, const POINT& point) { @@ -687,7 +687,7 @@ void NativeTextfieldWin::OnKeyDown(TCHAR key, UINT repeat_count, UINT flags) { // CRichEditCtrl changes its text on WM_KEYDOWN instead of WM_CHAR for many // different keys (backspace, ctrl-v, ...), so we call this in both cases. - HandleKeystroke(GetCurrentMessage()->message, key, repeat_count, flags); + HandleKeystroke(); } void NativeTextfieldWin::OnLButtonDblClk(UINT keys, const CPoint& point) { @@ -931,45 +931,21 @@ void NativeTextfieldWin::OnSysChar(TCHAR ch, UINT repeat_count, UINT flags) { SetMsgHandled(false); } -void NativeTextfieldWin::HandleKeystroke(UINT message, - TCHAR key, - UINT repeat_count, - UINT flags) { +void NativeTextfieldWin::HandleKeystroke() { + const MSG* msg = GetCurrentMessage(); ScopedFreeze freeze(this, GetTextObjectModel()); Textfield::Controller* controller = textfield_->GetController(); bool handled = false; if (controller) { - ui::EventType type; - switch (message) { - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - case WM_CHAR: - case WM_SYSCHAR: - type = ui::ET_KEY_PRESSED; - break; - case WM_KEYUP: - case WM_SYSKEYUP: - type = ui::ET_KEY_RELEASED; - break; - default: - NOTREACHED() << "Unknown message:" << message; - // Passing through to avoid crash on release build. - type = ui::ET_KEY_PRESSED; - } - KeyEvent key_event(type, - ui::KeyboardCodeForWindowsKeyCode(key), - KeyEvent::GetKeyStateFlags(), - repeat_count, - flags, - message); - handled = controller->HandleKeyEvent(textfield_, key_event); + KeyEvent event(*msg); + handled = controller->HandleKeyEvent(textfield_, event); } if (!handled) { OnBeforePossibleChange(); - if (key == ui::VKEY_HOME || key == ui::VKEY_END) { + if (msg->wParam == ui::VKEY_HOME || msg->wParam == ui::VKEY_END) { // DefWindowProc() might reset the keyboard layout when it receives a // keydown event for VKEY_HOME or VKEY_END. When the window was created // with WS_EX_LAYOUTRTL and the current keyboard layout is not a RTL one, @@ -984,10 +960,10 @@ void NativeTextfieldWin::HandleKeystroke(UINT message, // change behavior is surprising and inconsistent with keyboard behavior // elsewhere, so reset the layout in this case. HKL layout = GetKeyboardLayout(0); - DefWindowProc(message, key, MAKELPARAM(repeat_count, flags)); + DefWindowProc(msg->message, msg->wParam, msg->lParam); ActivateKeyboardLayout(layout, KLF_REORDER); } else { - DefWindowProc(message, key, MAKELPARAM(repeat_count, flags)); + DefWindowProc(msg->message, msg->wParam, msg->lParam); } // CRichEditCtrl automatically turns on IMF_AUTOKEYBOARD when the user diff --git a/views/controls/textfield/native_textfield_win.h b/views/controls/textfield/native_textfield_win.h index 3ac0276..d5a354e 100644 --- a/views/controls/textfield/native_textfield_win.h +++ b/views/controls/textfield/native_textfield_win.h @@ -187,7 +187,9 @@ class NativeTextfieldWin // Helper function for OnChar() and OnKeyDown() that handles keystrokes that // could change the text in the edit. - void HandleKeystroke(UINT message, TCHAR key, UINT repeat_count, UINT flags); + // Note: This function assumes GetCurrentMessage() returns a MSG with + // msg > WM_KEYFIRST and < WM_KEYLAST. + void HandleKeystroke(); // Every piece of code that can change the edit should call these functions // before and after the change. These functions determine if anything diff --git a/views/controls/textfield/textfield.cc b/views/controls/textfield/textfield.cc index 9028f88..e46d0f0 100644 --- a/views/controls/textfield/textfield.cc +++ b/views/controls/textfield/textfield.cc @@ -26,6 +26,7 @@ // ViewHierarchyChanged is removed. #include "views/controls/textfield/native_textfield_win.h" #include "views/controls/textfield/native_textfield_views.h" +#include "views/events/event_utils_win.h" #endif namespace views { @@ -317,7 +318,7 @@ bool Textfield::SkipDefaultKeyEventProcessing(const KeyEvent& e) { // We don't translate accelerators for ALT + NumPad digit on Windows, they are // used for entering special characters. We do translate alt-home. if (e.IsAltDown() && (key != ui::VKEY_HOME) && - NativeTextfieldWin::IsNumPadDigit(key, e.IsExtendedKey())) + NativeTextfieldWin::IsNumPadDigit(key, IsExtendedKey(e))) return true; #endif return false; diff --git a/views/events/event.cc b/views/events/event.cc index 565165b..2a814bd 100644 --- a/views/events/event.cc +++ b/views/events/event.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -8,12 +8,35 @@ namespace views { +//////////////////////////////////////////////////////////////////////////////// +// Event, protected: + Event::Event(ui::EventType type, int flags) : type_(type), time_stamp_(base::Time::NowFromSystemTime()), flags_(flags) { + Init(); +} + +Event::Event(NativeEvent native_event, ui::EventType type, int flags) + : type_(type), + time_stamp_(base::Time::NowFromSystemTime()), + flags_(flags) { + InitWithNativeEvent(native_event); +} + +Event::Event(NativeEvent2 native_event_2, ui::EventType type, int flags, + FromNativeEvent2 from_native) + : native_event_2_(native_event_2), + type_(type), + time_stamp_(base::Time::NowFromSystemTime()), + flags_(flags) { + InitWithNativeEvent2(native_event_2, from_native); } +//////////////////////////////////////////////////////////////////////////////// +// LocatedEvent, public: + LocatedEvent::LocatedEvent(const LocatedEvent& model, View* from, View* to) : Event(model), location_(model.location_) { @@ -21,14 +44,18 @@ LocatedEvent::LocatedEvent(const LocatedEvent& model, View* from, View* to) View::ConvertPointToView(from, to, &location_); } +//////////////////////////////////////////////////////////////////////////////// +// KeyEvent, public: + KeyEvent::KeyEvent(ui::EventType type, ui::KeyboardCode key_code, - int event_flags, int repeat_count, int message_flags) + int event_flags) : Event(type, event_flags), - key_code_(key_code), - repeat_count_(repeat_count), - message_flags_(message_flags) { + key_code_(key_code) { } +//////////////////////////////////////////////////////////////////////////////// +// MouseEvent, public: + MouseEvent::MouseEvent(ui::EventType type, View* from, View* to, @@ -43,6 +70,9 @@ MouseEvent::MouseEvent(const MouseEvent& model, View* from, View* to) : LocatedEvent(model, from, to) { } +//////////////////////////////////////////////////////////////////////////////// +// TouchEvent, public: + #if defined(TOUCH_UI) TouchEvent::TouchEvent(ui::EventType type, int x, int y, int flags, int touch_id) : LocatedEvent(type, gfx::Point(x, y), flags), diff --git a/views/events/event.h b/views/events/event.h index 385e49c..5382573 100644 --- a/views/events/event.h +++ b/views/events/event.h @@ -1,9 +1,9 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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 VIEWS_EVENT_H_ -#define VIEWS_EVENT_H_ +#ifndef VIEWS_EVENTS_EVENT_H_ +#define VIEWS_EVENTS_EVENT_H_ #pragma once #include "base/basictypes.h" @@ -13,10 +13,6 @@ #include "ui/gfx/point.h" #include "views/native_types.h" -#if defined(OS_LINUX) -typedef struct _GdkEventKey GdkEventKey; -#endif - #if defined(TOUCH_UI) typedef union _XEvent XEvent; #endif @@ -44,7 +40,13 @@ class View; //////////////////////////////////////////////////////////////////////////////// class Event { public: + // This type exists to distinguish between the NativeEvent and NativeEvent2 + // constructors. + // TODO(beng): remove once we rid views of Gtk/Gdk. + struct FromNativeEvent2 {}; + const NativeEvent& native_event() const { return native_event_; } + const NativeEvent2& native_event_2() const { return native_event_2_; } ui::EventType type() const { return type_; } const base::Time& time_stamp() const { return time_stamp_; } int flags() const { return flags_; } @@ -90,6 +92,12 @@ class Event { protected: Event(ui::EventType type, int flags); + Event(NativeEvent native_event, ui::EventType type, int flags); + // Because the world is complicated, sometimes we have two different kinds of + // NativeEvent in play in the same executable. See native_types.h for the tale + // of woe. + Event(NativeEvent2 native_event, ui::EventType type, int flags, + FromNativeEvent2); Event(const Event& model) : native_event_(model.native_event()), @@ -101,7 +109,13 @@ class Event { private: void operator=(const Event&); + // Safely initializes the native event members of this class. + void Init(); + void InitWithNativeEvent(NativeEvent native_event); + void InitWithNativeEvent2(NativeEvent2 native_event_2, FromNativeEvent2); + NativeEvent native_event_; + NativeEvent2 native_event_2_; ui::EventType type_; base::Time time_stamp_; int flags_; @@ -246,64 +260,28 @@ class TouchEvent : public LocatedEvent { #endif //////////////////////////////////////////////////////////////////////////////// -// // KeyEvent class // -// A key event is used for any input event related to the keyboard. -// Note: this event is about key pressed, not typed characters. +// KeyEvent encapsulates keyboard input events - key press and release. // -//////////////////////////////////////////////////////////////////////////////// class KeyEvent : public Event { public: - // Create a new key event - KeyEvent(ui::EventType type, - ui::KeyboardCode key_code, - int event_flags, - int repeat_count, - int message_flags); + explicit KeyEvent(NativeEvent native_event); + explicit KeyEvent(NativeEvent2 native_event_2, FromNativeEvent2); -#if defined(OS_WIN) + // Creates a new KeyEvent synthetically (i.e. not in response to an input + // event from the host environment). This is typically only used in testing as + // some metadata obtainable from the underlying native event is not present. + // TODO(beng): see if we can kill this. KeyEvent(ui::EventType type, ui::KeyboardCode key_code, - int event_flags, - int repeat_count, - int message_flags, - UINT message); -#endif -#if defined(OS_LINUX) - explicit KeyEvent(const GdkEventKey* event); - - const GdkEventKey* native_event() const { return native_event_; } -#endif -#if defined(TOUCH_UI) - // Create a key event from an X key event. - explicit KeyEvent(XEvent* xevent); -#endif + int event_flags); ui::KeyboardCode key_code() const { return key_code_; } -#if defined(OS_WIN) - bool IsExtendedKey() const; - - UINT message() const { return message_; } -#endif - - int repeat_count() const { return repeat_count_; } - -#if defined(OS_WIN) - static int GetKeyStateFlags(); -#endif - private: - ui::KeyboardCode key_code_; - int repeat_count_; - int message_flags_; -#if defined(OS_WIN) - UINT message_; -#elif defined(OS_LINUX) - const GdkEventKey* native_event_; -#endif + DISALLOW_COPY_AND_ASSIGN(KeyEvent); }; @@ -369,4 +347,4 @@ class DropTargetEvent : public LocatedEvent { } // namespace views -#endif // VIEWS_EVENT_H_ +#endif // VIEWS_EVENTS_EVENT_H_ diff --git a/views/events/event_gtk.cc b/views/events/event_gtk.cc index b74621a..37e06d0 100644 --- a/views/events/event_gtk.cc +++ b/views/events/event_gtk.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -6,24 +6,37 @@ #include <gdk/gdk.h> +#include "base/logging.h" #include "ui/base/keycodes/keyboard_code_conversion_gtk.h" namespace views { -KeyEvent::KeyEvent(const GdkEventKey* event) - : Event(event->type == GDK_KEY_PRESS ? - ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED, - GetFlagsFromGdkState(event->state)), - // TODO(erg): All these values are iffy. - key_code_(ui::WindowsKeyCodeForGdkKeyCode(event->keyval)), - repeat_count_(0), - message_flags_(0) -#if !defined(TOUCH_UI) - , native_event_(event) -#endif -{ +namespace { + +ui::EventType EventTypeFromNative(NativeEvent native_event) { + switch (native_event->type) { + case GDK_KEY_PRESS: + return ui::ET_KEY_PRESSED; + case GDK_KEY_RELEASE: + return ui::ET_KEY_RELEASED; + default: + NOTREACHED(); + break; + } + return ui::ET_UNKNOWN; } +GdkEventKey* GetGdkEventKeyFromNative(NativeEvent native_event) { + DCHECK(native_event->type == GDK_KEY_PRESS || + native_event->type == GDK_KEY_RELEASE); + return &native_event->key; +} + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// Event, public: + // static int Event::GetFlagsFromGdkState(int state) { int flags = 0; @@ -44,4 +57,48 @@ int Event::GetFlagsFromGdkState(int state) { return flags; } +//////////////////////////////////////////////////////////////////////////////// +// Event, private: + +void Event::Init() { + native_event_ = NULL; + native_event_2_ = NULL; +} + +void Event::InitWithNativeEvent(NativeEvent native_event) { + native_event_ = native_event; + // TODO(beng): remove once we rid views of Gtk/Gdk. + native_event_2_ = NULL; +} + +#if !defined(TOUCH_UI) +void Event::InitWithNativeEvent2(NativeEvent2 native_event_2, + FromNativeEvent2) { + // No one should ever call this on non-Touch Linux. + // TODO(beng): remove once we rid views of Gtk/Gdk. + NOTREACHED(); + native_event_2_ = NULL; +} +#endif + +//////////////////////////////////////////////////////////////////////////////// +// KeyEvent, public: + +KeyEvent::KeyEvent(NativeEvent native_event) + : Event(native_event, EventTypeFromNative(native_event), + GetFlagsFromGdkState( + GetGdkEventKeyFromNative(native_event)->state)), + key_code_(ui::WindowsKeyCodeForGdkKeyCode( + GetGdkEventKeyFromNative(native_event)->keyval)) { +} + +#if !defined(TOUCH_UI) +KeyEvent::KeyEvent(NativeEvent2 native_event_2, FromNativeEvent2 from_native) + : Event(native_event_2, ui::ET_UNKNOWN, 0, from_native) { + // No one should ever call this on Gtk-views. + // TODO(beng): remove once we rid views of Gtk/Gdk. + NOTREACHED(); +} +#endif + } // namespace views diff --git a/views/events/event_utils_win.cc b/views/events/event_utils_win.cc new file mode 100644 index 0000000..7d29271 --- /dev/null +++ b/views/events/event_utils_win.cc @@ -0,0 +1,31 @@ +// Copyright (c) 2011 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 "views/events/event_utils_win.h" + +#include "ui/base/events.h" +#include "views/events/event.h" + +namespace views { + +int GetRepeatCount(const KeyEvent& event) { + return LOWORD(event.native_event().lParam); +} + +bool IsExtendedKey(const KeyEvent& event) { + return (HIWORD(event.native_event().lParam) & KF_EXTENDED) == KF_EXTENDED; +} + +int GetWindowsFlags(const Event& event) { + // TODO(beng): need support for x1/x2. + int result = 0; + result |= (event.flags() & ui::EF_SHIFT_DOWN) ? MK_SHIFT : 0; + result |= (event.flags() & ui::EF_CONTROL_DOWN) ? MK_CONTROL : 0; + result |= (event.flags() & ui::EF_LEFT_BUTTON_DOWN) ? MK_LBUTTON : 0; + result |= (event.flags() & ui::EF_MIDDLE_BUTTON_DOWN) ? MK_MBUTTON : 0; + result |= (event.flags() & ui::EF_RIGHT_BUTTON_DOWN) ? MK_RBUTTON : 0; + return result; +} + +} // namespace views diff --git a/views/events/event_utils_win.h b/views/events/event_utils_win.h new file mode 100644 index 0000000..9133864 --- /dev/null +++ b/views/events/event_utils_win.h @@ -0,0 +1,33 @@ +// Copyright (c) 2011 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 VIEWS_EVENTS_EVENT_UTILS_WIN_H_ +#define VIEWS_EVENTS_EVENT_UTILS_WIN_H_ +#pragma once + +#include "ui/gfx/native_widget_types.h" + +// Windows-specific Event utilities. Add functionality here rather than adding +// #ifdefs to event.h + +namespace views { + +class Event; +class KeyEvent; + +// Returns the repeat count of the specified KeyEvent. Valid only for +// KeyEvents constructed from a MSG. +int GetRepeatCount(const KeyEvent& event); + +// Returns true if the affected key is a Windows extended key. See documentation +// for WM_KEYDOWN for explanation. +// Valid only for KeyEvents constructed from a MSG. +bool IsExtendedKey(const KeyEvent& event); + +// Return a mask of windows key/button state flags for the event object. +int GetWindowsFlags(const Event& event); + +} // namespace views + +#endif // VIEWS_EVENTS_EVENT_UTILS_WIN_H_ diff --git a/views/events/event_win.cc b/views/events/event_win.cc index 654d4c2..a31b111 100644 --- a/views/events/event_win.cc +++ b/views/events/event_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -6,18 +6,75 @@ #include <windows.h> +#include "base/logging.h" +#include "ui/base/keycodes/keyboard_code_conversion_win.h" + namespace views { -KeyEvent::KeyEvent(ui::EventType type, ui::KeyboardCode key_code, - int event_flags, int repeat_count, int message_flags, - UINT message) - : Event(type, event_flags), - key_code_(key_code), - repeat_count_(repeat_count), - message_flags_(message_flags), - message_(message) { +namespace { + +// Returns a mask corresponding to the set of modifier keys that are currently +// pressed. Windows key messages don't come with control key state as parameters +// as with mouse messages, so we need to explicitly ask for these states. +int GetKeyStateFlags() { + int flags = 0; + if (GetKeyState(VK_MENU) & 0x80) + flags |= ui::EF_ALT_DOWN; + if (GetKeyState(VK_SHIFT) & 0x80) + flags |= ui::EF_SHIFT_DOWN; + if (GetKeyState(VK_CONTROL) & 0x80) + flags |= ui::EF_CONTROL_DOWN; + return flags; +} + +// Convert windows message identifiers to Event types. +ui::EventType EventTypeFromNative(NativeEvent native_event) { + switch (native_event.message) { + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + return ui::ET_KEY_PRESSED; + case WM_KEYUP: + case WM_SYSKEYUP: + return ui::ET_KEY_RELEASED; + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_NCLBUTTONDOWN: + case WM_NCMBUTTONDOWN: + case WM_NCRBUTTONDOWN: + case WM_RBUTTONDOWN: + return ui::ET_MOUSE_PRESSED; + case WM_LBUTTONDBLCLK: + case WM_LBUTTONUP: + case WM_MBUTTONDBLCLK: + case WM_MBUTTONUP: + case WM_NCLBUTTONDBLCLK: + case WM_NCLBUTTONUP: + case WM_NCMBUTTONDBLCLK: + case WM_NCMBUTTONUP: + case WM_NCRBUTTONDBLCLK: + case WM_NCRBUTTONUP: + case WM_RBUTTONDBLCLK: + case WM_RBUTTONUP: + return ui::ET_MOUSE_RELEASED; + case WM_MOUSEMOVE: + case WM_NCMOUSEMOVE: + return ui::ET_MOUSE_MOVED; + case WM_MOUSEWHEEL: + return ui::ET_MOUSEWHEEL; + case WM_MOUSELEAVE: + case WM_NCMOUSELEAVE: + return ui::ET_MOUSE_EXITED; + default: + NOTREACHED(); + } + return ui::ET_UNKNOWN; } +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// Event, public: + int Event::GetWindowsFlags() const { // TODO: need support for x1/x2. int result = 0; @@ -47,23 +104,43 @@ int Event::ConvertWindowsFlags(UINT win_flags) { return r; } -// static -int KeyEvent::GetKeyStateFlags() { - // Windows Keyboard messages don't come with control key state as parameters - // like mouse messages do, so we need to explicitly probe for these key - // states. - int flags = 0; - if (GetKeyState(VK_MENU) & 0x80) - flags |= ui::EF_ALT_DOWN; - if (GetKeyState(VK_SHIFT) & 0x80) - flags |= ui::EF_SHIFT_DOWN; - if (GetKeyState(VK_CONTROL) & 0x80) - flags |= ui::EF_CONTROL_DOWN; - return flags; +//////////////////////////////////////////////////////////////////////////////// +// Event, private: + +void Event::Init() { + ZeroMemory(&native_event_, sizeof(native_event_)); + native_event_2_ = NULL; +} + +void Event::InitWithNativeEvent(NativeEvent native_event) { + native_event_ = native_event; + // TODO(beng): remove once we rid views of Gtk/Gdk. + native_event_2_ = NULL; +} + +void Event::InitWithNativeEvent2(NativeEvent2 native_event_2, + FromNativeEvent2) { + // No one should ever call this on Windows. + // TODO(beng): remove once we rid views of Gtk/Gdk. + NOTREACHED(); + native_event_2_ = NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// KeyEvent, public: + +KeyEvent::KeyEvent(NativeEvent native_event) + : Event(native_event, + EventTypeFromNative(native_event), + GetKeyStateFlags()), + key_code_(ui::KeyboardCodeForWindowsKeyCode(native_event.wParam)) { } -bool KeyEvent::IsExtendedKey() const { - return (message_flags_ & KF_EXTENDED) == KF_EXTENDED; +KeyEvent::KeyEvent(NativeEvent2 native_event_2, FromNativeEvent2 from_native) + : Event(native_event_2, ui::ET_UNKNOWN, 0, from_native) { + // No one should ever call this on Windows. + // TODO(beng): remove once we rid views of Gtk/Gdk. + NOTREACHED(); } } // namespace views diff --git a/views/events/event_x.cc b/views/events/event_x.cc index cce5999..a03fad6 100644 --- a/views/events/event_x.cc +++ b/views/events/event_x.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -62,6 +62,19 @@ int GetEventFlagsForButton(int button) { return 0; } +ui::EventType EventTypeFromNative(NativeEvent2 native_event) { + switch (native_event->type) { + case KeyPress: + return ui::ET_KEY_PRESSED; + case KeyRelease: + return ui::ET_KEY_RELEASED; + default: + NOTREACHED(); + break; + } + return ui::ET_UNKNOWN; +} + #if defined(HAVE_XINPUT2) int GetButtonMaskForX2Event(XIDeviceEvent* xievent) { int buttonflags = 0; @@ -212,22 +225,38 @@ int GetMouseEventFlags(XEvent* xev) { } // namespace -KeyEvent::KeyEvent(XEvent* xev) - : Event(xev->type == KeyPress ? - ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED, - GetEventFlagsFromXState(xev->xkey.state)), - key_code_(ui::KeyboardCodeFromXKeyEvent(xev)), - repeat_count_(0), - message_flags_(0), - native_event_(NULL) { +//////////////////////////////////////////////////////////////////////////////// +// Event, private: + +void Event::InitWithNativeEvent2(NativeEvent2 native_event_2) { + native_event_ = NULL; + // TODO(beng): remove once we rid views of Gtk/Gdk. + native_event_2_ = native_event_2; } +//////////////////////////////////////////////////////////////////////////////// +// KeyEvent, public: + +KeyEvent::KeyEvent(NativeEvent2 native_event_2, FromNativeEvent2) + : Event(native_event_2, + EventTypeFromNative(native_event_2), + GetEventFlagsFromXState(native_event_2->xkey.state), + FromNativeEvent2), + key_code_(ui::KeyboardCodeFromXKeyEvent(native_event_2)) { +} + +//////////////////////////////////////////////////////////////////////////////// +// MouseEvent, public: + MouseEvent::MouseEvent(XEvent* xev) : LocatedEvent(GetMouseEventType(xev), GetMouseEventLocation(xev), GetMouseEventFlags(xev)) { } +//////////////////////////////////////////////////////////////////////////////// +// MouseWheelEvent, public: + MouseWheelEvent::MouseWheelEvent(XEvent* xev) : LocatedEvent(ui::ET_MOUSEWHEEL, GetMouseEventLocation(xev), @@ -235,6 +264,9 @@ MouseWheelEvent::MouseWheelEvent(XEvent* xev) offset_(GetMouseWheelOffset(xev)) { } +//////////////////////////////////////////////////////////////////////////////// +// TouchEvent, public: + #if defined(HAVE_XINPUT2) TouchEvent::TouchEvent(XEvent* xev) : LocatedEvent(GetTouchEventType(xev), diff --git a/views/focus/accelerator_handler.h b/views/focus/accelerator_handler.h index 96eb55d..b10b587 100644 --- a/views/focus/accelerator_handler.h +++ b/views/focus/accelerator_handler.h @@ -35,7 +35,8 @@ void SetTouchDeviceList(std::vector<unsigned int>& devices); // for the window that is receiving these messages for accelerator processing. class AcceleratorHandler : public MessageLoopForUI::Dispatcher { public: - AcceleratorHandler(); + AcceleratorHandler(); + // Dispatcher method. This returns true if an accelerator was processed by the // focus manager #if defined(OS_WIN) diff --git a/views/focus/accelerator_handler_touch.cc b/views/focus/accelerator_handler_touch.cc index ec3b750..c00edfc 100644 --- a/views/focus/accelerator_handler_touch.cc +++ b/views/focus/accelerator_handler_touch.cc @@ -164,7 +164,7 @@ bool DispatchXEvent(XEvent* xev) { switch (xev->type) { case KeyPress: case KeyRelease: { - KeyEvent keyev(xev); + KeyEvent keyev(xev, FromNativeEvent2); return root->ProcessKeyEvent(keyev); } diff --git a/views/focus/accelerator_handler_win.cc b/views/focus/accelerator_handler_win.cc index b5e4c22..ad401f3 100644 --- a/views/focus/accelerator_handler_win.cc +++ b/views/focus/accelerator_handler_win.cc @@ -24,11 +24,7 @@ bool AcceleratorHandler::Dispatch(const MSG& msg) { switch (msg.message) { case WM_KEYDOWN: case WM_SYSKEYDOWN: { - KeyEvent event(ui::ET_KEY_PRESSED, - ui::KeyboardCodeForWindowsKeyCode(msg.wParam), - KeyEvent::GetKeyStateFlags(), - msg.lParam & 0xFFFF, - (msg.lParam & 0xFFFF0000) >> 16); + KeyEvent event(msg); process_message = focus_manager->OnKeyEvent(event); if (!process_message) { // Record that this key is pressed so we can remember not to diff --git a/views/native_types.h b/views/native_types.h index d61ca96..d3690a9 100644 --- a/views/native_types.h +++ b/views/native_types.h @@ -8,22 +8,38 @@ #include "ui/gfx/native_widget_types.h" +#if defined(OS_LINUX) +typedef union _GdkEvent GdkEvent; +#endif #if defined(TOUCH_UI) typedef union _XEvent XEvent; -#elif defined(OS_LINUX) -typedef union _GdkEvent GdkEvent; #endif namespace views { +// A note about NativeEvent and NativeEvent2. +// 1. Eventually TOOLKIT_VIEWS will converge on using XEvent as we remove +// Gtk/Gdk from the stack. +// 2. TOUCH_UI needs XEvents now for certain event types. +// 3. TOUCH_UI also needs GdkEvents for certain event types. +// +// => NativeEvent and NativeEvent2. +// +// Once we replace usage of Gtk/Gdk types with Xlib types across the board in +// views, we can remove NativeEvent2 and typedef XEvent* to NativeEvent. The +// world will then be beautiful(ish). + #if defined(OS_WIN) typedef MSG NativeEvent; #endif -#if defined(TOUCH_UI) -typedef XEvent* NativeEvent; -#elif defined(OS_LINUX) +#if defined(OS_LINUX) typedef GdkEvent* NativeEvent; #endif +#if defined(TOUCH_UI) +typedef XEvent* NativeEvent2; +#else +typedef void* NativeEvent2; +#endif } // namespace views diff --git a/views/view_unittest.cc b/views/view_unittest.cc index 111554b..d50bac6 100644 --- a/views/view_unittest.cc +++ b/views/view_unittest.cc @@ -1270,7 +1270,7 @@ class DefaultButtonTest : public ViewTest { } void SimularePressingEnterAndCheckDefaultButton(ButtonID button_id) { - KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, 0, 0, 0); + KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, 0); focus_manager_->OnKeyEvent(event); switch (button_id) { case OK: diff --git a/views/views.gyp b/views/views.gyp index b044497..077c167 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -261,6 +261,8 @@ 'events/event.h', 'events/event_gtk.cc', 'events/event_win.cc', + 'events/event_utils_win.cc', + 'events/event_utils_win.h', 'events/event_x.cc', 'focus/accelerator_handler.h', 'focus/accelerator_handler_gtk.cc', diff --git a/views/widget/gtk_views_window.cc b/views/widget/gtk_views_window.cc index b94c2cd..7da1490 100644 --- a/views/widget/gtk_views_window.cc +++ b/views/widget/gtk_views_window.cc @@ -18,7 +18,7 @@ static void gtk_views_window_move_focus(GtkWindow* window, if (focus_manager) { GdkEvent* key = gtk_get_current_event(); if (key && key->type == GDK_KEY_PRESS) { - views::KeyEvent key_event(reinterpret_cast<GdkEventKey*>(key)); + views::KeyEvent key_event(key); focus_manager->OnKeyEvent(key_event); } } else if (GTK_WINDOW_CLASS(gtk_views_window_parent_class)->move_focus) { diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc index d40ec45..fc3e616 100644 --- a/views/widget/widget_gtk.cc +++ b/views/widget/widget_gtk.cc @@ -882,7 +882,7 @@ bool WidgetGtk::HandleKeyboardEvent(GdkEventKey* event) { if (!focus_manager_) return false; - KeyEvent key(event); + KeyEvent key(reinterpret_cast<NativeEvent>(event)); int key_code = key.key_code(); bool handled = false; @@ -1168,7 +1168,7 @@ gboolean WidgetGtk::OnFocusOut(GtkWidget* widget, GdkEventFocus* event) { } gboolean WidgetGtk::OnKeyEvent(GtkWidget* widget, GdkEventKey* event) { - KeyEvent key(event); + KeyEvent key(reinterpret_cast<NativeEvent>(event)); // Always reset |should_handle_menu_key_release_| unless we are handling a // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc index bfa63b7..8eba43e 100644 --- a/views/widget/widget_win.cc +++ b/views/widget/widget_win.cc @@ -19,6 +19,7 @@ #include "ui/gfx/path.h" #include "views/accessibility/view_accessibility.h" #include "views/controls/native_control_win.h" +#include "views/focus/accelerator_handler.h" #include "views/focus/focus_util_win.h" #include "views/views_delegate.h" #include "views/widget/aero_tooltip_manager.h" @@ -47,14 +48,43 @@ bool IsWindowActive(HWND hwnd) { namespace views { +// A singleton object that keeps track of the current message. +class CurrentMessageWatcher : public MessageLoopForUI::Observer { + public: + CurrentMessageWatcher() { + MessageLoopForUI::current()->AddObserver(this); + } + virtual ~CurrentMessageWatcher() { + } + + const MSG& current_message() const { return current_messages_.back(); } + + private: + // Overridden from MessageLoop::Observer: + void WillProcessMessage(const MSG& msg) { + current_messages_.push_back(msg); + } + virtual void DidProcessMessage(const MSG& msg) { + current_messages_.pop_back(); + } + + std::vector<MSG> current_messages_; + + DISALLOW_COPY_AND_ASSIGN(CurrentMessageWatcher); +}; + // Property used to link the HWND to its RootView. static const char* const kRootViewWindowProperty = "__ROOT_VIEW__"; // Links the HWND to it's Widget (as a Widget, not a WidgetWin). static const char* const kWidgetKey = "__VIEWS_WIDGET__"; +// static bool WidgetWin::screen_reader_active_ = false; +// static +CurrentMessageWatcher* WidgetWin::message_watcher_ = NULL; + // A custom MSAA object id used to determine if a screen reader is actively // listening for MSAA events. #define OBJID_CUSTOM 1 @@ -82,6 +112,8 @@ WidgetWin::WidgetWin() delegate_(NULL), accessibility_view_events_index_(-1), accessibility_view_events_(kMaxAccessibilityViewEvents) { + if (!message_watcher_) + message_watcher_ = new CurrentMessageWatcher; } WidgetWin::~WidgetWin() { @@ -524,9 +556,8 @@ void WidgetWin::WillProcessMessage(const MSG& msg) { } void WidgetWin::DidProcessMessage(const MSG& msg) { - if (root_view_->NeedsPainting(true)) { + if (root_view_->NeedsPainting(true)) PaintNow(root_view_->GetScheduledPaintRect()); - } } //////////////////////////////////////////////////////////////////////////////// @@ -689,9 +720,7 @@ void WidgetWin::OnInitMenuPopup(HMENU menu, } void WidgetWin::OnKeyDown(TCHAR c, UINT rep_cnt, UINT flags) { - KeyEvent event(ui::ET_KEY_PRESSED, ui::KeyboardCodeForWindowsKeyCode(c), - KeyEvent::GetKeyStateFlags(), rep_cnt, flags, - WM_KEYDOWN); + KeyEvent event(message_watcher_->current_message()); RootView* root_view = GetFocusedViewRootView(); if (!root_view) root_view = root_view_.get(); @@ -700,9 +729,7 @@ void WidgetWin::OnKeyDown(TCHAR c, UINT rep_cnt, UINT flags) { } void WidgetWin::OnKeyUp(TCHAR c, UINT rep_cnt, UINT flags) { - KeyEvent event(ui::ET_KEY_RELEASED, ui::KeyboardCodeForWindowsKeyCode(c), - KeyEvent::GetKeyStateFlags(), rep_cnt, flags, - WM_KEYUP); + KeyEvent event(message_watcher_->current_message()); RootView* root_view = GetFocusedViewRootView(); if (!root_view) root_view = root_view_.get(); diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h index 3b7bede..ec92a9b 100644 --- a/views/widget/widget_win.h +++ b/views/widget/widget_win.h @@ -34,6 +34,7 @@ class Rect; namespace views { +class CurrentMessageWatcher; class DefaultThemeProvider; class DropTargetWin; class FocusSearch; @@ -599,6 +600,9 @@ class WidgetWin : public ui::WindowImpl, ViewProps props_; + // Keeps track of the current message. + static CurrentMessageWatcher* message_watcher_; + DISALLOW_COPY_AND_ASSIGN(WidgetWin); }; |