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 // TODO(nona): Bidi support. | |
James Su
2012/07/05 01:44:26
Yes, Bidi supporting is a big problem, besides it,
Seigo Nonaka
2012/07/05 06:59:45
Done.
| |
1055 const size_t loop_end_idx = std::min(bounds.size(), range.end()); | |
1056 for (size_t idx = range.start(); idx < loop_end_idx - 1; ++idx) { | |
1057 if (bounds[idx].x() > bounds[idx + 1].x()) { | |
1058 *line_break_point = idx + 1; | |
1059 return true; | |
1060 } | |
1061 } | |
1062 return false; | |
1063 } | |
1064 | |
1065 gfx::Rect RenderWidgetHostViewMac::GetFirstRectForCompositionRange( | |
1066 const ui::Range& range) { | |
1067 DCHECK(range.start() < composition_bounds_.size()); | |
James Su
2012/07/05 01:44:26
I'm still wondering if it's possible that an IME w
Seigo Nonaka
2012/07/05 06:59:45
Done.
| |
1068 DCHECK(range.end() <= composition_bounds_.size()); | |
1069 | |
1070 if (range.is_empty()) { | |
1071 return gfx::Rect(composition_bounds_[range.start()].x(), | |
1072 composition_bounds_[range.start()].y(), | |
1073 0, | |
1074 composition_bounds_[range.start()].height()); | |
1075 } | |
1076 | |
1077 size_t end_idx; | |
1078 if (!GetLineBreakIdx(composition_bounds_, range, &end_idx)) { | |
1079 end_idx = range.end(); | |
1080 } | |
1081 gfx::Rect rect = composition_bounds_[range.start()]; | |
1082 for (size_t i = range.start() + 1; i < end_idx; ++i) { | |
1083 rect = rect.Union(composition_bounds_[i]); | |
1084 } | |
1085 return rect; | |
1086 } | |
1087 | |
1088 ui::Range RenderWidgetHostViewMac::ConvertCharacterRangeToCompositionRange( | |
1089 const ui::Range& request_range) { | |
1090 if (composition_range_.is_empty()) | |
James Su
2012/07/05 01:44:26
I think it's better to return correct rect for an
Seigo Nonaka
2012/07/05 06:59:45
composition_range_.is_empty() == true means there
| |
1091 return ui::Range::InvalidRange(); | |
1092 | |
1093 if (request_range.is_reversed()) | |
1094 return ui::Range::InvalidRange(); | |
1095 | |
1096 if (request_range.start() < composition_range_.start() || | |
1097 request_range.start() >= composition_range_.end()) | |
James Su
2012/07/05 01:44:26
request_range.start() may equal to composition_ran
Seigo Nonaka
2012/07/05 06:59:45
Done.
| |
1098 return ui::Range::InvalidRange(); | |
1099 | |
1100 return ui::Range( | |
1101 request_range.start() - composition_range_.start(), | |
1102 request_range.end() - composition_range_.start()); | |
1103 } | |
1104 | |
1105 bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange( | |
1106 NSRange range, | |
1107 NSRect* rect) { | |
1108 TRACE_EVENT0("browser", | |
1109 "RenderWidgetHostViewMac::GetFirstRectForCharacterRange"); | |
1110 const ui::Range request_range_in_composition = | |
1111 ConvertCharacterRangeToCompositionRange(ui::Range(range)); | |
1112 if (request_range_in_composition == ui::Range::InvalidRange()) | |
1113 return false; | |
1114 *rect = NSRectFromCGRect( | |
1115 GetFirstRectForCompositionRange(request_range_in_composition).ToCGRect()); | |
1116 return true; | |
1117 } | |
1118 | |
1042 void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( | 1119 void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( |
1043 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, | 1120 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, |
1044 int gpu_host_id) { | 1121 int gpu_host_id) { |
1045 TRACE_EVENT0("browser", | 1122 TRACE_EVENT0("browser", |
1046 "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped"); | 1123 "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped"); |
1047 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1048 | 1125 |
1049 pending_swap_buffers_acks_.push_back(std::make_pair(params.route_id, | 1126 pending_swap_buffers_acks_.push_back(std::make_pair(params.route_id, |
1050 gpu_host_id)); | 1127 gpu_host_id)); |
1051 | 1128 |
(...skipping 1624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2676 TextInputClientMac::GetInstance()->GetCharacterIndexAtPoint( | 2753 TextInputClientMac::GetInstance()->GetCharacterIndexAtPoint( |
2677 renderWidgetHostView_->render_widget_host_, | 2754 renderWidgetHostView_->render_widget_host_, |
2678 gfx::Point(thePoint.x, thePoint.y)); | 2755 gfx::Point(thePoint.x, thePoint.y)); |
2679 return index; | 2756 return index; |
2680 } | 2757 } |
2681 | 2758 |
2682 - (NSRect)firstRectForCharacterRange:(NSRange)theRange | 2759 - (NSRect)firstRectForCharacterRange:(NSRange)theRange |
2683 actualRange:(NSRangePointer)actualRange { | 2760 actualRange:(NSRangePointer)actualRange { |
2684 // TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery. | 2761 // TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery. |
2685 if (actualRange) | 2762 if (actualRange) |
2686 *actualRange = theRange; | 2763 *actualRange = theRange; |
James Su
2012/07/05 01:44:26
Can you please help fix the logic of actualRange?
Seigo Nonaka
2012/07/05 06:59:45
Done for chached rectangle.
On 2012/07/05 01:44:2
| |
2687 NSRect rect = TextInputClientMac::GetInstance()->GetFirstRectForRange( | 2764 NSRect rect; |
2688 renderWidgetHostView_->render_widget_host_, theRange); | 2765 if (!renderWidgetHostView_->GetCachedFirstRectForCharacterRange(theRange, |
2766 &rect)) { | |
2767 rect = TextInputClientMac::GetInstance()->GetFirstRectForRange( | |
2768 renderWidgetHostView_->render_widget_host_, theRange); | |
2769 } | |
2689 | 2770 |
2690 // The returned rectangle is in WebKit coordinates (upper left origin), so | 2771 // The returned rectangle is in WebKit coordinates (upper left origin), so |
2691 // flip the coordinate system and then convert it into screen coordinates for | 2772 // flip the coordinate system and then convert it into screen coordinates for |
2692 // return. | 2773 // return. |
2693 NSRect viewFrame = [self frame]; | 2774 NSRect viewFrame = [self frame]; |
2694 rect.origin.y = NSHeight(viewFrame) - rect.origin.y; | 2775 rect.origin.y = NSHeight(viewFrame) - rect.origin.y; |
2695 rect.origin.y -= rect.size.height; | 2776 rect.origin.y -= rect.size.height; |
2696 rect = [self convertRectToBase:rect]; | 2777 rect = [self convertRectToBase:rect]; |
2697 rect.origin = [[self window] convertBaseToScreen:rect.origin]; | 2778 rect.origin = [[self window] convertBaseToScreen:rect.origin]; |
2698 return rect; | 2779 return rect; |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3091 if (!string) return NO; | 3172 if (!string) return NO; |
3092 | 3173 |
3093 // If the user is currently using an IME, confirm the IME input, | 3174 // 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. | 3175 // and then insert the text from the service, the same as TextEdit and Safari. |
3095 [self confirmComposition]; | 3176 [self confirmComposition]; |
3096 [self insertText:string]; | 3177 [self insertText:string]; |
3097 return YES; | 3178 return YES; |
3098 } | 3179 } |
3099 | 3180 |
3100 @end | 3181 @end |
OLD | NEW |