summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/keyboard_codes.h6
-rw-r--r--base/keyboard_codes_linux.h214
-rw-r--r--base/keyboard_codes_mac.h (renamed from base/keyboard_codes_posix.h)6
-rw-r--r--base/message_loop.cc40
-rw-r--r--base/message_loop.h35
-rw-r--r--base/message_pump_glib.cc17
-rw-r--r--base/message_pump_glib.h28
-rw-r--r--chrome/browser/autocomplete/search_provider_unittest.cc4
-rw-r--r--chrome/browser/browser_main.cc6
-rw-r--r--chrome/browser/browser_main_win.cc2
-rw-r--r--chrome/browser/first_run_win.cc2
-rw-r--r--chrome/chrome.gyp2
-rw-r--r--chrome/common/temp_scaffolding_stubs.h3
-rw-r--r--chrome/test/ui_test_utils.cc8
-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
29 files changed, 597 insertions, 282 deletions
diff --git a/base/keyboard_codes.h b/base/keyboard_codes.h
index 2f66ac1..3d8700f 100644
--- a/base/keyboard_codes.h
+++ b/base/keyboard_codes.h
@@ -9,8 +9,10 @@
#if defined(OS_WIN)
#include "base/keyboard_codes_win.h"
-#elif defined(OS_POSIX)
-#include "base/keyboard_codes_posix.h"
+#elif defined(OS_LINUX)
+#include "base/keyboard_codes_linux.h"
+#elif defined(OS_MACOSX)
+#include "base/keyboard_codes_mac.h"
#endif
#endif // BASE_KEYBOARD_CODES_H_
diff --git a/base/keyboard_codes_linux.h b/base/keyboard_codes_linux.h
new file mode 100644
index 0000000..50b30b1
--- /dev/null
+++ b/base/keyboard_codes_linux.h
@@ -0,0 +1,214 @@
+// 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.
+
+/*
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com. All rights reserved.
+ * Copyright (C) 2008, 2009 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF USE, DATA, OR
+ * PROFITS, OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BASE_KEYBOARD_CODES_LINUX_H_
+#define BASE_KEYBOARD_CODES_LINUX_H_
+
+#include <gdk/gdkkeysyms.h>
+#include <X11/XF86keysym.h>
+
+namespace base {
+
+enum {
+ VKEY_BACK = GDK_BackSpace,
+ VKEY_TAB = GDK_Tab,
+ VKEY_CLEAR = GDK_Clear,
+ VKEY_RETURN = GDK_Return,
+ VKEY_SHIFT = GDK_Shift_L, // TODO(jcampan): what about GDK_Shift_R?
+ VKEY_CONTROL = GDK_Control_L, // TODO(jcampan): what about GDK_Control_R?
+ VKEY_MENU = GDK_Menu,
+ VKEY_PAUSE = GDK_Pause,
+ VKEY_CAPITAL = GDK_Shift_Lock,
+ VKEY_KANA = GDK_Kana_Shift,
+ VKEY_HANGUL = GDK_Hangul,
+ // TODO(jcampan): not sure what the next 2 are.
+ VKEY_JUNJA = GDK_Hangul,
+ VKEY_FINAL = GDK_Hangul,
+ VKEY_HANJA = GDK_Hangul_Hanja,
+ VKEY_KANJI = GDK_Kanji,
+ VKEY_ESCAPE = GDK_Escape,
+ // TODO(jcampan): not sure what the next 4 are.
+ VKEY_CONVERT = 0x1C,
+ VKEY_NONCONVERT = 0x1D,
+ VKEY_ACCEPT = 0x1E,
+ VKEY_MODECHANGE = 0x1F,
+ VKEY_SPACE = GDK_space,
+ VKEY_PRIOR = GDK_Prior,
+ VKEY_NEXT = GDK_Next,
+ VKEY_END = GDK_End,
+ VKEY_HOME = GDK_Home,
+ VKEY_LEFT = GDK_Left,
+ VKEY_UP = GDK_Up,
+ VKEY_RIGHT = GDK_Right,
+ VKEY_DOWN = GDK_Down,
+ VKEY_SELECT = GDK_Select,
+ VKEY_PRINT = GDK_Print,
+ VKEY_EXECUTE = GDK_Execute,
+ VKEY_SNAPSHOT = 0x2C, // TODO(jcampan): not sure what this one is.
+ VKEY_INSERT = GDK_Insert,
+ VKEY_DELETE = GDK_Delete,
+ VKEY_HELP = GDK_Help,
+ VKEY_0 = GDK_0,
+ VKEY_1 = GDK_1,
+ VKEY_2 = GDK_2,
+ VKEY_3 = GDK_3,
+ VKEY_4 = GDK_4,
+ VKEY_5 = GDK_5,
+ VKEY_6 = GDK_6,
+ VKEY_7 = GDK_7,
+ VKEY_8 = GDK_8,
+ VKEY_9 = GDK_9,
+ VKEY_A = GDK_A,
+ VKEY_B = GDK_B,
+ VKEY_C = GDK_C,
+ VKEY_D = GDK_D,
+ VKEY_E = GDK_E,
+ VKEY_F = GDK_F,
+ VKEY_G = GDK_G,
+ VKEY_H = GDK_H,
+ VKEY_I = GDK_I,
+ VKEY_J = GDK_J,
+ VKEY_K = GDK_K,
+ VKEY_L = GDK_L,
+ VKEY_M = GDK_M,
+ VKEY_N = GDK_N,
+ VKEY_O = GDK_O,
+ VKEY_P = GDK_P,
+ VKEY_Q = GDK_Q,
+ VKEY_R = GDK_R,
+ VKEY_S = GDK_S,
+ VKEY_T = GDK_T,
+ VKEY_U = GDK_U,
+ VKEY_V = GDK_V,
+ VKEY_W = GDK_W,
+ VKEY_X = GDK_X,
+ VKEY_Y = GDK_Y,
+ VKEY_Z = GDK_Z,
+ VKEY_LWIN = GDK_Meta_L,
+ VKEY_RWIN = GDK_Meta_R,
+ VKEY_APPS = 0x5D, // TODO(jcampan): not sure what this one is.
+ VKEY_SLEEP = XF86XK_Sleep,
+ VKEY_NUMPAD0 = GDK_KP_0,
+ VKEY_NUMPAD1 = GDK_KP_1,
+ VKEY_NUMPAD2 = GDK_KP_2,
+ VKEY_NUMPAD3 = GDK_KP_3,
+ VKEY_NUMPAD4 = GDK_KP_4,
+ VKEY_NUMPAD5 = GDK_KP_5,
+ VKEY_NUMPAD6 = GDK_KP_6,
+ VKEY_NUMPAD7 = GDK_KP_7,
+ VKEY_NUMPAD8 = GDK_KP_8,
+ VKEY_NUMPAD9 = GDK_KP_9,
+ VKEY_MULTIPLY = GDK_KP_Multiply,
+ VKEY_ADD = GDK_KP_Add,
+ VKEY_SEPARATOR = GDK_KP_Separator,
+ VKEY_SUBTRACT = GDK_KP_Subtract,
+ VKEY_DECIMAL = GDK_KP_Decimal,
+ VKEY_DIVIDE = GDK_KP_Divide,
+ VKEY_F1 = GDK_F1,
+ VKEY_F2 = GDK_F2,
+ VKEY_F3 = GDK_F3,
+ VKEY_F4 = GDK_F4,
+ VKEY_F5 = GDK_F5,
+ VKEY_F6 = GDK_F6,
+ VKEY_F7 = GDK_F7,
+ VKEY_F8 = GDK_F8,
+ VKEY_F9 = GDK_F9,
+ VKEY_F10 = GDK_F10,
+ VKEY_F11 = GDK_F11,
+ VKEY_F12 = GDK_F12,
+ VKEY_F13 = GDK_F13,
+ VKEY_F14 = GDK_F14,
+ VKEY_F15 = GDK_F15,
+ VKEY_F16 = GDK_F16,
+ VKEY_F17 = GDK_F17,
+ VKEY_F18 = GDK_F18,
+ VKEY_F19 = GDK_F19,
+ VKEY_F20 = GDK_F20,
+ VKEY_F21 = GDK_F21,
+ VKEY_F22 = GDK_F22,
+ VKEY_F23 = GDK_F23,
+ VKEY_F24 = GDK_F24,
+ VKEY_NUMLOCK = GDK_Num_Lock,
+ VKEY_SCROLL = GDK_Scroll_Lock,
+ VKEY_LSHIFT = GDK_Shift_L,
+ VKEY_RSHIFT = GDK_Shift_R,
+ VKEY_LCONTROL = GDK_Control_L,
+ VKEY_RCONTROL = GDK_Control_R,
+ VKEY_LMENU = GDK_Alt_L,
+ VKEY_RMENU = GDK_Alt_R,
+ VKEY_BROWSER_BACK = XF86XK_Back,
+ VKEY_BROWSER_FORWARD = XF86XK_Forward,
+ VKEY_BROWSER_REFRESH = XF86XK_Refresh,
+ VKEY_BROWSER_STOP = XF86XK_Stop,
+ VKEY_BROWSER_SEARCH = XF86XK_Search,
+ VKEY_BROWSER_FAVORITES = XF86XK_Favorites,
+ VKEY_BROWSER_HOME = XF86XK_HomePage,
+ VKEY_VOLUME_MUTE = XF86XK_AudioMute,
+ VKEY_VOLUME_DOWN = XF86XK_AudioLowerVolume,
+ VKEY_VOLUME_UP = XF86XK_AudioRaiseVolume,
+ VKEY_MEDIA_NEXT_TRACK = XF86XK_AudioNext,
+ VKEY_MEDIA_PREV_TRACK = XF86XK_AudioPrev,
+ VKEY_MEDIA_STOP = XF86XK_AudioStop,
+ VKEY_MEDIA_PLAY_PAUSE = XF86XK_AudioPause,
+ VKEY_MEDIA_LAUNCH_MAIL = XF86XK_Mail,
+ VKEY_MEDIA_LAUNCH_MEDIA_SELECT = XF86XK_AudioMedia,
+ VKEY_MEDIA_LAUNCH_APP1 = XF86XK_Launch1,
+ VKEY_MEDIA_LAUNCH_APP2 = XF86XK_Launch2,
+ // TODO(jcampan): Figure-out values below.
+ VKEY_OEM_1 = 0xBA,
+ VKEY_OEM_PLUS = 0xBB,
+ VKEY_OEM_COMMA = 0xBC,
+ VKEY_OEM_MINUS = 0xBD,
+ VKEY_OEM_PERIOD = 0xBE,
+ VKEY_OEM_2 = 0xBF,
+ VKEY_OEM_3 = 0xC0,
+ VKEY_OEM_4 = 0xDB,
+ VKEY_OEM_5 = 0xDC,
+ VKEY_OEM_6 = 0xDD,
+ VKEY_OEM_7 = 0xDE,
+ VKEY_OEM_8 = 0xDF,
+ VKEY_OEM_102 = 0xE2,
+ VKEY_PROCESSKEY = 0xE5,
+ VKEY_PACKET = 0xE7,
+ VKEY_ATTN = 0xF6,
+ VKEY_CRSEL = 0xF7,
+ VKEY_EXSEL = 0xF8,
+ VKEY_EREOF = 0xF9,
+ VKEY_PLAY = 0xFA,
+ VKEY_ZOOM = XF86XK_ZoomIn,
+ VKEY_NONAME = 0xFC,
+ VKEY_PA1 = 0xFD,
+ VKEY_OEM_CLEAR = 0xFE,
+ VKEY_UNKNOWN = 0
+};
+
+} // namespace views
+
+#endif // BASE_KEYBOARD_CODES_LINUX_H_
diff --git a/base/keyboard_codes_posix.h b/base/keyboard_codes_mac.h
index 5100d96..9b414dc 100644
--- a/base/keyboard_codes_posix.h
+++ b/base/keyboard_codes_mac.h
@@ -28,8 +28,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef BASE_KEYBOARD_CODES_POSIX_H_
-#define BASE_KEYBOARD_CODES_POSIX_H_
+#ifndef BASE_KEYBOARD_CODES_MAC_H_
+#define BASE_KEYBOARD_CODES_MAC_H_
namespace base {
@@ -205,4 +205,4 @@ enum {
} // namespace views
-#endif // BASE_KEYBOARD_CODES_POSIX_H_
+#endif // BASE_KEYBOARD_CODES_MAC_H_
diff --git a/base/message_loop.cc b/base/message_loop.cc
index 4c91b1f..5464670 100644
--- a/base/message_loop.cc
+++ b/base/message_loop.cc
@@ -188,9 +188,10 @@ void MessageLoop::RunInternal() {
StartHistogrammer();
-#if defined(OS_WIN)
- if (state_->dispatcher) {
- pump_win()->RunWithDispatcher(this, state_->dispatcher);
+#if defined(OS_WIN) || defined(OS_LINUX)
+ if (state_->dispatcher && type() == TYPE_UI) {
+ static_cast<base::MessagePumpForUI*>(pump_.get())->
+ RunWithDispatcher(this, state_->dispatcher);
return;
}
#endif
@@ -480,7 +481,7 @@ MessageLoop::AutoRunState::AutoRunState(MessageLoop* loop) : loop_(loop) {
// Initialize the other fields:
quit_received = false;
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_LINUX)
dispatcher = NULL;
#endif
}
@@ -570,8 +571,20 @@ const LinearHistogram::DescriptionPair MessageLoop::event_descriptions_[] = {
//------------------------------------------------------------------------------
// MessageLoopForUI
-#if defined(OS_LINUX) || defined(OS_WIN)
+#if defined(OS_WIN)
+void MessageLoopForUI::WillProcessMessage(const MSG& message) {
+ pump_win()->WillProcessMessage(message);
+}
+void MessageLoopForUI::DidProcessMessage(const MSG& message) {
+ pump_win()->DidProcessMessage(message);
+}
+void MessageLoopForUI::PumpOutPendingPaintMessages() {
+ pump_ui()->PumpOutPendingPaintMessages();
+}
+
+#endif // defined(OS_WIN)
+#if defined(OS_LINUX) || defined(OS_WIN)
void MessageLoopForUI::AddObserver(Observer* observer) {
pump_ui()->AddObserver(observer);
}
@@ -580,27 +593,12 @@ void MessageLoopForUI::RemoveObserver(Observer* observer) {
pump_ui()->RemoveObserver(observer);
}
-#endif
-
-#if defined(OS_WIN)
-
void MessageLoopForUI::Run(Dispatcher* dispatcher) {
AutoRunState save_state(this);
state_->dispatcher = dispatcher;
RunHandler();
}
-
-void MessageLoopForUI::WillProcessMessage(const MSG& message) {
- pump_win()->WillProcessMessage(message);
-}
-void MessageLoopForUI::DidProcessMessage(const MSG& message) {
- pump_win()->DidProcessMessage(message);
-}
-void MessageLoopForUI::PumpOutPendingPaintMessages() {
- pump_ui()->PumpOutPendingPaintMessages();
-}
-
-#endif // defined(OS_WIN)
+#endif // defined(OS_LINUX) || defined(OS_WIN)
//------------------------------------------------------------------------------
// MessageLoopForIO
diff --git a/base/message_loop.h b/base/message_loop.h
index debbade..395ce6e 100644
--- a/base/message_loop.h
+++ b/base/message_loop.h
@@ -234,6 +234,14 @@ class MessageLoop : public base::MessagePump::Delegate {
// Returns true if we are currently running a nested message loop.
bool IsNested();
+#if defined(OS_WIN)
+ typedef base::MessagePumpWin::Dispatcher Dispatcher;
+ typedef base::MessagePumpWin::Observer Observer;
+#elif defined(OS_LINUX)
+ typedef base::MessagePumpForUI::Dispatcher Dispatcher;
+ typedef base::MessagePumpForUI::Observer Observer;
+#endif
+
//----------------------------------------------------------------------------
protected:
struct RunState {
@@ -244,8 +252,8 @@ class MessageLoop : public base::MessagePump::Delegate {
// once it becomes idle.
bool quit_received;
-#if defined(OS_WIN)
- base::MessagePumpWin::Dispatcher* dispatcher;
+#if defined(OS_WIN) || defined(OS_LINUX)
+ Dispatcher* dispatcher;
#endif
};
@@ -416,34 +424,25 @@ class MessageLoopForUI : public MessageLoop {
return static_cast<MessageLoopForUI*>(loop);
}
-#if defined(OS_LINUX)
- typedef base::MessagePumpForUI::Observer Observer;
-
- // See message_pump_glib for definitions of these methods.
- void AddObserver(Observer* observer);
- void RemoveObserver(Observer* observer);
-#endif
-
#if defined(OS_WIN)
- typedef base::MessagePumpWin::Dispatcher Dispatcher;
- typedef base::MessagePumpWin::Observer Observer;
-
- // Please see MessagePumpWin for definitions of these methods.
- void AddObserver(Observer* observer);
- void RemoveObserver(Observer* observer);
- void Run(Dispatcher* dispatcher);
void WillProcessMessage(const MSG& message);
void DidProcessMessage(const MSG& message);
void PumpOutPendingPaintMessages();
#endif
#if defined(OS_WIN) || defined(OS_LINUX)
+ // Please see message_pump_win/message_pump_glib for definitions of these
+ // methods.
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+ void Run(Dispatcher* dispatcher);
+
protected:
// TODO(rvargas): Make this platform independent.
base::MessagePumpForUI* pump_ui() {
return static_cast<base::MessagePumpForUI*>(pump_.get());
}
-#endif // defined(OS_WIN)
+#endif // defined(OS_WIN) || defined(OS_LINUX)
};
// Do not add any member variables to MessageLoopForUI! This is important b/c
diff --git a/base/message_pump_glib.cc b/base/message_pump_glib.cc
index ac0a080..6f050ba 100644
--- a/base/message_pump_glib.cc
+++ b/base/message_pump_glib.cc
@@ -153,7 +153,8 @@ MessagePumpForUI::~MessagePumpForUI() {
close(wakeup_pipe_write_);
}
-void MessagePumpForUI::Run(Delegate* delegate) {
+void MessagePumpForUI::RunWithDispatcher(Delegate* delegate,
+ Dispatcher* dispatcher) {
#ifndef NDEBUG
// Make sure we only run this on one thread. GTK only has one message pump
// so we can only have one UI loop per process.
@@ -165,6 +166,7 @@ void MessagePumpForUI::Run(Delegate* delegate) {
RunState state;
state.delegate = delegate;
+ state.dispatcher = dispatcher;
state.should_quit = false;
state.run_depth = state_ ? state_->run_depth + 1 : 1;
state.has_work = false;
@@ -309,9 +311,16 @@ void MessagePumpForUI::ScheduleDelayedWork(const Time& delayed_work_time) {
// static
void MessagePumpForUI::EventDispatcher(GdkEvent* event, gpointer data) {
- reinterpret_cast<MessagePumpForUI*>(data)->WillProcessEvent(event);
- gtk_main_do_event(event);
- reinterpret_cast<MessagePumpForUI*>(data)->DidProcessEvent(event);
+ MessagePumpForUI* message_pump = reinterpret_cast<MessagePumpForUI*>(data);
+
+ message_pump->WillProcessEvent(event);
+ if (message_pump->state_->dispatcher) {
+ if (!message_pump->state_->dispatcher->Dispatch(event))
+ message_pump->state_->should_quit = true;
+ } else {
+ gtk_main_do_event(event);
+ }
+ message_pump->DidProcessEvent(event);
}
} // namespace base
diff --git a/base/message_pump_glib.h b/base/message_pump_glib.h
index e8288a8..08e1964 100644
--- a/base/message_pump_glib.h
+++ b/base/message_pump_glib.h
@@ -31,10 +31,29 @@ class MessagePumpForUI : public MessagePump {
virtual void DidProcessEvent(GdkEvent* event) = 0;
};
+ // Dispatcher is used during a nested invocation of Run to dispatch events.
+ // If Run is invoked with a non-NULL Dispatcher, MessageLoop does not
+ // dispatch events (or invoke gtk_main_do_event), rather every event is
+ // passed to Dispatcher's Dispatch method for dispatch. It is up to the
+ // Dispatcher to dispatch, or not, the event.
+ //
+ // The nested loop is exited by either posting a quit, or returning false
+ // from Dispatch.
+ class Dispatcher {
+ public:
+ virtual ~Dispatcher() {}
+ // Dispatches the event. If true is returned processing continues as
+ // normal. If false is returned, the nested loop exits immediately.
+ virtual bool Dispatch(GdkEvent* event) = 0;
+ };
+
MessagePumpForUI();
- ~MessagePumpForUI();
+ virtual ~MessagePumpForUI();
+
+ // Like MessagePump::Run, but GdkEvent objects are routed through dispatcher.
+ virtual void RunWithDispatcher(Delegate* delegate, Dispatcher* dispatcher);
- virtual void Run(Delegate* delegate);
+ virtual void Run(Delegate* delegate) { RunWithDispatcher(delegate, NULL); }
virtual void Quit();
virtual void ScheduleWork();
virtual void ScheduleDelayedWork(const Time& delayed_work_time);
@@ -49,10 +68,10 @@ class MessagePumpForUI : public MessagePump {
bool HandleCheck();
void HandleDispatch();
- // Add an Observer, which will start receiving notifications immediately.
+ // Adds an Observer, which will start receiving notifications immediately.
void AddObserver(Observer* observer);
- // Remove an Observer. It is safe to call this method while an Observer is
+ // Removes an Observer. It is safe to call this method while an Observer is
// receiving a notification callback.
void RemoveObserver(Observer* observer);
@@ -61,6 +80,7 @@ class MessagePumpForUI : public MessagePump {
// separate between them in this structure type.
struct RunState {
Delegate* delegate;
+ Dispatcher* dispatcher;
// Used to flag that the current Run() invocation should return ASAP.
bool should_quit;
diff --git a/chrome/browser/autocomplete/search_provider_unittest.cc b/chrome/browser/autocomplete/search_provider_unittest.cc
index 6e1c196..deaaf56 100644
--- a/chrome/browser/autocomplete/search_provider_unittest.cc
+++ b/chrome/browser/autocomplete/search_provider_unittest.cc
@@ -141,9 +141,9 @@ void SearchProviderTest::RunTillProviderDone() {
return;
quit_when_done_ = true;
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_LINUX)
message_loop_.Run(NULL);
-#elif defined(OS_POSIX)
+#else
message_loop_.Run();
#endif
}
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index 302385d..3e85501 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -107,13 +107,13 @@
#include "net/http/http_network_layer.h"
#include "printing/printed_document.h"
#include "sandbox/src/sandbox.h"
-#include "views/widget/accelerator_handler.h"
#endif // defined(OS_WIN)
#if defined(TOOLKIT_GTK)
#include "chrome/common/gtk_util.h"
#elif defined(TOOLKIT_VIEWS)
#include "chrome/browser/views/chrome_views_delegate.h"
+#include "views/focus/accelerator_handler.h"
#endif
namespace Platform {
@@ -191,9 +191,11 @@ StringPiece NetResourceProvider(int key) {
}
void RunUIMessageLoop(BrowserProcess* browser_process) {
-#if defined(OS_WIN)
+#if defined(TOOLKIT_VIEWS)
views::AcceleratorHandler accelerator_handler;
MessageLoopForUI::current()->Run(&accelerator_handler);
+#elif defined(OS_LINUX)
+ MessageLoopForUI::current()->Run(NULL);
#elif defined(OS_POSIX)
MessageLoopForUI::current()->Run();
#endif
diff --git a/chrome/browser/browser_main_win.cc b/chrome/browser/browser_main_win.cc
index 8cf23fd..b4f1052 100644
--- a/chrome/browser/browser_main_win.cc
+++ b/chrome/browser/browser_main_win.cc
@@ -25,7 +25,7 @@
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "views/controls/message_box_view.h"
-#include "views/widget/accelerator_handler.h"
+#include "views/focus/accelerator_handler.h"
#include "views/window/window.h"
// Displays a warning message if the user is running chrome on windows 2000.
diff --git a/chrome/browser/first_run_win.cc b/chrome/browser/first_run_win.cc
index a00f456..30b6df32 100644
--- a/chrome/browser/first_run_win.cc
+++ b/chrome/browser/first_run_win.cc
@@ -56,9 +56,9 @@
#include "views/controls/image_view.h"
#include "views/controls/label.h"
#include "views/controls/link.h"
+#include "views/focus/accelerator_handler.h"
#include "views/grid_layout.h"
#include "views/standard_layout.h"
-#include "views/widget/accelerator_handler.h"
#include "views/widget/root_view.h"
#include "views/widget/widget_win.h"
#include "views/window/window.h"
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 2c2d0bb..2e27833 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -46,12 +46,12 @@
# TODO(jcampan): move these vars to views.gyp.
'views_unit_tests_sources': [
'../views/view_unittest.cc',
+ '../views/focus/focus_manager_unittest.cc',
],
'views_unit_tests_sources_win_specific': [
# TODO(jcampan): make the following tests work on Linux.
'../views/controls/label_unittest.cc',
'../views/controls/table/table_view_unittest.cc',
- '../views/focus/focus_manager_unittest.cc',
'../views/grid_layout_unittest.cc',
]
},
diff --git a/chrome/common/temp_scaffolding_stubs.h b/chrome/common/temp_scaffolding_stubs.h
index 8aab9f8..0158700 100644
--- a/chrome/common/temp_scaffolding_stubs.h
+++ b/chrome/common/temp_scaffolding_stubs.h
@@ -156,9 +156,6 @@ struct ViewHostMsg_DidPrintPage_Params;
namespace views {
-class AcceleratorHandler {
-};
-
#if !defined(TOOLKIT_VIEWS)
class MenuItemView {
public:
diff --git a/chrome/test/ui_test_utils.cc b/chrome/test/ui_test_utils.cc
index ee9b7d4..928ff87 100644
--- a/chrome/test/ui_test_utils.cc
+++ b/chrome/test/ui_test_utils.cc
@@ -18,8 +18,8 @@
#include "chrome/common/chrome_paths.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
-#if defined (OS_WIN)
-#include "views/widget/accelerator_handler.h"
+#if defined(TOOLKIT_VIEWS)
+#include "views/focus/accelerator_handler.h"
#endif
#include "googleurl/src/gurl.h"
#include "net/base/net_util.h"
@@ -260,9 +260,11 @@ void RunMessageLoop() {
MessageLoopForUI* loop = MessageLoopForUI::current();
bool did_allow_task_nesting = loop->NestableTasksAllowed();
loop->SetNestableTasksAllowed(true);
-#if defined (OS_WIN)
+#if defined(TOOLKIT_VIEWS)
views::AcceleratorHandler handler;
loop->Run(&handler);
+#elif defined(OS_LINUX)
+ loop->Run(NULL);
#else
loop->Run();
#endif
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;
}