blob: 45c1ee5c53dc80d6d67279de919631d87fdd174d [file] [log] [blame]
// 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_