summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshuchen <shuchen@chromium.org>2015-09-22 09:08:24 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-22 16:09:09 +0000
commit3146b3a43b240dcc6d64d5dc6986a311505104e8 (patch)
treeb0a0a83521fc5179f9ac423ea8a74eb943a21207
parentbcffdcb5dc5b6baa0de7d763ee58d32d4a483b70 (diff)
downloadchromium_src-3146b3a43b240dcc6d64d5dc6986a311505104e8.zip
chromium_src-3146b3a43b240dcc6d64d5dc6986a311505104e8.tar.gz
chromium_src-3146b3a43b240dcc6d64d5dc6986a311505104e8.tar.bz2
Implement "Look Up In Dictionary" context menu item asynchronously. (OS X)
Reduces the number of callers of the synchronous IPC in TextInputClientMac::GetAttributedSubstringFromRange() (so that eventually we can remove it). Note: This is the second attempt to commit cl https://codereview.chromium.org/1313553006, which caused regression crbug.com/528929, because the point getten from selection range may not be accurate to get the string through GetStringAtPoint. This cl fixes that issue by leveraging TextInputClientMsg_StringForRange IPCs instead of TextInputClientMsg_StringAtPoint. The change is cross browser & blink so it is 2-way patches. This cl is based on the blink cl https://codereview.chromium.org/1329103002. TextInputClientObserver::OnStringForRange() will send the IPC TextInputClientReplyMsg_GotStringForRange to carry the basepiont info, which is got by the new change in blink. So this cl should be landed after https://codereview.chromium.org/1329103002 is landed. TBR=sievers@chromium.org BUG=121917 TEST=crbug.com/528929 not repro; Select multiple words and lookup dictionary by context menu can work well; Select non-English words (e.g. Japanese/Chinese) and lookup dictionary by context menu can work well. Review URL: https://codereview.chromium.org/1318483007 Cr-Commit-Position: refs/heads/master@{#350164}
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac.h2
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac.mm56
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.mm33
-rw-r--r--content/browser/renderer_host/text_input_client_mac.h29
-rw-r--r--content/browser/renderer_host/text_input_client_mac.mm32
-rw-r--r--content/browser/renderer_host/text_input_client_message_filter.h3
-rw-r--r--content/browser/renderer_host/text_input_client_message_filter.mm8
-rw-r--r--content/common/text_input_client_messages.h5
-rw-r--r--content/renderer/text_input_client_observer.cc5
9 files changed, 112 insertions, 61 deletions
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index ee840c4..40f7d5b 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -208,6 +208,8 @@ class Layer;
- (void)updateCursor:(NSCursor*)cursor;
- (NSRect)firstViewRectForCharacterRange:(NSRange)theRange
actualRange:(NSRangePointer)actualRange;
+- (void)showLookUpDictionaryOverlayAtPoint:(NSPoint)point;
+- (void)showLookUpDictionaryOverlayFromRange:(NSRange)range;
@end
namespace content {
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 085e9f1..c05856c 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -180,6 +180,8 @@ static BOOL SupportsBackingPropertiesChangedNotification() {
- (void)updateScreenProperties;
- (void)setResponderDelegate:
(NSObject<RenderWidgetHostViewMacDelegate>*)delegate;
+- (void)showLookUpDictionaryOverlayInternal:(NSAttributedString*) string
+ baselinePoint:(NSPoint) baselinePoint;
@end
// A window subclass that allows the fullscreen window to become main and gain
@@ -2430,24 +2432,58 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
}
}
-// This is invoked only on 10.8 or newer when the user taps a word using
-// three fingers.
-- (void)quickLookWithEvent:(NSEvent*)event {
- NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
+- (void)showLookUpDictionaryOverlayInternal:(NSAttributedString*) string
+ baselinePoint:(NSPoint) baselinePoint {
+ if ([string length] == 0) {
+ // The PDF plugin does not support getting the attributed string at point.
+ // Until it does, use NSPerformService(), which opens Dictionary.app.
+ // TODO(shuchen): Support GetStringAtPoint() & GetStringFromRange() for PDF.
+ // See crbug.com/152438.
+ NSString* text = base::SysUTF8ToNSString(
+ renderWidgetHostView_->selected_text());
+ if ([text length] == 0)
+ return;
+ NSPasteboard* pasteboard = [NSPasteboard pasteboardWithUniqueName];
+ NSArray* types = [NSArray arrayWithObject:NSStringPboardType];
+ [pasteboard declareTypes:types owner:nil];
+ if ([pasteboard setString:text forType:NSStringPboardType])
+ NSPerformService(@"Look Up in Dictionary", pasteboard);
+ return;
+ }
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self showDefinitionForAttributedString:string
+ atPoint:baselinePoint];
+ });
+}
+
+- (void)showLookUpDictionaryOverlayFromRange:(NSRange)range {
+ TextInputClientMac::GetInstance()->GetStringFromRange(
+ renderWidgetHostView_->render_widget_host_, range,
+ ^(NSAttributedString* string, NSPoint baselinePoint) {
+ [self showLookUpDictionaryOverlayInternal:string
+ baselinePoint:baselinePoint];
+ }
+ );
+}
+
+- (void)showLookUpDictionaryOverlayAtPoint:(NSPoint)point {
TextInputClientMac::GetInstance()->GetStringAtPoint(
renderWidgetHostView_->render_widget_host_,
gfx::Point(point.x, NSHeight([self frame]) - point.y),
^(NSAttributedString* string, NSPoint baselinePoint) {
- if (string && [string length] > 0) {
- dispatch_async(dispatch_get_main_queue(), ^{
- [self showDefinitionForAttributedString:string
- atPoint:baselinePoint];
- });
- }
+ [self showLookUpDictionaryOverlayInternal:string
+ baselinePoint:baselinePoint];
}
);
}
+// This is invoked only on 10.8 or newer when the user taps a word using
+// three fingers.
+- (void)quickLookWithEvent:(NSEvent*)event {
+ NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
+ [self showLookUpDictionaryOverlayAtPoint:point];
+}
+
// This method handles 2 different types of hardware events.
// (Apple does not distinguish between them).
// a. Scrolling the middle wheel of a mouse.
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.mm b/content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.mm
index 92f10bc2..e004177 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.mm
@@ -22,38 +22,7 @@ void RenderWidgetHostViewMacDictionaryHelper::SetTargetView(
void RenderWidgetHostViewMacDictionaryHelper::ShowDefinitionForSelection() {
NSRange selection_range = [view_->cocoa_view() selectedRange];
- NSAttributedString* attr_string =
- [view_->cocoa_view() attributedSubstringForProposedRange:selection_range
- actualRange:nil];
- if (!attr_string) {
- if (view_->selected_text().empty())
- return;
- // The PDF plugin does not support getting the attributed string. Until it
- // does, use NSPerformService(), which opens Dictionary.app.
- // http://crbug.com/152438
- // TODO(asvitkine): This should be removed after the above support is added.
- NSString* text = base::SysUTF8ToNSString(view_->selected_text());
- NSPasteboard* pasteboard = [NSPasteboard pasteboardWithUniqueName];
- NSArray* types = [NSArray arrayWithObject:NSStringPboardType];
- [pasteboard declareTypes:types owner:nil];
- if ([pasteboard setString:text forType:NSStringPboardType])
- NSPerformService(@"Look Up in Dictionary", pasteboard);
- return;
- }
-
- NSRect rect =
- [view_->cocoa_view() firstViewRectForCharacterRange:selection_range
- actualRange:nil];
-
- NSDictionary* attrs = [attr_string attributesAtIndex:0 effectiveRange:nil];
- NSFont* font = [attrs objectForKey:NSFontAttributeName];
- rect.origin.y += NSHeight(rect) - [font ascender];
-
- rect.origin.x += offset_.x();
- rect.origin.y += offset_.y();
-
- [target_view_->cocoa_view() showDefinitionForAttributedString:attr_string
- atPoint:rect.origin];
+ [view_->cocoa_view() showLookUpDictionaryOverlayFromRange:selection_range];
}
} // namespace content
diff --git a/content/browser/renderer_host/text_input_client_mac.h b/content/browser/renderer_host/text_input_client_mac.h
index d682ebd..02d60142 100644
--- a/content/browser/renderer_host/text_input_client_mac.h
+++ b/content/browser/renderer_host/text_input_client_mac.h
@@ -73,16 +73,31 @@ class CONTENT_EXPORT TextInputClientMac {
// This async method is invoked from RenderWidgetHostViewCocoa's
// -quickLookWithEvent:, when the user taps a word using 3 fingers.
- // The reply callback will be invoked from the IO thread, the caller is
+ // The reply callback will be invoked from the IO thread; the caller is
// responsible for bouncing to the main thread if necessary.
// The callback parameters provide the attributed word under the point and
// the lower left baseline point of the text.
void GetStringAtPoint(RenderWidgetHost* rwh,
gfx::Point point,
- void (^replyHandler)(NSAttributedString*, NSPoint));
+ void (^reply_handler)(NSAttributedString*, NSPoint));
+
// This is called on the IO thread when we get the renderer's reply for
// GetStringAtPoint.
- void GetStringAtPointReply(NSAttributedString*, NSPoint);
+ void GetStringAtPointReply(NSAttributedString* string, NSPoint point);
+
+ // This async method is invoked when browser tries to retreive the text for
+ // certain range and doesn't want to wait for the reply from blink.
+ // The reply callback will be invoked from the IO thread; the caller is
+ // responsible for bouncing to the main thread if necessary.
+ // The callback parameters provide the attributed word under the point and
+ // the lower left baseline point of the text.
+ void GetStringFromRange(RenderWidgetHost* rwh,
+ NSRange range,
+ void (^reply_handler)(NSAttributedString*, NSPoint));
+
+ // This is called on the IO thread when we get the renderer's reply for
+ // GetStringFromRange.
+ void GetStringFromRangeReply(NSAttributedString* string, NSPoint point);
private:
friend struct base::DefaultSingletonTraits<TextInputClientMac>;
@@ -105,7 +120,13 @@ class CONTENT_EXPORT TextInputClientMac {
base::Lock lock_;
base::ConditionVariable condition_;
- base::mac::ScopedBlock<void(^)(NSAttributedString*, NSPoint)> replyHandler_;
+ // The callback when received IPC TextInputClientReplyMsg_GotStringAtPoint.
+ base::mac::ScopedBlock<void(^)(NSAttributedString*, NSPoint)>
+ replyForPointHandler_;
+
+ // The callback when received IPC TextInputClientReplyMsg_GotStringForRange.
+ base::mac::ScopedBlock<void(^)(NSAttributedString*, NSPoint)>
+ replyForRangeHandler_;
DISALLOW_COPY_AND_ASSIGN(TextInputClientMac);
};
diff --git a/content/browser/renderer_host/text_input_client_mac.mm b/content/browser/renderer_host/text_input_client_mac.mm
index dac24b3..58bf35f 100644
--- a/content/browser/renderer_host/text_input_client_mac.mm
+++ b/content/browser/renderer_host/text_input_client_mac.mm
@@ -36,18 +36,38 @@ TextInputClientMac* TextInputClientMac::GetInstance() {
void TextInputClientMac::GetStringAtPoint(
RenderWidgetHost* rwh,
gfx::Point point,
- void (^replyHandler)(NSAttributedString*, NSPoint)) {
- DCHECK(replyHandler_.get() == nil);
- replyHandler_.reset(replyHandler, base::scoped_policy::RETAIN);
+ void (^reply_handler)(NSAttributedString*, NSPoint)) {
+ DCHECK(replyForPointHandler_.get() == nil);
+ replyForPointHandler_.reset(reply_handler, base::scoped_policy::RETAIN);
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
rwhi->Send(new TextInputClientMsg_StringAtPoint(rwhi->GetRoutingID(), point));
}
void TextInputClientMac::GetStringAtPointReply(NSAttributedString* string,
NSPoint point) {
- if (replyHandler_.get()) {
- replyHandler_.get()(string, point);
- replyHandler_.reset();
+ if (replyForPointHandler_.get()) {
+ replyForPointHandler_.get()(string, point);
+ replyForPointHandler_.reset();
+ }
+}
+
+void TextInputClientMac::GetStringFromRange(
+ RenderWidgetHost* rwh,
+ NSRange range,
+ void (^reply_handler)(NSAttributedString*, NSPoint)) {
+ DCHECK(replyForRangeHandler_.get() == nil);
+ replyForRangeHandler_.reset(reply_handler, base::scoped_policy::RETAIN);
+ RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
+ rwhi->Send(new TextInputClientMsg_StringForRange(rwhi->GetRoutingID(),
+ gfx::Range(range)));
+}
+
+void TextInputClientMac::GetStringFromRangeReply(NSAttributedString* string,
+ NSPoint point) {
+ SetSubstringAndSignal(string);
+ if (replyForRangeHandler_.get()) {
+ replyForRangeHandler_.get()(string, point);
+ replyForRangeHandler_.reset();
}
}
diff --git a/content/browser/renderer_host/text_input_client_message_filter.h b/content/browser/renderer_host/text_input_client_message_filter.h
index 1918620..992a9a2 100644
--- a/content/browser/renderer_host/text_input_client_message_filter.h
+++ b/content/browser/renderer_host/text_input_client_message_filter.h
@@ -38,7 +38,8 @@ class CONTENT_EXPORT TextInputClientMessageFilter
void OnGotCharacterIndexForPoint(size_t index);
void OnGotFirstRectForRange(const gfx::Rect& rect);
void OnGotStringFromRange(
- const mac::AttributedStringCoder::EncodedString& string);
+ const mac::AttributedStringCoder::EncodedString& string,
+ const gfx::Point& point);
// Child process id.
int child_process_id_;
diff --git a/content/browser/renderer_host/text_input_client_message_filter.mm b/content/browser/renderer_host/text_input_client_message_filter.mm
index 090daaa..34e9467 100644
--- a/content/browser/renderer_host/text_input_client_message_filter.mm
+++ b/content/browser/renderer_host/text_input_client_message_filter.mm
@@ -65,13 +65,13 @@ void TextInputClientMessageFilter::OnGotFirstRectForRange(
}
void TextInputClientMessageFilter::OnGotStringFromRange(
- const mac::AttributedStringCoder::EncodedString& encoded_string) {
+ const mac::AttributedStringCoder::EncodedString& encoded_string,
+ const gfx::Point& point) {
TextInputClientMac* service = TextInputClientMac::GetInstance();
NSAttributedString* string =
mac::AttributedStringCoder::Decode(&encoded_string);
- if (![string length])
- string = nil;
- service->SetSubstringAndSignal(string);
+ service->GetStringFromRangeReply(
+ string, NSPointFromCGPoint(point.ToCGPoint()));
}
} // namespace content
diff --git a/content/common/text_input_client_messages.h b/content/common/text_input_client_messages.h
index 860bf10..8bd0db2 100644
--- a/content/common/text_input_client_messages.h
+++ b/content/common/text_input_client_messages.h
@@ -53,8 +53,9 @@ IPC_MESSAGE_ROUTED1(TextInputClientReplyMsg_GotFirstRectForRange,
#if defined(OS_MACOSX)
// Reply message for TextInputClientMsg_StringForRange.
-IPC_MESSAGE_ROUTED1(TextInputClientReplyMsg_GotStringForRange,
- mac::AttributedStringCoder::EncodedString)
+IPC_MESSAGE_ROUTED2(TextInputClientReplyMsg_GotStringForRange,
+ mac::AttributedStringCoder::EncodedString,
+ gfx::Point)
// Reply message for TextInputClientMsg_StringAtPoint
IPC_MESSAGE_ROUTED2(TextInputClientReplyMsg_GotStringAtPoint,
diff --git a/content/renderer/text_input_client_observer.cc b/content/renderer/text_input_client_observer.cc
index 049f87c..87c7486 100644
--- a/content/renderer/text_input_client_observer.cc
+++ b/content/renderer/text_input_client_observer.cc
@@ -88,16 +88,17 @@ void TextInputClientObserver::OnFirstRectForCharacterRange(gfx::Range range) {
void TextInputClientObserver::OnStringForRange(gfx::Range range) {
#if defined(OS_MACOSX)
+ blink::WebPoint baselinePoint;
NSAttributedString* string = nil;
blink::WebLocalFrame* frame = webview()->focusedFrame()->toWebLocalFrame();
if (frame) {
string = blink::WebSubstringUtil::attributedSubstringInRange(
- frame, range.start(), range.length());
+ frame, range.start(), range.length(), &baselinePoint);
}
scoped_ptr<const mac::AttributedStringCoder::EncodedString> encoded(
mac::AttributedStringCoder::Encode(string));
Send(new TextInputClientReplyMsg_GotStringForRange(routing_id(),
- *encoded.get()));
+ *encoded.get(), baselinePoint));
#else
NOTIMPLEMENTED();
#endif