blob: 1302bf690eedfff8f716f055768fb5088a4ffe4e [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_SELECTION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_SELECTION_H_
#include <stdint.h>
#include <optional>
#include <ostream>
#include "base/dcheck_is_on.h"
#include "base/logging.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/modules/accessibility/ax_position.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
// If the |AXSelection| is defined by endpoints that are present in the
// accessibility tree but not in the DOM tree, determines whether setting the
// selection will shrink or extend the |AXSelection| to encompass endpoints that
// are in the DOM.
// Conversely, if a DOM selection is converted to an |AXSelection| via the
// |FromSelection| method, but the endpoints of the DOM selection are not
// present in the accessibility tree, e.g. they are aria-hidden, determines
// whether the conversion will shrink or extend the DOM selection to encompass
// endpoints that are in the accessibility tree.
enum class AXSelectionBehavior { kShrinkToValidRange, kExtendToValidRange };
class MODULES_EXPORT AXSelection final {
DISALLOW_NEW();
public:
class Builder;
static void ClearCurrentSelection(Document&);
static AXSelection FromCurrentSelection(
const Document&,
const AXSelectionBehavior = AXSelectionBehavior::kExtendToValidRange);
static AXSelection FromCurrentSelection(const TextControlElement&);
static AXSelection FromSelection(
const SelectionInDOMTree&,
const AXSelectionBehavior = AXSelectionBehavior::kExtendToValidRange);
AXSelection(const AXSelection&) = default;
AXSelection& operator=(const AXSelection&) = default;
~AXSelection() = default;
const AXPosition Anchor() const { return anchor_; }
const AXPosition Focus() const { return focus_; }
// The selection is invalid if either the anchor or the focus position is
// invalid, or if the positions are in two separate documents.
bool IsValid() const;
operator bool() const { return IsValid(); }
const SelectionInDOMTree AsSelection(
const AXSelectionBehavior =
AXSelectionBehavior::kExtendToValidRange) const;
// Tries to set the DOM selection to this. Returns |false| if the selection
// has been cancelled via the "selectionstart" event or if the selection could
// not be set for any other reason.
bool Select(
const AXSelectionBehavior = AXSelectionBehavior::kExtendToValidRange);
// Returns a string representation of this object.
String ToString() const;
private:
// Holds the endpoints of a selection that affects the value of a text
// control, i.e. that is inside its shadow tree.
struct TextControlSelection final {
TextControlSelection(int start,
int end,
TextFieldSelectionDirection direction)
: start(start), end(end), direction(direction) {}
TextControlSelection()
: start(-1), end(-1), direction(kSelectionHasNoDirection) {}
int start;
int end;
TextFieldSelectionDirection direction;
};
AXSelection();
// If a layout is pending, update the style and layout along with the DOM
// tree and style versions of the AXSelection and associated AXPositions.
void UpdateSelectionIfNecessary();
// Determines whether this selection is targeted to the contents of a text
// field, and returns the start and end text offsets, as well as its
// direction. |start| should always be less than equal to |end|.
std::optional<TextControlSelection> AsTextControlSelection() const;
// The |AXPosition| where the selection starts.
AXPosition anchor_;
// The |AXPosition| where the selection ends.
AXPosition focus_;
#if DCHECK_IS_ON()
// TODO(accessibility): Use layout tree version in place of DOM and style
// versions.
uint64_t dom_tree_version_;
uint64_t style_version_;
#endif
friend class Builder;
};
class MODULES_EXPORT AXSelection::Builder final {
STACK_ALLOCATED();
public:
Builder() = default;
~Builder() = default;
Builder& SetAnchor(const AXPosition&);
Builder& SetAnchor(const Position&);
Builder& SetFocus(const AXPosition&);
Builder& SetFocus(const Position&);
Builder& SetSelection(const SelectionInDOMTree&);
const AXSelection Build();
private:
AXSelection selection_;
};
MODULES_EXPORT bool operator==(const AXSelection&, const AXSelection&);
MODULES_EXPORT bool operator!=(const AXSelection&, const AXSelection&);
MODULES_EXPORT std::ostream& operator<<(std::ostream&, const AXSelection&);
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_SELECTION_H_