diff options
author | xji@chromium.org <xji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-21 23:44:02 +0000 |
---|---|---|
committer | xji@chromium.org <xji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-21 23:44:02 +0000 |
commit | 69e38eca8034fe35c22744f59bee77f987ae8755 (patch) | |
tree | 217db5a362aab2e4809834f48935c46390b55e57 | |
parent | 4b495fc331fd4c5bd257b6c86ee1652aa58a9e0d (diff) | |
download | chromium_src-69e38eca8034fe35c22744f59bee77f987ae8755.zip chromium_src-69e38eca8034fe35c22744f59bee77f987ae8755.tar.gz chromium_src-69e38eca8034fe35c22744f59bee77f987ae8755.tar.bz2 |
This CL fixes
issue 6125 - [edit search engines] after hitting right ctrl+shift, can't change insertion point with the mouse
and
issue 8686 - RTL: Can't select RTL text from Chrome UI boxes
The problem is cursor positioning and cursor selection in CRichEditCtrl in RTL layout. (cursor positioning is fine even for RTL characters in LTR layout, but cursor positioning is not working even for LTR characters in RTL layout).
The fix is correctly calculation of input boundary in ClipXCoordToVisibleText(), and the fix is mostly part of Nick Carter's un-committed fix in https://svn.corp.google.com/review/chrome/desc/cb/ncarter/rtl_richedit_fixes@50605
BUG=6125
BUG=8686
Review URL: http://codereview.chromium.org/86003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14158 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_edit_view_win.cc | 49 | ||||
-rw-r--r-- | chrome/views/controls/text_field.cc | 48 |
2 files changed, 72 insertions, 25 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc index 648a90f..95a71b9 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc @@ -1841,23 +1841,40 @@ bool AutocompleteEditViewWin::IsSelectAllForRange(const CHARRANGE& sel) const { LONG AutocompleteEditViewWin::ClipXCoordToVisibleText( LONG x, bool is_triple_click) const { - // Clip the X coordinate to the left edge of the text. Careful: + // Clip the X coordinate to the left edge of the text. Careful: // PosFromChar(0) may return a negative X coordinate if the beginning of the // text has scrolled off the edit, so don't go past the clip rect's edge. + PARAFORMAT2 pf2; + GetParaFormat(pf2); + // Calculation of the clipped coordinate is more complicated if the paragraph + // layout is RTL layout, or if there is RTL characters inside the LTR layout + // paragraph. + bool ltr_text_in_ltr_layout = true; + if ((pf2.wEffects & PFE_RTLPARA) || + l10n_util::StringContainsStrongRTLChars(GetText())) { + ltr_text_in_ltr_layout = false; + } + const int length = GetTextLength(); RECT r; GetRect(&r); - const int left_bound = std::max(r.left, PosFromChar(0).x); - if (x < left_bound) - return left_bound; - - // See if we need to clip to the right edge of the text. - const int length = GetTextLength(); - // Asking for the coordinate of any character past the end of the text gets - // the pixel just to the right of the last character. - const int right_bound = std::min(r.right, PosFromChar(length).x); - if ((length == 0) || (x < right_bound)) - return x; - + // The values returned by PosFromChar() seem to refer always + // to the left edge of the character's bounding box. + const LONG first_position_x = PosFromChar(0).x; + LONG min_x = first_position_x; + if (!ltr_text_in_ltr_layout) { + for (int i = 1; i < length; ++i) + min_x = std::min(min_x, PosFromChar(i).x); + } + const LONG left_bound = std::max(r.left, min_x); + // PosFromChar(length) is a phantom character past the end of the text. It is + // not necessarily a right bound; in RTL controls it may be a left bound. So + // treat it as a right bound only if it is to the right of the first + // character. + LONG right_bound = r.right; + LONG end_position_x = PosFromChar(length).x; + if (end_position_x >= first_position_x) { + right_bound = std::min(right_bound, end_position_x); // LTR case. + } // For trailing characters that are 2 pixels wide of less (like "l" in some // fonts), we have a problem: // * Clicks on any pixel within the character will place the cursor before @@ -1868,6 +1885,12 @@ LONG AutocompleteEditViewWin::ClipXCoordToVisibleText( // triple-click, and moving to one past the last pixel in all other // scenarios. This way, all clicks that can move the cursor will place it at // the end of the text, but triple-click will still work. + if (x < left_bound) { + return (is_triple_click && ltr_text_in_ltr_layout) ? left_bound - 1 : + left_bound; + } + if ((length == 0) || (x < right_bound)) + return x; return is_triple_click ? (right_bound - 1) : right_bound; } diff --git a/chrome/views/controls/text_field.cc b/chrome/views/controls/text_field.cc index 875453a..93a41e9 100644 --- a/chrome/views/controls/text_field.cc +++ b/chrome/views/controls/text_field.cc @@ -879,20 +879,38 @@ LONG TextField::Edit::ClipXCoordToVisibleText(LONG x, // Clip the X coordinate to the left edge of the text. Careful: // PosFromChar(0) may return a negative X coordinate if the beginning of the // text has scrolled off the edit, so don't go past the clip rect's edge. + PARAFORMAT2 pf2; + GetParaFormat(pf2); + // Calculation of the clipped coordinate is more complicated if the paragraph + // layout is RTL layout, or if there is RTL characters inside the LTR layout + // paragraph. + bool ltr_text_in_ltr_layout = true; + if ((pf2.wEffects & PFE_RTLPARA) || + l10n_util::StringContainsStrongRTLChars(GetText())) { + ltr_text_in_ltr_layout = false; + } + const int length = GetTextLength(); RECT r; GetRect(&r); - const int left_bound = std::max(r.left, PosFromChar(0).x); - if (x < left_bound) - return left_bound; - - // See if we need to clip to the right edge of the text. - const int length = GetTextLength(); - // Asking for the coordinate of any character past the end of the text gets - // the pixel just to the right of the last character. - const int right_bound = std::min(r.right, PosFromChar(length).x); - if ((length == 0) || (x < right_bound)) - return x; - + // The values returned by PosFromChar() seem to refer always + // to the left edge of the character's bounding box. + const LONG first_position_x = PosFromChar(0).x; + LONG min_x = first_position_x; + if (!ltr_text_in_ltr_layout) { + for (int i = 1; i < length; ++i) + min_x = std::min(min_x, PosFromChar(i).x); + } + const LONG left_bound = std::max(r.left, min_x); + + // PosFromChar(length) is a phantom character past the end of the text. It is + // not necessarily a right bound; in RTL controls it may be a left bound. So + // treat it as a right bound only if it is to the right of the first + // character. + LONG right_bound = r.right; + LONG end_position_x = PosFromChar(length).x; + if (end_position_x >= first_position_x) { + right_bound = std::min(right_bound, end_position_x); // LTR case. + } // For trailing characters that are 2 pixels wide of less (like "l" in some // fonts), we have a problem: // * Clicks on any pixel within the character will place the cursor before @@ -903,6 +921,12 @@ LONG TextField::Edit::ClipXCoordToVisibleText(LONG x, // triple-click, and moving to one past the last pixel in all other // scenarios. This way, all clicks that can move the cursor will place it at // the end of the text, but triple-click will still work. + if (x < left_bound) { + return (is_triple_click && ltr_text_in_ltr_layout) ? left_bound - 1 : + left_bound; + } + if ((length == 0) || (x < right_bound)) + return x; return is_triple_click ? (right_bound - 1) : right_bound; } |