OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ui/views/cocoa/bridged_content_view.h" | 5 #import "ui/views/cocoa/bridged_content_view.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #import "base/mac/mac_util.h" | 8 #import "base/mac/mac_util.h" |
9 #import "base/mac/scoped_nsobject.h" | 9 #import "base/mac/scoped_nsobject.h" |
10 #import "base/mac/sdk_forward_declarations.h" | 10 #import "base/mac/sdk_forward_declarations.h" |
11 #include "base/strings/sys_string_conversions.h" | 11 #include "base/strings/sys_string_conversions.h" |
12 #include "skia/ext/skia_utils_mac.h" | 12 #include "skia/ext/skia_utils_mac.h" |
13 #import "ui/base/cocoa/appkit_utils.h" | 13 #import "ui/base/cocoa/appkit_utils.h" |
14 #include "ui/base/cocoa/cocoa_base_utils.h" | 14 #include "ui/base/cocoa/cocoa_base_utils.h" |
15 #include "ui/base/dragdrop/drag_drop_types.h" | 15 #include "ui/base/dragdrop/drag_drop_types.h" |
16 #include "ui/base/dragdrop/os_exchange_data_provider_mac.h" | 16 #include "ui/base/dragdrop/os_exchange_data_provider_mac.h" |
17 #include "ui/base/ime/input_method.h" | 17 #include "ui/base/ime/input_method.h" |
18 #include "ui/base/ime/text_edit_commands.h" | 18 #include "ui/base/ime/text_edit_commands.h" |
19 #include "ui/base/ime/text_input_client.h" | 19 #include "ui/base/ime/text_input_client.h" |
| 20 #include "ui/base/text/text_properties.h" |
20 #include "ui/compositor/canvas_painter.h" | 21 #include "ui/compositor/canvas_painter.h" |
21 #import "ui/events/cocoa/cocoa_event_utils.h" | 22 #import "ui/events/cocoa/cocoa_event_utils.h" |
22 #include "ui/events/event_utils.h" | 23 #include "ui/events/event_utils.h" |
23 #include "ui/events/keycodes/dom/dom_code.h" | 24 #include "ui/events/keycodes/dom/dom_code.h" |
24 #import "ui/events/keycodes/keyboard_code_conversion_mac.h" | 25 #import "ui/events/keycodes/keyboard_code_conversion_mac.h" |
25 #include "ui/gfx/canvas_paint_mac.h" | 26 #include "ui/gfx/canvas_paint_mac.h" |
26 #include "ui/gfx/decorated_text.h" | 27 #include "ui/gfx/decorated_text.h" |
27 #include "ui/gfx/geometry/rect.h" | 28 #include "ui/gfx/geometry/rect.h" |
28 #import "ui/gfx/mac/coordinate_conversion.h" | 29 #import "ui/gfx/mac/coordinate_conversion.h" |
29 #include "ui/gfx/path.h" | 30 #include "ui/gfx/path.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 } | 78 } |
78 | 79 |
79 // Dispatch |event| to |menu_controller| and return true if |event| is | 80 // Dispatch |event| to |menu_controller| and return true if |event| is |
80 // swallowed. | 81 // swallowed. |
81 bool DispatchEventToMenu(MenuController* menu_controller, ui::KeyEvent* event) { | 82 bool DispatchEventToMenu(MenuController* menu_controller, ui::KeyEvent* event) { |
82 return menu_controller && | 83 return menu_controller && |
83 menu_controller->OnWillDispatchKeyEvent(event) == | 84 menu_controller->OnWillDispatchKeyEvent(event) == |
84 ui::POST_DISPATCH_NONE; | 85 ui::POST_DISPATCH_NONE; |
85 } | 86 } |
86 | 87 |
87 // Returns true if |client| has RTL text. | |
88 bool IsTextRTL(const ui::TextInputClient* client) { | |
89 return client && client->GetTextDirection() == base::i18n::RIGHT_TO_LEFT; | |
90 } | |
91 | |
92 // Returns the boundary rectangle for composition characters in the | |
93 // |requested_range|. Sets |actual_range| corresponding to the returned | |
94 // rectangle. For cases, where there is no composition text or the | |
95 // |requested_range| lies outside the composition range, a zero width rectangle | |
96 // corresponding to the caret bounds is returned. Logic used is similar to | |
97 // RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange(...). | |
98 gfx::Rect GetFirstRectForRangeHelper(const ui::TextInputClient* client, | |
99 const gfx::Range& requested_range, | |
100 gfx::Range* actual_range) { | |
101 // NSRange doesn't support reversed ranges. | |
102 DCHECK(!requested_range.is_reversed()); | |
103 DCHECK(actual_range); | |
104 | |
105 // Set up default return values, to be returned in case of unusual cases. | |
106 gfx::Rect default_rect; | |
107 *actual_range = gfx::Range::InvalidRange(); | |
108 if (!client) | |
109 return default_rect; | |
110 | |
111 default_rect = client->GetCaretBounds(); | |
112 default_rect.set_width(0); | |
113 | |
114 // If possible, modify actual_range to correspond to caret position. | |
115 gfx::Range selection_range; | |
116 if (client->GetSelectionRange(&selection_range)) { | |
117 // Caret bounds correspond to end index of selection_range. | |
118 *actual_range = gfx::Range(selection_range.end()); | |
119 } | |
120 | |
121 gfx::Range composition_range; | |
122 if (!client->HasCompositionText() || | |
123 !client->GetCompositionTextRange(&composition_range) || | |
124 !composition_range.Contains(requested_range)) | |
125 return default_rect; | |
126 | |
127 DCHECK(!composition_range.is_reversed()); | |
128 | |
129 const size_t from = requested_range.start() - composition_range.start(); | |
130 const size_t to = requested_range.end() - composition_range.start(); | |
131 | |
132 // Pick the first character's bounds as the initial rectangle, then grow it to | |
133 // the full |requested_range| if possible. | |
134 const bool request_is_composition_end = from == composition_range.length(); | |
135 const size_t first_index = request_is_composition_end ? from - 1 : from; | |
136 gfx::Rect union_rect; | |
137 if (!client->GetCompositionCharacterBounds(first_index, &union_rect)) | |
138 return default_rect; | |
139 | |
140 // If requested_range is empty, return a zero width rectangle corresponding to | |
141 // it. | |
142 if (from == to) { | |
143 if (request_is_composition_end && !IsTextRTL(client)) { | |
144 // In case of an empty requested range at end of composition, return the | |
145 // rectangle to the right of the last compositioned character. | |
146 union_rect.set_origin(union_rect.top_right()); | |
147 } | |
148 union_rect.set_width(0); | |
149 *actual_range = requested_range; | |
150 return union_rect; | |
151 } | |
152 | |
153 // Toolkit-views textfields are always single-line, so no need to check for | |
154 // line breaks. | |
155 for (size_t i = from + 1; i < to; i++) { | |
156 gfx::Rect current_rect; | |
157 if (client->GetCompositionCharacterBounds(i, ¤t_rect)) { | |
158 union_rect.Union(current_rect); | |
159 } else { | |
160 *actual_range = | |
161 gfx::Range(requested_range.start(), i + composition_range.start()); | |
162 return union_rect; | |
163 } | |
164 } | |
165 *actual_range = requested_range; | |
166 return union_rect; | |
167 } | |
168 | |
169 // Returns the string corresponding to |requested_range| for the given |client|. | 88 // Returns the string corresponding to |requested_range| for the given |client|. |
170 // If a gfx::Range::InvalidRange() is passed, the full string stored by |client| | 89 // If a gfx::Range::InvalidRange() is passed, the full string stored by |client| |
171 // is returned. Sets |actual_range| corresponding to the returned string. | 90 // is returned. Sets |actual_range| corresponding to the returned string. |
172 base::string16 AttributedSubstringForRangeHelper( | 91 base::string16 AttributedSubstringForRangeHelper( |
173 const ui::TextInputClient* client, | 92 const ui::TextInputClient* client, |
174 const gfx::Range& requested_range, | 93 const gfx::Range& requested_range, |
175 gfx::Range* actual_range) { | 94 gfx::Range* actual_range) { |
176 // NSRange doesn't support reversed ranges. | 95 // NSRange doesn't support reversed ranges. |
177 DCHECK(!requested_range.is_reversed()); | 96 DCHECK(!requested_range.is_reversed()); |
178 DCHECK(actual_range); | 97 DCHECK(actual_range); |
(...skipping 1008 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1187 } | 1106 } |
1188 | 1107 |
1189 - (void)moveWordLeftAndModifySelection:(id)sender { | 1108 - (void)moveWordLeftAndModifySelection:(id)sender { |
1190 [self handleAction:ui::TextEditCommand::MOVE_WORD_LEFT_AND_MODIFY_SELECTION | 1109 [self handleAction:ui::TextEditCommand::MOVE_WORD_LEFT_AND_MODIFY_SELECTION |
1191 keyCode:ui::VKEY_LEFT | 1110 keyCode:ui::VKEY_LEFT |
1192 domCode:ui::DomCode::ARROW_LEFT | 1111 domCode:ui::DomCode::ARROW_LEFT |
1193 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; | 1112 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; |
1194 } | 1113 } |
1195 | 1114 |
1196 - (void)moveToLeftEndOfLine:(id)sender { | 1115 - (void)moveToLeftEndOfLine:(id)sender { |
1197 IsTextRTL(textInputClient_) ? [self moveToEndOfLine:sender] | 1116 ui::IsTextRTL(textInputClient_) ? [self moveToEndOfLine:sender] |
1198 : [self moveToBeginningOfLine:sender]; | 1117 : [self moveToBeginningOfLine:sender]; |
1199 } | 1118 } |
1200 | 1119 |
1201 - (void)moveToRightEndOfLine:(id)sender { | 1120 - (void)moveToRightEndOfLine:(id)sender { |
1202 IsTextRTL(textInputClient_) ? [self moveToBeginningOfLine:sender] | 1121 ui::IsTextRTL(textInputClient_) ? [self moveToBeginningOfLine:sender] |
1203 : [self moveToEndOfLine:sender]; | 1122 : [self moveToEndOfLine:sender]; |
1204 } | 1123 } |
1205 | 1124 |
1206 - (void)moveToLeftEndOfLineAndModifySelection:(id)sender { | 1125 - (void)moveToLeftEndOfLineAndModifySelection:(id)sender { |
1207 IsTextRTL(textInputClient_) | 1126 ui::IsTextRTL(textInputClient_) |
1208 ? [self moveToEndOfLineAndModifySelection:sender] | 1127 ? [self moveToEndOfLineAndModifySelection:sender] |
1209 : [self moveToBeginningOfLineAndModifySelection:sender]; | 1128 : [self moveToBeginningOfLineAndModifySelection:sender]; |
1210 } | 1129 } |
1211 | 1130 |
1212 - (void)moveToRightEndOfLineAndModifySelection:(id)sender { | 1131 - (void)moveToRightEndOfLineAndModifySelection:(id)sender { |
1213 IsTextRTL(textInputClient_) | 1132 ui::IsTextRTL(textInputClient_) |
1214 ? [self moveToBeginningOfLineAndModifySelection:sender] | 1133 ? [self moveToBeginningOfLineAndModifySelection:sender] |
1215 : [self moveToEndOfLineAndModifySelection:sender]; | 1134 : [self moveToEndOfLineAndModifySelection:sender]; |
1216 } | 1135 } |
1217 | 1136 |
1218 // Graphical Element transposition | 1137 // Graphical Element transposition |
1219 | 1138 |
1220 - (void)transpose:(id)sender { | 1139 - (void)transpose:(id)sender { |
1221 [self handleAction:ui::TextEditCommand::TRANSPOSE | 1140 [self handleAction:ui::TextEditCommand::TRANSPOSE |
1222 keyCode:ui::VKEY_T | 1141 keyCode:ui::VKEY_T |
1223 domCode:ui::DomCode::US_T | 1142 domCode:ui::DomCode::US_T |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1378 // For events that AppKit sends via doCommandBySelector:, first attempt to | 1297 // For events that AppKit sends via doCommandBySelector:, first attempt to |
1379 // handle as a Widget accelerator. Forward along the responder chain only if | 1298 // handle as a Widget accelerator. Forward along the responder chain only if |
1380 // the Widget doesn't handle it. | 1299 // the Widget doesn't handle it. |
1381 if (![self handleUnhandledKeyDownAsKeyEvent]) | 1300 if (![self handleUnhandledKeyDownAsKeyEvent]) |
1382 [[self nextResponder] doCommandBySelector:selector]; | 1301 [[self nextResponder] doCommandBySelector:selector]; |
1383 } | 1302 } |
1384 | 1303 |
1385 - (NSRect)firstRectForCharacterRange:(NSRange)range | 1304 - (NSRect)firstRectForCharacterRange:(NSRange)range |
1386 actualRange:(NSRangePointer)actualNSRange { | 1305 actualRange:(NSRangePointer)actualNSRange { |
1387 gfx::Range actualRange; | 1306 gfx::Range actualRange; |
1388 gfx::Rect rect = GetFirstRectForRangeHelper(textInputClient_, | 1307 gfx::Rect rect = ui::GetFirstRectForTextInputRange( |
1389 gfx::Range(range), &actualRange); | 1308 textInputClient_, gfx::Range(range), &actualRange); |
1390 if (actualNSRange) | 1309 if (actualNSRange) |
1391 *actualNSRange = actualRange.ToNSRange(); | 1310 *actualNSRange = actualRange.ToNSRange(); |
1392 return gfx::ScreenRectToNSRect(rect); | 1311 return gfx::ScreenRectToNSRect(rect); |
1393 } | 1312 } |
1394 | 1313 |
1395 - (BOOL)hasMarkedText { | 1314 - (BOOL)hasMarkedText { |
1396 return textInputClient_ && textInputClient_->HasCompositionText(); | 1315 return textInputClient_ && textInputClient_->HasCompositionText(); |
1397 } | 1316 } |
1398 | 1317 |
1399 - (void)insertText:(id)text replacementRange:(NSRange)replacementRange { | 1318 - (void)insertText:(id)text replacementRange:(NSRange)replacementRange { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1518 return [hostedView_->GetNativeViewAccessible() accessibilityHitTest:point]; | 1437 return [hostedView_->GetNativeViewAccessible() accessibilityHitTest:point]; |
1519 } | 1438 } |
1520 | 1439 |
1521 - (id)accessibilityFocusedUIElement { | 1440 - (id)accessibilityFocusedUIElement { |
1522 if (!hostedView_) | 1441 if (!hostedView_) |
1523 return nil; | 1442 return nil; |
1524 return [hostedView_->GetNativeViewAccessible() accessibilityFocusedUIElement]; | 1443 return [hostedView_->GetNativeViewAccessible() accessibilityFocusedUIElement]; |
1525 } | 1444 } |
1526 | 1445 |
1527 @end | 1446 @end |
OLD | NEW |