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