diff options
author | suzhe@chromium.org <suzhe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-11 03:36:24 +0000 |
---|---|---|
committer | suzhe@chromium.org <suzhe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-11 03:36:24 +0000 |
commit | f96cb05502a32c59e9d0fa158aa0441dea81be69 (patch) | |
tree | 6a5155b98ed669a92fd5f844c22882bb2e202012 /chrome/browser/autocomplete | |
parent | 3554ee417f54aa874716878a9af08d5db4dc7ce6 (diff) | |
download | chromium_src-f96cb05502a32c59e9d0fa158aa0441dea81be69.zip chromium_src-f96cb05502a32c59e9d0fa158aa0441dea81be69.tar.gz chromium_src-f96cb05502a32c59e9d0fa158aa0441dea81be69.tar.bz2 |
[Linux]Fix text justification of omnibox.
Without this CL, the omnibox inherits the default behavior of GtkTextView on handling text direction and justification, that is:
1. If the justification is set to left justification, then the content will be left justified if the content's text direction is LTR, otherwise it'll be right justified.
2. If the justification is set to right justification, then the content will be right justified if the content's text direction is LTR, otherwise it'll be left justified.
And if the content doesn't have a strong text direction, the keymap's direction will be used. If the keymap doesn't have a strong text direction either, the widget's direction (UI language direction) will be used.
This behavior is different than Chrome windows. On windows, if the UI language direction is LTR, then the content is always left justified, otherwise it's always right justified.
To achieve the same behavior, this CL adjust the justification automatically according to the content's (or keymap's) text direction and the widget direction, to make sure the justification is always in sync with the UI language direction.
BUG=34724 Text in omnibox and find bar is not right justified correct under RTL locale.
TEST=Run chrome with LTR locale, the text in omnibox should always be left justified, regardless of the text's direction. With RTL locale, the text should always be right justified. It matches the behavior of windows version.
Review URL: http://codereview.chromium.org/595021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38737 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autocomplete')
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc | 74 | ||||
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_edit_view_gtk.h | 21 |
2 files changed, 90 insertions, 5 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc index 102854d..2d0a458 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc @@ -192,6 +192,10 @@ void AutocompleteEditViewGtk::Init() { browser_defaults::kAutocompleteEditFontPixelSizeInPopup : browser_defaults::kAutocompleteEditFontPixelSize); + // One pixel left margin is necessary to make the cursor visible when UI + // language direction is LTR but |text_buffer_|'s content direction is RTL. + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_view_), 1); + // See SetEntryStyle() comments. gtk_widget_set_name(text_view_, "chrome-location-bar-entry"); @@ -263,6 +267,8 @@ void AutocompleteEditViewGtk::Init() { G_CALLBACK(&HandlePasteClipboardThunk), this); g_signal_connect_after(text_view_, "expose-event", G_CALLBACK(&HandleExposeEventThunk), this); + g_signal_connect(text_view_, "direction-changed", + G_CALLBACK(&HandleWidgetDirectionChangedThunk), this); #if !defined(TOOLKIT_VIEWS) registrar_.Add(this, @@ -290,13 +296,19 @@ int AutocompleteEditViewGtk::TextWidth() { GTK_TEXT_WINDOW_RIGHT) + gtk_text_view_get_left_margin(GTK_TEXT_VIEW(text_view_)) + gtk_text_view_get_right_margin(GTK_TEXT_VIEW(text_view_)); - GtkTextIter end; - GdkRectangle last_char_bounds; - gtk_text_buffer_get_end_iter( - gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view_)), &end); + + GtkTextIter start, end; + GdkRectangle first_char_bounds, last_char_bounds; + gtk_text_buffer_get_start_iter(text_buffer_, &start); + gtk_text_buffer_get_end_iter(text_buffer_, &end); + gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_), + &start, &first_char_bounds); gtk_text_view_get_iter_location(GTK_TEXT_VIEW(text_view_), &end, &last_char_bounds); - return last_char_bounds.x + last_char_bounds.width + horizontal_border_size; + return ((last_char_bounds.x > first_char_bounds.x) ? + (last_char_bounds.x + last_char_bounds.width - first_char_bounds.x) : + (first_char_bounds.x - last_char_bounds.x + last_char_bounds.width)) + + horizontal_border_size; } void AutocompleteEditViewGtk::SaveStateToTab(TabContents* tab) { @@ -516,6 +528,9 @@ bool AutocompleteEditViewGtk::OnAfterPossibleChange() { std::wstring new_text(GetText()); text_changed_ = (new_text != text_before_change_); + if (text_changed_) + AdjustTextJustification(); + // When the user has deleted text, we don't allow inline autocomplete. Make // sure to not flag cases like selecting part of the text and then pasting // (or typing) the prefix of that selection. (We detect these by making @@ -823,6 +838,13 @@ gboolean AutocompleteEditViewGtk::HandleViewFocusIn() { controller_->OnSetFocus(); // TODO(deanm): Some keyword hit business, etc here. + g_signal_connect( + gdk_keymap_get_for_display(gtk_widget_get_display(text_view_)), + "direction-changed", + G_CALLBACK(&HandleKeymapDirectionChangedThunk), this); + + AdjustTextJustification(); + return FALSE; // Continue propagation. } @@ -832,6 +854,11 @@ gboolean AutocompleteEditViewGtk::HandleViewFocusOut() { // Tell the model to reset itself. model_->OnKillFocus(); controller_->OnKillFocus(); + + g_signal_handlers_disconnect_by_func( + gdk_keymap_get_for_display(gtk_widget_get_display(text_view_)), + reinterpret_cast<gpointer>(&HandleKeymapDirectionChangedThunk), this); + return FALSE; // Pass the event on to the GtkTextView. } @@ -1350,6 +1377,7 @@ void AutocompleteEditViewGtk::SetTextAndSelectedRange(const std::wstring& text, std::string utf8 = WideToUTF8(text); gtk_text_buffer_set_text(text_buffer_, utf8.data(), utf8.length()); SetSelectedRange(range); + AdjustTextJustification(); } void AutocompleteEditViewGtk::SetSelectedRange(const CharRange& range) { @@ -1357,3 +1385,39 @@ void AutocompleteEditViewGtk::SetSelectedRange(const CharRange& range) { ItersFromCharRange(range, &bound, &insert); gtk_text_buffer_select_range(text_buffer_, &insert, &bound); } + +void AutocompleteEditViewGtk::AdjustTextJustification() { + PangoDirection content_dir = GetContentDirection(); + + // Use keymap direction if content does not have strong direction. + // It matches the behavior of GtkTextView. + if (content_dir == PANGO_DIRECTION_NEUTRAL) { + content_dir = gdk_keymap_get_direction( + gdk_keymap_get_for_display(gtk_widget_get_display(text_view_))); + } + + GtkTextDirection widget_dir = gtk_widget_get_direction(text_view_); + + if ((widget_dir == GTK_TEXT_DIR_RTL && content_dir == PANGO_DIRECTION_LTR) || + (widget_dir == GTK_TEXT_DIR_LTR && content_dir == PANGO_DIRECTION_RTL)) { + gtk_text_view_set_justification(GTK_TEXT_VIEW(text_view_), + GTK_JUSTIFY_RIGHT); + } else { + gtk_text_view_set_justification(GTK_TEXT_VIEW(text_view_), + GTK_JUSTIFY_LEFT); + } +} + +PangoDirection AutocompleteEditViewGtk::GetContentDirection() { + GtkTextIter iter; + gtk_text_buffer_get_start_iter(text_buffer_, &iter); + + PangoDirection dir = PANGO_DIRECTION_NEUTRAL; + do { + dir = pango_unichar_direction(gtk_text_iter_get_char(&iter)); + if (dir != PANGO_DIRECTION_NEUTRAL) + break; + } while (gtk_text_iter_forward_char(&iter)); + + return dir; +} diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h index 7923551..7549c6c 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h +++ b/chrome/browser/autocomplete/autocomplete_edit_view_gtk.h @@ -301,6 +301,18 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, } gboolean HandleExposeEvent(GdkEventExpose* expose); + static void HandleWidgetDirectionChangedThunk( + GtkWidget* widget, GtkTextDirection previous_direction, gpointer self) { + return reinterpret_cast<AutocompleteEditViewGtk*>(self)-> + AdjustTextJustification(); + } + + static void HandleKeymapDirectionChangedThunk(GdkKeymap* keymap, + gpointer self) { + return reinterpret_cast<AutocompleteEditViewGtk*>(self)-> + AdjustTextJustification(); + } + // Gets the GTK_TEXT_WINDOW_WIDGET coordinates for |text_view_| that bound the // given iters. gfx::Rect WindowBoundsFromIters(GtkTextIter* iter1, GtkTextIter* iter2); @@ -348,6 +360,15 @@ class AutocompleteEditViewGtk : public AutocompleteEditView, // Set the selection to |range|. void SetSelectedRange(const CharRange& range); + // Adjust the text justification according to the text direction of the widget + // and |text_buffer_|'s content, to make sure the real text justification is + // always in sync with the UI language direction. + void AdjustTextJustification(); + + // Get the text direction of |text_buffer_|'s content, by searching the first + // character that has a strong direction. + PangoDirection GetContentDirection(); + // The widget we expose, used for vertically centering the real text edit, // since the height will change based on the font / font size, etc. OwnedWidgetGtk alignment_; |