diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-02 18:31:52 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-02 18:31:52 +0000 |
commit | cc2c4eb51c6fc7c688151df5fc28e28d031cf3e3 (patch) | |
tree | cf110bb3cfe4fb2f19dfca7fd3c5d808cee2c8d9 /ui/views | |
parent | 832c698f26e0d26a05a699720b5ed214b7463c74 (diff) | |
download | chromium_src-cc2c4eb51c6fc7c688151df5fc28e28d031cf3e3.zip chromium_src-cc2c4eb51c6fc7c688151df5fc28e28d031cf3e3.tar.gz chromium_src-cc2c4eb51c6fc7c688151df5fc28e28d031cf3e3.tar.bz2 |
Begin to integrate Focus Manager. Add Windows accelerator handler implementation (commented out now due to lack of focus manager). Add some utilities to NativeWidget for obtaining NativeWidget from a NativeView.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/6286035
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73479 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/views')
-rw-r--r-- | ui/views/focus/accelerator_handler.h | 71 | ||||
-rw-r--r-- | ui/views/focus/accelerator_handler_win.cc | 60 | ||||
-rw-r--r-- | ui/views/views.gyp | 3 | ||||
-rw-r--r-- | ui/views/widget/native_widget.h | 12 | ||||
-rw-r--r-- | ui/views/widget/native_widget_win.cc | 43 | ||||
-rw-r--r-- | ui/views/widget/native_widget_win_unittest.cc | 92 | ||||
-rw-r--r-- | ui/views/widget/widget.cc | 3 | ||||
-rw-r--r-- | ui/views/widget/widget.h | 2 |
8 files changed, 284 insertions, 2 deletions
diff --git a/ui/views/focus/accelerator_handler.h b/ui/views/focus/accelerator_handler.h new file mode 100644 index 0000000..3f129ba --- /dev/null +++ b/ui/views/focus/accelerator_handler.h @@ -0,0 +1,71 @@ +// 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 UI_VIEWS_FOCUS_ACCELERATOR_HANDLER_H_ +#define UI_VIEWS_FOCUS_ACCELERATOR_HANDLER_H_ +#pragma once + +#include "build/build_config.h" + +#if defined(OS_LINUX) +#include <gdk/gdk.h> +#endif + +#include <set> +#include <vector> + +#include "base/message_loop.h" + +namespace ui { + +#if defined(TOUCH_UI) +// Dispatch an XEvent to the RootView. Return true if the event was dispatched +// and handled, false otherwise. +bool DispatchXEvent(XEvent* xevent); + +#if defined(HAVE_XINPUT2) +// Keep a list of touch devices so that it is possible to determine if a pointer +// event is a touch-event or a mouse-event. +void SetTouchDeviceList(std::vector<unsigned int>& devices); +#endif // HAVE_XINPUT2 +#endif // TOUCH_UI + +//////////////////////////////////////////////////////////////////////////////// +// AcceleratorHandler class +// +// An object that pre-screens all UI messages for potential accelerators. +// Registered accelerators are processed regardless of focus within a given +// Widget or Window. +// +// This processing is done at the Dispatcher level rather than on the Widget +// because of the global nature of this processing, and the fact that not all +// controls within a window need to be Widgets - some are native controls from +// the underlying toolkit wrapped by NativeViewHost. +// +class AcceleratorHandler : public MessageLoopForUI::Dispatcher { + public: + AcceleratorHandler(); + // Dispatcher method. This returns true if an accelerator was processed by the + // focus manager +#if defined(OS_WIN) + virtual bool Dispatch(const MSG& msg); +#else + virtual bool Dispatch(GdkEvent* event); +#if defined(TOUCH_UI) + virtual MessagePumpGlibXDispatcher::DispatchStatus Dispatch(XEvent* xev); +#endif +#endif + + 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 ui + +#endif // UI_VIEWS_FOCUS_ACCELERATOR_HANDLER_H_ diff --git a/ui/views/focus/accelerator_handler_win.cc b/ui/views/focus/accelerator_handler_win.cc new file mode 100644 index 0000000..02bd097 --- /dev/null +++ b/ui/views/focus/accelerator_handler_win.cc @@ -0,0 +1,60 @@ +// 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 "ui/views/focus/accelerator_handler.h" + +#include "ui/base/keycodes/keyboard_codes.h" +#include "ui/base/keycodes/keyboard_code_conversion_win.h" +#include "ui/views/events/event.h" +//#include "ui/views/focus/focus_manager.h" + +namespace ui { + +AcceleratorHandler::AcceleratorHandler() { +} + +bool AcceleratorHandler::Dispatch(const MSG& msg) { + bool process_message = true; + + if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) { + /* + FocusManager* focus_manager = + FocusManager::GetFocusManagerForNativeView(msg.hwnd); + if (focus_manager) { + switch (msg.message) { + case WM_KEYDOWN: + case WM_SYSKEYDOWN: { + process_message = focus_manager->OnKeyEvent(KeyEvent(msg)); + if (!process_message) { + // Record that this key is pressed so we can remember not to + // translate and dispatch the associated WM_KEYUP. + pressed_keys_.insert(msg.wParam); + } + 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; + } + } + } + */ + } + + if (process_message) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + return true; +} + +} // namespace ui diff --git a/ui/views/views.gyp b/ui/views/views.gyp index fa9ad5a..63e00ae 100644 --- a/ui/views/views.gyp +++ b/ui/views/views.gyp @@ -56,6 +56,8 @@ 'events/event.cc', 'events/event.h', 'events/event_win.cc', + 'focus/accelerator_handler.h', + 'focus/accelerator_handler_win.cc', 'layout/fill_layout.cc', 'layout/fill_layout.h', 'layout/layout_manager.cc', @@ -120,6 +122,7 @@ 'rendering/border_unittest.cc', 'run_all_unittests.cc', 'view_unittest.cc', + 'widget/native_widget_win_unittest.cc', 'widget/widget_unittest.cc', ], 'include_dirs': [ diff --git a/ui/views/widget/native_widget.h b/ui/views/widget/native_widget.h index f8508a2..6b9add7 100644 --- a/ui/views/widget/native_widget.h +++ b/ui/views/widget/native_widget.h @@ -32,6 +32,18 @@ class NativeWidget { static NativeWidget* CreateNativeWidget( internal::NativeWidgetListener* listener); + // Retrieves the NativeWidget implementation associated with the given + // NativeView or Window, or NULL if the supplied handle has no associated + // NativeView. + static NativeWidget* GetNativeWidgetForNativeView( + gfx::NativeView native_view); + static NativeWidget* GetNativeWidgetForNativeWindow( + gfx::NativeWindow native_window); + + // Retrieves the top NativeWidget in the hierarchy containing the given + // NativeView, or NULL if there is no NativeWidget that contains it. + static NativeWidget* GetTopLevelNativeWidget(gfx::NativeView native_view); + // See Widget for documentation and notes. virtual void InitWithNativeViewParent(gfx::NativeView parent, const gfx::Rect& bounds) = 0; diff --git a/ui/views/widget/native_widget_win.cc b/ui/views/widget/native_widget_win.cc index c5bd930..e435592 100644 --- a/ui/views/widget/native_widget_win.cc +++ b/ui/views/widget/native_widget_win.cc @@ -10,6 +10,7 @@ #include "gfx/native_theme_win.h" #include "ui/base/system_monitor/system_monitor.h" #include "ui/base/view_prop.h" +#include "ui/base/win/hwnd_util.h" #include "ui/views/view.h" #include "ui/views/widget/native_widget_listener.h" #include "ui/views/widget/widget.h" @@ -265,6 +266,7 @@ void NativeWidgetWin::OnCommand(UINT notification_code, int command_id, } LRESULT NativeWidgetWin::OnCreate(CREATESTRUCT* create_struct) { + SetNativeWindowProperty(kNativeWidgetKey, this); MessageLoopForUI::current()->AddObserver(this); return 0; } @@ -623,4 +625,45 @@ NativeWidget* NativeWidget::CreateNativeWidget( return new internal::NativeWidgetWin(listener); } +// static +NativeWidget* NativeWidget::GetNativeWidgetForNativeView( + gfx::NativeView native_view) { + if (!WindowImpl::IsWindowImpl(native_view)) + return NULL; + return reinterpret_cast<internal::NativeWidgetWin*>( + ViewProp::GetValue(native_view, internal::kNativeWidgetKey)); +} + +// static +NativeWidget* NativeWidget::GetNativeWidgetForNativeWindow( + gfx::NativeWindow native_window) { + return GetNativeWidgetForNativeView(native_window); +} + +// static +NativeWidget* NativeWidget::GetTopLevelNativeWidget( + gfx::NativeView native_view) { + // First, check if the top-level window is a Widget. + HWND root = ::GetAncestor(native_view, GA_ROOT); + if (!root) + return NULL; + + NativeWidget* widget = GetNativeWidgetForNativeView(root); + if (widget) + return widget; + + // Second, try to locate the last Widget window in the parent hierarchy. + HWND parent_hwnd = native_view; + NativeWidget* parent_widget; + do { + parent_widget = GetNativeWidgetForNativeView(parent_hwnd); + if (parent_widget) { + widget = parent_widget; + parent_hwnd = ::GetAncestor(parent_hwnd, GA_PARENT); + } + } while (parent_hwnd != NULL && parent_widget != NULL); + + return widget; +} + } // namespace ui diff --git a/ui/views/widget/native_widget_win_unittest.cc b/ui/views/widget/native_widget_win_unittest.cc new file mode 100644 index 0000000..b5cdf04 --- /dev/null +++ b/ui/views/widget/native_widget_win_unittest.cc @@ -0,0 +1,92 @@ +// 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 "testing/gtest/include/gtest/gtest.h" +#include "ui/base/win/window_impl.h" +#include "ui/views/view.h" +#include "ui/views/widget/native_widget.h" +#include "ui/views/widget/widget.h" + +namespace ui { + +class NativeWidgetTest : public testing::Test { + public: + NativeWidgetTest() {} + virtual ~NativeWidgetTest() {} + + Widget* CreateWidget() const { + Widget* widget = new Widget(new View); + widget->set_delete_on_destroy(false); + widget->InitWithNativeViewParent(NULL, gfx::Rect(10, 10, 200, 200)); + return widget; + } + + private: + DISALLOW_COPY_AND_ASSIGN(NativeWidgetTest); +}; + +class TestWindowImpl : public WindowImpl { + public: + TestWindowImpl() {} + virtual ~TestWindowImpl() {} + + virtual BOOL ProcessWindowMessage(HWND window, + UINT message, + WPARAM w_param, + LPARAM l_param, + LRESULT& result, + DWORD msg_mad_id = 0) { + return FALSE; + } + + private: + DISALLOW_COPY_AND_ASSIGN(TestWindowImpl); +}; + +TEST_F(NativeWidgetTest, CreateNativeWidget) { + scoped_ptr<Widget> widget(CreateWidget()); + EXPECT_TRUE(widget->native_widget()->GetNativeView() != NULL); +} + +TEST_F(NativeWidgetTest, GetNativeWidgetForNativeView) { + scoped_ptr<Widget> widget(CreateWidget()); + NativeWidget* a = widget->native_widget(); + HWND nv = widget->native_widget()->GetNativeView(); + NativeWidget* b = NativeWidget::GetNativeWidgetForNativeView(nv); + EXPECT_EQ(a, b); +} + +// |widget| has the toplevel NativeWidget. +TEST_F(NativeWidgetTest, GetTopLevelNativeWidget1) { + scoped_ptr<Widget> widget(CreateWidget()); + EXPECT_EQ(widget->native_widget(), + NativeWidget::GetTopLevelNativeWidget( + widget->native_widget()->GetNativeView())); +} + +// |toplevel_widget| has the toplevel NativeWidget. +TEST_F(NativeWidgetTest, GetTopLevelNativeWidget2) { + scoped_ptr<Widget> child_widget(CreateWidget()); + scoped_ptr<Widget> toplevel_widget(CreateWidget()); + SetParent(child_widget->native_widget()->GetNativeView(), + toplevel_widget->native_widget()->GetNativeView()); + EXPECT_EQ(toplevel_widget->native_widget(), + NativeWidget::GetTopLevelNativeWidget( + child_widget->native_widget()->GetNativeView())); +} + +// |child_widget| has the toplevel NativeWidget. +TEST_F(NativeWidgetTest, GetTopLevelNativeWidget3) { + scoped_ptr<Widget> child_widget(CreateWidget()); + + TestWindowImpl toplevel; + toplevel.Init(NULL, gfx::Rect(10, 10, 100, 100)); + + SetParent(child_widget->native_widget()->GetNativeView(), toplevel.hwnd()); + EXPECT_EQ(child_widget->native_widget(), + NativeWidget::GetTopLevelNativeWidget( + child_widget->native_widget()->GetNativeView())); +} + +} // namespace ui diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index 36af0b1..ba2daa6 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc @@ -47,7 +47,8 @@ Widget::Widget(View* contents_view) root_view_(new internal::RootView(this, contents_view))), is_mouse_button_pressed_(false), last_mouse_event_was_move_(false), - ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)) { + ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)), + delete_on_destroy_(true) { } Widget::~Widget() { diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index 9a68eab..b97e7933 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h @@ -41,7 +41,7 @@ class Widget : public internal::NativeWidgetListener { explicit Widget(View* contents_view); virtual ~Widget(); - bool set_delete_on_destroy(bool delete_on_destroy) { + void set_delete_on_destroy(bool delete_on_destroy) { delete_on_destroy_ = delete_on_destroy; } |