OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "content/browser/renderer_host/render_widget_host_view_mac.h" | 5 #include "content/browser/renderer_host/render_widget_host_view_mac.h" |
6 | 6 |
7 #import <objc/runtime.h> | 7 #import <objc/runtime.h> |
8 #include <OpenGL/gl.h> | 8 #include <OpenGL/gl.h> |
9 #include <QuartzCore/QuartzCore.h> | 9 #include <QuartzCore/QuartzCore.h> |
10 #include <stdint.h> | 10 #include <stdint.h> |
(...skipping 1826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1837 hasOpenMouseDown_ = NO; | 1837 hasOpenMouseDown_ = NO; |
1838 | 1838 |
1839 // TODO(suzhe): We should send mouse events to the input method first if it | 1839 // TODO(suzhe): We should send mouse events to the input method first if it |
1840 // wants to handle them. But it won't work without implementing method | 1840 // wants to handle them. But it won't work without implementing method |
1841 // - (NSUInteger)characterIndexForPoint:. | 1841 // - (NSUInteger)characterIndexForPoint:. |
1842 // See: http://code.google.com/p/chromium/issues/detail?id=47141 | 1842 // See: http://code.google.com/p/chromium/issues/detail?id=47141 |
1843 // Instead of sending mouse events to the input method first, we now just | 1843 // Instead of sending mouse events to the input method first, we now just |
1844 // simply confirm all ongoing composition here. | 1844 // simply confirm all ongoing composition here. |
1845 if (type == NSLeftMouseDown || type == NSRightMouseDown || | 1845 if (type == NSLeftMouseDown || type == NSRightMouseDown || |
1846 type == NSOtherMouseDown) { | 1846 type == NSOtherMouseDown) { |
1847 [self confirmComposition]; | 1847 [self finishComposingText]; |
1848 } | 1848 } |
1849 | 1849 |
1850 WebMouseEvent event = WebMouseEventBuilder::Build(theEvent, self); | 1850 WebMouseEvent event = WebMouseEventBuilder::Build(theEvent, self); |
1851 if (renderWidgetHostView_->ShouldRouteEvent(event)) { | 1851 if (renderWidgetHostView_->ShouldRouteEvent(event)) { |
1852 renderWidgetHostView_->render_widget_host_->delegate() | 1852 renderWidgetHostView_->render_widget_host_->delegate() |
1853 ->GetInputEventRouter() | 1853 ->GetInputEventRouter() |
1854 ->RouteMouseEvent(renderWidgetHostView_.get(), &event); | 1854 ->RouteMouseEvent(renderWidgetHostView_.get(), &event); |
1855 } else { | 1855 } else { |
1856 ui::LatencyInfo latency_info; | 1856 ui::LatencyInfo latency_info; |
1857 latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0); | 1857 latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0); |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2064 } | 2064 } |
2065 | 2065 |
2066 // Calling ForwardKeyboardEvent() could have destroyed the widget. When the | 2066 // Calling ForwardKeyboardEvent() could have destroyed the widget. When the |
2067 // widget was destroyed, |renderWidgetHostView_->render_widget_host_| will | 2067 // widget was destroyed, |renderWidgetHostView_->render_widget_host_| will |
2068 // be set to NULL. So we check it here and return immediately if it's NULL. | 2068 // be set to NULL. So we check it here and return immediately if it's NULL. |
2069 if (!renderWidgetHostView_->render_widget_host_) | 2069 if (!renderWidgetHostView_->render_widget_host_) |
2070 return; | 2070 return; |
2071 | 2071 |
2072 // Then send keypress and/or composition related events. | 2072 // Then send keypress and/or composition related events. |
2073 // If there was a marked text or the text to be inserted is longer than 1 | 2073 // If there was a marked text or the text to be inserted is longer than 1 |
2074 // character, then we send the text by calling ConfirmComposition(). | 2074 // character, then we send the text by calling FinishComposingText(). |
2075 // Otherwise, if the text to be inserted only contains 1 character, then we | 2075 // Otherwise, if the text to be inserted only contains 1 character, then we |
2076 // can just send a keypress event which is fabricated by changing the type of | 2076 // can just send a keypress event which is fabricated by changing the type of |
2077 // the keydown event, so that we can retain all necessary informations, such | 2077 // the keydown event, so that we can retain all necessary informations, such |
2078 // as unmodifiedText, etc. And we need to set event.skip_in_browser to true to | 2078 // as unmodifiedText, etc. And we need to set event.skip_in_browser to true to |
2079 // prevent the browser from handling it again. | 2079 // prevent the browser from handling it again. |
2080 // Note that, |textToBeInserted_| is a UTF-16 string, but it's fine to only | 2080 // Note that, |textToBeInserted_| is a UTF-16 string, but it's fine to only |
2081 // handle BMP characters here, as we can always insert non-BMP characters as | 2081 // handle BMP characters here, as we can always insert non-BMP characters as |
2082 // text. | 2082 // text. |
2083 BOOL textInserted = NO; | 2083 BOOL textInserted = NO; |
2084 if (textToBeInserted_.length() > | 2084 if (textToBeInserted_.length() > |
2085 ((hasMarkedText_ || oldHasMarkedText) ? 0u : 1u)) { | 2085 ((hasMarkedText_ || oldHasMarkedText) ? 0u : 1u)) { |
2086 widgetHost->ImeConfirmComposition( | 2086 widgetHost->ImeCommitText(textToBeInserted_, gfx::Range::InvalidRange(), 0); |
2087 textToBeInserted_, gfx::Range::InvalidRange(), false); | |
2088 textInserted = YES; | 2087 textInserted = YES; |
2089 } | 2088 } |
2090 | 2089 |
2091 // Updates or cancels the composition. If some text has been inserted, then | 2090 // Updates or cancels the composition. If some text has been inserted, then |
2092 // we don't need to cancel the composition explicitly. | 2091 // we don't need to cancel the composition explicitly. |
2093 if (hasMarkedText_ && markedText_.length()) { | 2092 if (hasMarkedText_ && markedText_.length()) { |
2094 // Sends the updated marked text to the renderer so it can update the | 2093 // Sends the updated marked text to the renderer so it can update the |
2095 // composition node in WebKit. | 2094 // composition node in WebKit. |
2096 // When marked text is available, |markedTextSelectedRange_| will be the | 2095 // When marked text is available, |markedTextSelectedRange_| will be the |
2097 // range being selected inside the marked text. | 2096 // range being selected inside the marked text. |
2098 widgetHost->ImeSetComposition(markedText_, underlines_, | 2097 widgetHost->ImeSetComposition(markedText_, underlines_, |
2099 setMarkedTextReplacementRange_, | 2098 setMarkedTextReplacementRange_, |
2100 markedTextSelectedRange_.location, | 2099 markedTextSelectedRange_.location, |
2101 NSMaxRange(markedTextSelectedRange_)); | 2100 NSMaxRange(markedTextSelectedRange_)); |
2102 } else if (oldHasMarkedText && !hasMarkedText_ && !textInserted) { | 2101 } else if (oldHasMarkedText && !hasMarkedText_ && !textInserted) { |
2103 if (unmarkTextCalled_) { | 2102 if (unmarkTextCalled_) { |
2104 widgetHost->ImeConfirmComposition( | 2103 widgetHost->ImeFinishComposingText(false); |
2105 base::string16(), gfx::Range::InvalidRange(), false); | |
2106 } else { | 2104 } else { |
2107 widgetHost->ImeCancelComposition(); | 2105 widgetHost->ImeCancelComposition(); |
2108 } | 2106 } |
2109 } | 2107 } |
2110 | 2108 |
2111 // Clear information from |interpretKeyEvents:| | 2109 // Clear information from |interpretKeyEvents:| |
2112 setMarkedTextReplacementRange_ = gfx::Range::InvalidRange(); | 2110 setMarkedTextReplacementRange_ = gfx::Range::InvalidRange(); |
2113 | 2111 |
2114 // If the key event was handled by the input method but it also generated some | 2112 // If the key event was handled by the input method but it also generated some |
2115 // edit commands, then we need to send the real key event and corresponding | 2113 // edit commands, then we need to send the real key event and corresponding |
(...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2943 // Delete the composition node of the renderer and finish an ongoing | 2941 // Delete the composition node of the renderer and finish an ongoing |
2944 // composition. | 2942 // composition. |
2945 // It seems an input method calls the setMarkedText method and set an empty | 2943 // It seems an input method calls the setMarkedText method and set an empty |
2946 // text when it cancels an ongoing composition, i.e. I have never seen an | 2944 // text when it cancels an ongoing composition, i.e. I have never seen an |
2947 // input method calls this method. | 2945 // input method calls this method. |
2948 hasMarkedText_ = NO; | 2946 hasMarkedText_ = NO; |
2949 markedText_.clear(); | 2947 markedText_.clear(); |
2950 markedTextSelectedRange_ = NSMakeRange(NSNotFound, 0); | 2948 markedTextSelectedRange_ = NSMakeRange(NSNotFound, 0); |
2951 underlines_.clear(); | 2949 underlines_.clear(); |
2952 | 2950 |
2953 // If we are handling a key down event, then ConfirmComposition() will be | 2951 // If we are handling a key down event, then FinishComposingText() will be |
2954 // called in keyEvent: method. | 2952 // called in keyEvent: method. |
2955 if (!handlingKeyDown_) { | 2953 if (!handlingKeyDown_) { |
2956 if (renderWidgetHostView_->GetActiveWidget()) { | 2954 if (renderWidgetHostView_->GetActiveWidget()) { |
2957 renderWidgetHostView_->GetActiveWidget()->ImeConfirmComposition( | 2955 renderWidgetHostView_->GetActiveWidget()->ImeFinishComposingText(false); |
2958 base::string16(), gfx::Range::InvalidRange(), false); | |
2959 } | 2956 } |
2960 } else { | 2957 } else { |
2961 unmarkTextCalled_ = YES; | 2958 unmarkTextCalled_ = YES; |
2962 } | 2959 } |
2963 } | 2960 } |
2964 | 2961 |
2965 - (void)setMarkedText:(id)string selectedRange:(NSRange)newSelRange | 2962 - (void)setMarkedText:(id)string selectedRange:(NSRange)newSelRange |
2966 replacementRange:(NSRange)replacementRange { | 2963 replacementRange:(NSRange)replacementRange { |
2967 // An input method updates the composition string. | 2964 // An input method updates the composition string. |
2968 // We send the given text and range to the renderer so it can update the | 2965 // We send the given text and range to the renderer so it can update the |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3049 // sent as an input method event as well. | 3046 // sent as an input method event as well. |
3050 // TODO(suzhe): It's hard for us to support replacementRange without accessing | 3047 // TODO(suzhe): It's hard for us to support replacementRange without accessing |
3051 // the full web content. | 3048 // the full web content. |
3052 BOOL isAttributedString = [string isKindOfClass:[NSAttributedString class]]; | 3049 BOOL isAttributedString = [string isKindOfClass:[NSAttributedString class]]; |
3053 NSString* im_text = isAttributedString ? [string string] : string; | 3050 NSString* im_text = isAttributedString ? [string string] : string; |
3054 if (handlingKeyDown_) { | 3051 if (handlingKeyDown_) { |
3055 textToBeInserted_.append(base::SysNSStringToUTF16(im_text)); | 3052 textToBeInserted_.append(base::SysNSStringToUTF16(im_text)); |
3056 } else { | 3053 } else { |
3057 gfx::Range replacement_range(replacementRange); | 3054 gfx::Range replacement_range(replacementRange); |
3058 if (renderWidgetHostView_->GetActiveWidget()) { | 3055 if (renderWidgetHostView_->GetActiveWidget()) { |
3059 renderWidgetHostView_->GetActiveWidget()->ImeConfirmComposition( | 3056 renderWidgetHostView_->GetActiveWidget()->ImeCommitText( |
3060 base::SysNSStringToUTF16(im_text), replacement_range, false); | 3057 base::SysNSStringToUTF16(im_text), replacement_range, 0); |
3061 } | 3058 } |
3062 } | 3059 } |
3063 | 3060 |
3064 // Inserting text will delete all marked text automatically. | 3061 // Inserting text will delete all marked text automatically. |
3065 hasMarkedText_ = NO; | 3062 hasMarkedText_ = NO; |
3066 } | 3063 } |
3067 | 3064 |
3068 - (void)insertText:(id)string { | 3065 - (void)insertText:(id)string { |
3069 [self insertText:string replacementRange:NSMakeRange(NSNotFound, 0)]; | 3066 [self insertText:string replacementRange:NSMakeRange(NSNotFound, 0)]; |
3070 } | 3067 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3178 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | 3175 #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
3179 NSInputManager *currentInputManager = [NSInputManager currentInputManager]; | 3176 NSInputManager *currentInputManager = [NSInputManager currentInputManager]; |
3180 [currentInputManager markedTextAbandoned:self]; | 3177 [currentInputManager markedTextAbandoned:self]; |
3181 #pragma clang diagnostic pop | 3178 #pragma clang diagnostic pop |
3182 | 3179 |
3183 hasMarkedText_ = NO; | 3180 hasMarkedText_ = NO; |
3184 // Should not call [self unmarkText] here, because it'll send unnecessary | 3181 // Should not call [self unmarkText] here, because it'll send unnecessary |
3185 // cancel composition IPC message to the renderer. | 3182 // cancel composition IPC message to the renderer. |
3186 } | 3183 } |
3187 | 3184 |
3188 - (void)confirmComposition { | 3185 - (void)finishComposingText { |
3189 if (!hasMarkedText_) | 3186 if (!hasMarkedText_) |
3190 return; | 3187 return; |
3191 | 3188 |
3192 if (renderWidgetHostView_->GetActiveWidget()) { | 3189 if (renderWidgetHostView_->GetActiveWidget()) { |
3193 renderWidgetHostView_->GetActiveWidget()->ImeConfirmComposition( | 3190 renderWidgetHostView_->GetActiveWidget()->ImeFinishComposingText(false); |
3194 base::string16(), gfx::Range::InvalidRange(), false); | |
3195 } | 3191 } |
3196 | 3192 |
3197 [self cancelComposition]; | 3193 [self cancelComposition]; |
3198 } | 3194 } |
3199 | 3195 |
3200 // Overriding a NSResponder method to support application services. | 3196 // Overriding a NSResponder method to support application services. |
3201 | 3197 |
3202 - (id)validRequestorForSendType:(NSString*)sendType | 3198 - (id)validRequestorForSendType:(NSString*)sendType |
3203 returnType:(NSString*)returnType { | 3199 returnType:(NSString*)returnType { |
3204 id requestor = nil; | 3200 id requestor = nil; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3251 [pboard declareTypes:toDeclare owner:nil]; | 3247 [pboard declareTypes:toDeclare owner:nil]; |
3252 return [pboard setString:text forType:NSStringPboardType]; | 3248 return [pboard setString:text forType:NSStringPboardType]; |
3253 } | 3249 } |
3254 | 3250 |
3255 - (BOOL)readSelectionFromPasteboard:(NSPasteboard*)pboard { | 3251 - (BOOL)readSelectionFromPasteboard:(NSPasteboard*)pboard { |
3256 NSString *string = [pboard stringForType:NSStringPboardType]; | 3252 NSString *string = [pboard stringForType:NSStringPboardType]; |
3257 if (!string) return NO; | 3253 if (!string) return NO; |
3258 | 3254 |
3259 // If the user is currently using an IME, confirm the IME input, | 3255 // If the user is currently using an IME, confirm the IME input, |
3260 // and then insert the text from the service, the same as TextEdit and Safari. | 3256 // and then insert the text from the service, the same as TextEdit and Safari. |
3261 [self confirmComposition]; | 3257 [self finishComposingText]; |
3262 [self insertText:string]; | 3258 [self insertText:string]; |
3263 return YES; | 3259 return YES; |
3264 } | 3260 } |
3265 | 3261 |
3266 - (BOOL)isOpaque { | 3262 - (BOOL)isOpaque { |
3267 return opaque_; | 3263 return opaque_; |
3268 } | 3264 } |
3269 | 3265 |
3270 // "-webkit-app-region: drag | no-drag" is implemented on Mac by excluding | 3266 // "-webkit-app-region: drag | no-drag" is implemented on Mac by excluding |
3271 // regions that are not draggable. (See ControlRegionView in | 3267 // regions that are not draggable. (See ControlRegionView in |
3272 // native_app_window_cocoa.mm). This requires the render host view to be | 3268 // native_app_window_cocoa.mm). This requires the render host view to be |
3273 // draggable by default. | 3269 // draggable by default. |
3274 - (BOOL)mouseDownCanMoveWindow { | 3270 - (BOOL)mouseDownCanMoveWindow { |
3275 return YES; | 3271 return YES; |
3276 } | 3272 } |
3277 | 3273 |
3278 @end | 3274 @end |
OLD | NEW |