summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authorjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-31 22:53:37 +0000
committerjcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-31 22:53:37 +0000
commit148d105e27c7c8c2cda0c81292690b9edafcae1f (patch)
treee278052fc84a6e5399aec5bd0d423162aecb6d16 /views
parentdc75d4823b598a9b9b313728a06f6b47d6a73929 (diff)
downloadchromium_src-148d105e27c7c8c2cda0c81292690b9edafcae1f.zip
chromium_src-148d105e27c7c8c2cda0c81292690b9edafcae1f.tar.gz
chromium_src-148d105e27c7c8c2cda0c81292690b9edafcae1f.tar.bz2
This CL adds accelerators to the Linux toolkit views.
The MessageLoop had to be modified to support Dispatchers on Linux. BUG=None TEST=On Windows and Linux, make sure the accelerators still work as expected. On Linux toolkit views, build and run the unit-tests. Review URL: http://codereview.chromium.org/159046 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22210 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r--views/event.h2
-rw-r--r--views/event_gtk.cc8
-rw-r--r--views/focus/accelerator_handler.h40
-rw-r--r--views/focus/accelerator_handler_gtk.cc61
-rw-r--r--views/focus/accelerator_handler_win.cc (renamed from views/widget/accelerator_handler.cc)17
-rw-r--r--views/focus/focus_manager.cc74
-rw-r--r--views/focus/focus_manager.h14
-rw-r--r--views/focus/focus_manager_unittest.cc185
-rw-r--r--views/view.cc3
-rw-r--r--views/view_unittest.cc4
-rw-r--r--views/views.gyp8
-rw-r--r--views/widget/accelerator_handler.h30
-rw-r--r--views/widget/widget_gtk.cc13
-rw-r--r--views/widget/widget_gtk.h15
-rw-r--r--views/window/dialog_client_view.cc32
15 files changed, 289 insertions, 217 deletions
diff --git a/views/event.h b/views/event.h
index 70d0abc..843ed00 100644
--- a/views/event.h
+++ b/views/event.h
@@ -234,7 +234,7 @@ class KeyEvent : public Event {
// Create a new key event
KeyEvent(EventType type, int ch, int repeat_count, int message_flags);
#elif defined(OS_LINUX)
- explicit KeyEvent(GdkEventKey* event);
+ KeyEvent(GdkEventKey* event, bool make_upper_case);
#endif
int GetCharacter() const {
diff --git a/views/event_gtk.cc b/views/event_gtk.cc
index ed55628..d1b9d88 100644
--- a/views/event_gtk.cc
+++ b/views/event_gtk.cc
@@ -8,12 +8,16 @@
namespace views {
-KeyEvent::KeyEvent(GdkEventKey* event)
+// TODO(jcampan): the same physical key can send different keyvals (ex: a or A).
+// In order for accelerators to work, we need to normalize that. The right
+// solution should probably to get the key-code out of the keystate.
+KeyEvent::KeyEvent(GdkEventKey* event, bool make_upper_case)
: Event(event->type == GDK_KEY_PRESS ?
Event::ET_KEY_PRESSED : Event::ET_KEY_RELEASED,
GetFlagsFromGdkState(event->state)),
// TODO(erg): All these values are iffy.
- character_(event->keyval),
+ character_(make_upper_case ? gdk_keyval_to_upper (event->keyval) :
+ event->keyval),
repeat_count_(0),
message_flags_(0) {
}
diff --git a/views/focus/accelerator_handler.h b/views/focus/accelerator_handler.h
new file mode 100644
index 0000000..618f541
--- /dev/null
+++ b/views/focus/accelerator_handler.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2006-2008 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_FOCUS_ACCELERATOR_HANDLER_H_
+#define VIEWS_FOCUS_ACCELERATOR_HANDLER_H_
+
+#if defined(OS_LINUX)
+#include <gdk/gdk.h>
+#endif
+
+#include "base/message_loop.h"
+
+namespace views {
+
+// This class delegates the key messages to the associated FocusManager class
+// for the window that is receiving these messages for accelerator processing.
+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);
+#endif
+
+ private:
+#if defined(OS_LINUX)
+ // Last key pressed and consumed as an accelerator.
+ guint last_key_pressed_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(AcceleratorHandler);
+};
+
+} // namespace views
+
+#endif // VIEWS_FOCUS_ACCELERATOR_HANDLER_H_
diff --git a/views/focus/accelerator_handler_gtk.cc b/views/focus/accelerator_handler_gtk.cc
new file mode 100644
index 0000000..938dfcc
--- /dev/null
+++ b/views/focus/accelerator_handler_gtk.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2009 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 <gtk/gtk.h>
+
+#include "views/focus/accelerator_handler.h"
+
+#include "views/focus/focus_manager.h"
+#include "views/widget/widget_gtk.h"
+#include "views/window/window_gtk.h"
+
+namespace views {
+
+AcceleratorHandler::AcceleratorHandler() : last_key_pressed_(0) {
+}
+
+bool AcceleratorHandler::Dispatch(GdkEvent* event) {
+ if (event->type != GDK_KEY_PRESS && event->type != GDK_KEY_RELEASE) {
+ gtk_main_do_event(event);
+ return true;
+ }
+
+ GdkEventKey* key_event = reinterpret_cast<GdkEventKey*>(event);
+ // Let's retrieve the focus manager for the GdkWindow.
+ GdkWindow* window = gdk_window_get_toplevel(key_event->window);
+ gpointer ptr;
+ gdk_window_get_user_data(window, &ptr);
+ DCHECK(ptr); // The top-level window is expected to always be associated
+ // with the top-level gtk widget.
+ WindowGtk* widget =
+ WidgetGtk::GetWindowForNative(reinterpret_cast<GtkWidget*>(ptr));
+ FocusManager* focus_manager = widget->GetFocusManager();
+ if (!focus_manager) {
+ NOTREACHED();
+ return true;
+ }
+
+ if (event->type == GDK_KEY_PRESS) {
+ KeyEvent view_key_event(key_event, true);
+ // FocusManager::OnKeyPressed and OnKeyReleased return false if this
+ // message has been consumed and should not be propagated further.
+ if (!focus_manager->OnKeyEvent(view_key_event)) {
+ last_key_pressed_ = key_event->keyval;
+ return true;
+ }
+ }
+
+ // Key release, make sure to filter-out the key release for key press consumed
+ // as accelerators to avoid unpaired key release.
+ if (event->type == GDK_KEY_RELEASE &&
+ key_event->keyval == last_key_pressed_) {
+ last_key_pressed_ = 0;
+ return true;
+ }
+
+ gtk_main_do_event(event);
+ return true;
+}
+
+} // namespace views
diff --git a/views/widget/accelerator_handler.cc b/views/focus/accelerator_handler_win.cc
index 7d1f991..eb8bfb9 100644
--- a/views/widget/accelerator_handler.cc
+++ b/views/focus/accelerator_handler_win.cc
@@ -1,9 +1,10 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2009 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/widget/accelerator_handler.h"
+#include "views/focus/accelerator_handler.h"
+#include "views/event.h"
#include "views/focus/focus_manager.h"
namespace views {
@@ -18,14 +19,16 @@ bool AcceleratorHandler::Dispatch(const MSG& msg) {
FocusManager* focus_manager =
FocusManager::GetFocusManagerForNativeView(msg.hwnd);
if (focus_manager) {
- // FocusManager::OnKeyDown and OnKeyUp return false if this message has
- // been consumed and should not be propagated further.
switch (msg.message) {
case WM_KEYDOWN:
- case WM_SYSKEYDOWN:
- process_message = focus_manager->OnKeyDown(msg.hwnd, msg.message,
- msg.wParam, msg.lParam);
+ case WM_SYSKEYDOWN: {
+ KeyEvent event(Event::ET_KEY_PRESSED,
+ msg.wParam,
+ msg.lParam & 0xFFFF,
+ (msg.lParam & 0xFFFF0000) >> 16);
+ process_message = focus_manager->OnKeyEvent(event);
break;
+ }
}
}
}
diff --git a/views/focus/focus_manager.cc b/views/focus/focus_manager.cc
index 04f1f9b..1a0f7ae 100644
--- a/views/focus/focus_manager.cc
+++ b/views/focus/focus_manager.cc
@@ -12,6 +12,7 @@
#include <gtk/gtk.h>
#endif
+#include "base/keyboard_codes.h"
#include "base/logging.h"
#include "views/accelerator.h"
#include "views/focus/view_storage.h"
@@ -19,10 +20,6 @@
#include "views/widget/root_view.h"
#include "views/widget/widget.h"
-#if defined(OS_WIN)
-#include "base/win_util.h"
-#endif
-
namespace views {
// FocusManager -----------------------------------------------------
@@ -41,49 +38,36 @@ FocusManager::~FocusManager() {
DCHECK(focus_change_listeners_.empty());
}
-#if defined(OS_WIN)
-// Message handlers.
-bool FocusManager::OnKeyDown(HWND window, UINT message, WPARAM wparam,
- LPARAM lparam) {
- DCHECK((message == WM_KEYDOWN) || (message == WM_SYSKEYDOWN));
- HWND hwnd = widget_->GetNativeView();
-
- if (!IsWindowVisible(hwnd)) {
- // We got a message for a hidden window. Because WidgetWin::Close hides the
- // window, then destroys it, it it possible to get a message after we've
- // hidden the window. If we allow the message to be dispatched chances are
- // we'll crash in some weird place. By returning false we make sure the
- // message isn't dispatched.
- return false;
- }
-
- int virtual_key_code = static_cast<int>(wparam);
- int repeat_count = LOWORD(lparam);
- int flags = HIWORD(lparam);
- KeyEvent key_event(Event::ET_KEY_PRESSED,
- virtual_key_code, repeat_count, flags);
-
+bool FocusManager::OnKeyEvent(const KeyEvent& event) {
// If the focused view wants to process the key event as is, let it be.
- if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(key_event))
+ if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event))
return true;
// Intercept Tab related messages for focus traversal.
// 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)
HWND top_window = widget_->GetNativeView();
HWND active_window = ::GetActiveWindow();
if ((active_window == top_window || ::IsChild(active_window, top_window)) &&
- IsTabTraversalKeyEvent(key_event)) {
- AdvanceFocus(win_util::IsShiftPressed());
+ IsTabTraversalKeyEvent(event)) {
+ AdvanceFocus(event.IsShiftDown());
return false;
}
+#else
+ if (IsTabTraversalKeyEvent(event)) {
+ AdvanceFocus(event.IsShiftDown());
+ return false;
+ }
+#endif
// Intercept arrow key messages to switch between grouped views.
+ int key_code = event.GetCharacter();
if (focused_view_ && focused_view_->GetGroup() != -1 &&
- (virtual_key_code == VK_UP || virtual_key_code == VK_DOWN ||
- virtual_key_code == VK_LEFT || virtual_key_code == VK_RIGHT)) {
- bool next = (virtual_key_code == VK_RIGHT || virtual_key_code == VK_DOWN);
+ (key_code == base::VKEY_UP || key_code == base::VKEY_DOWN ||
+ key_code == base::VKEY_LEFT || key_code == base::VKEY_RIGHT)) {
+ bool next = (key_code == base::VKEY_RIGHT || key_code == base::VKEY_DOWN);
std::vector<View*> views;
focused_view_->GetParent()->GetViewsWithGroup(focused_view_->GetGroup(),
&views);
@@ -103,22 +87,19 @@ bool FocusManager::OnKeyDown(HWND window, UINT message, WPARAM wparam,
}
// Process keyboard accelerators.
- // We process accelerators here as we have no way of knowing if a HWND has
- // really processed a key event. If the key combination matches an
- // accelerator, the accelerator is triggered, otherwise we forward the
- // event to the HWND.
- Accelerator accelerator(Accelerator(static_cast<int>(virtual_key_code),
- win_util::IsShiftPressed(),
- win_util::IsCtrlPressed(),
- win_util::IsAltPressed()));
+ // If the key combination matches an accelerator, the accelerator is
+ // triggered, otherwise the key event is proceed as usual.
+ Accelerator accelerator(event.GetCharacter(),
+ event.IsShiftDown(),
+ event.IsControlDown(),
+ event.IsAltDown());
if (ProcessAccelerator(accelerator)) {
// If a shortcut was activated for this keydown message, do not propagate
- // the message further.
+ // the event further.
return false;
}
return true;
}
-#endif
void FocusManager::ValidateFocusedView() {
if (focused_view_) {
@@ -410,7 +391,6 @@ bool FocusManager::ProcessAccelerator(const Accelerator& accelerator) {
return true;
}
}
-
return false;
}
@@ -424,12 +404,8 @@ AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator(
// static
bool FocusManager::IsTabTraversalKeyEvent(const KeyEvent& key_event) {
-#if defined(OS_WIN)
- return key_event.GetCharacter() == VK_TAB && !win_util::IsCtrlPressed();
-#else
- NOTIMPLEMENTED();
- return false;
-#endif
+ return key_event.GetCharacter() == base::VKEY_TAB &&
+ !key_event.IsControlDown();
}
void FocusManager::ViewRemoved(View* parent, View* removed) {
diff --git a/views/focus/focus_manager.h b/views/focus/focus_manager.h
index b1c87b6..3106f72 100644
--- a/views/focus/focus_manager.h
+++ b/views/focus/focus_manager.h
@@ -5,9 +5,6 @@
#ifndef VIEWS_FOCUS_FOCUS_MANAGER_H_
#define VIEWS_FOCUS_FOCUS_MANAGER_H_
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
#include <vector>
#include <map>
#include <list>
@@ -140,13 +137,10 @@ class FocusManager {
explicit FocusManager(Widget* widget);
~FocusManager();
-#if defined(OS_WIN)
- // OnKeyDown covers WM_KEYDOWN and WM_SYSKEYDOWN.
- bool OnKeyDown(HWND window,
- UINT message,
- WPARAM wparam,
- LPARAM lparam);
-#endif
+ // Processes the passed key event for accelerators and tab traversal.
+ // Returns false if the event has been consumed and should not be processed
+ // further.
+ bool OnKeyEvent(const KeyEvent& event);
// Returns true is the specified is part of the hierarchy of the window
// associated with this FocusManager.
diff --git a/views/focus/focus_manager_unittest.cc b/views/focus/focus_manager_unittest.cc
index 2ae52e1..fe5b8d0 100644
--- a/views/focus/focus_manager_unittest.cc
+++ b/views/focus/focus_manager_unittest.cc
@@ -10,6 +10,7 @@
#include "app/resource_bundle.h"
#include "base/gfx/rect.h"
+#include "base/keyboard_codes.h"
#include "base/string_util.h"
#include "third_party/skia/include/core/SkColor.h"
#include "views/background.h"
@@ -21,19 +22,28 @@
#include "views/controls/combobox/native_combobox_wrapper.h"
#include "views/controls/label.h"
#include "views/controls/link.h"
+#if defined(OS_WIN)
#include "views/controls/native_control.h"
#include "views/controls/scroll_view.h"
#include "views/controls/tabbed_pane/native_tabbed_pane_wrapper.h"
#include "views/controls/tabbed_pane/tabbed_pane.h"
#include "views/controls/textfield/textfield.h"
-#include "views/widget/accelerator_handler.h"
+#endif
+#include "views/focus/accelerator_handler.h"
#include "views/widget/root_view.h"
-#include "views/widget/widget_win.h"
+#include "views/window/window.h"
#include "views/window/window_delegate.h"
+
+#if defined(OS_WIN)
+#include "views/widget/widget_win.h"
#include "views/window/window_win.h"
+#else
+#include "views/window/window_gtk.h"
+#endif
namespace views {
+#if defined(OS_WIN)
static const int kWindowWidth = 600;
static const int kWindowHeight = 500;
@@ -93,9 +103,95 @@ static const int kHelpLinkID = count++; // 45
static const int kThumbnailContainerID = count++;
static const int kThumbnailStarID = count++;
static const int kThumbnailSuperStarID = count++;
+#endif
+
+class FocusManagerTest : public testing::Test, public WindowDelegate {
+ public:
+ FocusManagerTest()
+ : window_(NULL),
+ content_view_(NULL),
+ focus_change_listener_(NULL) {
+#if defined(OS_WIN)
+ OleInitialize(NULL);
+#endif
+ }
+
+ ~FocusManagerTest() {
+#if defined(OS_WIN)
+ OleUninitialize();
+#endif
+ }
-class FocusManagerTest;
+ virtual void SetUp() {
+ window_ = Window::CreateChromeWindow(NULL, bounds(), this);
+ InitContentView();
+ window_->Show();
+ }
+
+ virtual void TearDown() {
+ if (focus_change_listener_)
+ GetFocusManager()->RemoveFocusChangeListener(focus_change_listener_);
+ // window_->CloseNow();
+ window_->Close();
+
+ // Flush the message loop to make Purify happy.
+ message_loop()->RunAllPending();
+ }
+
+ FocusManager* GetFocusManager() {
+#if defined(OS_WIN)
+ return static_cast<WindowWin*>(window_)->GetFocusManager();
+#elif defined(OS_LINUX)
+ return static_cast<WindowGtk*>(window_)->GetFocusManager();
+#elif
+ NOTIMPLEMENTED();
+#endif
+ }
+
+ // WindowDelegate Implementation.
+ virtual View* GetContentsView() {
+ if (!content_view_)
+ content_view_ = new View();
+ return content_view_;
+ }
+
+ virtual void InitContentView() {
+ }
+
+ protected:
+ virtual gfx::Rect bounds() {
+ return gfx::Rect(0, 0, 500, 500);
+ }
+
+#if defined(OS_WIN)
+ // Mocks activating/deactivating the window.
+ void SimulateActivateWindow() {
+ ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL);
+ }
+ void SimulateDeactivateWindow() {
+ ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_INACTIVE, NULL);
+ }
+#endif
+
+ MessageLoopForUI* message_loop() { return &message_loop_; }
+
+ Window* window_;
+ View* content_view_;
+
+ void AddFocusChangeListener(FocusChangeListener* listener) {
+ ASSERT_FALSE(focus_change_listener_);
+ focus_change_listener_ = listener;
+ GetFocusManager()->AddFocusChangeListener(listener);
+ }
+
+ private:
+ FocusChangeListener* focus_change_listener_;
+ MessageLoopForUI message_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(FocusManagerTest);
+};
+#if defined(OS_WIN)
// BorderView is a NativeControl that creates a tab control as its child and
// takes a View to add as the child of the tab control. The tab control is used
// to give a nice background for the view. At some point we'll have a real
@@ -183,81 +279,6 @@ class DummyComboboxModel : public Combobox::Model {
}
};
-class FocusManagerTest : public testing::Test, public WindowDelegate {
- public:
- FocusManagerTest()
- : window_(NULL),
- focus_change_listener_(NULL),
- content_view_(NULL) {
- OleInitialize(NULL);
- }
-
- ~FocusManagerTest() {
- OleUninitialize();
- }
-
- virtual void SetUp() {
- window_ = static_cast<WindowWin*>(
- Window::CreateChromeWindow(NULL, bounds(), this));
- InitContentView();
- window_->Show();
- }
-
- virtual void TearDown() {
- if (focus_change_listener_)
- GetFocusManager()->RemoveFocusChangeListener(focus_change_listener_);
- window_->CloseNow();
-
- // Flush the message loop to make Purify happy.
- message_loop()->RunAllPending();
- }
-
- FocusManager* GetFocusManager() {
- return FocusManager::GetFocusManagerForNativeView(
- window_->GetNativeWindow());
- }
-
- // WindowDelegate Implementation.
- virtual View* GetContentsView() {
- if (!content_view_)
- content_view_ = new View();
- return content_view_;
- }
-
- virtual void InitContentView() {
- }
-
- protected:
- virtual gfx::Rect bounds() {
- return gfx::Rect(0, 0, 500, 500);
- }
-
- // Mocks activating/deactivating the window.
- void SimulateActivateWindow() {
- ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL);
- }
- void SimulateDeactivateWindow() {
- ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_INACTIVE, NULL);
- }
-
- MessageLoopForUI* message_loop() { return &message_loop_; }
-
- WindowWin* window_;
- View* content_view_;
-
- void AddFocusChangeListener(FocusChangeListener* listener) {
- ASSERT_FALSE(focus_change_listener_);
- focus_change_listener_ = listener;
- GetFocusManager()->AddFocusChangeListener(listener);
- }
-
- private:
- FocusChangeListener* focus_change_listener_;
- MessageLoopForUI message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(FocusManagerTest);
-};
-
class FocusTraversalTest : public FocusManagerTest {
public:
~FocusTraversalTest();
@@ -975,6 +996,8 @@ TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) {
}
}
+#endif // WIN_OS
+
// Counts accelerator calls.
class TestAcceleratorTarget : public AcceleratorTarget {
public:
@@ -997,8 +1020,8 @@ class TestAcceleratorTarget : public AcceleratorTarget {
TEST_F(FocusManagerTest, CallsNormalAcceleratorTarget) {
FocusManager* focus_manager = GetFocusManager();
- Accelerator return_accelerator(VK_RETURN, false, false, false);
- Accelerator escape_accelerator(VK_ESCAPE, false, false, false);
+ Accelerator return_accelerator(base::VKEY_RETURN, false, false, false);
+ Accelerator escape_accelerator(base::VKEY_ESCAPE, false, false, false);
TestAcceleratorTarget return_target(true);
TestAcceleratorTarget escape_target(true);
@@ -1115,7 +1138,7 @@ class SelfUnregisteringAcceleratorTarget : public AcceleratorTarget {
TEST_F(FocusManagerTest, CallsSelfDeletingAcceleratorTarget) {
FocusManager* focus_manager = GetFocusManager();
- Accelerator return_accelerator(VK_RETURN, false, false, false);
+ Accelerator return_accelerator(base::VKEY_RETURN, false, false, false);
SelfUnregisteringAcceleratorTarget target(return_accelerator, focus_manager);
EXPECT_EQ(target.accelerator_count(), 0);
EXPECT_EQ(NULL,
diff --git a/views/view.cc b/views/view.cc
index 820f3ec..4adef5b 100644
--- a/views/view.cc
+++ b/views/view.cc
@@ -995,8 +995,6 @@ void View::RegisterPendingAccelerators() {
return;
}
- // TODO(port): Fix this once we have a FocusManger for Linux.
-#if defined(OS_WIN)
FocusManager* focus_manager = GetFocusManager();
if (!focus_manager) {
// Some crash reports seem to show that we may get cases where we have no
@@ -1011,7 +1009,6 @@ void View::RegisterPendingAccelerators() {
focus_manager->RegisterAccelerator(*iter, this);
}
registered_accelerator_count_ = accelerators_->size();
-#endif
}
void View::UnregisterAccelerators() {
diff --git a/views/view_unittest.cc b/views/view_unittest.cc
index 8591e3b..6778135 100644
--- a/views/view_unittest.cc
+++ b/views/view_unittest.cc
@@ -7,6 +7,7 @@
#include "app/gfx/canvas.h"
#include "app/gfx/path.h"
#include "base/clipboard.h"
+#include "base/keyboard_codes.h"
#include "base/message_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "views/background.h"
@@ -1058,7 +1059,8 @@ class DefaultButtonTest : public ViewTest {
void SimularePressingEnterAndCheckDefaultButton(ButtonID button_id) {
#if defined(OS_WIN)
- focus_manager_->OnKeyDown(native_window_, WM_KEYDOWN, VK_RETURN, 0);
+ KeyEvent event(Event::ET_KEY_PRESSED, VK_RETURN, 0, 0);
+ focus_manager_->OnKeyEvent(event);
#else
// TODO(platform)
return;
diff --git a/views/views.gyp b/views/views.gyp
index a9b09d3..b9c7a26 100644
--- a/views/views.gyp
+++ b/views/views.gyp
@@ -177,6 +177,9 @@
'event_win.cc',
'fill_layout.cc',
'fill_layout.h',
+ 'focus/accelerator_handler.h',
+ 'focus/accelerator_handler_gtk.cc',
+ 'focus/accelerator_handler_win.cc',
'focus/external_focus_tracker.cc',
'focus/external_focus_tracker.h',
'focus/focus_manager_gtk.cc',
@@ -205,8 +208,6 @@
'view_constants.h',
'view_gtk.cc',
'view_win.cc',
- 'widget/accelerator_handler.cc',
- 'widget/accelerator_handler.h',
'widget/aero_tooltip_manager.cc',
'widget/aero_tooltip_manager.h',
'widget/default_theme_provider.cc',
@@ -281,7 +282,6 @@
'controls/tree/tree_view.cc',
'event_win.cc',
'resize_corner.cc',
- 'widget/accelerator_handler.cc',
'widget/aero_tooltip_manager.cc',
'widget/root_view_drop_target.cc',
'widget/tooltip_manager.cc',
@@ -302,6 +302,6 @@
],
}],
],
- },
+ }
],
}
diff --git a/views/widget/accelerator_handler.h b/views/widget/accelerator_handler.h
deleted file mode 100644
index 5ee896c..0000000
--- a/views/widget/accelerator_handler.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2006-2008 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_WIDGET_ACCELERATOR_HANDLER_H_
-#define VIEWS_WIDGET_ACCELERATOR_HANDLER_H_
-
-#include "base/message_loop.h"
-
-namespace views {
-
-// This class delegates WM_KEYDOWN and WM_SYSKEYDOWN messages to
-// the associated FocusManager class for the window that is receiving
-// these messages for accelerator processing. The BrowserProcess object
-// holds a singleton instance of this class which can be used by other
-// custom message loop dispatcher objects to implement default accelerator
-// handling.
-class AcceleratorHandler : public MessageLoopForUI::Dispatcher {
- public:
- AcceleratorHandler();
- // Dispatcher method. This returns true if an accelerator was
- // processed by the focus manager
- virtual bool Dispatch(const MSG& msg);
- private:
- DISALLOW_EVIL_CONSTRUCTORS(AcceleratorHandler);
-};
-
-} // namespace views
-
-#endif // VIEWS_WIDGET_ACCELERATOR_HANDLER_H_
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc
index a77bd14..677e58c 100644
--- a/views/widget/widget_gtk.cc
+++ b/views/widget/widget_gtk.cc
@@ -70,6 +70,8 @@ WidgetGtk::WidgetGtk(Type type)
ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)),
delete_on_destroy_(true),
transparent_(false) {
+ if (type_ != TYPE_CHILD)
+ focus_manager_.reset(new FocusManager(this));
}
WidgetGtk::~WidgetGtk() {
@@ -398,9 +400,16 @@ ThemeProvider* WidgetGtk::GetThemeProvider() const {
return default_theme_provider_.get();
}
+FocusManager* WidgetGtk::GetFocusManager() {
+ return focus_manager_.get();
+}
+
////////////////////////////////////////////////////////////////////////////////
// WidgetGtk, MessageLoopForUI::Observer implementation:
+void WidgetGtk::WillProcessEvent(GdkEvent* event) {
+}
+
void WidgetGtk::DidProcessEvent(GdkEvent* event) {
if (root_view_->NeedsPainting(true))
PaintNow(root_view_->GetScheduledPaintRect());
@@ -518,12 +527,12 @@ gboolean WidgetGtk::OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event) {
}
gboolean WidgetGtk::OnKeyPress(GtkWidget* widget, GdkEventKey* event) {
- KeyEvent key_event(event);
+ KeyEvent key_event(event, false);
return root_view_->ProcessKeyEvent(key_event);
}
gboolean WidgetGtk::OnKeyRelease(GtkWidget* widget, GdkEventKey* event) {
- KeyEvent key_event(event);
+ KeyEvent key_event(event, false);
return root_view_->ProcessKeyEvent(key_event);
}
diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h
index 61a85d9..fbb6c0e 100644
--- a/views/widget/widget_gtk.h
+++ b/views/widget/widget_gtk.h
@@ -99,11 +99,15 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
virtual Window* GetWindow();
virtual const Window* GetWindow() const;
virtual ThemeProvider* GetThemeProvider() const;
+ virtual FocusManager* GetFocusManager();
// MessageLoopForUI::Observer.
- virtual void WillProcessEvent(GdkEvent* event) {}
+ virtual void WillProcessEvent(GdkEvent* event);
virtual void DidProcessEvent(GdkEvent* event);
+ // Retrieves the WindowGtk associated with |widget|.
+ static WindowGtk* GetWindowForNative(GtkWidget* widget);
+
protected:
virtual void OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation);
virtual void OnPaint(GtkWidget* widget, GdkEventExpose* event);
@@ -135,8 +139,7 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
// is true.
virtual bool ReleaseCaptureOnMouseReleased() { return true; }
- // Sets and retrieves the WidgetGtk in the userdata section of the widget.
- static WindowGtk* GetWindowForNative(GtkWidget* widget);
+ // Sets the WindowGtk in the userdata section of the widget.
static void SetWindowForNative(GtkWidget* widget, WindowGtk* window);
// Are we a subclass of WindowGtk?
@@ -215,6 +218,12 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
// must be destroyed AFTER root_view_.
scoped_ptr<TooltipManagerGtk> tooltip_manager_;
+ // The focus manager keeping track of focus for this Widget and any of its
+ // children. NULL for non top-level widgets.
+ // WARNING: RootView's destructor calls into the FocusManager. As such, this
+ // must be destroyed AFTER root_view_.
+ scoped_ptr<FocusManager> focus_manager_;
+
// The root of the View hierarchy attached to this window.
scoped_ptr<RootView> root_view_;
diff --git a/views/window/dialog_client_view.cc b/views/window/dialog_client_view.cc
index 612b1c5..9c40b7f 100644
--- a/views/window/dialog_client_view.cc
+++ b/views/window/dialog_client_view.cc
@@ -8,6 +8,7 @@
#include "app/gfx/font.h"
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "base/keyboard_codes.h"
#include "grit/app_strings.h"
#include "views/controls/button/native_button.h"
#include "views/standard_layout.h"
@@ -128,13 +129,9 @@ void DialogClientView::ShowDialogButtons() {
ok_button_->SetGroup(kButtonGroup);
if (is_default_button)
default_button_ = ok_button_;
-#if defined(OS_WIN)
if (!(buttons & MessageBoxFlags::DIALOGBUTTON_CANCEL))
- ok_button_->AddAccelerator(Accelerator(VK_ESCAPE, false, false, false));
-#else
- NOTIMPLEMENTED();
- // TODO(port): add accelerators
-#endif
+ ok_button_->AddAccelerator(Accelerator(base::VKEY_ESCAPE,
+ false, false, false));
AddChildView(ok_button_);
}
if (buttons & MessageBoxFlags::DIALOGBUTTON_CANCEL && !cancel_button_) {
@@ -154,12 +151,8 @@ void DialogClientView::ShowDialogButtons() {
MessageBoxFlags::DIALOGBUTTON_CANCEL,
label, is_default_button);
cancel_button_->SetGroup(kButtonGroup);
-#if defined(OS_WIN)
- cancel_button_->AddAccelerator(Accelerator(VK_ESCAPE, false, false, false));
-#else
- NOTIMPLEMENTED();
- // TODO(port): add accelerators
-#endif
+ cancel_button_->AddAccelerator(Accelerator(base::VKEY_ESCAPE,
+ false, false, false));
if (is_default_button)
default_button_ = ok_button_;
AddChildView(cancel_button_);
@@ -167,12 +160,7 @@ void DialogClientView::ShowDialogButtons() {
if (!buttons) {
// Register the escape key as an accelerator which will close the window
// if there are no dialog buttons.
-#if defined(OS_WIN)
- AddAccelerator(Accelerator(VK_ESCAPE, false, false, false));
-#else
- NOTIMPLEMENTED();
- // TODO(port): add accelerators
-#endif
+ AddAccelerator(Accelerator(base::VKEY_ESCAPE, false, false, false));
}
}
@@ -370,12 +358,8 @@ gfx::Size DialogClientView::GetPreferredSize() {
}
bool DialogClientView::AcceleratorPressed(const Accelerator& accelerator) {
-#if defined(OS_WIN)
- DCHECK(accelerator.GetKeyCode() == VK_ESCAPE); // We only expect Escape key.
-#else
- NOTIMPLEMENTED();
- // TODO(port): add accelerators
-#endif
+ // We only expect Escape key.
+ DCHECK(accelerator.GetKeyCode() == base::VKEY_ESCAPE);
Close();
return true;
}