| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // 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_PLATFORM_WIDGET_WIDGET_BASE_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_WIDGET_BASE_H_ |
| |
| #include "base/time/time.h" |
| #include "cc/paint/element_id.h" |
| #include "cc/trees/browser_controls_params.h" |
| #include "components/viz/common/surfaces/local_surface_id.h" |
| #include "mojo/public/cpp/bindings/associated_receiver.h" |
| #include "mojo/public/cpp/bindings/associated_remote.h" |
| #include "third_party/blink/public/common/metrics/document_update_reason.h" |
| #include "third_party/blink/public/common/page/content_to_visible_time_reporter.h" |
| #include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h" |
| #include "third_party/blink/public/mojom/page/record_content_to_visible_time_request.mojom-blink-forward.h" |
| #include "third_party/blink/public/mojom/page/widget.mojom-blink.h" |
| #include "third_party/blink/public/platform/cross_variant_mojo_util.h" |
| #include "third_party/blink/public/platform/web_text_input_info.h" |
| #include "third_party/blink/renderer/platform/platform_export.h" |
| #include "third_party/blink/renderer/platform/text/text_direction.h" |
| #include "third_party/blink/renderer/platform/timer.h" |
| #include "third_party/blink/renderer/platform/weborigin/kurl.h" |
| #include "third_party/blink/renderer/platform/widget/compositing/layer_tree_view_delegate.h" |
| #include "third_party/blink/renderer/platform/widget/input/widget_base_input_handler.h" |
| #include "ui/base/ime/text_input_mode.h" |
| #include "ui/base/ime/text_input_type.h" |
| |
| namespace cc { |
| class AnimationHost; |
| class LayerTreeHost; |
| class LayerTreeSettings; |
| class TaskGraphRunner; |
| class UkmRecorderFactory; |
| } // namespace cc |
| |
| namespace ui { |
| class Cursor; |
| } |
| |
| namespace blink { |
| class ImeEventGuard; |
| class LayerTreeView; |
| class WidgetBaseClient; |
| class WidgetInputHandlerManager; |
| class WidgetCompositor; |
| |
| namespace scheduler { |
| class WebAgentGroupScheduler; |
| class WebRenderWidgetSchedulingState; |
| } |
| |
| // This class is the foundational class for all widgets that blink creates. |
| // (WebPagePopupImpl, WebFrameWidgetImpl) will contain an instance of this |
| // class. For simplicity purposes this class will be a member of those classes. |
| // |
| // Co-orindates handled in this class can be in the "blink coordinate space" |
| // which is scaled DSF baked in if UseZoomForDSF is enabled, otherwise they |
| // are equivalent to DIPs. |
| class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget, |
| public LayerTreeViewDelegate { |
| public: |
| WidgetBase( |
| WidgetBaseClient* client, |
| CrossVariantMojoAssociatedRemote<mojom::WidgetHostInterfaceBase> |
| widget_host, |
| CrossVariantMojoAssociatedReceiver<mojom::WidgetInterfaceBase> widget, |
| scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| bool hidden, |
| bool never_composited, |
| bool is_for_child_local_root); |
| ~WidgetBase() override; |
| |
| // Initialize the compositor. |settings| is typically null. When |settings| is |
| // null the default settings will be used, tests may provide a |settings| |
| // object to override the defaults. |
| // |
| // TODO(dtapuska): The WebFrameWidgetImpl should be responsible for making |
| // the FrameWidgetInputHandlerImpl, but currently it is done in the general |
| // widget input handler classes directly, so we have to plumb through the |
| // main-thread mojom implementation. |
| // The `frame_widget_input_handler` must be invalidated when the WidgetBase is |
| // destroyed/invalidated. |
| void InitializeCompositing( |
| scheduler::WebAgentGroupScheduler& agent_group_scheduler, |
| cc::TaskGraphRunner* task_graph_runner, |
| bool for_child_local_root_frame, |
| const ScreenInfo& screen_info, |
| std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory, |
| const cc::LayerTreeSettings* settings, |
| base::WeakPtr<mojom::blink::FrameWidgetInputHandler> |
| frame_widget_input_handler); |
| |
| // Shutdown the compositor. |
| void Shutdown(); |
| |
| // Set the compositor as visible. If |visible| is true, then the compositor |
| // will request a new layer frame sink, begin producing frames from the |
| // compositor scheduler, and in turn will update the document lifecycle. |
| void SetCompositorVisible(bool visible); |
| |
| void AddPresentationCallback( |
| uint32_t frame_token, |
| base::OnceCallback<void(base::TimeTicks)> callback); |
| |
| // mojom::blink::Widget overrides: |
| void ForceRedraw(mojom::blink::Widget::ForceRedrawCallback callback) override; |
| void GetWidgetInputHandler( |
| mojo::PendingReceiver<mojom::blink::WidgetInputHandler> request, |
| mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host) override; |
| void UpdateVisualProperties( |
| const VisualProperties& visual_properties) override; |
| void UpdateScreenRects(const gfx::Rect& widget_screen_rect, |
| const gfx::Rect& window_screen_rect, |
| UpdateScreenRectsCallback callback) override; |
| void WasHidden() override; |
| void WasShown(base::TimeTicks show_request_timestamp, |
| bool was_evicted, |
| mojom::blink::RecordContentToVisibleTimeRequestPtr |
| record_tab_switch_time_request) override; |
| |
| // LayerTreeDelegate overrides: |
| // Applies viewport related properties during a commit from the compositor |
| // thread. |
| void ApplyViewportChanges(const cc::ApplyViewportChangesArgs& args) override; |
| void UpdateCompositorScrollState( |
| const cc::CompositorCommitData& commit_data) override; |
| void BeginMainFrame(base::TimeTicks frame_time) override; |
| void OnDeferMainFrameUpdatesChanged(bool) override; |
| void OnDeferCommitsChanged(bool) override; |
| void DidBeginMainFrame() override; |
| void RequestNewLayerTreeFrameSink( |
| LayerTreeFrameSinkCallback callback) override; |
| void DidCommitAndDrawCompositorFrame() override; |
| void DidObserveFirstScrollDelay( |
| base::TimeDelta first_scroll_delay, |
| base::TimeTicks first_scroll_timestamp) override; |
| void WillCommitCompositorFrame() override; |
| void DidCommitCompositorFrame(base::TimeTicks commit_start_time) override; |
| void DidCompletePageScaleAnimation() override; |
| void RecordStartOfFrameMetrics() override; |
| void RecordEndOfFrameMetrics( |
| base::TimeTicks frame_begin_time, |
| cc::ActiveFrameSequenceTrackers trackers) override; |
| std::unique_ptr<cc::BeginMainFrameMetrics> GetBeginMainFrameMetrics() |
| override; |
| std::unique_ptr<cc::WebVitalMetrics> GetWebVitalMetrics() override; |
| void BeginUpdateLayers() override; |
| void EndUpdateLayers() override; |
| void UpdateVisualState() override; |
| void WillBeginMainFrame() override; |
| void RunPaintBenchmark(int repeat_count, |
| cc::PaintBenchmarkResult& result) override; |
| |
| cc::AnimationHost* AnimationHost() const; |
| cc::LayerTreeHost* LayerTreeHost() const; |
| bool IsComposited() const; |
| scheduler::WebRenderWidgetSchedulingState* RendererWidgetSchedulingState() |
| const; |
| |
| mojom::blink::WidgetHost* GetWidgetHostRemote() { return widget_host_.get(); } |
| |
| // Returns if we should gather begin main frame metrics. If there is no |
| // compositor thread this returns false. |
| static bool ShouldRecordBeginMainFrameMetrics(); |
| |
| // Set the current cursor relay to browser if necessary. |
| void SetCursor(const ui::Cursor& cursor); |
| |
| // Dispatch the virtual keyboard and update text input state. |
| void ShowVirtualKeyboardOnElementFocus(); |
| |
| // Process the touch action. |
| void ProcessTouchAction(cc::TouchAction touch_action); |
| |
| WidgetBaseInputHandler& input_handler() { return input_handler_; } |
| |
| WidgetInputHandlerManager* widget_input_handler_manager() { |
| return widget_input_handler_manager_.get(); |
| } |
| |
| gfx::Rect CompositorViewportRect() const; |
| |
| WidgetBaseClient* client() { return client_; } |
| |
| void SetToolTipText(const String& tooltip_text, TextDirection dir); |
| |
| // Posts a task with the given delay, then calls ScheduleAnimation() on the |
| // WidgetBaseClient. |
| void RequestAnimationAfterDelay(const base::TimeDelta& delay); |
| |
| void ShowVirtualKeyboard(); |
| void UpdateSelectionBounds(); |
| void UpdateTextInputState(); |
| void ClearTextInputState(); |
| void ForceTextInputStateUpdate(); |
| void RequestCompositionUpdates(bool immediate_request, bool monitor_updates); |
| void UpdateCompositionInfo(bool immediate_request); |
| void SetFocus(bool enable); |
| bool has_focus() const { return has_focus_; } |
| void MouseCaptureLost(); |
| void CursorVisibilityChange(bool is_visible); |
| void QueueSyntheticEvent( |
| std::unique_ptr<blink::WebCoalescedInputEvent> event); |
| void SetEditCommandsForNextKeyEvent( |
| Vector<mojom::blink::EditCommandPtr> edit_commands); |
| void SetMouseCapture(bool capture); |
| void ImeSetComposition(const String& text, |
| const Vector<ui::ImeTextSpan>& ime_text_spans, |
| const gfx::Range& replacement_range, |
| int selection_start, |
| int selection_end); |
| void ImeCommitText(const String& text, |
| const Vector<ui::ImeTextSpan>& ime_text_spans, |
| const gfx::Range& replacement_range, |
| int relative_cursor_pos); |
| void ImeFinishComposingText(bool keep_selection); |
| bool IsForProvisionalFrame(); |
| void FlushInputProcessedCallback(); |
| void CancelCompositionForPepper(); |
| |
| void RequestPresentationAfterScrollAnimationEnd( |
| mojom::blink::Widget::ForceRedrawCallback callback); |
| |
| void OnImeEventGuardStart(ImeEventGuard* guard); |
| void OnImeEventGuardFinish(ImeEventGuard* guard); |
| |
| bool is_hidden() const { return is_hidden_; } |
| void set_is_pasting(bool value) { is_pasting_ = value; } |
| bool is_pasting() const { return is_pasting_; } |
| void set_handling_select_range(bool value) { handling_select_range_ = value; } |
| bool handling_select_range() const { return handling_select_range_; } |
| |
| bool ComputePreferCompositingToLCDText(); |
| |
| const viz::LocalSurfaceId& local_surface_id_from_parent() { |
| return local_surface_id_from_parent_; |
| } |
| |
| // Called to get the position of the widget's window in screen |
| // coordinates. Note, the window includes any decorations such as borders, |
| // scrollbars, URL bar, tab strip, etc. if they exist. |
| gfx::Rect WindowRect(); |
| |
| // Called to get the view rect in screen coordinates. This is the actual |
| // content view area, i.e. doesn't include any window decorations. |
| gfx::Rect ViewRect(); |
| |
| // Sets the pending window rects (in screen coordinates). This is used because |
| // the window rect is delivered asynchronously to the browser. Pass in nullptr |
| // to clear the pending window rect once the browser has acknowledged the |
| // request. |
| void SetPendingWindowRect(const gfx::Rect& rect); |
| |
| // Must correspond with a previous call to SetPendingWindowRect. |
| void AckPendingWindowRect(); |
| |
| // Returns the location/bounds of the widget (in screen coordinates). |
| const gfx::Rect& WidgetScreenRect() const { return widget_screen_rect_; } |
| |
| // Returns the bounds of the screen the widget is contained in (in screen |
| // coordinates). |
| const gfx::Rect& WindowScreenRect() const { return window_screen_rect_; } |
| |
| // Sets the screen rects (in screen coordinates). |
| void SetScreenRects(const gfx::Rect& widget_screen_rect, |
| const gfx::Rect& window_screen_rect); |
| |
| // Returns the visible viewport size. |
| const gfx::Size& VisibleViewportSizeInDIPs() const { |
| return visible_viewport_size_in_dips_; |
| } |
| |
| // Set the visible viewport size. |
| void SetVisibleViewportSizeInDIPs(const gfx::Size& size) { |
| visible_viewport_size_in_dips_ = size; |
| } |
| |
| // Converts from DIPs to Blink coordinate space (ie. Viewport/Physical |
| // pixels). |
| gfx::PointF DIPsToBlinkSpace(const gfx::PointF& point); |
| gfx::Point DIPsToRoundedBlinkSpace(const gfx::Point& point); |
| gfx::Size DIPsToCeiledBlinkSpace(const gfx::Size& size); |
| gfx::RectF DIPsToBlinkSpace(const gfx::RectF& rect); |
| float DIPsToBlinkSpace(float scalar); |
| |
| // Converts from Blink coordinate (ie. Viewport/Physical pixels) space to |
| // DIPs. |
| gfx::PointF BlinkSpaceToDIPs(const gfx::PointF& point); |
| gfx::Point BlinkSpaceToFlooredDIPs(const gfx::Point& point); |
| gfx::Size BlinkSpaceToFlooredDIPs(const gfx::Size& size); |
| gfx::Rect BlinkSpaceToEnclosedDIPs(const gfx::Rect& rect); |
| gfx::RectF BlinkSpaceToDIPs(const gfx::RectF& rectF); |
| |
| // Returns whether Zoom for DSF is enabled for the widget. |
| bool UseZoomForDsf() { return use_zoom_for_dsf_; } |
| |
| void BindWidgetCompositor( |
| mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver); |
| |
| base::WeakPtr<WidgetBase> GetWeakPtr() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| // Update the surface allocation information, compositor viewport rect and |
| // screen info on the widget. |
| void UpdateSurfaceAndScreenInfo( |
| const viz::LocalSurfaceId& new_local_surface_id, |
| const gfx::Rect& compositor_viewport_pixel_rect, |
| const ScreenInfo& new_screen_info); |
| // Similar to UpdateSurfaceAndScreenInfo but the screen info remains the same. |
| void UpdateSurfaceAndCompositorRect( |
| const viz::LocalSurfaceId& new_local_surface_id, |
| const gfx::Rect& compositor_viewport_pixel_rect); |
| // Similar to UpdateSurfaceAndScreenInfo but the surface allocation |
| // and compositor viewport rect remains the same. |
| void UpdateScreenInfo(const ScreenInfo& new_screen_info); |
| // Similar to UpdateSurfaceAndScreenInfo but the surface allocation |
| // remains the same. |
| void UpdateCompositorViewportAndScreenInfo( |
| const gfx::Rect& compositor_viewport_pixel_rect, |
| const ScreenInfo& new_screen_info); |
| // Similar to UpdateSurfaceAndScreenInfo but the surface allocation and screen |
| // info remains the same. |
| void UpdateCompositorViewportRect( |
| const gfx::Rect& compositor_viewport_pixel_rect); |
| const ScreenInfo& GetScreenInfo(); |
| |
| const viz::LocalSurfaceId& local_surface_id_from_parent() const { |
| return local_surface_id_from_parent_; |
| } |
| |
| private: |
| bool CanComposeInline(); |
| void UpdateTextInputStateInternal(bool show_virtual_keyboard, |
| bool immediate_request); |
| bool ShouldHandleImeEvents(); |
| // Returns the range of the text that is being composed or the selection if |
| // the composition does not exist. |
| void GetCompositionRange(gfx::Range* range); |
| void GetCompositionCharacterBounds(Vector<gfx::Rect>* bounds); |
| ui::TextInputType GetTextInputType(); |
| |
| // Returns true if the composition range or composition character bounds |
| // should be sent to the browser process. |
| bool ShouldUpdateCompositionInfo(const gfx::Range& range, |
| const Vector<gfx::Rect>& bounds); |
| |
| // Sets the "hidden" state of this widget. All modification of is_hidden_ |
| // should use this method so that we can properly inform the RenderThread of |
| // our state. |
| void SetHidden(bool hidden); |
| |
| // Called after the delay given in `RequestAnimationAfterDelay()`. |
| void RequestAnimationAfterDelayTimerFired(TimerBase*); |
| |
| // Indicates that we are never visible, so never produce graphical output. |
| const bool never_composited_; |
| // Indicates this is for a child local root. |
| const bool is_for_child_local_root_; |
| // When true, the device scale factor is a part of blink coordinates. |
| const bool use_zoom_for_dsf_; |
| |
| // The client which handles behaviour specific to the type of widget. |
| WidgetBaseClient* const client_; |
| |
| mojo::AssociatedRemote<mojom::blink::WidgetHost> widget_host_; |
| mojo::AssociatedReceiver<mojom::blink::Widget> receiver_; |
| |
| std::unique_ptr<LayerTreeView> layer_tree_view_; |
| scoped_refptr<WidgetInputHandlerManager> widget_input_handler_manager_; |
| std::unique_ptr<scheduler::WebRenderWidgetSchedulingState> |
| render_widget_scheduling_state_; |
| bool has_focus_ = false; |
| WidgetBaseInputHandler input_handler_{this}; |
| scoped_refptr<WidgetCompositor> widget_compositor_; |
| |
| // Stores the current selection bounds. |
| gfx::Rect selection_focus_rect_; |
| gfx::Rect selection_anchor_rect_; |
| |
| // Stores the current composition character bounds. |
| Vector<gfx::Rect> composition_character_bounds_; |
| |
| // Stores the current composition range. |
| gfx::Range composition_range_ = gfx::Range::InvalidRange(); |
| |
| // True if the IME requests updated composition info. |
| bool monitor_composition_info_ = false; |
| |
| // Stores information about the current text input. |
| blink::WebTextInputInfo text_input_info_; |
| |
| // Stores the current text input type of |webwidget_|. |
| ui::TextInputType text_input_type_ = ui::TEXT_INPUT_TYPE_NONE; |
| |
| // Stores the current text input mode of |webwidget_|. |
| ui::TextInputMode text_input_mode_ = ui::TEXT_INPUT_MODE_DEFAULT; |
| |
| // Stores the current virtualkeyboardpolicy of |webwidget_|. |
| ui::mojom::VirtualKeyboardPolicy vk_policy_ = |
| ui::mojom::VirtualKeyboardPolicy::AUTO; |
| |
| // Stores the current control and selection bounds of |webwidget_| |
| // that are used to position the candidate window during IME composition. |
| // These are stored in DIPs if use-zoom-for-dsf is disabled and are relative |
| // to the widget |
| gfx::Rect frame_control_bounds_; |
| gfx::Rect frame_selection_bounds_; |
| |
| // Stores the current text input flags of |webwidget_|. |
| int text_input_flags_ = 0; |
| |
| // Indicates whether currently focused input field has next/previous focusable |
| // form input field. |
| int next_previous_flags_; |
| |
| // Stores the current type of composition text rendering of |webwidget_|. |
| bool can_compose_inline_ = true; |
| |
| // Stores whether the IME should always be hidden for |webwidget_|. |
| bool always_hide_ime_ = false; |
| |
| // Used to inform didChangeSelection() when it is called in the context |
| // of handling a FrameInputHandler::SelectRange IPC. |
| bool handling_select_range_ = false; |
| |
| // Whether or not this RenderWidget is currently pasting. |
| bool is_pasting_ = false; |
| |
| // Object to record tab switch time into this RenderWidget |
| ContentToVisibleTimeReporter tab_switch_time_recorder_; |
| |
| // Properties of the screen hosting the WidgetBase. Rects in this structure |
| // do not include any scaling by device scale factor, so are logical pixels |
| // not physical device pixels. |
| ScreenInfo screen_info_; |
| viz::LocalSurfaceId local_surface_id_from_parent_; |
| |
| // It is possible that one ImeEventGuard is nested inside another |
| // ImeEventGuard. We keep track of the outermost one, and update it as needed. |
| ImeEventGuard* ime_event_guard_ = nullptr; |
| |
| // The screen rects of the view and the window that contains it. These do not |
| // include any scaling by device scale factor, so are logical pixels not |
| // physical device pixels. |
| gfx::Rect widget_screen_rect_; |
| gfx::Rect window_screen_rect_; |
| |
| // While we are waiting for the browser to update window sizes, we track the |
| // pending size temporarily. |
| int pending_window_rect_count_ = 0; |
| |
| // A pending window rect that is inflight and hasn't been acknowledged by the |
| // browser yet. This should only be set if |pending_window_rect_count_| is |
| // non-zero. |
| base::Optional<gfx::Rect> pending_window_rect_; |
| |
| // The size of the visible viewport (in DIPs). |
| // TODO(dtapuska): Figure out if we can change this to Blink Space. |
| // See https://crbug.com/1131389 |
| gfx::Size visible_viewport_size_in_dips_; |
| |
| // Indicates that we shouldn't bother generated paint events. |
| bool is_hidden_; |
| |
| // Delayed callback to ensure we have only one delayed ScheduleAnimation() |
| // call going at a time. |
| TaskRunnerTimer<WidgetBase> request_animation_after_delay_timer_; |
| |
| // The task runner on the main thread used for compositor tasks. |
| scoped_refptr<base::SingleThreadTaskRunner> |
| main_thread_compositor_task_runner_; |
| |
| base::WeakPtrFactory<WidgetBase> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_WIDGET_BASE_H_ |