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

Side by Side Diff: chrome/browser/ui/views/link_disambiguation/link_disambiguation_popup.cc

Issue 351683002: Adds link disambiguation popup support to Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: removed scrolling cruft Created 6 years, 4 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
(Empty)
1 // Copyright (c) 2014 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.
4
5 #include "chrome/browser/ui/views/link_disambiguation/link_disambiguation_popup. h"
6
7 #include "ui/aura/client/screen_position_client.h"
8 #include "ui/events/event.h"
9 #include "ui/events/event_processor.h"
10 #include "ui/events/event_utils.h"
11 #include "ui/events/gesture_event_details.h"
12 #include "ui/gfx/display.h"
13 #include "ui/gfx/image/image.h"
14 #include "ui/gfx/image/image_skia.h"
15 #include "ui/gfx/screen.h"
16 #include "ui/views/bubble/bubble_delegate.h"
17 #include "ui/views/controls/image_view.h"
18
19 class LinkDisambiguationPopup::ZoomBubbleView
20 : public views::BubbleDelegateView {
21 public:
22 ZoomBubbleView(const gfx::Rect& target_rect,
23 const gfx::ImageSkia* zoomed_skia_image,
24 const aura::Window* content,
25 LinkDisambiguationPopup* popup,
26 content::WebContentsViewDelegate::GestureCallback gesture_cb);
27
28 void Close();
29
30 private:
31 // views::View overrides
32 virtual gfx::Size GetPreferredSize() const OVERRIDE;
33 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
34
35 // WidgetObserver overrides
36 virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
sky 2014/08/04 20:05:19 This is async. I think OnWidgetClosing should work
luken 2014/09/11 01:07:26 Done.
37
38 float scale_;
39 const aura::Window* content_;
40 content::WebContentsViewDelegate::GestureCallback gesture_cb_;
41 LinkDisambiguationPopup* popup_;
42 const gfx::Rect target_rect_;
43
44 DISALLOW_COPY_AND_ASSIGN(ZoomBubbleView);
45 };
46
47 LinkDisambiguationPopup::ZoomBubbleView::ZoomBubbleView(
48 const gfx::Rect& target_rect,
49 const gfx::ImageSkia* zoomed_skia_image,
50 const aura::Window* content,
51 LinkDisambiguationPopup* popup,
52 content::WebContentsViewDelegate::GestureCallback gesture_cb)
53 : BubbleDelegateView(NULL, views::BubbleBorder::FLOAT),
54 scale_(static_cast<float>(zoomed_skia_image->width()) /
55 static_cast<float>(target_rect.width())),
56 content_(content),
57 gesture_cb_(gesture_cb),
58 popup_(popup),
59 target_rect_(target_rect) {
60 views::ImageView* image_view = new views::ImageView();
61 image_view->SetBounds(
62 0, 0, zoomed_skia_image->width(), zoomed_skia_image->height());
63 image_view->SetImage(zoomed_skia_image);
64
65 AddChildView(image_view);
66
67 views::BubbleDelegateView::CreateBubble(this);
68 }
69
70 void LinkDisambiguationPopup::ZoomBubbleView::Close() {
71 if (GetWidget())
72 GetWidget()->Close();
73 }
74
75 gfx::Size LinkDisambiguationPopup::ZoomBubbleView::GetPreferredSize() const {
76 return target_rect_.size();
77 }
78
79 void LinkDisambiguationPopup::ZoomBubbleView::OnGestureEvent(
80 ui::GestureEvent* event) {
81 // If we receive gesture events that are outside of our bounds we close
82 // ourselves, as perhaps the user has decided on a different part of the page.
83 if (event->location().x() > bounds().width() ||
sky 2014/08/04 20:05:19 Under what circumstances does this happen?
luken 2014/09/11 01:07:26 I found with a debugger that the ZoomBubbleView wo
84 event->location().y() > bounds().height()) {
85 Close();
86 return;
87 }
88
89 // Scale the gesture event back to the size of the original |target_rect_|,
90 // and then offset it to be relative to that |target_rect_| before sending
91 // it back to the callback.
92 gfx::PointF xform_location(
93 (event->location().x() / scale_) + target_rect_.x(),
94 (event->location().y() / scale_) + target_rect_.y());
95 ui::GestureEventDetails xform_details(event->details());
96 xform_details.set_bounding_box(gfx::RectF(
97 (event->details().bounding_box().x() / scale_) + target_rect_.x(),
98 (event->details().bounding_box().y() / scale_) + target_rect_.y(),
99 event->details().bounding_box().width() / scale_,
sky 2014/08/04 20:05:19 Why do you scale the size of the bounding box? Sho
luken 2014/09/11 01:07:26 I found that this worked better than not. The user
100 event->details().bounding_box().height() / scale_));
101 ui::GestureEvent xform_event(xform_location.x(),
102 xform_location.y(),
103 event->flags(),
104 event->time_stamp(),
105 xform_details);
106 gesture_cb_.Run(&xform_event);
107 event->SetHandled();
108
109 // If we completed a tap we close ourselves, as the web content will navigate
110 // if the user hit a link.
111 if (xform_event.type() == ui::EventType::ET_GESTURE_TAP)
112 Close();
113 }
114
115 void LinkDisambiguationPopup::ZoomBubbleView::OnWidgetDestroying(
116 views::Widget* widget) {
117 popup_->InvalidateBubbleView();
118 }
119
120 LinkDisambiguationPopup::LinkDisambiguationPopup()
121 : content_(NULL),
122 view_(NULL) {
123 }
124
125 LinkDisambiguationPopup::~LinkDisambiguationPopup() {
126 Close();
127 }
128
129 void LinkDisambiguationPopup::Show(
130 const SkBitmap& zoomed_bitmap,
131 const gfx::Rect& target_rect,
132 const gfx::NativeView content,
133 const content::WebContentsViewDelegate::GestureCallback& callback) {
134 content_ = content;
135
136 view_ = new ZoomBubbleView(
137 target_rect,
138 gfx::Image::CreateFrom1xBitmap(zoomed_bitmap).ToImageSkia(),
139 content_,
140 this,
141 callback);
142
143 // Center the zoomed bubble over the target rectangle, constrained to the
144 // work area in the current display. Since |target_rect| is provided in
145 // |content_| coordinate system, we must convert it into Screen coordinates
146 // for correct window positioning.
147 aura::client::ScreenPositionClient* screen_position_client =
148 aura::client::GetScreenPositionClient(content_->GetRootWindow());
149 gfx::Point target_screen(target_rect.x() + (target_rect.width() / 2),
150 target_rect.y() + (target_rect.height() / 2));
151 if (screen_position_client)
152 screen_position_client->ConvertPointToScreen(content_, &target_screen);
153 const gfx::Display display =
154 gfx::Screen::GetScreenFor(content)->GetDisplayNearestWindow(content);
155 gfx::Insets work_area = display.GetWorkAreaInsets();
156 int bounds_x = std::max(work_area.left(),
sky 2014/08/04 20:05:19 AdjustRectToFit?
luken 2014/09/11 01:07:26 Done.
157 target_screen.x() - (zoomed_bitmap.width() / 2));
158 int bounds_y = std::max(work_area.top(),
159 target_screen.y() - (zoomed_bitmap.height() / 2));
160 view_->GetWidget()->SetBounds(gfx::Rect(
161 bounds_x, bounds_y, zoomed_bitmap.width(), zoomed_bitmap.height()));
162 view_->GetWidget()->Show();
163 }
164
165 void LinkDisambiguationPopup::Close() {
166 if (view_) {
167 view_->Close();
168 view_ = NULL;
169 }
170 }
171
172 void LinkDisambiguationPopup::InvalidateBubbleView() {
173 view_ = NULL;
174 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698