diff options
author | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-27 01:15:04 +0000 |
---|---|---|
committer | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-27 01:15:04 +0000 |
commit | f5ea625c204a27b5ec7b6d8c5177c866623f305a (patch) | |
tree | b2e6affcfd256675c0dfcf7bb06f272a43ed6737 | |
parent | 085d9cf7081dbb63842e91f369b7eb6974ad752b (diff) | |
download | chromium_src-f5ea625c204a27b5ec7b6d8c5177c866623f305a.zip chromium_src-f5ea625c204a27b5ec7b6d8c5177c866623f305a.tar.gz chromium_src-f5ea625c204a27b5ec7b6d8c5177c866623f305a.tar.bz2 |
Don't emit focus event when moving focus around when re-creating fixed widget.
- This fixes the crash in compact navigation bar without a adjustment.
- I didn't remove the adjustment because ths is necessary to make the compact navigation bar transparent. (currently, the clipping code assumes that the fixed widget and the actual opaque child have the same side, which is not the case for AutocompleteEditView.
BUG=chromium-os:1010
TEST=manual: compact nav bar does not crash.
Review URL: http://codereview.chromium.org/548151
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37198 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/chromeos/chromeos_browser_view.cc | 8 | ||||
-rw-r--r-- | views/controls/native/native_view_host_gtk.cc | 80 |
2 files changed, 79 insertions, 9 deletions
diff --git a/chrome/browser/chromeos/chromeos_browser_view.cc b/chrome/browser/chromeos/chromeos_browser_view.cc index 69675a1..1f10ad05 100644 --- a/chrome/browser/chromeos/chromeos_browser_view.cc +++ b/chrome/browser/chromeos/chromeos_browser_view.cc @@ -276,10 +276,10 @@ class ChromeosBrowserViewLayoutManager : public ChromeBrowserViewLayoutManager { if (compact_navigation_bar_->IsVisible()) { gfx::Size cnb_bounds = compact_navigation_bar_->GetPreferredSize(); - // This (+1/-1) is a quick hack for the bug - // http://code.google.com/p/chromium-os/issues/detail?id=1010 - // while investigating the issue. It could be in gtk or around - // NativeViewHostGtk::CreateFixed, but it will take some time. + // Adjust the size of the compact nativation bar to avoid creating + // a fixed widget with its own gdk window. AutocompleteEditView + // expects the parent view to be transparent, but a fixed with + // its own window is not. compact_navigation_bar_->SetBounds(curx, bounds.y() + 1, cnb_bounds.width(), bounds.height() - 1); diff --git a/views/controls/native/native_view_host_gtk.cc b/views/controls/native/native_view_host_gtk.cc index 7c762bc..e8862e0 100644 --- a/views/controls/native/native_view_host_gtk.cc +++ b/views/controls/native/native_view_host_gtk.cc @@ -14,6 +14,75 @@ namespace views { +namespace { +static bool signal_id_initialized_ = false; +static guint focus_in_event_signal_id_; +static guint focus_out_event_signal_id_; + +//////////////////////////////////////////////////////////////////////////////// +// Utility functions to block focus signals while re-creating +// Fixed widget. + +void InitSignalIds() { + if (!signal_id_initialized_) { + signal_id_initialized_ = true; + focus_in_event_signal_id_ = + g_signal_lookup("focus-in-event", GTK_TYPE_WIDGET); + focus_out_event_signal_id_ = + g_signal_lookup("focus-out-event", GTK_TYPE_WIDGET); + } +} + +// Blocks a |signal_id| on the given |widget| if any. +void BlockSignal(GtkWidget* widget, guint signal_id) { + int handler_id = g_signal_handler_find(G_OBJECT(widget), + G_SIGNAL_MATCH_ID, + signal_id, + 0, NULL, NULL, NULL); + if (handler_id) { + g_signal_handler_block(G_OBJECT(widget), handler_id); + } +} + +// Unblocks a |signal_id| on the given |widget| if any. +void UnblockSignal(GtkWidget* widget, guint signal_id) { + int handler_id = g_signal_handler_find(G_OBJECT(widget), + G_SIGNAL_MATCH_ID, + signal_id, + 0, NULL, NULL, NULL); + if (handler_id) { + g_signal_handler_unblock(G_OBJECT(widget), handler_id); + } +} + +// Blocks focus in/out signals of the widget and its descendent +// children. +// Note: Due to the limiation of Gtk API, this only blocks the 1st +// handler found and won't block the rest if there is more than one handlers. +// See bug http://crbug.com/33236. +void BlockFocusSignals(GtkWidget* widget, gpointer data) { + if (!widget) + return; + InitSignalIds(); + BlockSignal(widget, focus_in_event_signal_id_); + BlockSignal(widget, focus_out_event_signal_id_); + if (GTK_IS_CONTAINER(widget)) + gtk_container_foreach(GTK_CONTAINER(widget), BlockFocusSignals, data); +} + +// Unlocks focus in/out signals of the widget and its descendent children. +void UnblockFocusSignals(GtkWidget* widget, gpointer data) { + if (!widget) + return; + InitSignalIds(); + UnblockSignal(widget, focus_in_event_signal_id_); + UnblockSignal(widget, focus_out_event_signal_id_); + if (GTK_IS_CONTAINER(widget)) + gtk_container_foreach(GTK_CONTAINER(widget), UnblockFocusSignals, data); +} + +} // namespace + //////////////////////////////////////////////////////////////////////////////// // NativeViewHostGtk, public: @@ -183,7 +252,10 @@ void NativeViewHostGtk::SetFocus() { void NativeViewHostGtk::CreateFixed(bool needs_window) { GtkWidget* focused_widget = GetFocusedDescendant(); - bool fixed_is_focused = (focused_widget == fixed_); + + // We move focus around and do not want focus events to be emitted + // during this process. + BlockFocusSignals(GetHostWidget()->GetNativeView(), NULL); if (focused_widget) { // A descendant of our fixed has focus. When we destroy the fixed focus is @@ -208,11 +280,9 @@ void NativeViewHostGtk::CreateFixed(bool needs_window) { gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view()); if (widget_gtk && host_->native_view() && focused_widget) { - if (fixed_is_focused) - gtk_widget_grab_focus(fixed_); - else - gtk_widget_grab_focus(focused_widget); + gtk_widget_grab_focus(focused_widget); } + UnblockFocusSignals(GetHostWidget()->GetNativeView(), NULL); } void NativeViewHostGtk::DestroyFixed() { |