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
3 // found in the LICENSE file.
5 #import <Cocoa/Cocoa.h>
7 #include "chrome/browser/speech/speech_recognition_bubble.h"
9 #import "base/mac/scoped_nsobject.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
12 #include "chrome/browser/ui/cocoa/browser_window_controller.h"
13 #include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
14 #import "chrome/browser/ui/cocoa/speech_recognition_window_controller.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/browser/web_contents_view.h"
17 #include "ui/gfx/image/image_skia_util_mac.h"
19 using content::WebContents;
23 // A class to bridge between the speech recognition C++ code and the Objective-C
24 // bubble implementation. See chrome/browser/speech/speech_recognition_bubble.h
25 // for more information on how this gets used.
26 class SpeechRecognitionBubbleImpl : public SpeechRecognitionBubbleBase {
28 SpeechRecognitionBubbleImpl(WebContents* web_contents,
30 const gfx::Rect& element_rect);
31 virtual ~SpeechRecognitionBubbleImpl();
32 virtual void Show() OVERRIDE;
33 virtual void Hide() OVERRIDE;
34 virtual void UpdateLayout() OVERRIDE;
35 virtual void UpdateImage() OVERRIDE;
38 base::scoped_nsobject<SpeechRecognitionWindowController> window_;
40 gfx::Rect element_rect_;
43 SpeechRecognitionBubbleImpl::SpeechRecognitionBubbleImpl(
44 WebContents* web_contents,
46 const gfx::Rect& element_rect)
47 : SpeechRecognitionBubbleBase(web_contents),
49 element_rect_(element_rect) {
52 SpeechRecognitionBubbleImpl::~SpeechRecognitionBubbleImpl() {
54 [window_.get() close];
57 void SpeechRecognitionBubbleImpl::UpdateImage() {
59 [window_.get() setImage:gfx::NSImageFromImageSkia(icon_image())];
62 void SpeechRecognitionBubbleImpl::Show() {
68 // Find the screen coordinates for the given tab and position the bubble's
69 // arrow anchor point inside that to point at the bottom-left of the html
70 // input element rect if the position is valid, otherwise point it towards
71 // the page icon in the omnibox.
72 gfx::NativeView view = GetWebContents()->GetView()->GetNativeView();
73 NSWindow* parent_window = [view window];
74 NSRect tab_bounds = [view bounds];
75 int anchor_x = tab_bounds.origin.x + element_rect_.x() +
76 element_rect_.width() - kBubbleTargetOffsetX;
77 int anchor_y = tab_bounds.origin.y + tab_bounds.size.height -
78 element_rect_.y() - element_rect_.height();
80 NSPoint anchor = NSMakePoint(anchor_x, anchor_y);
81 if (NSPointInRect(anchor, tab_bounds)) {
82 // Good, convert to window coordinates.
83 anchor = [view convertPoint:anchor toView:nil];
85 LocationBarViewMac* locationBar =
86 [[parent_window windowController] locationBarBridge];
89 anchor = locationBar->GetPageInfoBubblePoint();
91 // This is very rare, but possible. Just use the top-left corner.
92 // See http://crbug.com/119237
93 anchor = NSMakePoint(NSMinX(tab_bounds), NSMaxY(tab_bounds));
94 anchor = [view convertPoint:anchor toView:nil];
98 anchor = [parent_window convertBaseToScreen:anchor];
100 window_.reset([[SpeechRecognitionWindowController alloc]
101 initWithParentWindow:parent_window
106 [window_.get() show];
109 void SpeechRecognitionBubbleImpl::Hide() {
113 [window_.get() close];
117 void SpeechRecognitionBubbleImpl::UpdateLayout() {
121 [window_.get() updateLayout:display_mode()
122 messageText:message_text()
123 iconImage:gfx::NSImageFromImageSkia(icon_image())];
128 SpeechRecognitionBubble* SpeechRecognitionBubble::CreateNativeBubble(
129 WebContents* web_contents,
131 const gfx::Rect& element_rect) {
132 return new SpeechRecognitionBubbleImpl(web_contents, delegate, element_rect);