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

Unified 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: first patch ready for review Created 6 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/link_disambiguation/link_disambiguation_popup.cc
diff --git a/chrome/browser/ui/views/link_disambiguation/link_disambiguation_popup.cc b/chrome/browser/ui/views/link_disambiguation/link_disambiguation_popup.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7b0f488c744bfa3c93a25db8caa189889958f383
--- /dev/null
+++ b/chrome/browser/ui/views/link_disambiguation/link_disambiguation_popup.cc
@@ -0,0 +1,172 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/link_disambiguation/link_disambiguation_popup.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "ui/aura/client/screen_position_client.h"
+#include "ui/events/event.h"
+#include "ui/events/event_processor.h"
+#include "ui/events/event_utils.h"
+#include "ui/events/gesture_event_details.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/views/bubble/bubble_delegate.h"
+#include "ui/views/controls/image_view.h"
+
+class LinkDisambiguationPopup::ZoomBubbleView
+ : public views::BubbleDelegateView {
+ public:
+ typedef base::Callback<void(void)> InvalidationCallback;
+
+ ZoomBubbleView(const gfx::Rect& target_rect,
+ const gfx::ImageSkia* zoomed_skia_image,
+ const aura::Window* content,
+ InvalidationCallback invalidation_cb,
+ content::WebContentsViewDelegate::GestureCallback gesture_cb);
+
+ void Close();
+
+ private:
+ // views::View overrides
+ virtual gfx::Size GetPreferredSize() const OVERRIDE;
+ virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
+
+ // WidgetObserver overrides
+ virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
+
+ float scale_;
+ const aura::Window* content_;
+ content::WebContentsViewDelegate::GestureCallback gesture_cb_;
+ InvalidationCallback invalidation_cb_;
+ gfx::Rect target_rect_;
+};
+
+LinkDisambiguationPopup::ZoomBubbleView::ZoomBubbleView(
+ const gfx::Rect& target_rect,
+ const gfx::ImageSkia* zoomed_skia_image,
+ const aura::Window* content,
+ InvalidationCallback invalidation_cb,
+ content::WebContentsViewDelegate::GestureCallback gesture_cb)
+ : BubbleDelegateView(NULL, views::BubbleBorder::FLOAT),
+ scale_(0.0f),
+ content_(content),
+ gesture_cb_(gesture_cb),
+ invalidation_cb_(invalidation_cb),
+ target_rect_(target_rect) {
+ scale_ = static_cast<float>(zoomed_skia_image->width()) /
+ static_cast<float>(target_rect.width());
+
+ views::ImageView* image_view = new views::ImageView();
+ image_view->SetBounds(
+ 0, 0, zoomed_skia_image->width(), zoomed_skia_image->height());
+ image_view->SetImage(zoomed_skia_image);
+
+ AddChildView(image_view);
+
+ views::BubbleDelegateView::CreateBubble(this);
+}
+
+void LinkDisambiguationPopup::ZoomBubbleView::Close() {
+ if (GetWidget())
+ GetWidget()->Close();
+}
+
+gfx::Size LinkDisambiguationPopup::ZoomBubbleView::GetPreferredSize() const {
+ return target_rect_.size();
+}
+
+void LinkDisambiguationPopup::ZoomBubbleView::OnGestureEvent(
+ ui::GestureEvent* event) {
+ // Scale the gesture event back to the size of the original |target_rect_|,
+ // and then offset it to be relative to that |target_rect_| before sending
+ // it back to the callback.
+ gfx::PointF xform_location(
+ (event->location().x() / scale_) + target_rect_.x(),
+ (event->location().y() / scale_) + target_rect_.y());
+ ui::GestureEventDetails xform_details(event->details());
+ xform_details.set_bounding_box(gfx::RectF(
+ (event->details().bounding_box().x() / scale_) + target_rect_.x(),
+ (event->details().bounding_box().y() / scale_) + target_rect_.y(),
+ event->details().bounding_box().width() / scale_,
+ event->details().bounding_box().height() / scale_));
+ ui::GestureEvent xform_event(xform_location.x(),
+ xform_location.y(),
+ event->flags(),
+ event->time_stamp(),
+ xform_details);
+ gesture_cb_.Run(&xform_event);
+ event->SetHandled();
+
+ // If we completed a tap we close ourselves, as the web content will navigate
+ // if the user hit a link.
+ if (xform_event.type() == ui::EventType::ET_GESTURE_TAP) {
+ invalidation_cb_.Run();
+ Close();
+ }
+}
+
+void LinkDisambiguationPopup::ZoomBubbleView::OnWidgetDestroying(
+ views::Widget* widget) {
+ invalidation_cb_.Run();
+}
+
+LinkDisambiguationPopup::LinkDisambiguationPopup()
+ : view_(NULL) { }
+
+LinkDisambiguationPopup::~LinkDisambiguationPopup() {
+ Close();
+}
+
+void LinkDisambiguationPopup::SetBitmap(const SkBitmap& zoomed_bitmap) {
+ // Need to make a deep copy of this image as it is promptly deleted on behalf
+ // of the caller after this function is called.
+ SkBitmap zoom_copy;
+ if (!zoomed_bitmap.deepCopyTo(&zoom_copy))
+ return;
+ zoomed_image_ = gfx::Image::CreateFrom1xBitmap(zoom_copy);
+}
+
+void LinkDisambiguationPopup::Show(
+ const gfx::Rect& target_rect,
+ const gfx::NativeView content,
+ content::WebContentsViewDelegate::GestureCallback callback) {
+ if (zoomed_image_.IsEmpty())
+ return;
+ content_ = content;
+
+ view_ = new ZoomBubbleView(
+ target_rect,
+ zoomed_image_.ToImageSkia(),
+ content_,
+ base::Bind(&LinkDisambiguationPopup::InvalidateBubbleView,
+ base::Unretained(this)),
+ callback);
+
+ // Center the zoomed bubble over the target rectangle. Since |target_rect|
+ // is provided in |content_| coordinate system, we must convert it into
+ // Screen coordinates for correct window positioning.
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(content_->GetRootWindow());
+ gfx::Point target_screen(target_rect.x(), target_rect.y());
+ if (screen_position_client)
+ screen_position_client->ConvertPointToScreen(content_, &target_screen);
+ int bounds_x = std::max(0, target_screen.x() - (zoomed_image_.Width() / 2));
+ int bounds_y = std::max(0, target_screen.y() - (zoomed_image_.Height() / 2));
+ view_->GetWidget()->SetBounds(gfx::Rect(bounds_x, bounds_y,
+ zoomed_image_.Width(), zoomed_image_.Height()));
+ view_->GetWidget()->Show();
+ view_->GetWidget()->SetCapture(view_);
+}
+
+void LinkDisambiguationPopup::Close() {
+ if (view_) {
+ view_->Close();
+ view_ = NULL;
+ }
+}
+
+void LinkDisambiguationPopup::InvalidateBubbleView() {
+ view_ = NULL;
+}

Powered by Google App Engine
This is Rietveld 408576698