blob: f1684a16fbb4918034bf81428958e0aebfc53ac9 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_POPUP_SELECTION_H_
#define COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_POPUP_SELECTION_H_
#include <stddef.h>
#include <tuple>
#include <vector>
class AutocompleteProviderClient;
class AutocompleteResult;
class AutocompleteInput;
class TemplateURLService;
struct OmniboxPopupSelection {
// Directions for stepping through selections. These may apply for going
// up/down by lines or cycling left/right through states within a line.
enum Direction { kForward, kBackward };
// When changing selections, these are the possible stepping behaviors.
enum Step {
// Step by an entire line regardless of line state. Usually used for the
// Up and Down arrow keys.
kWholeLine,
// Step by a state if another one is available on the current line;
// otherwise step by line. Usually used for the Tab and Shift+Tab keys.
kStateOrLine,
// Step across all lines to the first or last line. Usually used for the
// PgUp and PgDn keys.
kAllLines
};
// See `state` below for details. The order matters; earlier items will be
// selected first when tabbing through the popup. They are not persisted
// anywhere and can be freely changed.
enum LineState {
// NORMAL means the row is focused, and Enter key navigates to the match.
NORMAL,
// KEYWORD_MODE state is used when in Keyword mode. If the keyword search
// button is enabled, keyword mode is entered when the keyword button is
// focused.
KEYWORD_MODE,
// FOCUSED_BUTTON_AIM state means that the AIM page action button in the
// omnibox text field is focused.
FOCUSED_BUTTON_AIM,
// FOCUSED_BUTTON_ACTION state means an Action button (such as a Pedal)
// is in focus.
FOCUSED_BUTTON_ACTION,
// FOCUSED_BUTTON_THUMBS_UP state means the thumbs up button is focused.
FOCUSED_BUTTON_THUMBS_UP,
// FOCUSED_BUTTON_THUMBS_DOWN state means the thumbs down button is focused.
// Pressing enter will attempt to submit feedback form for this suggestion.
FOCUSED_BUTTON_THUMBS_DOWN,
// FOCUSED_BUTTON_REMOVE_SUGGESTION state means the Remove Suggestion (X)
// button is focused. Pressing enter will attempt to remove this suggestion.
FOCUSED_BUTTON_REMOVE_SUGGESTION,
// `NULL_RESULT_MESSAGE` IPH match types are not normally focusable, but
// their links still need to be tab-accessible, so this state is available
// when such a match has an IPH URL link.
FOCUSED_IPH_LINK,
// Whenever new line state is added, accessibility label for current
// selection should be revisited
// (`OmniboxEditModel::GetPopupAccessibilityLabelForCurrentSelection()`).
LINE_STATE_MAX_VALUE
};
// The sentinel value for `line` which means no line is selected.
static const size_t kNoMatch;
// The selected line. This is `kNoMatch` when nothing is selected, which
// should only be true when a) the popup is closed or b) an empty suggestion
// is selected (e.g. the default suggestion in zero-input mode).
size_t line;
// If the selected line has both a normal match and a keyword match, this
// determines whether the normal match (if NORMAL) or the keyword match
// (if KEYWORD) is selected. Likewise, if the selected line has a normal
// match and a secondary button match, this determines whether the button
// match (if FOCUSED_BUTTON_*) is selected.
LineState state;
// When `state` is `FOCUSED_BUTTON_ACTION`, this indicates which action
// is selected by index into `AutocompleteMatch::actions`. Other states
// keep an unused zero index.
size_t action_index = 0u;
explicit OmniboxPopupSelection(size_t line,
LineState state = NORMAL,
size_t action_index = 0)
: line(line), state(state), action_index(action_index) {}
friend bool operator==(const OmniboxPopupSelection&,
const OmniboxPopupSelection&) = default;
// Special handling is required for ordering, since `kNoMatch` can have an
// associated `FOCUSED_BUTTON_AIM` state and we need `kNoMatch` to be treated
// as the smallest value while it is being represented as the maximum value of
// size_t (static_cast<size_t>(-1)).
friend std::strong_ordering operator<=>(const OmniboxPopupSelection& a,
const OmniboxPopupSelection& b) {
auto sort_key = [](const OmniboxPopupSelection& selection) {
return std::make_tuple(selection.line == kNoMatch ? 0 : 1, selection.line,
selection.state, selection.action_index);
};
return sort_key(a) <=> sort_key(b);
}
// Returns true if going to this selection from given `from` selection
// results in activation of keyword state when it wasn't active before.
bool IsChangeToKeyword(OmniboxPopupSelection from) const;
// Returns true if this selection represents a button being focused.
bool IsButtonFocused() const;
// Returns true if this selection represents taking an action.
bool IsAction() const;
// Returns true if the control represented by this selection's `state` is
// present on the match for `line` in given `result`.
bool IsControlPresentOnMatch(const AutocompleteResult& result) const;
// Returns the next selection after this one in given `result`.
OmniboxPopupSelection GetNextSelection(
const AutocompleteInput& input,
const AutocompleteResult& result,
TemplateURLService* template_url_service,
const AutocompleteProviderClient* client,
Direction direction,
Step step) const;
private:
// This is a utility function to support `GetNextSelection`.
static std::vector<OmniboxPopupSelection> GetAllAvailableSelectionsSorted(
const AutocompleteInput& input,
const AutocompleteResult& result,
TemplateURLService* template_url_service,
const AutocompleteProviderClient* client,
Step step);
};
#endif // COMPONENTS_OMNIBOX_BROWSER_OMNIBOX_POPUP_SELECTION_H_