diff options
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; } |