1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/webui/ash/lobster/lobster_view.h"
#include "ash/constants/ash_features.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/rect.h"
namespace ash {
namespace {
constexpr int kLobsterAnchorVerticalPadding = 16;
constexpr int kLobsterScreenEdgePadding = 16;
constexpr int kLobsterResultCornerRadius = 20;
constexpr int kLobsterHeightThreshold = 400;
} // namespace
LobsterView::LobsterView(WebUIContentsWrapper* contents_wrapper,
const gfx::Rect& caret_bounds)
: DraggableBubbleDialogView(contents_wrapper), caret_bounds_(caret_bounds) {
set_has_parent(false);
set_corner_radius(kLobsterResultCornerRadius);
// Disable the default offscreen adjustment so that we can customise it.
set_adjust_if_offscreen(false);
}
LobsterView::~LobsterView() = default;
void LobsterView::ResizeDueToAutoResize(content::WebContents* source,
const gfx::Size& new_size) {
WebUIBubbleDialogView::ResizeDueToAutoResize(source, new_size);
gfx::Rect screen_work_area = display::Screen::GetScreen()
->GetDisplayMatching(caret_bounds_)
.work_area();
screen_work_area.Inset(kLobsterScreenEdgePadding);
// If the contents is very tall, just place it at the center of the screen.
if (new_size.height() > kLobsterHeightThreshold) {
SetArrowWithoutResizing(views::BubbleBorder::FLOAT);
SetAnchorRect(screen_work_area);
return;
}
// Otherwise, try to place it under at the bottom left of the selection.
gfx::Rect anchor = caret_bounds_;
anchor.Outset(gfx::Outsets::VH(kLobsterAnchorVerticalPadding, 0));
gfx::Rect lobster_contents_bounds = gfx::Rect(anchor.bottom_left(), new_size);
// If horizontally offscreen, just move it to the right edge of the screen.
if (lobster_contents_bounds.right() > screen_work_area.right()) {
lobster_contents_bounds.set_x(screen_work_area.right() - new_size.width());
}
// If vertically offscreen, try above the selection.
if (lobster_contents_bounds.bottom() > screen_work_area.bottom()) {
lobster_contents_bounds.set_y(anchor.y() - new_size.height());
}
// If still vertically offscreen, just move it to the bottom of the screen.
if (lobster_contents_bounds.y() < screen_work_area.y()) {
lobster_contents_bounds.set_y(screen_work_area.bottom() -
new_size.height());
}
// Compute widget bounds, which includes the border and shadow around the main
// contents. Then, adjust again to ensure the whole widget is onscreen.
gfx::Rect widget_bounds(lobster_contents_bounds);
widget_bounds.Inset(-GetBubbleFrameView()->bubble_border()->GetInsets());
widget_bounds.AdjustToFit(screen_work_area);
GetWidget()->SetBounds(widget_bounds);
}
void LobsterView::ShowUI() {
WebUIBubbleDialogView::ShowUI();
if (base::FeatureList::IsEnabled(ash::features::kLobsterDraggingSupport)) {
SetupDraggingSupport();
}
}
void LobsterView::SetContentsBounds(content::WebContents* source,
const gfx::Rect& bounds) {
if (views::WebView* web_view_ptr = web_view()) {
web_view_ptr->SetPreferredSize(bounds.size());
}
GetWidget()->SetBounds(bounds);
}
bool LobsterView::IsDraggingEnabled() {
return base::FeatureList::IsEnabled(ash::features::kLobsterDraggingSupport);
}
bool LobsterView::IsResizingEnabled() {
return false;
}
BEGIN_METADATA(LobsterView)
END_METADATA
} // namespace ash
|