diff options
author | kinaba@chromium.org <kinaba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-02 04:17:22 +0000 |
---|---|---|
committer | kinaba@chromium.org <kinaba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-02 04:17:22 +0000 |
commit | 5f7c4fedfa98229c863acbd8977747571c37cb7d (patch) | |
tree | a02664db0e8988d1bb3eb6af271ee3d5abddbc03 /chrome/browser/chromeos/native_dialog_window.cc | |
parent | ac8c1c3254aa0f1b1f11081189d85c17d70333ef (diff) | |
download | chromium_src-5f7c4fedfa98229c863acbd8977747571c37cb7d.zip chromium_src-5f7c4fedfa98229c863acbd8977747571c37cb7d.tar.gz chromium_src-5f7c4fedfa98229c863acbd8977747571c37cb7d.tar.bz2 |
Make Tab key to work on new bookmark dialog.
BUG=chromium-os:7725
TEST=Right-click on bookmark bar and select "Add page..." or "Add folder...", then click Tab key.
Review URL: http://codereview.chromium.org/7544011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95047 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chromeos/native_dialog_window.cc')
-rw-r--r-- | chrome/browser/chromeos/native_dialog_window.cc | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/chrome/browser/chromeos/native_dialog_window.cc b/chrome/browser/chromeos/native_dialog_window.cc index 1eaee09..d2913cd 100644 --- a/chrome/browser/chromeos/native_dialog_window.cc +++ b/chrome/browser/chromeos/native_dialog_window.cc @@ -69,6 +69,7 @@ class NativeDialogHost : public views::DialogDelegateView { protected: CHROMEGTK_CALLBACK_0(NativeDialogHost, void, OnCheckResize); CHROMEGTK_CALLBACK_0(NativeDialogHost, void, OnDialogDestroy); + CHROMEGTK_CALLBACK_1(NativeDialogHost, gboolean, OnKeyPressed, GdkEvent*); // views::View implementation: virtual gfx::Size GetPreferredSize(); @@ -80,6 +81,9 @@ class NativeDialogHost : public views::DialogDelegateView { // Init and attach to native dialog. void Init(); + // Enable moving focuses over native widgets by the Tab key. + void InitNativeFocusMove(GtkWidget* contents); + // Check and apply minimum size restriction. void CheckSize(); @@ -158,6 +162,21 @@ void NativeDialogHost::OnDialogDestroy(GtkWidget* widget) { GetWidget()->Close(); } +gboolean NativeDialogHost::OnKeyPressed(GtkWidget* widget, GdkEvent* event) { + // Manually handle focus movement by Tab key. + // See the comments in NativeDialogHost::InitNativeFocusMove for more detail. + views::KeyEvent key_event(event); + if (views::FocusManager::IsTabTraversalKeyEvent(key_event)) { + GtkWindow* window = GetWidget()->GetNativeWindow(); + GtkDirectionType dir = + key_event.IsShiftDown() ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD; + static_cast<GtkWindowClass*>( + g_type_class_peek(GTK_TYPE_WINDOW))->move_focus(window, dir); + return true; + } + return false; +} + /////////////////////////////////////////////////////////////////////////////// // NativeDialogHost, views::DialogDelegate implementation: void NativeDialogHost::WindowClosing() { @@ -225,6 +244,8 @@ void NativeDialogHost::Init() { AddChildView(contents_view_); contents_view_->Attach(contents); + InitNativeFocusMove(contents); + g_signal_connect(GetWidget()->GetNativeWindow(), "check-resize", G_CALLBACK(&OnCheckResizeThunk), this); @@ -256,6 +277,43 @@ void NativeDialogHost::Init() { gtk_widget_grab_focus(focus_widget); } +void NativeDialogHost::InitNativeFocusMove(GtkWidget* contents) { + // Fix for http://crosbug.com/7725. + // + // When a native GTK dialog is hosted on views+GTK, the views framework + // prevents Tab key events to be passed to the GTK's handler in three places: + // 1. views::FocusManager::OnKeyEvent + // It intercepts key events _after_ the usual event handlers through the + // native widget hierarchy and _before_ the native key binding handlers. + // Since moving focus by Tab is implemented as a key binding, it cannot + // be reached. As a workaround for NativeDialogHost, we install an usual + // key event handler for capturing Tab key, before FocusManager. + // 2. ::gtk_views_window_move_focus + // The default "move_focus" method of GtkWindow is overridden by views + // to invoke views::FocusManager. This is avoided by calling the default + // GtkWindow->move_focus explicitly in the OnKeyPressed handler. + // 3. ::gtk_views_fixed_init + // Several GTK widgets of type GtkViewsFixed are inserted between the + // dialog window and the dialog controls, so that views framework can + // observe native events. The problem is that these widgets have CAN_FOCUS + // flags, which means they don't propagate focuses to the child controls. + // Here we turn the flag off to make descendant dialog controls focusable. + // Note that, these "stealing" behaviors of views are required ones in the + // usual situation where native widgets are used just as a hidden background + // implementation of views. Only when a native widget hierarchy is hosted and + // directly exposed to the users, the following workaround is necessary. + + g_signal_connect(contents, "key_press_event", + G_CALLBACK(&OnKeyPressedThunk), this); + + GtkWidget* window = GTK_WIDGET(GetWidget()->GetNativeWindow()); + GtkWidget* anscestor = gtk_widget_get_parent(GTK_WIDGET(contents)); + while (anscestor && anscestor != window) { + GTK_WIDGET_UNSET_FLAGS(anscestor, GTK_CAN_FOCUS); + anscestor = gtk_widget_get_parent(anscestor); + } +} + void NativeDialogHost::CheckSize() { // Apply the minimum size. if (preferred_size_.width() < min_size_.width()) |