summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_gtk.cc74
-rw-r--r--chrome/browser/autocomplete/autocomplete_edit_view_gtk.h21
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_;