File: ax_system_caret_win.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (142 lines) | stat: -rw-r--r-- 4,579 bytes parent folder | download | duplicates (2)
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/accessibility/platform/ax_system_caret_win.h"

#include <windows.h>

#include "base/check.h"
#include "base/notreached.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/platform/ax_platform_node_win.h"
#include "ui/display/win/screen_win.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/rect_f.h"

namespace ui {

AXSystemCaretWin::AXSystemCaretWin(gfx::AcceleratedWidget event_target)
    : event_target_(event_target), caret_(AXPlatformNode::Create(*this)) {
  // The caret object is not part of the accessibility tree and so doesn't need
  // a node ID. A globally unique ID is used when firing Win events, retrieved
  // via |unique_id|.
  data_.id = -1;
  data_.role = ax::mojom::Role::kCaret;
  // |get_accState| should return 0 which means that the caret is visible.
  data_.state = 0;
  data_.AddState(ax::mojom::State::kInvisible);
  // According to MSDN, "Edit" should be the name of the caret object.
  data_.SetName(u"Edit");
  data_.relative_bounds.offset_container_id = -1;

  if (event_target_) {
    ::NotifyWinEvent(EVENT_OBJECT_CREATE, event_target_, OBJID_CARET,
                     -caret_->GetUniqueId());
  }
}

AXSystemCaretWin::~AXSystemCaretWin() {
  if (event_target_) {
    ::NotifyWinEvent(EVENT_OBJECT_DESTROY, event_target_, OBJID_CARET,
                     -caret_->GetUniqueId());
  }
}

Microsoft::WRL::ComPtr<IAccessible> AXSystemCaretWin::GetCaret() const {
  Microsoft::WRL::ComPtr<IAccessible> caret_accessible;
  HRESULT hr = static_cast<AXPlatformNodeWin&>(*caret_).QueryInterface(
      IID_PPV_ARGS(&caret_accessible));
  DCHECK(SUCCEEDED(hr));
  return caret_accessible;
}

void AXSystemCaretWin::MoveCaretTo(const gfx::Rect& bounds_physical_pixels) {
  if (bounds_physical_pixels.IsEmpty())
    return;

  // If the caret has non-empty bounds, assume it has been made visible.
  bool newly_visible = false;
  if (data_.HasState(ax::mojom::State::kInvisible)) {
    newly_visible = true;
    data_.RemoveState(ax::mojom::State::kInvisible);
  }

  if (!event_target_)
    return;

  if (newly_visible) {
    ::NotifyWinEvent(EVENT_OBJECT_SHOW, event_target_, OBJID_CARET,
                     -caret_->GetUniqueId());
  }

  gfx::RectF new_location(bounds_physical_pixels);
  // Avoid redundant caret move events (if the location stays the same), but
  // always fire when it's made visible again.
  if (data_.relative_bounds.bounds != new_location || newly_visible) {
    data_.relative_bounds.bounds = new_location;
    ::NotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, event_target_, OBJID_CARET,
                     -caret_->GetUniqueId());
  }
}

void AXSystemCaretWin::Hide() {
  if (!data_.HasState(ax::mojom::State::kInvisible)) {
    data_.AddState(ax::mojom::State::kInvisible);
    data_.relative_bounds.bounds.set_width(0);
    if (event_target_) {
      ::NotifyWinEvent(EVENT_OBJECT_HIDE, event_target_, OBJID_CARET,
                       -caret_->GetUniqueId());
    }
  }
}

const AXNodeData& AXSystemCaretWin::GetData() const {
  return data_;
}

gfx::NativeViewAccessible AXSystemCaretWin::GetParent() const {
  if (!event_target_)
    return nullptr;

  gfx::NativeViewAccessible parent;
  HRESULT hr =
      ::AccessibleObjectFromWindow(event_target_, OBJID_WINDOW, IID_IAccessible,
                                   reinterpret_cast<void**>(&parent));
  if (SUCCEEDED(hr))
    return parent;
  return nullptr;
}

gfx::Rect AXSystemCaretWin::GetBoundsRect(
    const AXCoordinateSystem coordinate_system,
    const AXClippingBehavior clipping_behavior,
    AXOffscreenResult* offscreen_result) const {
  switch (coordinate_system) {
    case AXCoordinateSystem::kScreenPhysicalPixels:
      // We could optionally add clipping here if ever needed.
      return ToEnclosingRect(data_.relative_bounds.bounds);
    case AXCoordinateSystem::kScreenDIPs:
      return display::win::GetScreenWin()->ScreenToDIPRect(
          event_target_, ToEnclosingRect(data_.relative_bounds.bounds));
    case AXCoordinateSystem::kRootFrame:
    case AXCoordinateSystem::kFrame:
      NOTIMPLEMENTED();
      return gfx::Rect();
  }
}

gfx::AcceleratedWidget
AXSystemCaretWin::GetTargetForNativeAccessibilityEvent() {
  return event_target_;
}

bool AXSystemCaretWin::ShouldIgnoreHoveredStateForTesting() {
  return false;
}

AXPlatformNodeId AXSystemCaretWin::GetUniqueId() const {
  return unique_id_;
}

}  // namespace ui