File: delegated_ink_trail_presenter.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 (158 lines) | stat: -rw-r--r-- 6,735 bytes parent folder | download | duplicates (5)
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// 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.

#include "third_party/blink/renderer/modules/delegated_ink/delegated_ink_trail_presenter.h"

#include "base/trace_event/trace_event.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_ink_trail_style.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/events/pointer_event.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "ui/gfx/delegated_ink_metadata.h"

namespace blink {

DelegatedInkTrailPresenter::DelegatedInkTrailPresenter(Element* element,
                                                       LocalFrame* frame)
    : presentation_area_(element), local_frame_(frame) {
  DCHECK(!presentation_area_ ||
         presentation_area_->GetDocument() == local_frame_->GetDocument());
}

void DelegatedInkTrailPresenter::updateInkTrailStartPoint(
    ScriptState* state,
    PointerEvent* evt,
    InkTrailStyle* style,
    ExceptionState& exception_state) {
  if (!state->ContextIsValid()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidStateError,
        "The object is no longer associated with a window.");
    return;
  }

  if (!evt->isTrusted()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kNotAllowedError,
        "Only trusted pointerevents are accepted.");
    return;
  }

  // If diameter is less than or equal to 0, then nothing is going to be
  // displayed anyway, so just bail early and save the effort.
  if (!(style->diameter() > 0)) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kNotSupportedError,
        "Delegated ink trail diameter must be greater than 0.");
    return;
  }

  Color color;
  if (!CSSParser::ParseColor(color, style->color())) {
    exception_state.ThrowTypeError("Unknown color.");
    return;
  }

  LayoutView* layout_view = local_frame_->ContentLayoutObject();
  LayoutBox* layout_box = nullptr;
  if (presentation_area_) {
    layout_box = presentation_area_->GetLayoutBox();
  } else {
    // If presentation_area_ wasn't provided, then default to the layout
    // viewport.
    layout_box = layout_view;
  }
  // The layout might not be initialized or the associated element deleted from
  // the DOM.
  if (!layout_box || !layout_view)
    return;

  // Use the event's absolute location as it is already scaled by the page
  // zoom factor. Convert to absolute point so that a point from the root frame
  // is obtained in the case of an iframe.
  gfx::PointF point = evt->AbsoluteLocation();
  point = layout_view->LocalToAbsolutePoint(point, kTraverseDocumentBoundaries);
  // Convert to visual viewport space so that page scale factor is taken into
  // consideration.
  const VisualViewport& visual_viewport =
      local_frame_->GetPage()->GetVisualViewport();
  gfx::PointF point_visual_viewport =
      visual_viewport.RootFrameToViewport(point);

  // Intersect with the visible viewport so that the presentation area can't
  // extend beyond the edges of the window or over the scrollbars. The frame
  // visual viewport loop accounts for all iframe viewports, and the page visual
  // viewport accounts for the full window. Convert everything to root frame
  // coordinates in order to make sure offsets aren't lost along the way.
  PhysicalRect border_box_rect_absolute = layout_box->LocalToAbsoluteRect(
      layout_box->PhysicalBorderBoxRect(), kTraverseDocumentBoundaries);

  while (layout_view->GetFrame()->OwnerLayoutObject()) {
    PhysicalRect frame_visual_viewport_absolute =
        layout_view->LocalToAbsoluteRect(
            PhysicalRect(
                layout_view->GetScrollableArea()->VisibleContentRect()),
            kTraverseDocumentBoundaries);
    border_box_rect_absolute.Intersect(frame_visual_viewport_absolute);

    layout_view = layout_view->GetFrame()->OwnerLayoutObject()->View();
  }

  border_box_rect_absolute.Intersect(
      PhysicalRect(visual_viewport.VisibleContentRect()));

  gfx::RectF area = gfx::RectF(border_box_rect_absolute);
  area = visual_viewport.RootFrameToViewport(area);

  // This is used to know if the user starts inking with the pointer down or
  // not, so that we can stop drawing delegated ink trails as quickly as
  // possible if the left button state changes, as presumably that indicates the
  // the end of inking.
  // Touch events do not need to be special cased here. When something is
  // physically touching the screen to trigger a touch event, it is converted to
  // a pointerevent with kLeftButtonDown, and if a stylus with hovering
  // capabilities sent the touch event, then the resulting pointerevent will not
  // have the kLeftButtonDown modifier. In either case, it will match the
  // expectations of a normal mouse event, so it doesn't need to be handled
  // separately.
  const bool is_hovering =
      !(evt->GetModifiers() & WebInputEvent::Modifiers::kLeftButtonDown);

  const double diameter_in_physical_pixels =
      style->diameter() * layout_view->StyleRef().EffectiveZoom() *
      local_frame_->GetPage()->PageScaleFactor();
  std::unique_ptr<gfx::DelegatedInkMetadata> metadata =
      std::make_unique<gfx::DelegatedInkMetadata>(
          point_visual_viewport, diameter_in_physical_pixels, color.Rgb(),
          evt->PlatformTimeStamp(), area, is_hovering);

  TRACE_EVENT_WITH_FLOW1("delegated_ink_trails",
                         "DelegatedInkTrailPresenter::updateInkTrailStartPoint",
                         TRACE_ID_GLOBAL(metadata->trace_id()),
                         TRACE_EVENT_FLAG_FLOW_OUT, "metadata",
                         metadata->ToString());

  if (last_delegated_ink_metadata_timestamp_ == metadata->timestamp())
    return;

  last_delegated_ink_metadata_timestamp_ = metadata->timestamp();
  Page* page = local_frame_->GetPage();
  page->GetChromeClient().SetDelegatedInkMetadata(local_frame_,
                                                  std::move(metadata));
}

void DelegatedInkTrailPresenter::Trace(Visitor* visitor) const {
  ScriptWrappable::Trace(visitor);
  visitor->Trace(presentation_area_);
  visitor->Trace(local_frame_);
}

}  // namespace blink