| 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 |