Chromium Code Reviews| 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 #include <QuartzCore/QuartzCore.h> | 7 #include <QuartzCore/QuartzCore.h> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| (...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 640 void RenderWidgetHostViewMac::ImeCancelComposition() { | 640 void RenderWidgetHostViewMac::ImeCancelComposition() { |
| 641 [cocoa_view_ cancelComposition]; | 641 [cocoa_view_ cancelComposition]; |
| 642 } | 642 } |
| 643 | 643 |
| 644 void RenderWidgetHostViewMac::ImeCompositionRangeChanged( | 644 void RenderWidgetHostViewMac::ImeCompositionRangeChanged( |
| 645 const ui::Range& range, | 645 const ui::Range& range, |
| 646 const std::vector<gfx::Rect>& character_bounds) { | 646 const std::vector<gfx::Rect>& character_bounds) { |
| 647 // The RangeChanged message is only sent with valid values. The current | 647 // The RangeChanged message is only sent with valid values. The current |
| 648 // caret position (start == end) will be sent if there is no IME range. | 648 // caret position (start == end) will be sent if there is no IME range. |
| 649 [cocoa_view_ setMarkedRange:range.ToNSRange()]; | 649 [cocoa_view_ setMarkedRange:range.ToNSRange()]; |
| 650 composition_range_ = range; | |
| 651 composition_bounds_ = character_bounds; | |
| 650 } | 652 } |
| 651 | 653 |
| 652 void RenderWidgetHostViewMac::DidUpdateBackingStore( | 654 void RenderWidgetHostViewMac::DidUpdateBackingStore( |
| 653 const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy, | 655 const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy, |
| 654 const std::vector<gfx::Rect>& copy_rects) { | 656 const std::vector<gfx::Rect>& copy_rects) { |
| 655 GotSoftwareFrame(); | 657 GotSoftwareFrame(); |
| 656 | 658 |
| 657 if (!is_hidden_) { | 659 if (!is_hidden_) { |
| 658 std::vector<gfx::Rect> rects(copy_rects); | 660 std::vector<gfx::Rect> rects(copy_rects); |
| 659 | 661 |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1032 pending_swap_buffers_acks_.front().first, | 1034 pending_swap_buffers_acks_.front().first, |
| 1033 pending_swap_buffers_acks_.front().second, | 1035 pending_swap_buffers_acks_.front().second, |
| 1034 0); | 1036 0); |
| 1035 if (render_widget_host_) | 1037 if (render_widget_host_) |
| 1036 render_widget_host_->AcknowledgeSwapBuffersToRenderer(); | 1038 render_widget_host_->AcknowledgeSwapBuffersToRenderer(); |
| 1037 } | 1039 } |
| 1038 pending_swap_buffers_acks_.erase(pending_swap_buffers_acks_.begin()); | 1040 pending_swap_buffers_acks_.erase(pending_swap_buffers_acks_.begin()); |
| 1039 } | 1041 } |
| 1040 } | 1042 } |
| 1041 | 1043 |
| 1044 bool RenderWidgetHostViewMac::GetLineBreakIdx( | |
| 1045 const std::vector<gfx::Rect>& bounds, | |
| 1046 const ui::Range& range, | |
| 1047 size_t* line_break_point) { | |
| 1048 DCHECK(line_break_point); | |
| 1049 if (range.start() >= bounds.size() || range.is_reversed() || range.is_empty()) | |
| 1050 return false; | |
| 1051 | |
| 1052 // Detect line break by comparing x value because we can't assume the | |
| 1053 // each character's height is fixed. | |
| 1054 const size_t loop_end_idx = std::min(bounds.size(), range.end()); | |
| 1055 for (size_t idx = range.start(); idx < loop_end_idx - 1; ++idx) { | |
| 1056 if (bounds[idx].x() > bounds[idx + 1].x()) { | |
|
James Su
2012/07/04 01:44:04
I'm wondering if it works for text with complex la
Seigo Nonaka
2012/07/04 06:56:58
Yes, this logic does not work for bidi characters.
| |
| 1057 *line_break_point = idx + 1; | |
| 1058 return true; | |
| 1059 } | |
| 1060 } | |
| 1061 return false; | |
| 1062 } | |
| 1063 | |
| 1064 gfx::Rect RenderWidgetHostViewMac::GetFirstRectForCompositionRange( | |
| 1065 const ui::Range& range) { | |
| 1066 DCHECK(range.start() < composition_bounds_.size()); | |
| 1067 DCHECK(range.end() < composition_bounds_.size()); | |
|
James Su
2012/07/04 01:44:04
start and end may equal to composition_bounds_.siz
Seigo Nonaka
2012/07/04 06:56:58
Done for range.end().
start point is inclusive, so
| |
| 1068 int right = 0; | |
| 1069 if (range.is_empty()) { | |
| 1070 right = composition_bounds_[range.start()].x(); | |
| 1071 } else { | |
| 1072 size_t line_break_idx; | |
| 1073 if (GetLineBreakIdx(composition_bounds_, range, &line_break_idx)) { | |
| 1074 right = composition_bounds_[line_break_idx - 1].right(); | |
| 1075 } else { | |
| 1076 right = composition_bounds_[range.end() - 1].right(); | |
| 1077 } | |
| 1078 } | |
| 1079 return gfx::Rect( | |
| 1080 composition_bounds_[range.start()].x(), | |
| 1081 composition_bounds_[range.start()].y(), | |
| 1082 right - composition_bounds_[range.start()].x(), | |
| 1083 composition_bounds_[range.start()].height()); | |
|
James Su
2012/07/04 01:44:04
I think we should return the union rect of all rec
Seigo Nonaka
2012/07/04 06:56:58
Done.
| |
| 1084 } | |
| 1085 | |
| 1086 ui::Range RenderWidgetHostViewMac::ConvertCharacterRangeToCompositionRange( | |
| 1087 const ui::Range& request_range) { | |
| 1088 if (composition_range_.is_empty()) | |
|
James Su
2012/07/04 01:44:04
I think we probably should handle the empty case,
Seigo Nonaka
2012/07/04 06:56:58
This check means that we don't have any cached com
| |
| 1089 return ui::Range::InvalidRange(); | |
| 1090 | |
| 1091 if (request_range.is_reversed()) | |
| 1092 return ui::Range::InvalidRange(); | |
| 1093 | |
| 1094 if (request_range.start() < composition_range_.start() || | |
| 1095 request_range.start() >= composition_range_.end()) | |
|
James Su
2012/07/04 01:44:04
request_rang.end() > composition_range_.end() ?
Seigo Nonaka
2012/07/04 06:56:58
The end is exclusive, so treating out of range is
| |
| 1096 return ui::Range::InvalidRange(); | |
| 1097 | |
| 1098 return ui::Range( | |
| 1099 request_range.start() - composition_range_.start(), | |
| 1100 request_range.end() - composition_range_.start()); | |
| 1101 } | |
| 1102 | |
| 1103 bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange( | |
| 1104 NSRange range, | |
| 1105 NSRect* rect) { | |
| 1106 TRACE_EVENT0("browser", | |
| 1107 "RenderWidgetHostViewMac::GetFirstRectForCharacterRange"); | |
| 1108 const ui::Range request_range_in_composition = | |
| 1109 ConvertCharacterRangeToCompositionRange(ui::Range(range)); | |
| 1110 if (request_range_in_composition == ui::Range::InvalidRange()) | |
| 1111 return false; | |
| 1112 *rect = NSRectFromCGRect( | |
| 1113 GetFirstRectForCompositionRange(request_range_in_composition).ToCGRect()); | |
| 1114 return true; | |
| 1115 } | |
| 1116 | |
| 1042 void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( | 1117 void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( |
| 1043 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, | 1118 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, |
| 1044 int gpu_host_id) { | 1119 int gpu_host_id) { |
| 1045 TRACE_EVENT0("browser", | 1120 TRACE_EVENT0("browser", |
| 1046 "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped"); | 1121 "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped"); |
| 1047 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1048 | 1123 |
| 1049 pending_swap_buffers_acks_.push_back(std::make_pair(params.route_id, | 1124 pending_swap_buffers_acks_.push_back(std::make_pair(params.route_id, |
| 1050 gpu_host_id)); | 1125 gpu_host_id)); |
| 1051 | 1126 |
| (...skipping 1625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2677 renderWidgetHostView_->render_widget_host_, | 2752 renderWidgetHostView_->render_widget_host_, |
| 2678 gfx::Point(thePoint.x, thePoint.y)); | 2753 gfx::Point(thePoint.x, thePoint.y)); |
| 2679 return index; | 2754 return index; |
| 2680 } | 2755 } |
| 2681 | 2756 |
| 2682 - (NSRect)firstRectForCharacterRange:(NSRange)theRange | 2757 - (NSRect)firstRectForCharacterRange:(NSRange)theRange |
| 2683 actualRange:(NSRangePointer)actualRange { | 2758 actualRange:(NSRangePointer)actualRange { |
| 2684 // TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery. | 2759 // TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery. |
| 2685 if (actualRange) | 2760 if (actualRange) |
| 2686 *actualRange = theRange; | 2761 *actualRange = theRange; |
| 2687 NSRect rect = TextInputClientMac::GetInstance()->GetFirstRectForRange( | 2762 NSRect rect; |
| 2688 renderWidgetHostView_->render_widget_host_, theRange); | 2763 if (!renderWidgetHostView_->GetCachedFirstRectForCharacterRange(theRange, |
| 2764 &rect)) { | |
| 2765 rect = TextInputClientMac::GetInstance()->GetFirstRectForRange( | |
| 2766 renderWidgetHostView_->render_widget_host_, theRange); | |
| 2767 } | |
| 2689 | 2768 |
| 2690 // The returned rectangle is in WebKit coordinates (upper left origin), so | 2769 // The returned rectangle is in WebKit coordinates (upper left origin), so |
| 2691 // flip the coordinate system and then convert it into screen coordinates for | 2770 // flip the coordinate system and then convert it into screen coordinates for |
| 2692 // return. | 2771 // return. |
| 2693 NSRect viewFrame = [self frame]; | 2772 NSRect viewFrame = [self frame]; |
| 2694 rect.origin.y = NSHeight(viewFrame) - rect.origin.y; | 2773 rect.origin.y = NSHeight(viewFrame) - rect.origin.y; |
| 2695 rect.origin.y -= rect.size.height; | 2774 rect.origin.y -= rect.size.height; |
| 2696 rect = [self convertRectToBase:rect]; | 2775 rect = [self convertRectToBase:rect]; |
| 2697 rect.origin = [[self window] convertBaseToScreen:rect.origin]; | 2776 rect.origin = [[self window] convertBaseToScreen:rect.origin]; |
| 2698 return rect; | 2777 return rect; |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3091 if (!string) return NO; | 3170 if (!string) return NO; |
| 3092 | 3171 |
| 3093 // If the user is currently using an IME, confirm the IME input, | 3172 // If the user is currently using an IME, confirm the IME input, |
| 3094 // and then insert the text from the service, the same as TextEdit and Safari. | 3173 // and then insert the text from the service, the same as TextEdit and Safari. |
| 3095 [self confirmComposition]; | 3174 [self confirmComposition]; |
| 3096 [self insertText:string]; | 3175 [self insertText:string]; |
| 3097 return YES; | 3176 return YES; |
| 3098 } | 3177 } |
| 3099 | 3178 |
| 3100 @end | 3179 @end |
| OLD | NEW |