Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: content/browser/renderer_host/render_widget_host_view_mac.mm

Issue 10656019: Use cached composition bounds for firstRectForCharacterRange (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fix style nits Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 617 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 // See http://crbug.com/73039. 628 // See http://crbug.com/73039.
629 [NSApp updateWindows]; 629 [NSApp updateWindows];
630 UseInputWindow(TSMGetActiveDocument(), !can_compose_inline_); 630 UseInputWindow(TSMGetActiveDocument(), !can_compose_inline_);
631 } 631 }
632 } 632 }
633 } 633 }
634 634
635 void RenderWidgetHostViewMac::SelectionBoundsChanged( 635 void RenderWidgetHostViewMac::SelectionBoundsChanged(
636 const gfx::Rect& start_rect, 636 const gfx::Rect& start_rect,
637 const gfx::Rect& end_rect) { 637 const gfx::Rect& end_rect) {
638 if (start_rect == end_rect)
639 caret_rect_ = start_rect;
638 } 640 }
639 641
640 void RenderWidgetHostViewMac::ImeCancelComposition() { 642 void RenderWidgetHostViewMac::ImeCancelComposition() {
641 [cocoa_view_ cancelComposition]; 643 [cocoa_view_ cancelComposition];
642 } 644 }
643 645
644 void RenderWidgetHostViewMac::ImeCompositionRangeChanged( 646 void RenderWidgetHostViewMac::ImeCompositionRangeChanged(
645 const ui::Range& range, 647 const ui::Range& range,
646 const std::vector<gfx::Rect>& character_bounds) { 648 const std::vector<gfx::Rect>& character_bounds) {
647 // The RangeChanged message is only sent with valid values. The current 649 // 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. 650 // caret position (start == end) will be sent if there is no IME range.
649 [cocoa_view_ setMarkedRange:range.ToNSRange()]; 651 [cocoa_view_ setMarkedRange:range.ToNSRange()];
652 composition_range_ = range;
653 composition_bounds_ = character_bounds;
650 } 654 }
651 655
652 void RenderWidgetHostViewMac::DidUpdateBackingStore( 656 void RenderWidgetHostViewMac::DidUpdateBackingStore(
653 const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy, 657 const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
654 const std::vector<gfx::Rect>& copy_rects) { 658 const std::vector<gfx::Rect>& copy_rects) {
655 GotSoftwareFrame(); 659 GotSoftwareFrame();
656 660
657 if (!is_hidden_) { 661 if (!is_hidden_) {
658 std::vector<gfx::Rect> rects(copy_rects); 662 std::vector<gfx::Rect> rects(copy_rects);
659 663
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
783 selected_text_ = UTF16ToUTF8(text.substr(pos, n)); 787 selected_text_ = UTF16ToUTF8(text.substr(pos, n));
784 } 788 }
785 789
786 [cocoa_view_ setSelectedRange:range.ToNSRange()]; 790 [cocoa_view_ setSelectedRange:range.ToNSRange()];
787 // Updaes markedRange when there is no marked text so that retrieving 791 // Updaes markedRange when there is no marked text so that retrieving
788 // markedRange immediately after calling setMarkdText: returns the current 792 // markedRange immediately after calling setMarkdText: returns the current
789 // caret position. 793 // caret position.
790 if (![cocoa_view_ hasMarkedText]) { 794 if (![cocoa_view_ hasMarkedText]) {
791 [cocoa_view_ setMarkedRange:range.ToNSRange()]; 795 [cocoa_view_ setMarkedRange:range.ToNSRange()];
792 } 796 }
797
798 RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
793 } 799 }
794 800
795 void RenderWidgetHostViewMac::SetShowingContextMenu(bool showing) { 801 void RenderWidgetHostViewMac::SetShowingContextMenu(bool showing) {
796 content::RenderWidgetHostViewBase::SetShowingContextMenu(showing); 802 content::RenderWidgetHostViewBase::SetShowingContextMenu(showing);
797 803
798 // Create a fake mouse event to inform the render widget that the mouse 804 // Create a fake mouse event to inform the render widget that the mouse
799 // left or entered. 805 // left or entered.
800 NSWindow* window = [cocoa_view_ window]; 806 NSWindow* window = [cocoa_view_ window];
801 // TODO(asvitkine): If the location outside of the event stream doesn't 807 // TODO(asvitkine): If the location outside of the event stream doesn't
802 // correspond to the current event (due to delayed event processing), then 808 // correspond to the current event (due to delayed event processing), then
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
1032 pending_swap_buffers_acks_.front().first, 1038 pending_swap_buffers_acks_.front().first,
1033 pending_swap_buffers_acks_.front().second, 1039 pending_swap_buffers_acks_.front().second,
1034 0); 1040 0);
1035 if (render_widget_host_) 1041 if (render_widget_host_)
1036 render_widget_host_->AcknowledgeSwapBuffersToRenderer(); 1042 render_widget_host_->AcknowledgeSwapBuffersToRenderer();
1037 } 1043 }
1038 pending_swap_buffers_acks_.erase(pending_swap_buffers_acks_.begin()); 1044 pending_swap_buffers_acks_.erase(pending_swap_buffers_acks_.begin());
1039 } 1045 }
1040 } 1046 }
1041 1047
1048 bool RenderWidgetHostViewMac::GetLineBreakIdx(
1049 const std::vector<gfx::Rect>& bounds,
1050 const ui::Range& range,
1051 size_t* line_break_point) {
1052 DCHECK(line_break_point);
1053 if (range.start() >= bounds.size() || range.is_reversed() || range.is_empty())
1054 return false;
1055
1056 // We can't check line breaking completely from only rectangle array. Thus we
1057 // assume the line breaking as the next character's y offset is larger than
1058 // a threshold. Currently the threshold is determined as minimum y offset plus
1059 // 75% of maximum height.
1060 // TODO(nona): Check the threshold is reliable or not.
1061 // TODO(nona): Bidi support.
1062 const size_t loop_end_idx = std::min(bounds.size(), range.end());
1063 int max_height = 0;
1064 int min_y_offset = kint32max;
1065 for (size_t idx = range.start(); idx < loop_end_idx; ++idx) {
1066 max_height = std::max(max_height, bounds[idx].height());
1067 min_y_offset = std::min(min_y_offset, bounds[idx].y());
1068 }
1069 int line_break_threshold = min_y_offset + (max_height * 3 / 4);
1070 for (size_t idx = range.start(); idx < loop_end_idx; ++idx) {
1071 if (bounds[idx].y() > line_break_threshold) {
1072 *line_break_point = idx;
1073 return true;
1074 }
1075 }
1076 return false;
1077 }
1078
1079 gfx::Rect RenderWidgetHostViewMac::GetFirstRectForCompositionRange(
1080 const ui::Range& range,
1081 ui::Range* actual_range) {
1082 DCHECK(actual_range);
1083 DCHECK(!composition_bounds_.empty());
1084 DCHECK(range.start() <= composition_bounds_.size());
1085 DCHECK(range.end() <= composition_bounds_.size());
1086
1087 if (range.is_empty()) {
1088 *actual_range = range;
1089 if (range.start() == composition_bounds_.size()) {
1090 return gfx::Rect(composition_bounds_[range.start() - 1].right(),
1091 composition_bounds_[range.start() - 1].y(),
1092 0,
1093 composition_bounds_[range.start() - 1].height());
1094 } else {
1095 return gfx::Rect(composition_bounds_[range.start()].x(),
1096 composition_bounds_[range.start()].y(),
1097 0,
1098 composition_bounds_[range.start()].height());
1099 }
1100 }
1101
1102 size_t end_idx;
1103 if (!GetLineBreakIdx(composition_bounds_, range, &end_idx)) {
1104 end_idx = range.end();
1105 }
1106 *actual_range = ui::Range(range.start(), end_idx);
1107 gfx::Rect rect = composition_bounds_[range.start()];
1108 for (size_t i = range.start() + 1; i < end_idx; ++i) {
1109 rect = rect.Union(composition_bounds_[i]);
1110 }
1111 return rect;
1112 }
1113
1114 ui::Range RenderWidgetHostViewMac::ConvertCharacterRangeToCompositionRange(
1115 const ui::Range& request_range) {
1116 if (composition_range_.is_empty())
1117 return ui::Range::InvalidRange();
1118
1119 if (request_range.is_reversed())
1120 return ui::Range::InvalidRange();
1121
1122 if (request_range.start() < composition_range_.start() ||
1123 request_range.start() > composition_range_.end() ||
1124 request_range.end() > composition_range_.end()) {
1125 return ui::Range::InvalidRange();
1126 }
1127
1128 return ui::Range(
1129 request_range.start() - composition_range_.start(),
1130 request_range.end() - composition_range_.start());
1131 }
1132
1133 bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange(
1134 NSRange range,
Nico 2012/07/21 16:43:27 nit: indent arguments 4
Seigo Nonaka 2012/07/23 08:36:55 Done.
1135 NSRect* rect,
1136 NSRange* actual_range) {
Nico 2012/07/21 16:43:27 Add a comment "// This exists to make IMEs more re
Seigo Nonaka 2012/07/23 08:36:55 Done.
1137 TRACE_EVENT0("browser",
1138 "RenderWidgetHostViewMac::GetFirstRectForCharacterRange");
1139
1140 // If requested range is same as caret location, we can just return it.
1141 if (selection_range_.is_empty() && ui::Range(range) == selection_range_) {
1142 *actual_range = range;
1143 *rect = NSRectFromCGRect(caret_rect_.ToCGRect());
1144 return true;
1145 }
1146
1147 const ui::Range request_range_in_composition =
1148 ConvertCharacterRangeToCompositionRange(ui::Range(range));
Nico 2012/07/21 16:43:27 nit: indent continuations 2 more
Seigo Nonaka 2012/07/23 08:36:55 Done.
1149 if (request_range_in_composition == ui::Range::InvalidRange())
1150 return false;
1151
1152 ui::Range ui_actual_range;
1153 *rect = NSRectFromCGRect(GetFirstRectForCompositionRange(
1154 request_range_in_composition,
1155 &ui_actual_range).ToCGRect());
1156 if (actual_range) {
1157 *actual_range = ui::Range(
1158 composition_range_.start() + ui_actual_range.start(),
1159 composition_range_.start() + ui_actual_range.end()).ToNSRange();
1160 }
1161 return true;
1162 }
1163
1042 void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( 1164 void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped(
1043 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, 1165 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
1044 int gpu_host_id) { 1166 int gpu_host_id) {
1045 TRACE_EVENT0("browser", 1167 TRACE_EVENT0("browser",
1046 "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped"); 1168 "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped");
1047 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1048 1170
1049 pending_swap_buffers_acks_.push_back(std::make_pair(params.route_id, 1171 pending_swap_buffers_acks_.push_back(std::make_pair(params.route_id,
1050 gpu_host_id)); 1172 gpu_host_id));
1051 1173
(...skipping 1622 matching lines...) Expand 10 before | Expand all | Expand 10 after
2674 2796
2675 NSUInteger index = 2797 NSUInteger index =
2676 TextInputClientMac::GetInstance()->GetCharacterIndexAtPoint( 2798 TextInputClientMac::GetInstance()->GetCharacterIndexAtPoint(
2677 renderWidgetHostView_->render_widget_host_, 2799 renderWidgetHostView_->render_widget_host_,
2678 gfx::Point(thePoint.x, thePoint.y)); 2800 gfx::Point(thePoint.x, thePoint.y));
2679 return index; 2801 return index;
2680 } 2802 }
2681 2803
2682 - (NSRect)firstRectForCharacterRange:(NSRange)theRange 2804 - (NSRect)firstRectForCharacterRange:(NSRange)theRange
2683 actualRange:(NSRangePointer)actualRange { 2805 actualRange:(NSRangePointer)actualRange {
2684 // TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery. 2806 NSRect rect;
2685 if (actualRange) 2807 if (!renderWidgetHostView_->GetCachedFirstRectForCharacterRange(
2686 *actualRange = theRange; 2808 theRange,
2687 NSRect rect = TextInputClientMac::GetInstance()->GetFirstRectForRange( 2809 &rect,
2688 renderWidgetHostView_->render_widget_host_, theRange); 2810 actualRange)) {
2811 rect = TextInputClientMac::GetInstance()->GetFirstRectForRange(
2812 renderWidgetHostView_->render_widget_host_, theRange);
2813
2814 // TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery.
2815 if (actualRange)
2816 *actualRange = theRange;
2817 }
2689 2818
2690 // The returned rectangle is in WebKit coordinates (upper left origin), so 2819 // The returned rectangle is in WebKit coordinates (upper left origin), so
2691 // flip the coordinate system and then convert it into screen coordinates for 2820 // flip the coordinate system and then convert it into screen coordinates for
2692 // return. 2821 // return.
2693 NSRect viewFrame = [self frame]; 2822 NSRect viewFrame = [self frame];
2694 rect.origin.y = NSHeight(viewFrame) - rect.origin.y; 2823 rect.origin.y = NSHeight(viewFrame) - rect.origin.y;
2695 rect.origin.y -= rect.size.height; 2824 rect.origin.y -= rect.size.height;
2696 rect = [self convertRectToBase:rect]; 2825 rect = [self convertRectToBase:rect];
2697 rect.origin = [[self window] convertBaseToScreen:rect.origin]; 2826 rect.origin = [[self window] convertBaseToScreen:rect.origin];
2698 return rect; 2827 return rect;
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
3091 if (!string) return NO; 3220 if (!string) return NO;
3092 3221
3093 // If the user is currently using an IME, confirm the IME input, 3222 // 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. 3223 // and then insert the text from the service, the same as TextEdit and Safari.
3095 [self confirmComposition]; 3224 [self confirmComposition];
3096 [self insertText:string]; 3225 [self insertText:string];
3097 return YES; 3226 return YES;
3098 } 3227 }
3099 3228
3100 @end 3229 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698