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/scoped_nsobject.h" | 8 #import "base/mac/scoped_nsobject.h" |
9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
10 #include "ui/base/ime/text_input_client.h" | 10 #include "ui/base/ime/text_input_client.h" |
| 11 #import "ui/events/cocoa/cocoa_event_utils.h" |
| 12 #include "ui/events/keycodes/dom3/dom_code.h" |
| 13 #import "ui/events/keycodes/keyboard_code_conversion_mac.h" |
11 #include "ui/gfx/canvas_paint_mac.h" | 14 #include "ui/gfx/canvas_paint_mac.h" |
12 #include "ui/gfx/geometry/rect.h" | 15 #include "ui/gfx/geometry/rect.h" |
13 #include "ui/strings/grit/ui_strings.h" | 16 #include "ui/strings/grit/ui_strings.h" |
14 #include "ui/views/view.h" | 17 #include "ui/views/view.h" |
15 #include "ui/views/widget/widget.h" | 18 #include "ui/views/widget/widget.h" |
16 | 19 |
17 namespace { | 20 namespace { |
18 | 21 |
19 // Convert a |point| in |source_window|'s AppKit coordinate system (origin at | 22 // Convert a |point| in |source_window|'s AppKit coordinate system (origin at |
20 // the bottom left of the window) to |target_window|'s content rect, with the | 23 // the bottom left of the window) to |target_window|'s content rect, with the |
(...skipping 14 matching lines...) Expand all Loading... |
35 } | 38 } |
36 | 39 |
37 } | 40 } |
38 | 41 |
39 @interface BridgedContentView () | 42 @interface BridgedContentView () |
40 | 43 |
41 // Translates the location of |theEvent| to toolkit-views coordinates and passes | 44 // Translates the location of |theEvent| to toolkit-views coordinates and passes |
42 // the event to NativeWidgetMac for handling. | 45 // the event to NativeWidgetMac for handling. |
43 - (void)handleMouseEvent:(NSEvent*)theEvent; | 46 - (void)handleMouseEvent:(NSEvent*)theEvent; |
44 | 47 |
45 // Execute a command on the currently focused TextInputClient. | 48 // Handles an NSResponder Action Message by mapping it to a corresponding text |
46 // |commandId| should be a resource ID from ui_strings.grd. | 49 // editing command from ui_strings.grd and, when not being sent to a |
47 - (void)doCommandByID:(int)commandId; | 50 // TextInputClient, the keyCode that toolkit-views expects internally. |
| 51 // For example, moveToLeftEndOfLine: would pass ui::VKEY_HOME in non-RTL locales |
| 52 // even though the Home key on Mac defaults to moveToBeginningOfDocument:. |
| 53 // This approach also allows action messages a user |
| 54 // may have remapped in ~/Library/KeyBindings/DefaultKeyBinding.dict to be |
| 55 // catered for. |
| 56 // Note: default key bindings in Mac can be read from StandardKeyBinding.dict |
| 57 // which lives in /System/Library/Frameworks/AppKit.framework/Resources. Do |
| 58 // `plutil -convert xml1 -o StandardKeyBinding.xml StandardKeyBinding.dict` to |
| 59 // get something readable. |
| 60 - (void)handleAction:(int)commandId |
| 61 keyCode:(ui::KeyboardCode)keyCode |
| 62 domCode:(ui::DomCode)domCode |
| 63 eventFlags:(int)eventFlags; |
48 | 64 |
49 @end | 65 @end |
50 | 66 |
51 @implementation BridgedContentView | 67 @implementation BridgedContentView |
52 | 68 |
53 @synthesize hostedView = hostedView_; | 69 @synthesize hostedView = hostedView_; |
54 @synthesize textInputClient = textInputClient_; | 70 @synthesize textInputClient = textInputClient_; |
55 | 71 |
56 - (id)initWithView:(views::View*)viewToHost { | 72 - (id)initWithView:(views::View*)viewToHost { |
57 DCHECK(viewToHost); | 73 DCHECK(viewToHost); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 // BridgedContentView private implementation. | 120 // BridgedContentView private implementation. |
105 | 121 |
106 - (void)handleMouseEvent:(NSEvent*)theEvent { | 122 - (void)handleMouseEvent:(NSEvent*)theEvent { |
107 if (!hostedView_) | 123 if (!hostedView_) |
108 return; | 124 return; |
109 | 125 |
110 ui::MouseEvent event(theEvent); | 126 ui::MouseEvent event(theEvent); |
111 hostedView_->GetWidget()->OnMouseEvent(&event); | 127 hostedView_->GetWidget()->OnMouseEvent(&event); |
112 } | 128 } |
113 | 129 |
114 - (void)doCommandByID:(int)commandId { | 130 - (void)handleAction:(int)commandId |
115 if (textInputClient_ && textInputClient_->IsEditingCommandEnabled(commandId)) | 131 keyCode:(ui::KeyboardCode)keyCode |
| 132 domCode:(ui::DomCode)domCode |
| 133 eventFlags:(int)eventFlags { |
| 134 if (!hostedView_) |
| 135 return; |
| 136 |
| 137 // If there's an active TextInputClient, it ignores the key and processes the |
| 138 // logical editing action. |
| 139 if (commandId && textInputClient_ && |
| 140 textInputClient_->IsEditingCommandEnabled(commandId)) { |
116 textInputClient_->ExecuteEditingCommand(commandId); | 141 textInputClient_->ExecuteEditingCommand(commandId); |
| 142 return; |
| 143 } |
| 144 |
| 145 // Otherwise, process the action as a regular key event. |
| 146 ui::KeyEvent event(ui::ET_KEY_PRESSED, keyCode, domCode, eventFlags); |
| 147 hostedView_->GetWidget()->OnKeyEvent(&event); |
117 } | 148 } |
118 | 149 |
119 // NSView implementation. | 150 // NSView implementation. |
120 | 151 |
121 - (BOOL)acceptsFirstResponder { | 152 - (BOOL)acceptsFirstResponder { |
122 return YES; | 153 return YES; |
123 } | 154 } |
124 | 155 |
125 - (void)setFrameSize:(NSSize)newSize { | 156 - (void)setFrameSize:(NSSize)newSize { |
126 [super setFrameSize:newSize]; | 157 [super setFrameSize:newSize]; |
(...skipping 13 matching lines...) Expand all Loading... |
140 if (hostedView_->GetWidget()->GetLayer()) | 171 if (hostedView_->GetWidget()->GetLayer()) |
141 return; | 172 return; |
142 | 173 |
143 gfx::CanvasSkiaPaint canvas(dirtyRect, false /* opaque */); | 174 gfx::CanvasSkiaPaint canvas(dirtyRect, false /* opaque */); |
144 hostedView_->GetWidget()->OnNativeWidgetPaint(&canvas); | 175 hostedView_->GetWidget()->OnNativeWidgetPaint(&canvas); |
145 } | 176 } |
146 | 177 |
147 // NSResponder implementation. | 178 // NSResponder implementation. |
148 | 179 |
149 - (void)keyDown:(NSEvent*)theEvent { | 180 - (void)keyDown:(NSEvent*)theEvent { |
150 if (textInputClient_) | 181 // Convert the event into an action message, according to OSX key mappings. |
151 [self interpretKeyEvents:@[ theEvent ]]; | 182 [self interpretKeyEvents:@[ theEvent ]]; |
152 else | |
153 [super keyDown:theEvent]; | |
154 } | 183 } |
155 | 184 |
156 - (void)mouseDown:(NSEvent*)theEvent { | 185 - (void)mouseDown:(NSEvent*)theEvent { |
157 [self handleMouseEvent:theEvent]; | 186 [self handleMouseEvent:theEvent]; |
158 } | 187 } |
159 | 188 |
160 - (void)rightMouseDown:(NSEvent*)theEvent { | 189 - (void)rightMouseDown:(NSEvent*)theEvent { |
161 [self handleMouseEvent:theEvent]; | 190 [self handleMouseEvent:theEvent]; |
162 } | 191 } |
163 | 192 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 } | 226 } |
198 | 227 |
199 - (void)scrollWheel:(NSEvent*)theEvent { | 228 - (void)scrollWheel:(NSEvent*)theEvent { |
200 if (!hostedView_) | 229 if (!hostedView_) |
201 return; | 230 return; |
202 | 231 |
203 ui::MouseWheelEvent event(theEvent); | 232 ui::MouseWheelEvent event(theEvent); |
204 hostedView_->GetWidget()->OnMouseEvent(&event); | 233 hostedView_->GetWidget()->OnMouseEvent(&event); |
205 } | 234 } |
206 | 235 |
207 - (void)deleteBackward:(id)sender { | 236 //////////////////////////////////////////////////////////////////////////////// |
208 [self doCommandByID:IDS_DELETE_BACKWARD]; | 237 // NSResponder Action Messages. Keep sorted according NSResponder.h (from the |
| 238 // 10.9 SDK). The list should eventually be complete. Anything not defined will |
| 239 // beep when interpretKeyEvents: would otherwise call it. |
| 240 // TODO(tapted): Make this list complete. |
| 241 |
| 242 // The insertText action message forwards to the TextInputClient unless a menu |
| 243 // is active. |
| 244 - (void)insertText:(id)text { |
| 245 [self insertText:text replacementRange:NSMakeRange(NSNotFound, 0)]; |
209 } | 246 } |
210 | 247 |
211 - (void)deleteForward:(id)sender { | 248 // Selection movement and scrolling. |
212 [self doCommandByID:IDS_DELETE_FORWARD]; | 249 |
| 250 - (void)moveRight:(id)sender { |
| 251 [self handleAction:IDS_MOVE_RIGHT |
| 252 keyCode:ui::VKEY_RIGHT |
| 253 domCode:ui::DomCode::ARROW_RIGHT |
| 254 eventFlags:0]; |
213 } | 255 } |
214 | 256 |
215 - (void)moveLeft:(id)sender { | 257 - (void)moveLeft:(id)sender { |
216 [self doCommandByID:IDS_MOVE_LEFT]; | 258 [self handleAction:IDS_MOVE_LEFT |
| 259 keyCode:ui::VKEY_LEFT |
| 260 domCode:ui::DomCode::ARROW_LEFT |
| 261 eventFlags:0]; |
217 } | 262 } |
218 | 263 |
219 - (void)moveRight:(id)sender { | 264 - (void)moveUp:(id)sender { |
220 [self doCommandByID:IDS_MOVE_RIGHT]; | 265 [self handleAction:0 |
| 266 keyCode:ui::VKEY_UP |
| 267 domCode:ui::DomCode::ARROW_UP |
| 268 eventFlags:0]; |
221 } | 269 } |
222 | 270 |
223 - (void)insertText:(id)text { | 271 - (void)moveDown:(id)sender { |
224 if (textInputClient_) | 272 [self handleAction:0 |
225 textInputClient_->InsertText(base::SysNSStringToUTF16(text)); | 273 keyCode:ui::VKEY_DOWN |
| 274 domCode:ui::DomCode::ARROW_DOWN |
| 275 eventFlags:0]; |
| 276 } |
| 277 |
| 278 - (void)moveWordRight:(id)sender { |
| 279 [self handleAction:IDS_MOVE_WORD_RIGHT |
| 280 keyCode:ui::VKEY_RIGHT |
| 281 domCode:ui::DomCode::ARROW_RIGHT |
| 282 eventFlags:ui::EF_CONTROL_DOWN]; |
| 283 } |
| 284 |
| 285 - (void)moveWordLeft:(id)sender { |
| 286 [self handleAction:IDS_MOVE_WORD_LEFT |
| 287 keyCode:ui::VKEY_LEFT |
| 288 domCode:ui::DomCode::ARROW_LEFT |
| 289 eventFlags:ui::EF_CONTROL_DOWN]; |
| 290 } |
| 291 |
| 292 - (void)moveLeftAndModifySelection:(id)sender { |
| 293 [self handleAction:IDS_MOVE_LEFT_AND_MODIFY_SELECTION |
| 294 keyCode:ui::VKEY_LEFT |
| 295 domCode:ui::DomCode::ARROW_LEFT |
| 296 eventFlags:ui::EF_SHIFT_DOWN]; |
| 297 } |
| 298 |
| 299 - (void)moveRightAndModifySelection:(id)sender { |
| 300 [self handleAction:IDS_MOVE_RIGHT_AND_MODIFY_SELECTION |
| 301 keyCode:ui::VKEY_RIGHT |
| 302 domCode:ui::DomCode::ARROW_RIGHT |
| 303 eventFlags:ui::EF_SHIFT_DOWN]; |
| 304 } |
| 305 |
| 306 - (void)moveWordRightAndModifySelection:(id)sender { |
| 307 [self handleAction:IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION |
| 308 keyCode:ui::VKEY_RIGHT |
| 309 domCode:ui::DomCode::ARROW_RIGHT |
| 310 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; |
| 311 } |
| 312 |
| 313 - (void)moveWordLeftAndModifySelection:(id)sender { |
| 314 [self handleAction:IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION |
| 315 keyCode:ui::VKEY_LEFT |
| 316 domCode:ui::DomCode::ARROW_LEFT |
| 317 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; |
| 318 } |
| 319 |
| 320 - (void)moveToLeftEndOfLine:(id)sender { |
| 321 [self handleAction:IDS_MOVE_TO_BEGINNING_OF_LINE |
| 322 keyCode:ui::VKEY_HOME |
| 323 domCode:ui::DomCode::HOME |
| 324 eventFlags:0]; |
| 325 } |
| 326 |
| 327 - (void)moveToRightEndOfLine:(id)sender { |
| 328 [self handleAction:IDS_MOVE_TO_END_OF_LINE |
| 329 keyCode:ui::VKEY_END |
| 330 domCode:ui::DomCode::END |
| 331 eventFlags:0]; |
| 332 } |
| 333 |
| 334 - (void)moveToLeftEndOfLineAndModifySelection:(id)sender { |
| 335 [self handleAction:IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION |
| 336 keyCode:ui::VKEY_HOME |
| 337 domCode:ui::DomCode::HOME |
| 338 eventFlags:ui::EF_SHIFT_DOWN]; |
| 339 } |
| 340 |
| 341 - (void)moveToRightEndOfLineAndModifySelection:(id)sender { |
| 342 [self handleAction:IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION |
| 343 keyCode:ui::VKEY_END |
| 344 domCode:ui::DomCode::END |
| 345 eventFlags:ui::EF_SHIFT_DOWN]; |
| 346 } |
| 347 |
| 348 // Insertions and Indentations. |
| 349 |
| 350 - (void)insertNewline:(id)sender { |
| 351 [self handleAction:0 |
| 352 keyCode:ui::VKEY_RETURN |
| 353 domCode:ui::DomCode::ENTER |
| 354 eventFlags:0]; |
| 355 } |
| 356 |
| 357 // Deletions. |
| 358 |
| 359 - (void)deleteForward:(id)sender { |
| 360 [self handleAction:IDS_DELETE_FORWARD |
| 361 keyCode:ui::VKEY_DELETE |
| 362 domCode:ui::DomCode::DEL |
| 363 eventFlags:0]; |
| 364 } |
| 365 |
| 366 - (void)deleteBackward:(id)sender { |
| 367 [self handleAction:IDS_DELETE_BACKWARD |
| 368 keyCode:ui::VKEY_BACK |
| 369 domCode:ui::DomCode::BACKSPACE |
| 370 eventFlags:0]; |
| 371 } |
| 372 |
| 373 - (void)deleteWordForward:(id)sender { |
| 374 [self handleAction:IDS_DELETE_WORD_FORWARD |
| 375 keyCode:ui::VKEY_DELETE |
| 376 domCode:ui::DomCode::DEL |
| 377 eventFlags:ui::EF_CONTROL_DOWN]; |
| 378 } |
| 379 |
| 380 - (void)deleteWordBackward:(id)sender { |
| 381 [self handleAction:IDS_DELETE_WORD_BACKWARD |
| 382 keyCode:ui::VKEY_BACK |
| 383 domCode:ui::DomCode::BACKSPACE |
| 384 eventFlags:ui::EF_CONTROL_DOWN]; |
| 385 } |
| 386 |
| 387 // Cancellation. |
| 388 |
| 389 - (void)cancelOperation:(id)sender { |
| 390 [self handleAction:0 |
| 391 keyCode:ui::VKEY_ESCAPE |
| 392 domCode:ui::DomCode::ESCAPE |
| 393 eventFlags:0]; |
226 } | 394 } |
227 | 395 |
228 // Support for Services in context menus. | 396 // Support for Services in context menus. |
229 // Currently we only support reading and writing plain strings. | 397 // Currently we only support reading and writing plain strings. |
230 - (id)validRequestorForSendType:(NSString*)sendType | 398 - (id)validRequestorForSendType:(NSString*)sendType |
231 returnType:(NSString*)returnType { | 399 returnType:(NSString*)returnType { |
232 BOOL canWrite = [sendType isEqualToString:NSStringPboardType] && | 400 BOOL canWrite = [sendType isEqualToString:NSStringPboardType] && |
233 [self selectedRange].length > 0; | 401 [self selectedRange].length > 0; |
234 BOOL canRead = [returnType isEqualToString:NSStringPboardType]; | 402 BOOL canRead = [returnType isEqualToString:NSStringPboardType]; |
235 // Valid if (sendType, returnType) is either (string, nil), (nil, string), | 403 // Valid if (sendType, returnType) is either (string, nil), (nil, string), |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 } | 531 } |
364 | 532 |
365 return [super accessibilityAttributeValue:attribute]; | 533 return [super accessibilityAttributeValue:attribute]; |
366 } | 534 } |
367 | 535 |
368 - (id)accessibilityHitTest:(NSPoint)point { | 536 - (id)accessibilityHitTest:(NSPoint)point { |
369 return [hostedView_->GetNativeViewAccessible() accessibilityHitTest:point]; | 537 return [hostedView_->GetNativeViewAccessible() accessibilityHitTest:point]; |
370 } | 538 } |
371 | 539 |
372 @end | 540 @end |
OLD | NEW |