diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-02 20:12:13 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-02 20:12:13 +0000 |
commit | c94f85914e13f04fa35a56c82ce0eb3cd46f46cf (patch) | |
tree | 4931dd5dacc240aa9e9482cf4a14bbda4dc94b25 /aura | |
parent | e0379d56b61dc1bca0ee1c66b93b9c19279332b3 (diff) | |
download | chromium_src-c94f85914e13f04fa35a56c82ce0eb3cd46f46cf.zip chromium_src-c94f85914e13f04fa35a56c82ce0eb3cd46f46cf.tar.gz chromium_src-c94f85914e13f04fa35a56c82ce0eb3cd46f46cf.tar.bz2 |
Beginnings of basic Focus and Key Events.
http://crbug.com/93934
http://crbug.com/93949
TEST=see unittest
Review URL: http://codereview.chromium.org/7830031
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@99434 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'aura')
-rw-r--r-- | aura/aura.gyp | 2 | ||||
-rw-r--r-- | aura/demo/demo_main.cc | 6 | ||||
-rw-r--r-- | aura/desktop.cc | 4 | ||||
-rw-r--r-- | aura/desktop.h | 3 | ||||
-rw-r--r-- | aura/desktop_host_win.cc | 16 | ||||
-rw-r--r-- | aura/desktop_host_win.h | 9 | ||||
-rw-r--r-- | aura/event.cc | 20 | ||||
-rw-r--r-- | aura/event.h | 20 | ||||
-rw-r--r-- | aura/event_win.cc | 7 | ||||
-rw-r--r-- | aura/focus_manager.cc | 32 | ||||
-rw-r--r-- | aura/focus_manager.h | 37 | ||||
-rw-r--r-- | aura/root_window.cc | 23 | ||||
-rw-r--r-- | aura/root_window.h | 10 | ||||
-rw-r--r-- | aura/window.cc | 15 | ||||
-rw-r--r-- | aura/window.h | 21 | ||||
-rw-r--r-- | aura/window_delegate.h | 7 | ||||
-rw-r--r-- | aura/window_manager.cc | 4 | ||||
-rw-r--r-- | aura/window_unittest.cc | 61 |
18 files changed, 293 insertions, 4 deletions
diff --git a/aura/aura.gyp b/aura/aura.gyp index cbea4f6..de8586f 100644 --- a/aura/aura.gyp +++ b/aura/aura.gyp @@ -29,6 +29,8 @@ 'event.cc', 'event.h', 'event_win.cc', + 'focus_manager.cc', + 'focus_manager.h', 'hit_test.h', 'root_window.cc', 'root_window.h', diff --git a/aura/demo/demo_main.cc b/aura/demo/demo_main.cc index c994390..7b87559 100644 --- a/aura/demo/demo_main.cc +++ b/aura/demo/demo_main.cc @@ -23,6 +23,12 @@ class DemoWindowDelegate : public aura::WindowDelegate { public: explicit DemoWindowDelegate(SkColor color) : color_(color) {} + virtual void OnFocus() OVERRIDE {} + virtual void OnBlur() OVERRIDE {} + virtual bool OnKeyEvent(aura::KeyEvent* event) OVERRIDE { + return false; + } + virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE { return HTCAPTION; } diff --git a/aura/desktop.cc b/aura/desktop.cc index 2bac955..b0ffbad1 100644 --- a/aura/desktop.cc +++ b/aura/desktop.cc @@ -52,6 +52,10 @@ bool Desktop::OnMouseEvent(const MouseEvent& event) { return window_->HandleMouseEvent(event); } +bool Desktop::OnKeyEvent(const KeyEvent& event) { + return window_->HandleKeyEvent(event); +} + // static Desktop* Desktop::GetInstance() { if (!instance_) { diff --git a/aura/desktop.h b/aura/desktop.h index 3139cae..88f02f3c 100644 --- a/aura/desktop.h +++ b/aura/desktop.h @@ -45,6 +45,9 @@ class Desktop { // Handles a mouse event. Returns true if handled. bool OnMouseEvent(const MouseEvent& event); + // Handles a key event. Returns true if handled. + bool OnKeyEvent(const KeyEvent& event); + // Compositor we're drawing to. ui::Compositor* compositor() { return compositor_.get(); } diff --git a/aura/desktop_host_win.cc b/aura/desktop_host_win.cc index d922221..e0a3d16 100644 --- a/aura/desktop_host_win.cc +++ b/aura/desktop_host_win.cc @@ -63,6 +63,14 @@ void DesktopHostWin::OnClose() { MessageLoopForUI::current()->Quit(); } +LRESULT DesktopHostWin::OnKeyEvent(UINT message, + WPARAM w_param, + LPARAM l_param) { + MSG msg = { hwnd(), message, w_param, l_param }; + SetMsgHandled(desktop_->OnKeyEvent(KeyEvent(msg))); + return 0; +} + LRESULT DesktopHostWin::OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param) { @@ -82,4 +90,12 @@ void DesktopHostWin::OnPaint(HDC dc) { ValidateRect(hwnd(), NULL); } +void DesktopHostWin::OnSize(UINT param, const CSize& size) { + if (desktop_) { + gfx::Rect bounds(desktop_->window()->bounds().origin(), + gfx::Size(size.cx, size.cy)); + desktop_->window()->SetBounds(bounds, 0); + } +} + } // namespace aura diff --git a/aura/desktop_host_win.h b/aura/desktop_host_win.h index 185cf1f..f138848 100644 --- a/aura/desktop_host_win.h +++ b/aura/desktop_host_win.h @@ -33,13 +33,22 @@ class DesktopHostWin : public DesktopHost, public ui::WindowImpl { MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange) MESSAGE_RANGE_HANDLER_EX(WM_NCMOUSEMOVE, WM_NCXBUTTONDBLCLK, OnMouseRange) + // Key events. + MESSAGE_HANDLER_EX(WM_KEYDOWN, OnKeyEvent) + MESSAGE_HANDLER_EX(WM_KEYUP, OnKeyEvent) + MESSAGE_HANDLER_EX(WM_SYSKEYDOWN, OnKeyEvent) + MESSAGE_HANDLER_EX(WM_SYSKEYUP, OnKeyEvent) + MSG_WM_CLOSE(OnClose) MSG_WM_PAINT(OnPaint) + MSG_WM_SIZE(OnSize) END_MSG_MAP() void OnClose(); + LRESULT OnKeyEvent(UINT message, WPARAM w_param, LPARAM l_param); LRESULT OnMouseRange(UINT message, WPARAM w_param, LPARAM l_param); void OnPaint(HDC dc); + void OnSize(UINT param, const CSize& size); Desktop* desktop_; diff --git a/aura/event.cc b/aura/event.cc index 055f004..bce1bee 100644 --- a/aura/event.cc +++ b/aura/event.cc @@ -38,9 +38,29 @@ LocatedEvent::LocatedEvent(const LocatedEvent& model, Window::ConvertPointToWindow(source, target, &location_); } +LocatedEvent::LocatedEvent(ui::EventType type, + const gfx::Point& location, + int flags) + : Event(type, flags), + location_(location) { +} + MouseEvent::MouseEvent(const MouseEvent& model, Window* source, Window* target) : LocatedEvent(model, source, target) { } +MouseEvent::MouseEvent(ui::EventType type, + const gfx::Point& location, + int flags) + : LocatedEvent(type, location, flags) { +} + +KeyEvent::KeyEvent(ui::EventType type, + ui::KeyboardCode key_code, + int flags) + : Event(type, flags), + key_code_(key_code) { +} + } // namespace aura diff --git a/aura/event.h b/aura/event.h index be08345..27a9843 100644 --- a/aura/event.h +++ b/aura/event.h @@ -62,6 +62,9 @@ class LocatedEvent : public Event { // converted from |source| coordinate system to |target| coordinate system. LocatedEvent(const LocatedEvent& model, Window* source, Window* target); + // Used for synthetic events in testing. + LocatedEvent(ui::EventType type, const gfx::Point& location, int flags); + gfx::Point location_; private: @@ -77,10 +80,27 @@ class MouseEvent : public LocatedEvent { // converted from |source| coordinate system to |target| coordinate system. MouseEvent(const MouseEvent& model, Window* source, Window* target); + // Used for synthetic events in testing. + MouseEvent(ui::EventType type, const gfx::Point& location, int flags); + private: DISALLOW_COPY_AND_ASSIGN(MouseEvent); }; +class KeyEvent : public Event { + public: + explicit KeyEvent(NativeEvent native_event); + + // Used for synthetic events in testing. + KeyEvent(ui::EventType type, + ui::KeyboardCode key_code, + int flags); + + ui::KeyboardCode key_code() const { return key_code_; } + + private: + ui::KeyboardCode key_code_; +}; } // namespace aura diff --git a/aura/event_win.cc b/aura/event_win.cc index 415cd30..d8cb700 100644 --- a/aura/event_win.cc +++ b/aura/event_win.cc @@ -196,4 +196,11 @@ MouseEvent::MouseEvent(NativeEvent native_event) } } +KeyEvent::KeyEvent(NativeEvent native_event) + : Event(native_event, + EventTypeFromNative(native_event), + GetKeyStateFlags()), + key_code_(ui::KeyboardCodeForWindowsKeyCode(native_event.wParam)) { +} + } // namespace aura diff --git a/aura/focus_manager.cc b/aura/focus_manager.cc new file mode 100644 index 0000000..d2a49d5 --- /dev/null +++ b/aura/focus_manager.cc @@ -0,0 +1,32 @@ +// 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 "aura/focus_manager.h" + +#include "aura/window.h" +#include "aura/window_delegate.h" + +namespace aura { +namespace internal { + +FocusManager::FocusManager(Window* owner) + : owner_(owner), + focused_window_(NULL) { +} + +FocusManager::~FocusManager() { +} + +void FocusManager::SetFocusedWindow(Window* focused_window) { + if (focused_window == focused_window_) + return; + if (focused_window_) + focused_window_->delegate()->OnBlur(); + focused_window_ = focused_window; + if (focused_window_) + focused_window_->delegate()->OnFocus(); +} + +} // namespace internal +} // namespace aura diff --git a/aura/focus_manager.h b/aura/focus_manager.h new file mode 100644 index 0000000..6bb1d74 --- /dev/null +++ b/aura/focus_manager.h @@ -0,0 +1,37 @@ +// 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 AURA_FOCUS_MANAGER_H_ +#define AURA_FOCUS_MANAGER_H_ +#pragma once + +#include "base/basictypes.h" + +namespace aura { +class Window; + +namespace internal { + +// The FocusManager, when attached to a Window, tracks changes to keyboard input +// focus within that Window's hierarchy. +class FocusManager { + public: + explicit FocusManager(Window* owner); + ~FocusManager(); + + void SetFocusedWindow(Window* window); + + Window* focused_window() { return focused_window_; } + + private: + Window* owner_; + Window* focused_window_; + + DISALLOW_COPY_AND_ASSIGN(FocusManager); +}; + +} // namespace internal +} // namespace aura + +#endif // AURA_FOCUS_MANAGER_H_ diff --git a/aura/root_window.cc b/aura/root_window.cc index d14dcda..b260871 100644 --- a/aura/root_window.cc +++ b/aura/root_window.cc @@ -6,13 +6,17 @@ #include "base/logging.h" #include "aura/event.h" +#include "aura/focus_manager.h" #include "aura/window_delegate.h" #include "ui/base/events.h" namespace aura { namespace internal { -RootWindow::RootWindow() : Window(NULL), mouse_pressed_handler_(NULL) { +RootWindow::RootWindow() + : Window(NULL), + mouse_pressed_handler_(NULL), + ALLOW_THIS_IN_INITIALIZER_LIST(focus_manager_(new FocusManager(this))) { } RootWindow::~RootWindow() { @@ -33,5 +37,22 @@ bool RootWindow::HandleMouseEvent(const MouseEvent& event) { return false; } +bool RootWindow::HandleKeyEvent(const KeyEvent& event) { + Window* focused_window = GetFocusManager()->focused_window(); + if (focused_window) { + KeyEvent translated_event(event); + return GetFocusManager()->focused_window()->OnKeyEvent(&translated_event); + } + return false; +} + +bool RootWindow::IsTopLevelWindowContainer() const { + return true; +} + +FocusManager* RootWindow::GetFocusManager() { + return focus_manager_.get(); +} + } // namespace internal } // namespace aura diff --git a/aura/root_window.h b/aura/root_window.h index e2f02fd..87017343 100644 --- a/aura/root_window.h +++ b/aura/root_window.h @@ -11,6 +11,8 @@ namespace aura { namespace internal { +class FocusManager; + // A Window subclass that handles event targeting for certain types of // MouseEvent. class RootWindow : public Window { @@ -21,8 +23,16 @@ class RootWindow : public Window { // Handles a mouse event. Returns true if handled. bool HandleMouseEvent(const MouseEvent& event); + // Handles a key event. Returns true if handled. + bool HandleKeyEvent(const KeyEvent& event); + + // Overridden from Window: + virtual bool IsTopLevelWindowContainer() const OVERRIDE; + virtual FocusManager* GetFocusManager() OVERRIDE; + private: Window* mouse_pressed_handler_; + scoped_ptr<FocusManager> focus_manager_; DISALLOW_COPY_AND_ASSIGN(RootWindow); }; diff --git a/aura/window.cc b/aura/window.cc index 2ebc210..9ac5549 100644 --- a/aura/window.cc +++ b/aura/window.cc @@ -21,7 +21,8 @@ Window::Window(WindowDelegate* delegate) : delegate_(delegate), visibility_(VISIBILITY_HIDDEN), parent_(NULL), - id_(-1) { + id_(-1), + user_data_(NULL) { } Window::~Window() { @@ -76,6 +77,10 @@ void Window::SetParent(Window* parent) { Desktop::GetInstance()->window()->AddChild(this); } +bool Window::IsTopLevelWindowContainer() const { + return false; +} + void Window::MoveChildToFront(Window* child) { DCHECK_EQ(child->parent(), this); const Windows::iterator i(std::find(children_.begin(), children_.end(), @@ -123,6 +128,10 @@ bool Window::OnMouseEvent(MouseEvent* event) { return window_manager_->OnMouseEvent(event) || delegate_->OnMouseEvent(event); } +bool Window::OnKeyEvent(KeyEvent* event) { + return delegate_->OnKeyEvent(event); +} + bool Window::HitTest(const gfx::Point& point) { gfx::Rect local_bounds(gfx::Point(), bounds().size()); // TODO(beng): hittest masks. @@ -143,6 +152,10 @@ Window* Window::GetEventHandlerForPoint(const gfx::Point& point) { return this; } +internal::FocusManager* Window::GetFocusManager() { + return parent_ ? parent_->GetFocusManager() : NULL; +} + void Window::Draw() { if (visibility_ != VISIBILITY_HIDDEN) layer_->Draw(); diff --git a/aura/window.h b/aura/window.h index 0b5bfd4..5ebfb1a 100644 --- a/aura/window.h +++ b/aura/window.h @@ -23,10 +23,15 @@ class Layer; namespace aura { class Desktop; +class KeyEvent; class MouseEvent; class WindowDelegate; class WindowManager; +namespace internal { +class FocusManager; +} + // Aura window implementation. Interesting events are sent to the // WindowDelegate. // TODO(beng): resolve ownership. @@ -74,6 +79,9 @@ class Window : public ui::LayerDelegate { void SetParent(Window* parent); Window* parent() { return parent_; } + // Returns true if this Window is the container for toplevel windows. + virtual bool IsTopLevelWindowContainer() const; + // Move the specified child of this Window to the front of the z-order. // TODO(beng): this is (obviously) feeble. void MoveChildToFront(Window* child); @@ -94,6 +102,9 @@ class Window : public ui::LayerDelegate { // Handles a mouse event. Returns true if handled. bool OnMouseEvent(MouseEvent* event); + // Handles a key event. Returns true if handled. + bool OnKeyEvent(KeyEvent* event); + WindowDelegate* delegate() { return delegate_; } // Returns true if the mouse pointer at the specified |point| can trigger an @@ -107,6 +118,14 @@ class Window : public ui::LayerDelegate { // event targeting. Window* GetEventHandlerForPoint(const gfx::Point& point); + // Returns the FocusManager for the Window, which may be attached to a parent + // Window. Can return NULL if the Window has no FocusManager. + virtual internal::FocusManager* GetFocusManager(); + + // The Window does not own this object. + void set_user_data(void* user_data) { user_data_ = user_data; } + void* user_data() const { return user_data_; } + private: typedef std::vector<Window*> Windows; @@ -142,6 +161,8 @@ class Window : public ui::LayerDelegate { scoped_ptr<WindowManager> window_manager_; + void* user_data_; + DISALLOW_COPY_AND_ASSIGN(Window); }; diff --git a/aura/window_delegate.h b/aura/window_delegate.h index 4627d4f..ee4866b 100644 --- a/aura/window_delegate.h +++ b/aura/window_delegate.h @@ -13,11 +13,18 @@ class Point; namespace aura { +class KeyEvent; class MouseEvent; // Delegate interface for aura::Window. class WindowDelegate { public: + // Sent to the Window's delegate when the Window gains or loses focus. + virtual void OnFocus() = 0; + virtual void OnBlur() = 0; + + virtual bool OnKeyEvent(KeyEvent* event) = 0; + // Returns the non-client component (see hit_test.h) containing |point|, in // window coordinates. virtual int GetNonClientComponent(const gfx::Point& point) const = 0; diff --git a/aura/window_manager.cc b/aura/window_manager.cc index ea07281..b9423b3 100644 --- a/aura/window_manager.cc +++ b/aura/window_manager.cc @@ -5,6 +5,7 @@ #include "aura/window_manager.h" #include "aura/event.h" +#include "aura/focus_manager.h" #include "aura/window.h" #include "aura/window_delegate.h" @@ -25,6 +26,9 @@ WindowManager::~WindowManager() { bool WindowManager::OnMouseEvent(MouseEvent* event) { switch (event->type()) { case ui::ET_MOUSE_PRESSED: + // TODO(beng): some windows (e.g. disabled ones, tooltips, etc) may not be + // focusable. + owner_->GetFocusManager()->SetFocusedWindow(owner_); window_component_ = owner_->delegate()->GetNonClientComponent(event->location()); MoveWindowToFront(); diff --git a/aura/window_unittest.cc b/aura/window_unittest.cc index db09a86..3035ee4 100644 --- a/aura/window_unittest.cc +++ b/aura/window_unittest.cc @@ -3,12 +3,16 @@ // found in the LICENSE file. #include "aura/desktop.h" +#include "aura/event.h" +#include "aura/focus_manager.h" +#include "aura/root_window.h" #include "aura/window_delegate.h" #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/message_loop.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/canvas_skia.h" +#include "ui/base/keycodes/keyboard_codes.h" namespace aura { namespace internal { @@ -19,10 +23,21 @@ namespace { // (deletes itself when the Window it is attached to is destroyed). class TestWindowDelegate : public WindowDelegate { public: - TestWindowDelegate(SkColor color) : color_(color) {} + TestWindowDelegate(SkColor color) + : color_(color), + last_key_code_(ui::VKEY_UNKNOWN) { + } virtual ~TestWindowDelegate() {} + ui::KeyboardCode last_key_code() const { return last_key_code_; } + // Overridden from WindowDelegate: + virtual void OnFocus() OVERRIDE {} + virtual void OnBlur() OVERRIDE {} + virtual bool OnKeyEvent(KeyEvent* event) OVERRIDE { + last_key_code_ = event->key_code(); + return true; + } virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE { return HTCLIENT; } @@ -36,6 +51,7 @@ class TestWindowDelegate : public WindowDelegate { private: SkColor color_; + ui::KeyboardCode last_key_code_; DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate); }; @@ -59,7 +75,15 @@ class WindowTest : public testing::Test { int id, const gfx::Rect& bounds, Window* parent) { - Window* window = new Window(new TestWindowDelegate(color)); + return CreateTestWindowWithDelegate(new TestWindowDelegate(color), + id, bounds, parent); + } + + Window* CreateTestWindowWithDelegate(WindowDelegate* delegate, + int id, + const gfx::Rect& bounds, + Window* parent) { + Window* window = new Window(delegate); window->set_id(id); window->Init(); window->SetBounds(bounds, 0); @@ -122,6 +146,39 @@ TEST_F(WindowTest, GetEventHandlerForPoint) { EXPECT_EQ(w13.get(), desktop->GetEventHandlerForPoint(gfx::Point(26, 481))); } +TEST_F(WindowTest, Focus) { + scoped_ptr<Window> w1( + CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500), NULL)); + scoped_ptr<Window> w11( + CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get())); + scoped_ptr<Window> w111( + CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get())); + scoped_ptr<Window> w1111( + CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get())); + scoped_ptr<Window> w12( + CreateTestWindow(SK_ColorMAGENTA, 12, gfx::Rect(10, 420, 25, 25), + w1.get())); + TestWindowDelegate* w121delegate = new TestWindowDelegate(SK_ColorYELLOW); + scoped_ptr<Window> w121( + CreateTestWindowWithDelegate(w121delegate, 121, gfx::Rect(5, 5, 5, 5), + w12.get())); + scoped_ptr<Window> w13( + CreateTestWindow(SK_ColorGRAY, 13, gfx::Rect(5, 470, 50, 50), w1.get())); + + // Click on a sub-window (w121) to focus it. + Desktop* desktop = Desktop::GetInstance(); + gfx::Point click_point = w121->bounds().CenterPoint(); + Window::ConvertPointToWindow(w121->parent(), desktop->window(), &click_point); + desktop->OnMouseEvent( + MouseEvent(ui::ET_MOUSE_PRESSED, click_point, ui::EF_LEFT_BUTTON_DOWN)); + internal::FocusManager* focus_manager = w121->GetFocusManager(); + EXPECT_EQ(w121.get(), focus_manager->focused_window()); + + // The key press should be sent to the focused sub-window. + desktop->OnKeyEvent(KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_E, 0)); + EXPECT_EQ(ui::VKEY_E, w121delegate->last_key_code()); +} + } // namespace internal } // namespace aura |