summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos/native_dialog_window.cc
diff options
context:
space:
mode:
authorkinaba@chromium.org <kinaba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-02 04:17:22 +0000
committerkinaba@chromium.org <kinaba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-02 04:17:22 +0000
commit5f7c4fedfa98229c863acbd8977747571c37cb7d (patch)
treea02664db0e8988d1bb3eb6af271ee3d5abddbc03 /chrome/browser/chromeos/native_dialog_window.cc
parentac8c1c3254aa0f1b1f11081189d85c17d70333ef (diff)
downloadchromium_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.cc58
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())