summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-11 16:51:25 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-11 16:51:25 +0000
commit6545f1cdbbe569d404f916bef157f201028b63a0 (patch)
tree4d849f4aad386cc4cad08f94f314d78cfb7f55a5 /views
parent5d451ad21fc1836a024cabecc1172c32fbe92b03 (diff)
downloadchromium_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')
-rw-r--r--views/controls/button/custom_button.cc2
-rw-r--r--views/controls/textfield/native_textfield_gtk.cc4
-rw-r--r--views/controls/textfield/native_textfield_views_unittest.cc2
-rw-r--r--views/controls/textfield/native_textfield_win.cc42
-rw-r--r--views/controls/textfield/native_textfield_win.h4
-rw-r--r--views/controls/textfield/textfield.cc3
-rw-r--r--views/events/event.cc40
-rw-r--r--views/events/event.h84
-rw-r--r--views/events/event_gtk.cc83
-rw-r--r--views/events/event_utils_win.cc31
-rw-r--r--views/events/event_utils_win.h33
-rw-r--r--views/events/event_win.cc125
-rw-r--r--views/events/event_x.cc50
-rw-r--r--views/focus/accelerator_handler.h3
-rw-r--r--views/focus/accelerator_handler_touch.cc2
-rw-r--r--views/focus/accelerator_handler_win.cc6
-rw-r--r--views/native_types.h26
-rw-r--r--views/view_unittest.cc2
-rw-r--r--views/views.gyp2
-rw-r--r--views/widget/gtk_views_window.cc2
-rw-r--r--views/widget/widget_gtk.cc4
-rw-r--r--views/widget/widget_win.cc43
-rw-r--r--views/widget/widget_win.h4
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);
};