diff options
Diffstat (limited to 'chromium/ui/views/focus')
-rw-r--r-- | chromium/ui/views/focus/accelerator_handler.h | 46 | ||||
-rw-r--r-- | chromium/ui/views/focus/accelerator_handler_aura.cc | 26 | ||||
-rw-r--r-- | chromium/ui/views/focus/accelerator_handler_win.cc | 55 | ||||
-rw-r--r-- | chromium/ui/views/focus/focus_manager.cc | 70 | ||||
-rw-r--r-- | chromium/ui/views/focus/focus_manager.h | 11 | ||||
-rw-r--r-- | chromium/ui/views/focus/focus_manager_test.cc | 18 | ||||
-rw-r--r-- | chromium/ui/views/focus/focus_manager_test.h | 9 | ||||
-rw-r--r-- | chromium/ui/views/focus/focus_manager_unittest.cc | 131 | ||||
-rw-r--r-- | chromium/ui/views/focus/focus_manager_unittest_win.cc | 281 | ||||
-rw-r--r-- | chromium/ui/views/focus/focus_traversal_unittest.cc | 38 | ||||
-rw-r--r-- | chromium/ui/views/focus/view_storage.h | 2 |
11 files changed, 152 insertions, 535 deletions
diff --git a/chromium/ui/views/focus/accelerator_handler.h b/chromium/ui/views/focus/accelerator_handler.h deleted file mode 100644 index 29f353e697c..00000000000 --- a/chromium/ui/views/focus/accelerator_handler.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2012 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 UI_VIEWS_FOCUS_ACCELERATOR_HANDLER_H_ -#define UI_VIEWS_FOCUS_ACCELERATOR_HANDLER_H_ - -#include "build/build_config.h" - -#include <set> -#include <vector> - -#include "base/compiler_specific.h" -#include "base/message_loop/message_loop.h" -#include "ui/views/views_export.h" - -namespace views { - -#if defined(USE_AURA) && defined(USE_X11) -// Dispatch an XEvent to the RootView. Return true if the event was dispatched -// and handled, false otherwise. -bool VIEWS_EXPORT DispatchXEvent(XEvent* xevent); -#endif // USE_AURA && USE_X11 - -// This class delegates the key messages to the associated FocusManager class -// for the window that is receiving these messages for accelerator processing. -class VIEWS_EXPORT AcceleratorHandler : public base::MessageLoop::Dispatcher { - public: - AcceleratorHandler(); - - // Dispatcher method. This returns true if an accelerator was processed by the - // focus manager - virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE; - - private: -#if defined(OS_WIN) - // The keys currently pressed and consumed by the FocusManager. - std::set<WPARAM> pressed_keys_; -#endif - - DISALLOW_COPY_AND_ASSIGN(AcceleratorHandler); -}; - -} // namespace views - -#endif // UI_VIEWS_FOCUS_ACCELERATOR_HANDLER_H_ diff --git a/chromium/ui/views/focus/accelerator_handler_aura.cc b/chromium/ui/views/focus/accelerator_handler_aura.cc deleted file mode 100644 index 8daa0f394e9..00000000000 --- a/chromium/ui/views/focus/accelerator_handler_aura.cc +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2012 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 "ui/views/focus/accelerator_handler.h" - -namespace views { - -AcceleratorHandler::AcceleratorHandler() { -} - -bool AcceleratorHandler::Dispatch(const base::NativeEvent& event) { -#if defined(OS_WIN) - TranslateMessage(&event); - DispatchMessage(&event); -#endif // defined(OS_WIN) - return true; -} - -#if defined(USE_X11) -bool DispatchXEvent(XEvent* xev) { - return false; -} -#endif // defined(USE_X11) - -} // namespace views diff --git a/chromium/ui/views/focus/accelerator_handler_win.cc b/chromium/ui/views/focus/accelerator_handler_win.cc deleted file mode 100644 index ea82daed717..00000000000 --- a/chromium/ui/views/focus/accelerator_handler_win.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2012 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 "ui/views/focus/accelerator_handler.h" - -#include "ui/events/event.h" -#include "ui/events/keycodes/keyboard_code_conversion_win.h" -#include "ui/events/keycodes/keyboard_codes.h" -#include "ui/views/focus/focus_manager.h" -#include "ui/views/widget/widget.h" - -namespace views { - -AcceleratorHandler::AcceleratorHandler() { -} - -bool AcceleratorHandler::Dispatch(const base::NativeEvent& msg) { - if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) { - Widget* widget = Widget::GetTopLevelWidgetForNativeView(msg.hwnd); - FocusManager* focus_manager = widget ? widget->GetFocusManager() : NULL; - if (focus_manager) { - switch (msg.message) { - case WM_KEYDOWN: - case WM_SYSKEYDOWN: { - ui::KeyEvent event(msg, false); - if (!focus_manager->OnKeyEvent(event)) { - // Record that this key is pressed so we can remember not to - // translate and dispatch the associated WM_KEYUP. - pressed_keys_.insert(msg.wParam); - return true; - } - break; - } - case WM_KEYUP: - case WM_SYSKEYUP: { - std::set<WPARAM>::iterator iter = pressed_keys_.find(msg.wParam); - if (iter != pressed_keys_.end()) { - // Don't translate/dispatch the KEYUP since we have eaten the - // associated KEYDOWN. - pressed_keys_.erase(iter); - return true; - } - break; - } - } - } - } - - TranslateMessage(&msg); - DispatchMessage(&msg); - return true; -} - -} // namespace views diff --git a/chromium/ui/views/focus/focus_manager.cc b/chromium/ui/views/focus/focus_manager.cc index f52712e6234..4808b4422cb 100644 --- a/chromium/ui/views/focus/focus_manager.cc +++ b/chromium/ui/views/focus/focus_manager.cc @@ -11,6 +11,10 @@ #include "base/logging.h" #include "build/build_config.h" #include "ui/base/accelerators/accelerator.h" +#include "ui/base/ime/input_method.h" +#include "ui/base/ime/text_input_client.h" +#include "ui/base/ime/text_input_focus_manager.h" +#include "ui/base/ui_base_switches_util.h" #include "ui/events/event.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/focus/focus_manager_delegate.h" @@ -64,6 +68,7 @@ bool FocusManager::OnKeyEvent(const ui::KeyEvent& event) { modifiers |= ui::EF_ALT_DOWN; ui::Accelerator accelerator(event.key_code(), modifiers); accelerator.set_type(event.type()); + accelerator.set_is_repeat(event.IsRepeat()); if (event.type() == ui::ET_KEY_PRESSED) { // If the focused view wants to process the key event as is, let it be. @@ -75,20 +80,10 @@ bool FocusManager::OnKeyEvent(const ui::KeyEvent& event) { // Note that we don't do focus traversal if the root window is not part of // the active window hierarchy as this would mean we have no focused view // and would focus the first focusable view. -#if defined(OS_WIN) && !defined(USE_AURA) - HWND top_window = widget_->GetNativeView(); - HWND active_window = ::GetActiveWindow(); - if ((active_window == top_window || ::IsChild(active_window, top_window)) && - IsTabTraversalKeyEvent(event)) { - AdvanceFocus(event.IsShiftDown()); - return false; - } -#else if (IsTabTraversalKeyEvent(event)) { AdvanceFocus(event.IsShiftDown()); return false; } -#endif if (arrow_key_traversal_enabled_ && ProcessArrowKeyTraversal(event)) return false; @@ -319,8 +314,13 @@ View* FocusManager::GetNextFocusableView(View* original_starting_view, void FocusManager::SetFocusedViewWithReason( View* view, FocusChangeReason reason) { - if (focused_view_ == view) + if (focused_view_ == view) { + // In the case that the widget lost the focus and gained it back without + // changing the focused view, we have to make the text input client focused. + // TODO(yukishiino): Remove this hack once we fix http://crbug.com/383236 + FocusTextInputClient(focused_view_); return; + } base::AutoReset<bool> auto_changing_focus(&is_changing_focus_, true); // Update the reason for the focus change (since this is checked by @@ -331,14 +331,18 @@ void FocusManager::SetFocusedViewWithReason( View* old_focused_view = focused_view_; focused_view_ = view; - if (old_focused_view) + if (old_focused_view) { old_focused_view->Blur(); + BlurTextInputClient(old_focused_view); + } // Also make |focused_view_| the stored focus view. This way the stored focus // view is remembered if focus changes are requested prior to a show or while // hidden. SetStoredFocusView(focused_view_); - if (focused_view_) + if (focused_view_) { + FocusTextInputClient(focused_view_); focused_view_->Focus(); + } FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_, OnDidChangeFocus(old_focused_view, focused_view_)); @@ -437,6 +441,46 @@ void FocusManager::ClearStoredFocusedView() { SetStoredFocusView(NULL); } +void FocusManager::OnTextInputClientChanged(View* view) { + if (view == focused_view_) + FocusTextInputClient(view); +} + +void FocusManager::FocusTextInputClient(View* view) { + if (!switches::IsTextInputFocusManagerEnabled()) + return; + + // If the widget is not active, do not steal the text input focus. + if (!widget_->IsActive()) + return; + + ui::TextInputClient* text_input_client = + view ? view->GetTextInputClient() : NULL; + ui::TextInputFocusManager::GetInstance()-> + FocusTextInputClient(text_input_client); + ui::InputMethod* input_method = widget_->GetHostInputMethod(); + if (input_method) { + input_method->OnTextInputTypeChanged(text_input_client); + input_method->OnCaretBoundsChanged(text_input_client); + } +} + +void FocusManager::BlurTextInputClient(View* view) { + if (!switches::IsTextInputFocusManagerEnabled()) + return; + + ui::TextInputClient* text_input_client = + view ? view->GetTextInputClient() : NULL; + if (text_input_client && text_input_client->HasCompositionText()) { + text_input_client->ConfirmCompositionText(); + ui::InputMethod* input_method = widget_->GetHostInputMethod(); + if (input_method && input_method->GetTextInputClient() == text_input_client) + input_method->CancelComposition(text_input_client); + } + ui::TextInputFocusManager::GetInstance()-> + BlurTextInputClient(text_input_client); +} + // Find the next (previous if reverse is true) focusable view for the specified // FocusTraversable, starting at the specified view, traversing down the // FocusTraversable hierarchy. diff --git a/chromium/ui/views/focus/focus_manager.h b/chromium/ui/views/focus/focus_manager.h index 7d7c7dc16e0..ebdc2a3d88e 100644 --- a/chromium/ui/views/focus/focus_manager.h +++ b/chromium/ui/views/focus/focus_manager.h @@ -72,8 +72,8 @@ // is FocusTraversable. namespace ui { -class AcceleratorTarget; class AcceleratorManager; +class AcceleratorTarget; class EventHandler; class KeyEvent; } @@ -213,6 +213,15 @@ class VIEWS_EXPORT FocusManager { // Returns true if in the process of changing the focused view. bool is_changing_focus() const { return is_changing_focus_; } + // Changes the text input focus to |view->GetTextInputClient()| iff |view| + // is focused. Views must call this method when their internal + // TextInputClient instance changes. + void OnTextInputClientChanged(View* view); + + // Moves the text input focus into/out from |view|. + void FocusTextInputClient(View* view); + void BlurTextInputClient(View* view); + // Disable shortcut handling. static void set_shortcut_handling_suspended(bool suspended) { shortcut_handling_suspended_ = suspended; diff --git a/chromium/ui/views/focus/focus_manager_test.cc b/chromium/ui/views/focus/focus_manager_test.cc index 528f345ce63..6debc794dff 100644 --- a/chromium/ui/views/focus/focus_manager_test.cc +++ b/chromium/ui/views/focus/focus_manager_test.cc @@ -100,24 +100,6 @@ void FocusManagerTest::SetAccessiblePanes(const std::vector<View*>& panes) { accessible_panes_ = panes; } -#if defined(OS_WIN) && !defined(USE_AURA) -void FocusManagerTest::SimulateActivateWindow() { - SendMessage(GetWidget()->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL); -} - -void FocusManagerTest::SimulateDeactivateWindow() { - SendMessage(GetWidget()->GetNativeWindow(), WM_ACTIVATE, WA_INACTIVE, NULL); -} - -void FocusManagerTest::PostKeyDown(ui::KeyboardCode key_code) { - PostMessage(GetWidget()->GetNativeView(), WM_KEYDOWN, key_code, 0); -} - -void FocusManagerTest::PostKeyUp(ui::KeyboardCode key_code) { - PostMessage(GetWidget()->GetNativeView(), WM_KEYUP, key_code, 0); -} -#endif - //////////////////////////////////////////////////////////////////////////////// // TestFocusChangeListener diff --git a/chromium/ui/views/focus/focus_manager_test.h b/chromium/ui/views/focus/focus_manager_test.h index 4afbf4f7758..e54138673b0 100644 --- a/chromium/ui/views/focus/focus_manager_test.h +++ b/chromium/ui/views/focus/focus_manager_test.h @@ -43,15 +43,6 @@ class FocusManagerTest : public ViewsTestBase, public WidgetDelegate { // For testing FocusManager::RotatePaneFocus(). void SetAccessiblePanes(const std::vector<View*>& panes); -#if defined(OS_WIN) && !defined(USE_AURA) - // Mocks activating/deactivating the window. - void SimulateActivateWindow(); - void SimulateDeactivateWindow(); - - void PostKeyDown(ui::KeyboardCode key_code); - void PostKeyUp(ui::KeyboardCode key_code); -#endif - private: View* contents_view_; FocusChangeListener* focus_change_listener_; diff --git a/chromium/ui/views/focus/focus_manager_unittest.cc b/chromium/ui/views/focus/focus_manager_unittest.cc index fcb82b7f310..3513e2b70a7 100644 --- a/chromium/ui/views/focus/focus_manager_unittest.cc +++ b/chromium/ui/views/focus/focus_manager_unittest.cc @@ -2,38 +2,29 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ui/views/focus/focus_manager.h" + #include <utility> #include <vector> +#include "base/command_line.h" #include "base/strings/utf_string_conversions.h" +#include "ui/aura/client/focus_client.h" +#include "ui/aura/window.h" #include "ui/base/accelerators/accelerator.h" +#include "ui/base/ime/dummy_text_input_client.h" +#include "ui/base/ime/text_input_focus_manager.h" +#include "ui/base/ui_base_switches.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/views/accessible_pane_view.h" #include "ui/views/controls/button/label_button.h" -#include "ui/views/controls/textfield/textfield.h" -#include "ui/views/focus/accelerator_handler.h" #include "ui/views/focus/focus_manager_factory.h" #include "ui/views/focus/focus_manager_test.h" #include "ui/views/focus/widget_focus_manager.h" #include "ui/views/widget/widget.h" -#if defined(USE_AURA) -#include "ui/aura/client/focus_client.h" -#include "ui/aura/window.h" -#endif - namespace views { -void FocusNativeView(gfx::NativeView view) { -#if defined(USE_AURA) - aura::client::GetFocusClient(view)->FocusWindow(view); -#elif defined(OS_WIN) - SetFocus(view); -#else -#error -#endif -} - enum FocusTestEventType { ON_FOCUS = 0, ON_BLUR @@ -67,6 +58,8 @@ class SimpleTestView : public View { private: std::vector<FocusTestEvent>* event_list_; + + DISALLOW_COPY_AND_ASSIGN(SimpleTestView); }; // Tests that the appropriate Focus related methods are called when a View @@ -149,14 +142,14 @@ TEST_F(FocusManagerTest, WidgetFocusChangeListener) { widget_listener.ClearFocusChanges(); gfx::NativeView native_view1 = widget1->GetNativeView(); - FocusNativeView(native_view1); + aura::client::GetFocusClient(native_view1)->FocusWindow(native_view1); ASSERT_EQ(2, static_cast<int>(widget_listener.focus_changes().size())); EXPECT_EQ(native_view1, widget_listener.focus_changes()[0].second); EXPECT_EQ(native_view1, widget_listener.focus_changes()[1].second); widget_listener.ClearFocusChanges(); gfx::NativeView native_view2 = widget2->GetNativeView(); - FocusNativeView(native_view2); + aura::client::GetFocusClient(native_view2)->FocusWindow(native_view2); ASSERT_EQ(2, static_cast<int>(widget_listener.focus_changes().size())); EXPECT_EQ(NativeViewPair(native_view1, native_view2), widget_listener.focus_changes()[0]); @@ -164,26 +157,6 @@ TEST_F(FocusManagerTest, WidgetFocusChangeListener) { widget_listener.focus_changes()[1]); } -#if !defined(USE_AURA) -class TestTextfield : public Textfield { - public: - TestTextfield() {} - virtual gfx::NativeView TestGetNativeControlView() { - return native_wrapper_->GetTestingHandle(); - } -}; - -// Tests that NativeControls do set the focused View appropriately on the -// FocusManager. -TEST_F(FocusManagerTest, DISABLED_FocusNativeControls) { - TestTextfield* textfield = new TestTextfield(); - GetContentsView()->AddChildView(textfield); - // Simulate the native view getting the native focus (such as by user click). - FocusNativeView(textfield->TestGetNativeControlView()); - EXPECT_EQ(textfield, GetFocusManager()->GetFocusedView()); -} -#endif - // Counts accelerator calls. class TestAcceleratorTarget : public ui::AcceleratorTarget { public: @@ -537,10 +510,11 @@ class FocusManagerDtorTest : public FocusManagerTest { class LabelButtonDtorTracked : public LabelButton { public: - LabelButtonDtorTracked(const string16& text, DtorTrackVector* dtor_tracker) + LabelButtonDtorTracked(const base::string16& text, + DtorTrackVector* dtor_tracker) : LabelButton(NULL, text), dtor_tracker_(dtor_tracker) { - SetStyle(STYLE_NATIVE_TEXTBUTTON); + SetStyle(STYLE_BUTTON); }; virtual ~LabelButtonDtorTracked() { dtor_tracker_->push_back("LabelButtonDtorTracked"); @@ -586,25 +560,6 @@ class FocusManagerDtorTest : public FocusManagerTest { DtorTrackVector dtor_tracker_; }; -#if !defined(USE_AURA) -TEST_F(FocusManagerDtorTest, FocusManagerDestructedLast) { - // Setup views hierarchy. - GetContentsView()->AddChildView(new TestTextfield()); - GetContentsView()->AddChildView(new LabelButtonDtorTracked( - ASCIIToUTF16("button"), &dtor_tracker_)); - - // Close the window. - GetWidget()->Close(); - RunPendingMessages(); - - // Test window, button and focus manager should all be destructed. - ASSERT_EQ(3, static_cast<int>(dtor_tracker_.size())); - - // Focus manager should be the last one to destruct. - ASSERT_STREQ("FocusManagerDtorTracked", dtor_tracker_[2].c_str()); -} -#endif - namespace { class FocusInAboutToRequestFocusFromTabTraversalView : public View { @@ -819,16 +774,72 @@ TEST_F(FocusManagerTest, StoreFocusedView) { View view; GetFocusManager()->SetFocusedView(&view); GetFocusManager()->StoreFocusedView(false); + EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView()); EXPECT_TRUE(GetFocusManager()->RestoreFocusedView()); EXPECT_EQ(&view, GetFocusManager()->GetStoredFocusView()); // Repeat with |true|. GetFocusManager()->SetFocusedView(&view); GetFocusManager()->StoreFocusedView(true); + EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView()); EXPECT_TRUE(GetFocusManager()->RestoreFocusedView()); EXPECT_EQ(&view, GetFocusManager()->GetStoredFocusView()); } +class TextInputTestView : public View { + public: + TextInputTestView() {} + + virtual ui::TextInputClient* GetTextInputClient() OVERRIDE { + return &text_input_client_; + } + + private: + ui::DummyTextInputClient text_input_client_; + + DISALLOW_COPY_AND_ASSIGN(TextInputTestView); +}; + +TEST_F(FocusManagerTest, TextInputClient) { + base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); + cmd_line->AppendSwitch(switches::kEnableTextInputFocusManager); + + View* view = new TextInputTestView; + ui::TextInputClient* text_input_client = view->GetTextInputClient(); + view->SetFocusable(true); + GetContentsView()->AddChildView(view); + ui::TextInputFocusManager* text_input_focus_manager = + ui::TextInputFocusManager::GetInstance(); + + GetFocusManager()->SetFocusedView(view); + EXPECT_EQ(view, GetFocusManager()->GetFocusedView()); + EXPECT_EQ(text_input_client, + text_input_focus_manager->GetFocusedTextInputClient()); + GetFocusManager()->StoreFocusedView(false); + EXPECT_TRUE(GetFocusManager()->RestoreFocusedView()); + EXPECT_EQ(text_input_client, + text_input_focus_manager->GetFocusedTextInputClient()); + + // Repeat with |true|. + GetFocusManager()->SetFocusedView(view); + EXPECT_EQ(view, GetFocusManager()->GetFocusedView()); + EXPECT_EQ(text_input_client, + text_input_focus_manager->GetFocusedTextInputClient()); + GetFocusManager()->StoreFocusedView(true); + EXPECT_TRUE(GetFocusManager()->RestoreFocusedView()); + EXPECT_EQ(text_input_client, + text_input_focus_manager->GetFocusedTextInputClient()); + + // Focus the view twice in a row. + GetFocusManager()->SetFocusedView(view); + EXPECT_EQ(text_input_client, + text_input_focus_manager->GetFocusedTextInputClient()); + ui::TextInputFocusManager::GetInstance()->FocusTextInputClient(NULL); + GetFocusManager()->SetFocusedView(view); + EXPECT_EQ(text_input_client, + text_input_focus_manager->GetFocusedTextInputClient()); +} + namespace { // Trivial WidgetDelegate implementation that allows setting return value of diff --git a/chromium/ui/views/focus/focus_manager_unittest_win.cc b/chromium/ui/views/focus/focus_manager_unittest_win.cc deleted file mode 100644 index 267a8b78df3..00000000000 --- a/chromium/ui/views/focus/focus_manager_unittest_win.cc +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright (c) 2012 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 "ui/views/focus/focus_manager.h" - -#include "base/memory/scoped_ptr.h" -#include "base/run_loop.h" -#include "base/strings/utf_string_conversions.h" -#include "ui/events/event.h" -#include "ui/views/controls/button/label_button.h" -#include "ui/views/focus/accelerator_handler.h" -#include "ui/views/focus/focus_manager_test.h" -#include "ui/views/widget/widget.h" - -namespace views { - -namespace { - -class MessageTrackingView : public View { - public: - MessageTrackingView() : accelerator_pressed_(false) { - } - - void Reset() { - accelerator_pressed_ = false; - keys_pressed_.clear(); - keys_released_.clear(); - } - - const std::vector<ui::KeyboardCode>& keys_pressed() const { - return keys_pressed_; - } - - const std::vector<ui::KeyboardCode>& keys_released() const { - return keys_released_; - } - - bool accelerator_pressed() const { - return accelerator_pressed_; - } - - // Overridden from View: - virtual bool OnKeyPressed(const ui::KeyEvent& e) OVERRIDE { - keys_pressed_.push_back(e.key_code()); - return true; - } - virtual bool OnKeyReleased(const ui::KeyEvent& e) OVERRIDE { - keys_released_.push_back(e.key_code()); - return true; - } - virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE { - accelerator_pressed_ = true; - return true; - } - - private: - bool accelerator_pressed_; - std::vector<ui::KeyboardCode> keys_pressed_; - std::vector<ui::KeyboardCode> keys_released_; - - DISALLOW_COPY_AND_ASSIGN(MessageTrackingView); -}; - -} // namespace - -// Test that when activating/deactivating the top window, the focus is stored/ -// restored properly. -TEST_F(FocusManagerTest, FocusStoreRestore) { - // Simulate an activate, otherwise the deactivate isn't going to do anything. - SimulateActivateWindow(); - - LabelButton* button = new LabelButton(NULL, ASCIIToUTF16("Press me")); - button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON); - View* view = new View(); - view->SetFocusable(true); - - GetContentsView()->AddChildView(button); - button->SetBounds(10, 10, 200, 30); - GetContentsView()->AddChildView(view); - RunPendingMessages(); - - TestFocusChangeListener listener; - AddFocusChangeListener(&listener); - - view->RequestFocus(); - RunPendingMessages(); - - // Required for VS2010: http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair - views::View* null_view = NULL; - - // Deacivate the window, it should store its focus. - SimulateDeactivateWindow(); - EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view)); - EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(view, null_view)); - listener.ClearFocusChanges(); - - // Reactivate, focus should come-back to the previously focused view. - SimulateActivateWindow(); - EXPECT_EQ(view, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view)); - listener.ClearFocusChanges(); - - // Same test with a NativeControl. - button->RequestFocus(); - SimulateDeactivateWindow(); - EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view, button)); - EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(button, null_view)); - listener.ClearFocusChanges(); - - SimulateActivateWindow(); - EXPECT_EQ(button, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, button)); - listener.ClearFocusChanges(); - - /* - // Now test that while the window is inactive we can change the focused view - // (we do that in several places). - SimulateDeactivateWindow(); - // TODO: would have to mock the window being inactive (with a TestWidgetWin - // that would return false on IsActive()). - GetFocusManager()->SetFocusedView(view); - ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL); - - EXPECT_EQ(view, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size())); - EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(button, null_view)); - EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(null_view, view)); - */ -} - -// Test that the focus manager is created successfully for the first view -// window parented to a native dialog. -TEST_F(FocusManagerTest, CreationForNativeRoot) { - // Create a window class. - WNDCLASSEX class_ex; - memset(&class_ex, 0, sizeof(class_ex)); - class_ex.cbSize = sizeof(WNDCLASSEX); - class_ex.lpfnWndProc = &DefWindowProc; - class_ex.lpszClassName = L"TestWindow"; - ATOM atom = RegisterClassEx(&class_ex); - ASSERT_TRUE(atom); - - // Create a native dialog window. - HWND hwnd = CreateWindowEx(0, class_ex.lpszClassName, NULL, - WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, - NULL, NULL, NULL, NULL); - ASSERT_TRUE(hwnd); - - // Create a view window parented to native dialog. - scoped_ptr<Widget> widget1(new Widget); - Widget::InitParams params(Widget::InitParams::TYPE_CONTROL); - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.parent = hwnd; - params.bounds = gfx::Rect(0, 0, 100, 100); - params.top_level = true; // This is top level in views hierarchy. - widget1->Init(params); - - // Get the focus manager directly from the first window. Should exist - // because the first window is the root widget. - views::FocusManager* focus_manager1 = widget1->GetFocusManager(); - EXPECT_TRUE(focus_manager1); - - // Create another view window parented to the first view window. - scoped_ptr<Widget> widget2(new Widget); - params.parent = widget1->GetNativeView(); - params.top_level = false; // This is child widget. - widget2->Init(params); - - // Access the shared focus manager directly from the second window. - views::FocusManager* focus_manager2 = widget2->GetFocusManager(); - EXPECT_EQ(focus_manager2, focus_manager1); - - // Access the shared focus manager indirectly from the first window handle. - gfx::NativeWindow native_window = widget1->GetNativeWindow(); - views::Widget* widget = - views::Widget::GetWidgetForNativeWindow(native_window); - EXPECT_EQ(widget->GetFocusManager(), focus_manager1); - - // Access the shared focus manager indirectly from the second window handle. - native_window = widget2->GetNativeWindow(); - widget = views::Widget::GetWidgetForNativeWindow(native_window); - EXPECT_EQ(widget->GetFocusManager(), focus_manager1); - - // Access the shared focus manager indirectly from the first view handle. - gfx::NativeView native_view = widget1->GetNativeView(); - widget = views::Widget::GetTopLevelWidgetForNativeView(native_view); - EXPECT_EQ(widget->GetFocusManager(), focus_manager1); - - // Access the shared focus manager indirectly from the second view handle. - native_view = widget2->GetNativeView(); - widget = views::Widget::GetTopLevelWidgetForNativeView(native_view); - EXPECT_EQ(widget->GetFocusManager(), focus_manager1); - - DestroyWindow(hwnd); -} - -// Tests that the keyup messages are eaten for accelerators. -// Windows-only, Windows is the only platform that handles accelerators in -// AcceleratorHandler. NativeWidgetAura::OnKeyEvent handles them in other -// configurations. -TEST_F(FocusManagerTest, IgnoreKeyupForAccelerators) { - FocusManager* focus_manager = GetFocusManager(); - MessageTrackingView* mtv = new MessageTrackingView(); - mtv->AddAccelerator(ui::Accelerator(ui::VKEY_0, ui::EF_NONE)); - mtv->AddAccelerator(ui::Accelerator(ui::VKEY_1, ui::EF_NONE)); - GetContentsView()->AddChildView(mtv); - focus_manager->SetFocusedView(mtv); - - // First send a non-accelerator key sequence. - PostKeyDown(ui::VKEY_9); - PostKeyUp(ui::VKEY_9); - AcceleratorHandler accelerator_handler; - scoped_ptr<base::RunLoop> run_loop(new base::RunLoop(&accelerator_handler)); - run_loop->RunUntilIdle(); - // Make sure we get a key-up and key-down. - ASSERT_EQ(1U, mtv->keys_pressed().size()); - EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]); - ASSERT_EQ(1U, mtv->keys_released().size()); - EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]); - EXPECT_FALSE(mtv->accelerator_pressed()); - mtv->Reset(); - - // Same thing with repeat and more than one key at once. - PostKeyDown(ui::VKEY_9); - PostKeyDown(ui::VKEY_9); - PostKeyDown(ui::VKEY_8); - PostKeyDown(ui::VKEY_9); - PostKeyDown(ui::VKEY_7); - PostKeyUp(ui::VKEY_9); - PostKeyUp(ui::VKEY_7); - PostKeyUp(ui::VKEY_8); - run_loop.reset(new base::RunLoop(&accelerator_handler)); - run_loop->RunUntilIdle(); - // Make sure we get a key-up and key-down. - ASSERT_EQ(5U, mtv->keys_pressed().size()); - EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]); - EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[1]); - EXPECT_EQ(ui::VKEY_8, mtv->keys_pressed()[2]); - EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[3]); - EXPECT_EQ(ui::VKEY_7, mtv->keys_pressed()[4]); - ASSERT_EQ(3U, mtv->keys_released().size()); - EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]); - EXPECT_EQ(ui::VKEY_7, mtv->keys_released()[1]); - EXPECT_EQ(ui::VKEY_8, mtv->keys_released()[2]); - EXPECT_FALSE(mtv->accelerator_pressed()); - mtv->Reset(); - - // Now send an accelerator key sequence. - PostKeyDown(ui::VKEY_0); - PostKeyUp(ui::VKEY_0); - run_loop.reset(new base::RunLoop(&accelerator_handler)); - run_loop->RunUntilIdle(); - EXPECT_TRUE(mtv->keys_pressed().empty()); - EXPECT_TRUE(mtv->keys_released().empty()); - EXPECT_TRUE(mtv->accelerator_pressed()); - mtv->Reset(); - - // Same thing with repeat and more than one key at once. - PostKeyDown(ui::VKEY_0); - PostKeyDown(ui::VKEY_1); - PostKeyDown(ui::VKEY_1); - PostKeyDown(ui::VKEY_0); - PostKeyDown(ui::VKEY_0); - PostKeyUp(ui::VKEY_1); - PostKeyUp(ui::VKEY_0); - run_loop.reset(new base::RunLoop(&accelerator_handler)); - run_loop->RunUntilIdle(); - EXPECT_TRUE(mtv->keys_pressed().empty()); - EXPECT_TRUE(mtv->keys_released().empty()); - EXPECT_TRUE(mtv->accelerator_pressed()); - mtv->Reset(); -} - -} // namespace views diff --git a/chromium/ui/views/focus/focus_traversal_unittest.cc b/chromium/ui/views/focus/focus_traversal_unittest.cc index c3e8159a5fa..6f0ba34ecb2 100644 --- a/chromium/ui/views/focus/focus_traversal_unittest.cc +++ b/chromium/ui/views/focus/focus_traversal_unittest.cc @@ -20,11 +20,12 @@ #include "ui/views/controls/scroll_view.h" #include "ui/views/controls/tabbed_pane/tabbed_pane.h" #include "ui/views/controls/textfield/textfield.h" -#include "ui/views/focus/accelerator_handler.h" #include "ui/views/focus/focus_manager_test.h" #include "ui/views/widget/root_view.h" #include "ui/views/widget/widget.h" +using base::ASCIIToUTF16; + namespace views { namespace { @@ -89,7 +90,7 @@ class DummyComboboxModel : public ui::ComboboxModel { public: // Overridden from ui::ComboboxModel: virtual int GetItemCount() const OVERRIDE { return 10; } - virtual string16 GetItemAt(int index) OVERRIDE { + virtual base::string16 GetItemAt(int index) OVERRIDE { return ASCIIToUTF16("Item ") + base::IntToString16(index); } }; @@ -157,11 +158,7 @@ class BorderView : public NativeViewHost { if (!widget_) { widget_ = new Widget; Widget::InitParams params(Widget::InitParams::TYPE_CONTROL); -#if defined(OS_WIN) || defined(USE_AURA) params.parent = details.parent->GetWidget()->GetNativeView(); -#else - NOTREACHED(); -#endif widget_->Init(params); widget_->SetFocusTraversableParentView(this); widget_->SetContentsView(child_); @@ -294,7 +291,7 @@ void FocusTraversalTest::InitContentView() { cb->set_id(kTopCheckBoxID); left_container_ = new PaneView(); - left_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK)); + left_container_->SetBorder(Border::CreateSolidBorder(1, SK_ColorBLACK)); left_container_->set_background( Background::CreateSolidBackground(240, 240, 240)); left_container_->set_id(kLeftContainerID); @@ -361,7 +358,7 @@ void FocusTraversalTest::InitContentView() { y += label_height + gap_between_labels; LabelButton* button = new LabelButton(NULL, ASCIIToUTF16("Click me")); - button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON); + button->SetStyle(Button::STYLE_BUTTON); button->SetBounds(label_x, y + 10, 80, 30); button->set_id(kFruitButtonID); left_container_->AddChildView(button); @@ -379,7 +376,7 @@ void FocusTraversalTest::InitContentView() { left_container_->AddChildView(combobox); right_container_ = new PaneView(); - right_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK)); + right_container_->SetBorder(Border::CreateSolidBorder(1, SK_ColorBLACK)); right_container_->set_background( Background::CreateSolidBackground(240, 240, 240)); right_container_->set_id(kRightContainerID); @@ -410,7 +407,7 @@ void FocusTraversalTest::InitContentView() { y += radio_button_height + gap_between_radio_buttons; View* inner_container = new View(); - inner_container->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK)); + inner_container->SetBorder(Border::CreateSolidBorder(1, SK_ColorBLACK)); inner_container->set_background( Background::CreateSolidBackground(230, 230, 230)); inner_container->set_id(kInnerContainerID); @@ -457,7 +454,7 @@ void FocusTraversalTest::InitContentView() { y = 250; int width = 60; button = new LabelButton(NULL, ASCIIToUTF16("OK")); - button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON); + button->SetStyle(Button::STYLE_BUTTON); button->set_id(kOKButtonID); button->SetIsDefault(true); @@ -465,13 +462,13 @@ void FocusTraversalTest::InitContentView() { button->SetBounds(150, y, width, 30); button = new LabelButton(NULL, ASCIIToUTF16("Cancel")); - button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON); + button->SetStyle(Button::STYLE_BUTTON); button->set_id(kCancelButtonID); GetContentsView()->AddChildView(button); button->SetBounds(220, y, width, 30); button = new LabelButton(NULL, ASCIIToUTF16("Help")); - button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON); + button->SetStyle(Button::STYLE_BUTTON); button->set_id(kHelpButtonID); GetContentsView()->AddChildView(button); button->SetBounds(290, y, width, 30); @@ -525,7 +522,7 @@ void FocusTraversalTest::InitContentView() { text_field->set_id(kSearchTextfieldID); button = new LabelButton(NULL, ASCIIToUTF16("Search")); - button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON); + button->SetStyle(Button::STYLE_BUTTON); contents->AddChildView(button); button->SetBounds(112, 5, 60, 30); button->set_id(kSearchButtonID); @@ -549,12 +546,12 @@ void FocusTraversalTest::InitContentView() { contents->set_background(Background::CreateSolidBackground(SK_ColorBLUE)); contents->set_id(kThumbnailContainerID); button = new LabelButton(NULL, ASCIIToUTF16("Star")); - button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON); + button->SetStyle(Button::STYLE_BUTTON); contents->AddChildView(button); button->SetBounds(5, 5, 50, 30); button->set_id(kThumbnailStarID); button = new LabelButton(NULL, ASCIIToUTF16("SuperStar")); - button->SetStyle(Button::STYLE_NATIVE_TEXTBUTTON); + button->SetStyle(Button::STYLE_BUTTON); contents->AddChildView(button); button->SetBounds(60, 5, 100, 30); button->set_id(kThumbnailSuperStarID); @@ -579,9 +576,6 @@ TEST_F(FocusTraversalTest, NormalTraversal) { kSearchTextfieldID, kSearchButtonID, kHelpLinkID, kThumbnailContainerID, kThumbnailStarID, kThumbnailSuperStarID }; - // Uncomment the following line to manually test the UI of this test. - // base::RunLoop(new AcceleratorHandler()).Run(); - // Let's traverse the whole focus hierarchy (several times, to make sure it // loops OK). GetFocusManager()->ClearFocus(); @@ -631,9 +625,6 @@ TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) { v->SetEnabled(false); } - // Uncomment the following line to manually test the UI of this test. - // base::RunLoop(new AcceleratorHandler()).Run(); - View* focused_view; // Let's do one traversal (several times, to make sure it loops ok). GetFocusManager()->ClearFocus(); @@ -682,9 +673,6 @@ TEST_F(FocusTraversalTest, TraversalWithInvisibleViews) { v->SetVisible(false); } - // Uncomment the following line to manually test the UI of this test. - // base::RunLoop(new AcceleratorHandler()).Run(); - View* focused_view; // Let's do one traversal (several times, to make sure it loops ok). GetFocusManager()->ClearFocus(); diff --git a/chromium/ui/views/focus/view_storage.h b/chromium/ui/views/focus/view_storage.h index 629aec1cbb9..5e36f3c5e9b 100644 --- a/chromium/ui/views/focus/view_storage.h +++ b/chromium/ui/views/focus/view_storage.h @@ -17,7 +17,7 @@ template <typename T> struct DefaultSingletonTraits; // used for example in the FocusManager to store/restore focused views when the // main window becomes active/inactive. // It automatically removes a view from the storage if the view is removed from -// the tree hierarchy. +// the tree hierarchy or when the view is destroyed, which ever comes first. // // To use it, you first need to create a view storage id that can then be used // to store/retrieve views. |