blob: 9cc1ffb62c883c714acccabafde30a623f8742ee [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_POPUP_POPUP_VIEW_UTILS_H_
#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_POPUP_POPUP_VIEW_UTILS_H_
#include "base/containers/span.h"
#include "components/autofill/core/browser/ui/popup_item_ids.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_border_arrow_utils.h"
#include "ui/views/style/typography.h"
namespace content {
class WebContents;
} // namespace content
namespace autofill {
// Specifies how the popup cell was selected.
enum PopupCellSelectionSource {
// (Un)selections with no direct user input, e.g. unselection by timeout.
kNonUserInput,
kMouse,
kKeyboard,
};
// Sets the |x| and |width| components of |popup_bounds| as the x-coordinate
// of the starting point and the width of the popup, taking into account the
// direction it's supposed to grow (either to the left or to the right).
// Components |y| and |height| of |popup_bounds| are not changed.
// TODO(crbug.com/1247645): Rename content_area_bounds to max_bounding_box.
void CalculatePopupXAndWidth(int popup_preferred_width,
const gfx::Rect& content_area_bounds,
const gfx::Rect& element_bounds,
bool is_rtl,
gfx::Rect* popup_bounds);
// Sets the |width| and |x| component of |popup_bounds|. Without
// additional constraints, in LTR the pop-up's is left-aligned with the
// horizontal center of |element_bounds|. If the space available to the
// right side it insufficient to achieve the |popup_preferred_width|, the left
// border of the pop-up is moved further to the left.
// In RTL the logic is revered. The pop-up is right-aligned with the horizontal
// center of |element_bounds|. If the space to the left is insufficient, the
// pop-up will grow towards the right.
// TODO(crbug.com/1247645): Rename content_area_bounds to max_bounding_box.
void CalculatePopupXAndWidthHorizontallyCentered(
int popup_preferred_width,
const gfx::Rect& content_area_bounds,
const gfx::Rect& element_bounds,
bool is_rtl,
gfx::Rect* popup_bounds);
// Sets the |y| and |height| components of |popup_bounds| as the y-coordinate
// of the starting point and the height of the popup, taking into account the
// direction it's supposed to grow (either up or down). Components |x| and
// |width| of |popup_bounds| are not changed.
// TODO(crbug.com/1247645): Rename content_area_bounds to max_bounding_box.
void CalculatePopupYAndHeight(int popup_preferred_height,
const gfx::Rect& content_area_bounds,
const gfx::Rect& element_bounds,
gfx::Rect* popup_bounds);
// Convenience method which handles both the vertical and horizontal bounds
// and returns a new Rect. If |horizontally_centered| is true, the pop-up is
// horizontally aligned with the center of |element_bounds|.
// TODO(crbug.com/1247645): Rename content_area_bounds to max_bounding_box.
gfx::Rect CalculatePopupBounds(const gfx::Size& desired_size,
const gfx::Rect& content_area_bounds,
const gfx::Rect& element_bounds,
bool is_rtl,
bool horizontally_centered);
// Returns whether there is enough height within |content_area_bounds| above or
// below |element_bounds| to display |item_height|, and that the first dropdown
// item will actually be visible within the bounds of the content area.
// TODO(crbug.com/1247645): Rename content_area_bounds to max_bounding_box.
bool CanShowDropdownHere(int item_height,
const gfx::Rect& content_area_bounds,
const gfx::Rect& element_bounds);
// Returns whether there is any open prompt in |web_contents| with bounds that
// overlap |screen_bounds|.
// This is unreliable on Windows because bubbles are not necessarily children of
// the root view of the current tab.
bool BoundsOverlapWithAnyOpenPrompt(const gfx::Rect& screen_bounds,
content::WebContents* web_contents);
// Returns the total vertical space on |content_area_bounds| on a specific
// |side| of the |element_bounds|.
int GetAvailableVerticalSpaceOnSideOfElement(
const gfx::Rect& content_area_bounds,
const gfx::Rect& element_bounds,
views::BubbleArrowSide side);
// Returns the total horizontal space on |content_area_bounds| on a
// specific |side| of the |element_bounds|.
int GetAvailableHorizontalSpaceOnSideOfElement(
const gfx::Rect& content_area_bounds,
const gfx::Rect& element_bounds,
views::BubbleArrowSide side);
// Returns true if there is enough space to place the popup with
// |popup_preferred_size| plus an additional |spacing| on a specific
// |side| of the |element_bounds| in the |content_area_bounds|. |spacing|
// defines the number of additional pixels the popup should be displaced from
// the element.
bool IsPopupPlaceableOnSideOfElement(const gfx::Rect& content_area_bounds,
const gfx::Rect& element_bounds,
const gfx::Size& popup_preferred_size,
int spacing,
views::BubbleArrowSide side);
// Returns the first side from popup_preferred_sides, for which the popup with
// a |popup_preferred_size| fits on the side of the |element_bounds| in
// the |content_area_bounds| taking the arrow length into account.
// If neither side bits, the function returns kBottom.
views::BubbleArrowSide GetOptimalArrowSide(
const gfx::Rect& content_area_bounds,
const gfx::Rect& element_bounds,
const gfx::Size& popup_preferred_size,
base::span<const views::BubbleArrowSide> popup_preferred_sides);
// Determines the optimal position of a popup with |popup_preferred_size| next
// to an UI element with |element_bounds|. The arrow pointer dimensions are
// not taken into account if it is present. |content_area_bounds| are the
// boundaries of the view port, |right_to_left| indicates if the website uses
// text written from right to left. |scrollbar_width| is the width of a scroll
// bar and |maximum_offset_to_center| is the maximum number of pixels the popup
// can be moved towards the center of |element_bounds| and
// |maximum_width_percentage_to_center| is the maxmum percentage of the
// element's width for the popup to move towards the center. |popup_bounds| is
// the current rect of the popup that is modified by this function. The
// function returns the arrow position that is used on the popup.
views::BubbleBorder::Arrow GetOptimalPopupPlacement(
const gfx::Rect& content_area_bounds,
const gfx::Rect& element_bounds,
const gfx::Size& popup_preferred_size,
bool right_to_left,
int scrollbar_width,
int maximum_pixel_offset_to_center,
int maximum_width_percentage_to_center,
gfx::Rect& popup_bounds,
base::span<const views::BubbleArrowSide> popup_preferred_sides);
// Returns whether there is an open permissions prompt in |web_contents| with
// bounds that overlap |screen_bounds|.
bool BoundsOverlapWithOpenPermissionsPrompt(const gfx::Rect& screen_bounds,
content::WebContents* web_contents);
// Returns whether there is picture-in-picture window with bounds that overlap
// `screen_bounds`. Assuming:
// 1. the pip window is shown in the active tab.
// 2. this function is called from the frame of the contents that show the
// autofill popup.
bool BoundsOverlapWithPictureInPictureWindow(const gfx::Rect& screen_bounds);
// Returns whether a popup may vertically exceed the bounds of |web_contents|.
// This is permitted for extension popups. Here we only enforce that the
// autofill popup is at least attached to the extension popup (or overlaps the
// extension popup) and stays within the bounds of the browser window.
bool PopupMayExceedContentAreaBounds(content::WebContents* web_contents);
// Returns whether the suggestion with this `popup_item_id` belongs into the
// footer section of the popup. Returns `false` for separators, which may belong
// either to the main or the footer section.
bool IsFooterPopupItemId(PopupItemId popup_item_id);
// Return whether the suggestion with this `popup_item_id` can have child
// suggestions.
bool IsExpandablePopupItemId(PopupItemId popup_item_id);
// Returns whether the Autofill popup will have new styles features applied to
// it. This should be the case for features launched after M117.
// TODO(crbug.com/1459990): Remove once feature is rolled out. Both the granular
// filling feature and the autocomplete delete apply the new styles. Therefore
// we can remove this method once any is launched.
// TODO(crbug.com/40283949): Remove once feature is rolled out.
bool ShouldApplyNewAutofillPopupStyle();
// Depending on the current style (see `ShouldApplyNewAutofillPopupStyle()`),
// return styles for primary and secondary texts.
views::style::TextStyle GetPrimaryTextStyle();
views::style::TextStyle GetSecondaryTextStyle();
} // namespace autofill
#endif // CHROME_BROWSER_UI_VIEWS_AUTOFILL_POPUP_POPUP_VIEW_UTILS_H_