diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-11 16:51:25 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-11 16:51:25 +0000 |
commit | 6545f1cdbbe569d404f916bef157f201028b63a0 (patch) | |
tree | 4d849f4aad386cc4cad08f94f314d78cfb7f55a5 /views | |
parent | 5d451ad21fc1836a024cabecc1172c32fbe92b03 (diff) | |
download | chromium_src-6545f1cdbbe569d404f916bef157f201028b63a0.zip chromium_src-6545f1cdbbe569d404f916bef157f201028b63a0.tar.gz chromium_src-6545f1cdbbe569d404f916bef157f201028b63a0.tar.bz2 |
Adds the ability to construct a KeyEvent from a NativeEvent[2], and converts some code to use it.
Removes some of the Windows-specific stuff from KeyEvent.
BUG=72040
TEST=none
Review URL: http://codereview.chromium.org/6487002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@74614 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
23 files changed, 430 insertions, 167 deletions
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); }; |