diff options
Diffstat (limited to 'chromium/content/renderer/input')
18 files changed, 855 insertions, 1602 deletions
diff --git a/chromium/content/renderer/input/frame_input_handler_impl.cc b/chromium/content/renderer/input/frame_input_handler_impl.cc index 3f710c7066e..977ebdf25c9 100644 --- a/chromium/content/renderer/input/frame_input_handler_impl.cc +++ b/chromium/content/renderer/input/frame_input_handler_impl.cc @@ -8,12 +8,10 @@ #include "base/bind.h" #include "base/check.h" -#include "content/common/input/ime_text_span_conversions.h" -#include "content/common/input/input_handler.mojom.h" #include "content/renderer/ime_event_guard.h" #include "content/renderer/input/widget_input_handler_manager.h" +#include "content/renderer/render_frame_impl.h" #include "content/renderer/render_thread_impl.h" -#include "content/renderer/render_view_impl.h" #include "content/renderer/render_widget.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -23,40 +21,15 @@ namespace content { FrameInputHandlerImpl::FrameInputHandlerImpl( - base::WeakPtr<RenderFrameImpl> render_frame, - mojo::PendingReceiver<mojom::FrameInputHandler> receiver) - : render_frame_(render_frame), - input_event_queue_( - render_frame->GetLocalRootRenderWidget()->GetInputEventQueue()), - main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) { - weak_this_ = weak_ptr_factory_.GetWeakPtr(); - // If we have created an input event queue move the mojo request over to the - // compositor thread. - if (RenderThreadImpl::current() && - RenderThreadImpl::current()->compositor_task_runner() && - input_event_queue_) { - // Mojo channel bound on compositor thread. - RenderThreadImpl::current()->compositor_task_runner()->PostTask( - FROM_HERE, base::BindOnce(&FrameInputHandlerImpl::BindNow, - base::Unretained(this), std::move(receiver))); - } else { - // Mojo channel bound on main thread. - BindNow(std::move(receiver)); - } -} + base::WeakPtr<RenderWidget> widget, + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, + scoped_refptr<MainThreadEventQueue> input_event_queue) + : widget_(widget), + input_event_queue_(input_event_queue), + main_thread_task_runner_(main_thread_task_runner) {} FrameInputHandlerImpl::~FrameInputHandlerImpl() {} -// static -void FrameInputHandlerImpl::CreateMojoService( - base::WeakPtr<RenderFrameImpl> render_frame, - mojo::PendingReceiver<mojom::FrameInputHandler> receiver) { - DCHECK(render_frame); - - // Owns itself. Will be deleted when message pipe is destroyed. - new FrameInputHandlerImpl(render_frame, std::move(receiver)); -} - void FrameInputHandlerImpl::RunOnMainThread(base::OnceClosure closure) { if (input_event_queue_) { input_event_queue_->QueueClosure(std::move(closure)); @@ -69,269 +42,316 @@ void FrameInputHandlerImpl::SetCompositionFromExistingText( int32_t start, int32_t end, const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::SetCompositionFromExistingText, - weak_this_, start, end, ui_ime_text_spans)); - return; - } - - if (!render_frame_) - return; + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, int32_t start, int32_t end, + const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) { + if (!widget) + return; - ImeEventGuard guard(render_frame_->GetLocalRootRenderWidget()->AsWeakPtr()); + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + ImeEventGuard guard(widget); - render_frame_->GetWebFrame()->SetCompositionFromExistingText( - start, end, ConvertUiImeTextSpansToBlinkImeTextSpans(ui_ime_text_spans)); + focused_frame->SetCompositionFromExistingText(start, end, + ui_ime_text_spans); + }, + widget_, start, end, ui_ime_text_spans)); } void FrameInputHandlerImpl::ExtendSelectionAndDelete(int32_t before, int32_t after) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::ExtendSelectionAndDelete, - weak_this_, before, after)); - return; - } - if (!render_frame_) - return; - render_frame_->GetWebFrame()->ExtendSelectionAndDelete(before, after); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, int32_t before, int32_t after) { + if (!widget) + return; + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + focused_frame->ExtendSelectionAndDelete(before, after); + }, + widget_, before, after)); } void FrameInputHandlerImpl::DeleteSurroundingText(int32_t before, int32_t after) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::DeleteSurroundingText, - weak_this_, before, after)); - return; - } - if (!render_frame_) - return; - render_frame_->GetWebFrame()->DeleteSurroundingText(before, after); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, int32_t before, int32_t after) { + if (!widget) + return; + + if (!widget) + return; + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + focused_frame->DeleteSurroundingText(before, after); + }, + widget_, before, after)); } void FrameInputHandlerImpl::DeleteSurroundingTextInCodePoints(int32_t before, int32_t after) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread(base::BindOnce( - &FrameInputHandlerImpl::DeleteSurroundingTextInCodePoints, weak_this_, - before, after)); - return; - } - if (!render_frame_) - return; - render_frame_->GetWebFrame()->DeleteSurroundingTextInCodePoints(before, - after); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, int32_t before, int32_t after) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + focused_frame->DeleteSurroundingTextInCodePoints(before, after); + }, + widget_, before, after)); } void FrameInputHandlerImpl::SetEditableSelectionOffsets(int32_t start, int32_t end) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::SetEditableSelectionOffsets, - weak_this_, start, end)); - return; - } - if (!render_frame_) - return; - HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange); - render_frame_->GetWebFrame()->SetEditableSelectionOffsets(start, end); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, int32_t start, int32_t end) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + HandlingState handling_state(widget, UpdateState::kIsSelectingRange); + focused_frame->SetEditableSelectionOffsets(start, end); + }, + widget_, start, end)); } void FrameInputHandlerImpl::ExecuteEditCommand( const std::string& command, const base::Optional<base::string16>& value) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread(base::BindOnce(&FrameInputHandlerImpl::ExecuteEditCommand, - weak_this_, command, value)); - return; - } - if (!render_frame_) - return; - if (value) { - render_frame_->GetWebFrame()->ExecuteCommand( - blink::WebString::FromUTF8(command), - blink::WebString::FromUTF16(value.value())); - return; - } + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const std::string& command, + const base::Optional<base::string16>& value) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + + if (value) { + focused_frame->ExecuteCommand( + blink::WebString::FromUTF8(command), + blink::WebString::FromUTF16(value.value())); + return; + } - render_frame_->GetWebFrame()->ExecuteCommand( - blink::WebString::FromUTF8(command)); + focused_frame->ExecuteCommand(blink::WebString::FromUTF8(command)); + }, + widget_, command, value)); } void FrameInputHandlerImpl::Undo() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "Undo", UpdateState::kNone)); + widget_, "Undo", UpdateState::kNone)); } void FrameInputHandlerImpl::Redo() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "Redo", UpdateState::kNone)); + widget_, "Redo", UpdateState::kNone)); } void FrameInputHandlerImpl::Cut() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "Cut", UpdateState::kIsSelectingRange)); + widget_, "Cut", UpdateState::kIsSelectingRange)); } void FrameInputHandlerImpl::Copy() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "Copy", UpdateState::kIsSelectingRange)); + widget_, "Copy", UpdateState::kIsSelectingRange)); } void FrameInputHandlerImpl::CopyToFindPboard() { #if defined(OS_MACOSX) - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::CopyToFindPboard, weak_this_)); - return; - } - if (!render_frame_) - return; - render_frame_->OnCopyToFindPboard(); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + + RenderFrameImpl* render_frame = + RenderFrameImpl::FromWebFrame(focused_frame); + + if (!render_frame) + return; + + render_frame->OnCopyToFindPboard(); + }, + widget_)); #endif } void FrameInputHandlerImpl::Paste() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "Paste", UpdateState::kIsPasting)); + widget_, "Paste", UpdateState::kIsPasting)); } void FrameInputHandlerImpl::PasteAndMatchStyle() { - RunOnMainThread(base::BindOnce( - &FrameInputHandlerImpl::ExecuteCommandOnMainThread, weak_this_, - "PasteAndMatchStyle", UpdateState::kIsPasting)); + RunOnMainThread( + base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, + widget_, "PasteAndMatchStyle", UpdateState::kIsPasting)); } void FrameInputHandlerImpl::Replace(const base::string16& word) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::Replace, weak_this_, word)); - return; - } - if (!render_frame_) - return; - blink::WebLocalFrame* frame = render_frame_->GetWebFrame(); - if (!frame->HasSelection()) - frame->SelectWordAroundCaret(); - frame->ReplaceSelection(blink::WebString::FromUTF16(word)); - render_frame_->SyncSelectionIfRequired(); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const base::string16& word) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + + RenderFrameImpl* render_frame = + RenderFrameImpl::FromWebFrame(focused_frame); + + if (!render_frame) + return; + + if (!focused_frame->HasSelection()) + focused_frame->SelectWordAroundCaret(); + focused_frame->ReplaceSelection(blink::WebString::FromUTF16(word)); + render_frame->SyncSelectionIfRequired(); + }, + widget_, word)); } void FrameInputHandlerImpl::ReplaceMisspelling(const base::string16& word) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread(base::BindOnce(&FrameInputHandlerImpl::ReplaceMisspelling, - weak_this_, word)); - return; - } - if (!render_frame_) - return; - blink::WebLocalFrame* frame = render_frame_->GetWebFrame(); - if (!frame->HasSelection()) - return; - frame->ReplaceMisspelledRange(blink::WebString::FromUTF16(word)); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const base::string16& word) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + if (!focused_frame->HasSelection()) + return; + focused_frame->ReplaceMisspelledRange( + blink::WebString::FromUTF16(word)); + }, + widget_, word)); } void FrameInputHandlerImpl::Delete() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "Delete", UpdateState::kNone)); + widget_, "Delete", UpdateState::kNone)); } void FrameInputHandlerImpl::SelectAll() { RunOnMainThread( base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread, - weak_this_, "SelectAll", UpdateState::kIsSelectingRange)); + widget_, "SelectAll", UpdateState::kIsSelectingRange)); } void FrameInputHandlerImpl::CollapseSelection() { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::CollapseSelection, weak_this_)); - return; - } - - if (!render_frame_) - return; - const blink::WebRange& range = render_frame_->GetWebFrame() - ->GetInputMethodController() - ->GetSelectionOffsets(); - if (range.IsNull()) - return; - - HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange); - render_frame_->GetWebFrame()->SelectRange( - blink::WebRange(range.EndOffset(), 0), - blink::WebLocalFrame::kHideSelectionHandle, - blink::mojom::SelectionMenuBehavior::kHide); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + const blink::WebRange& range = + focused_frame->GetInputMethodController()->GetSelectionOffsets(); + if (range.IsNull()) + return; + + HandlingState handling_state(widget, UpdateState::kIsSelectingRange); + focused_frame->SelectRange(blink::WebRange(range.EndOffset(), 0), + blink::WebLocalFrame::kHideSelectionHandle, + blink::mojom::SelectionMenuBehavior::kHide); + }, + widget_)); } void FrameInputHandlerImpl::SelectRange(const gfx::Point& base, const gfx::Point& extent) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { // TODO(dtapuska): This event should be coalesced. Chrome IPC uses // one outstanding event and an ACK to handle coalescing on the browser // side. We should be able to clobber them in the main thread event queue. - RunOnMainThread(base::BindOnce(&FrameInputHandlerImpl::SelectRange, - weak_this_, base, extent)); - return; - } + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const gfx::Point& base, + const gfx::Point& extent) { + if (!widget) + return; - if (!render_frame_) - return; - RenderWidget* window_widget = render_frame_->GetLocalRootRenderWidget(); - HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange); - render_frame_->GetWebFrame()->SelectRange( - window_widget->ConvertWindowPointToViewport(base), - window_widget->ConvertWindowPointToViewport(extent)); + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + + HandlingState handling_state(widget, UpdateState::kIsSelectingRange); + focused_frame->SelectRange( + widget->ConvertWindowPointToViewport(base), + widget->ConvertWindowPointToViewport(extent)); + }, + widget_, base, extent)); } #if defined(OS_ANDROID) void FrameInputHandlerImpl::SelectWordAroundCaret( SelectWordAroundCaretCallback callback) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::SelectWordAroundCaret, - weak_this_, std::move(callback))); - return; - } - - bool did_select = false; - int start_adjust = 0; - int end_adjust = 0; - if (render_frame_) { - blink::WebLocalFrame* frame = render_frame_->GetWebFrame(); - blink::WebRange initial_range = frame->SelectionRange(); - render_frame_->GetLocalRootRenderWidget()->SetHandlingInputEvent(true); - if (!initial_range.IsNull()) - did_select = frame->SelectWordAroundCaret(); - if (did_select) { - blink::WebRange adjusted_range = frame->SelectionRange(); - DCHECK(!adjusted_range.IsNull()); - start_adjust = adjusted_range.StartOffset() - initial_range.StartOffset(); - end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset(); - } - render_frame_->GetLocalRootRenderWidget()->SetHandlingInputEvent(false); - } - // If the mojom channel is registered with compositor thread, we have to run // the callback on compositor thread. Otherwise run it on main thread. Mojom // requires the callback runs on the same thread. - if (RenderThreadImpl::current() && - RenderThreadImpl::current()->compositor_task_runner() && - input_event_queue_) { - RenderThreadImpl::current()->compositor_task_runner()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), did_select, start_adjust, - end_adjust)); - } else { - std::move(callback).Run(did_select, start_adjust, end_adjust); + if (!main_thread_task_runner_->BelongsToCurrentThread()) { + callback = base::BindOnce( + [](scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, + SelectWordAroundCaretCallback callback, bool did_select, + int32_t start_adjust, int32_t end_adjust) { + compositor_task_runner->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), did_select, + start_adjust, end_adjust)); + }, + base::ThreadTaskRunnerHandle::Get(), std::move(callback)); } + + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, + SelectWordAroundCaretCallback callback) { + if (!widget) { + std::move(callback).Run(false, 0, 0); + return; + } + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) { + std::move(callback).Run(false, 0, 0); + return; + } + + bool did_select = false; + int start_adjust = 0; + int end_adjust = 0; + blink::WebRange initial_range = focused_frame->SelectionRange(); + widget->SetHandlingInputEvent(true); + if (!initial_range.IsNull()) + did_select = focused_frame->SelectWordAroundCaret(); + if (did_select) { + blink::WebRange adjusted_range = focused_frame->SelectionRange(); + DCHECK(!adjusted_range.IsNull()); + start_adjust = + adjusted_range.StartOffset() - initial_range.StartOffset(); + end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset(); + } + widget->SetHandlingInputEvent(false); + std::move(callback).Run(did_select, start_adjust, end_adjust); + }, + widget_, std::move(callback))); } #endif // defined(OS_ANDROID) @@ -339,147 +359,126 @@ void FrameInputHandlerImpl::AdjustSelectionByCharacterOffset( int32_t start, int32_t end, blink::mojom::SelectionMenuBehavior selection_menu_behavior) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::AdjustSelectionByCharacterOffset, - weak_this_, start, end, selection_menu_behavior)); - return; - } - - if (!render_frame_) - return; - blink::WebRange range = render_frame_->GetWebFrame() - ->GetInputMethodController() - ->GetSelectionOffsets(); - if (range.IsNull()) - return; - - // Sanity checks to disallow empty and out of range selections. - if (start - end > range.length() || range.StartOffset() + start < 0) - return; - - HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange); - // A negative adjust amount moves the selection towards the beginning of - // the document, a positive amount moves the selection towards the end of - // the document. - render_frame_->GetWebFrame()->SelectRange( - blink::WebRange(range.StartOffset() + start, - range.length() + end - start), - blink::WebLocalFrame::kPreserveHandleVisibility, selection_menu_behavior); + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, int32_t start, int32_t end, + blink::mojom::SelectionMenuBehavior selection_menu_behavior) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + + blink::WebRange range = + focused_frame->GetInputMethodController()->GetSelectionOffsets(); + if (range.IsNull()) + return; + + // Sanity checks to disallow empty and out of range selections. + if (start - end > range.length() || range.StartOffset() + start < 0) + return; + + HandlingState handling_state(widget, UpdateState::kIsSelectingRange); + // A negative adjust amount moves the selection towards the beginning of + // the document, a positive amount moves the selection towards the end + // of the document. + focused_frame->SelectRange( + blink::WebRange(range.StartOffset() + start, + range.length() + end - start), + blink::WebLocalFrame::kPreserveHandleVisibility, + selection_menu_behavior); + }, + widget_, start, end, selection_menu_behavior)); } void FrameInputHandlerImpl::MoveRangeSelectionExtent(const gfx::Point& extent) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - // TODO(dtapuska): This event should be coalesced. Chrome IPC uses - // one outstanding event and an ACK to handle coalescing on the browser - // side. We should be able to clobber them in the main thread event queue. - RunOnMainThread(base::BindOnce( - &FrameInputHandlerImpl::MoveRangeSelectionExtent, weak_this_, extent)); - return; - } + // TODO(dtapuska): This event should be coalesced. Chrome IPC uses + // one outstanding event and an ACK to handle coalescing on the browser + // side. We should be able to clobber them in the main thread event queue. + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const gfx::Point& extent) { + if (!widget) + return; - if (!render_frame_) - return; - HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange); - render_frame_->GetWebFrame()->MoveRangeSelectionExtent( - render_frame_->GetLocalRootRenderWidget()->ConvertWindowPointToViewport( - extent)); + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + + HandlingState handling_state(widget, UpdateState::kIsSelectingRange); + focused_frame->MoveRangeSelectionExtent( + widget->ConvertWindowPointToViewport(extent)); + }, + widget_, extent)); } void FrameInputHandlerImpl::ScrollFocusedEditableNodeIntoRect( const gfx::Rect& rect) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread(base::BindOnce( - &FrameInputHandlerImpl::ScrollFocusedEditableNodeIntoRect, weak_this_, - rect)); - return; - } + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const gfx::Rect& rect) { + if (!widget) + return; - if (!render_frame_) - return; + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; - // OnSynchronizeVisualProperties does not call DidChangeVisibleViewport - // on OOPIFs. Since we are starting a new scroll operation now, call - // DidChangeVisibleViewport to ensure that we don't assume the element - // is already in view and ignore the scroll. - render_frame_->ResetHasScrolledFocusedEditableIntoView(); - render_frame_->ScrollFocusedEditableElementIntoRect(rect); -} + RenderFrameImpl* render_frame = + RenderFrameImpl::FromWebFrame(focused_frame); -void FrameInputHandlerImpl::MoveCaret(const gfx::Point& point) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - RunOnMainThread( - base::BindOnce(&FrameInputHandlerImpl::MoveCaret, weak_this_, point)); - return; - } + if (!render_frame) + return; - if (!render_frame_) - return; - - render_frame_->GetWebFrame()->MoveCaretSelection( - render_frame_->GetLocalRootRenderWidget()->ConvertWindowPointToViewport( - point)); + // OnSynchronizeVisualProperties does not call DidChangeVisibleViewport + // on OOPIFs. Since we are starting a new scroll operation now, call + // DidChangeVisibleViewport to ensure that we don't assume the element + // is already in view and ignore the scroll. + render_frame->ResetHasScrolledFocusedEditableIntoView(); + render_frame->ScrollFocusedEditableElementIntoRect(rect); + }, + widget_, rect)); } -void FrameInputHandlerImpl::GetWidgetInputHandler( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host) { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - main_thread_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&FrameInputHandlerImpl::GetWidgetInputHandler, - weak_this_, std::move(receiver), std::move(host))); - return; - } - if (!render_frame_) - return; - render_frame_->GetLocalRootRenderWidget() - ->widget_input_handler_manager() - ->AddAssociatedInterface(std::move(receiver), std::move(host)); +void FrameInputHandlerImpl::MoveCaret(const gfx::Point& point) { + RunOnMainThread(base::BindOnce( + [](base::WeakPtr<RenderWidget> widget, const gfx::Point& point) { + if (!widget) + return; + + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) + return; + focused_frame->MoveCaretSelection( + widget->ConvertWindowPointToViewport(point)); + }, + widget_, point)); } void FrameInputHandlerImpl::ExecuteCommandOnMainThread( + base::WeakPtr<RenderWidget> widget, const std::string& command, UpdateState update_state) { - if (!render_frame_) + if (!widget) return; - HandlingState handling_state(render_frame_, update_state); - render_frame_->GetWebFrame()->ExecuteCommand( - blink::WebString::FromUTF8(command)); -} - -void FrameInputHandlerImpl::Release() { - if (!main_thread_task_runner_->BelongsToCurrentThread()) { - // Close the receiver on the compositor thread first before telling the main - // thread to delete this object. - receiver_.reset(); - main_thread_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&FrameInputHandlerImpl::Release, weak_this_)); + HandlingState handling_state(widget, update_state); + auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget(); + if (!focused_frame) return; - } - delete this; -} - -void FrameInputHandlerImpl::BindNow( - mojo::PendingReceiver<mojom::FrameInputHandler> receiver) { - receiver_.Bind(std::move(receiver)); - receiver_.set_disconnect_handler( - base::BindOnce(&FrameInputHandlerImpl::Release, base::Unretained(this))); + focused_frame->ExecuteCommand(blink::WebString::FromUTF8(command)); } FrameInputHandlerImpl::HandlingState::HandlingState( - const base::WeakPtr<RenderFrameImpl>& render_frame, + const base::WeakPtr<RenderWidget>& render_widget, UpdateState state) - : render_frame_(render_frame), - original_select_range_value_(render_frame->handling_select_range()), - original_pasting_value_(render_frame->IsPasting()) { + : render_widget_(render_widget), + original_select_range_value_(render_widget->handling_select_range()), + original_pasting_value_(render_widget->is_pasting()) { switch (state) { case UpdateState::kIsPasting: - render_frame->set_is_pasting(true); + render_widget->set_is_pasting(true); FALLTHROUGH; // Matches RenderFrameImpl::OnPaste() which sets both. case UpdateState::kIsSelectingRange: - render_frame->set_handling_select_range(true); + render_widget->set_handling_select_range(true); break; case UpdateState::kNone: break; @@ -488,10 +487,10 @@ FrameInputHandlerImpl::HandlingState::HandlingState( FrameInputHandlerImpl::HandlingState::~HandlingState() { // RenderFrame may have been destroyed while this object was on the stack. - if (!render_frame_) + if (!render_widget_) return; - render_frame_->set_handling_select_range(original_select_range_value_); - render_frame_->set_is_pasting(original_pasting_value_); + render_widget_->set_handling_select_range(original_select_range_value_); + render_widget_->set_is_pasting(original_pasting_value_); } } // namespace content diff --git a/chromium/content/renderer/input/frame_input_handler_impl.h b/chromium/content/renderer/input/frame_input_handler_impl.h index 7780f07a68e..052a8be277c 100644 --- a/chromium/content/renderer/input/frame_input_handler_impl.h +++ b/chromium/content/renderer/input/frame_input_handler_impl.h @@ -8,19 +8,19 @@ #include "base/memory/ref_counted.h" #include "build/build_config.h" #include "content/common/content_export.h" -#include "content/common/input/input_handler.mojom.h" -#include "content/renderer/render_frame_impl.h" +#include "content/renderer/render_widget.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" +#include "third_party/blink/public/mojom/input/input_handler.mojom.h" namespace content { class MainThreadEventQueue; -// This class provides an implementation of FrameInputHandler mojo interface. -// When a compositor thread is being used in the renderer the mojo channel -// is bound on the compositor thread. Method calls, and events received on the -// compositor thread are then placed in the MainThreadEventQueue for -// the associated RenderWidget. This is done as to ensure that input related +// This class provides an implementation of FrameWidgetInputHandler mojo +// interface. When a compositor thread is being used in the renderer the mojo +// channel is bound on the compositor thread. Method calls, and events received +// on the compositor thread are then placed in the MainThreadEventQueue for the +// associated RenderWidget. This is done as to ensure that input related // messages and events that are handled on the compositor thread aren't // executed before other input events that need to be processed on the // main thread. ie. Since some messages flow to the compositor thread @@ -38,11 +38,14 @@ class MainThreadEventQueue; // // When a compositor thread isn't used the mojo channel is just bound // on the main thread and messages are handled right away. -class CONTENT_EXPORT FrameInputHandlerImpl : public mojom::FrameInputHandler { +class CONTENT_EXPORT FrameInputHandlerImpl + : public blink::mojom::FrameWidgetInputHandler { public: - static void CreateMojoService( - base::WeakPtr<RenderFrameImpl> render_frame, - mojo::PendingReceiver<mojom::FrameInputHandler> receiver); + FrameInputHandlerImpl( + base::WeakPtr<RenderWidget> widget, + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner, + scoped_refptr<MainThreadEventQueue> input_event_queue); + ~FrameInputHandlerImpl() override; void SetCompositionFromExistingText( int32_t start, @@ -78,48 +81,34 @@ class CONTENT_EXPORT FrameInputHandlerImpl : public mojom::FrameInputHandler { void MoveRangeSelectionExtent(const gfx::Point& extent) override; void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect) override; void MoveCaret(const gfx::Point& point) override; - void GetWidgetInputHandler( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host) override; private: - ~FrameInputHandlerImpl() override; enum class UpdateState { kNone, kIsPasting, kIsSelectingRange }; class HandlingState { public: - HandlingState(const base::WeakPtr<RenderFrameImpl>& render_frame, + HandlingState(const base::WeakPtr<RenderWidget>& render_widget, UpdateState state); ~HandlingState(); private: - base::WeakPtr<RenderFrameImpl> render_frame_; + base::WeakPtr<RenderWidget> render_widget_; bool original_select_range_value_; bool original_pasting_value_; }; - FrameInputHandlerImpl( - base::WeakPtr<RenderFrameImpl> render_frame, - mojo::PendingReceiver<mojom::FrameInputHandler> receiver); - void RunOnMainThread(base::OnceClosure closure); - void BindNow(mojo::PendingReceiver<mojom::FrameInputHandler> receiver); - void ExecuteCommandOnMainThread(const std::string& command, - UpdateState state); + static void ExecuteCommandOnMainThread(base::WeakPtr<RenderWidget> widget, + const std::string& command, + UpdateState state); void Release(); - mojo::Receiver<mojom::FrameInputHandler> receiver_{this}; - - // |render_frame_| should only be accessed on the main thread. Use - // GetRenderFrame so that it will DCHECK this for you. - base::WeakPtr<RenderFrameImpl> render_frame_; + // |render_widget_| should only be accessed on the main thread. + base::WeakPtr<RenderWidget> widget_; scoped_refptr<MainThreadEventQueue> input_event_queue_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; - base::WeakPtr<FrameInputHandlerImpl> weak_this_; - base::WeakPtrFactory<FrameInputHandlerImpl> weak_ptr_factory_{this}; - DISALLOW_COPY_AND_ASSIGN(FrameInputHandlerImpl); }; diff --git a/chromium/content/renderer/input/input_event_prediction.cc b/chromium/content/renderer/input/input_event_prediction.cc index 30a63b7f73d..b6632a6a8b4 100644 --- a/chromium/content/renderer/input/input_event_prediction.cc +++ b/chromium/content/renderer/input/input_event_prediction.cc @@ -8,7 +8,7 @@ #include "base/metrics/field_trial.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_functions.h" -#include "content/public/common/content_features.h" +#include "third_party/blink/public/common/features.h" using blink::WebInputEvent; using blink::WebMouseEvent; @@ -44,10 +44,10 @@ InputEventPrediction::InputEventPrediction(bool enable_resampling) // flag. std::string predictor_name = enable_resampling_ - ? GetFieldTrialParamValueByFeature(features::kResamplingInputEvents, - "predictor") + ? GetFieldTrialParamValueByFeature( + blink::features::kResamplingInputEvents, "predictor") : GetFieldTrialParamValueByFeature( - features::kInputPredictorTypeChoice, "predictor"); + blink::features::kInputPredictorTypeChoice, "predictor"); if (predictor_name.empty()) selected_predictor_type_ = diff --git a/chromium/content/renderer/input/input_event_prediction_unittest.cc b/chromium/content/renderer/input/input_event_prediction_unittest.cc index 0ad1d1df08f..95c3b52b6bd 100644 --- a/chromium/content/renderer/input/input_event_prediction_unittest.cc +++ b/chromium/content/renderer/input/input_event_prediction_unittest.cc @@ -7,15 +7,16 @@ #include <string> #include "base/test/scoped_feature_list.h" -#include "content/common/input/synthetic_web_input_event_builders.h" -#include "content/public/common/content_features.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" #include "ui/events/base_event_utils.h" namespace content { namespace { +using blink::SyntheticWebMouseEventBuilder; +using blink::SyntheticWebTouchEvent; using blink::WebInputEvent; using blink::WebMouseEvent; using blink::WebPointerProperties; @@ -28,7 +29,7 @@ class InputEventPredictionTest : public testing::Test { InputEventPredictionTest() { // Default to enable resampling with empty predictor for testing. ConfigureFieldTrialAndInitialize( - features::kResamplingInputEvents, + blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameEmpty); } @@ -70,7 +71,7 @@ class InputEventPredictionTest : public testing::Test { const std::string& predictor_type) { ConfigureFieldTrial(feature, predictor_type); event_predictor_ = std::make_unique<InputEventPrediction>( - base::FeatureList::IsEnabled(features::kResamplingInputEvents)); + base::FeatureList::IsEnabled(blink::features::kResamplingInputEvents)); } protected: @@ -87,32 +88,32 @@ TEST_F(InputEventPredictionTest, PredictorType) { EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeEmpty); - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameEmpty); EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeEmpty); - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameKalman); EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeKalman); - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameKalman); EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeKalman); - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameLsq); EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeLsq); // Default to Kalman predictor. - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, ""); + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, ""); EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeKalman); - ConfigureFieldTrialAndInitialize(features::kInputPredictorTypeChoice, + ConfigureFieldTrialAndInitialize(blink::features::kInputPredictorTypeChoice, blink::features::kScrollPredictorNameLsq); EXPECT_FALSE(event_predictor_->enable_resampling_); // When enable_resampling_ is true, kInputPredictorTypeChoice flag has no @@ -285,7 +286,8 @@ TEST_F(InputEventPredictionTest, TouchScrollStartedRemoveAllTouchPoints) { TEST_F(InputEventPredictionTest, ResamplingDisabled) { // When resampling is disabled, default to use kalman filter. - ConfigureFieldTrialAndInitialize(features::kInputPredictorTypeChoice, ""); + ConfigureFieldTrialAndInitialize(blink::features::kInputPredictorTypeChoice, + ""); EXPECT_FALSE(event_predictor_->enable_resampling_); EXPECT_EQ(event_predictor_->selected_predictor_type_, PredictorType::kScrollPredictorTypeKalman); @@ -321,7 +323,7 @@ TEST_F(InputEventPredictionTest, ResamplingDisabled) { // Test that when dt > maxResampling, resampling is cut off . TEST_F(InputEventPredictionTest, NoResampleWhenExceedMaxResampleTime) { - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameKalman); base::TimeDelta predictor_max_resample_time = @@ -397,7 +399,7 @@ TEST_F(InputEventPredictionTest, NoResampleWhenExceedMaxResampleTime) { // Test that when dt between events is 6ms, first predicted point is 6ms ahead. TEST_F(InputEventPredictionTest, PredictedEventsTimeIntervalEqualRealEvents) { - ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, + ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, blink::features::kScrollPredictorNameKalman); base::TimeTicks event_time = ui::EventTimeForNow(); diff --git a/chromium/content/renderer/input/main_thread_event_queue.cc b/chromium/content/renderer/input/main_thread_event_queue.cc index ac3ef9423a1..48bf221d93f 100644 --- a/chromium/content/renderer/input/main_thread_event_queue.cc +++ b/chromium/content/renderer/input/main_thread_event_queue.cc @@ -12,6 +12,7 @@ #include "content/common/input/event_with_latency_info.h" #include "content/common/input_messages.h" #include "content/renderer/render_widget.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/input/web_coalesced_input_event.h" #include "third_party/blink/public/common/input/web_input_event_attribution.h" @@ -48,16 +49,14 @@ constexpr base::TimeDelta kAsyncTouchMoveInterval = } // namespace -class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, - public MainThreadEventQueueTask { +class QueuedWebInputEvent : public MainThreadEventQueueTask { public: - QueuedWebInputEvent(ui::WebScopedInputEvent event, - const ui::LatencyInfo& latency, + QueuedWebInputEvent(std::unique_ptr<blink::WebCoalescedInputEvent> event, bool originally_cancelable, HandledEventCallback callback, bool known_by_scheduler, const blink::WebInputEventAttribution& attribution) - : WebCoalescedInputEvent(std::move(event), latency), + : event_(std::move(event)), originally_cancelable_(originally_cancelable), callback_(std::move(callback)), known_by_scheduler_count_(known_by_scheduler ? 1 : 0), @@ -67,19 +66,21 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, bool AreCoalescablePointerRawUpdateEvents(QueuedWebInputEvent* other_event) { // There is no pointermove at this point in the queue. - DCHECK(Event().GetType() != WebInputEvent::Type::kPointerMove && - other_event->Event().GetType() != WebInputEvent::Type::kPointerMove); + DCHECK(event_->Event().GetType() != WebInputEvent::Type::kPointerMove && + other_event->event_->Event().GetType() != + WebInputEvent::Type::kPointerMove); // Events with modifiers differing by kRelativeMotionEvent should not be // coalesced. In case of a pointer lock, kRelativeMotionEvent is sent // when the cursor is recentered. Events post the recentered event have // a big delta compared to the previous events and hence should not be // coalesced. - return Event().GetType() == WebInputEvent::Type::kPointerRawUpdate && - other_event->Event().GetType() == + return event_->Event().GetType() == WebInputEvent::Type::kPointerRawUpdate && - ((Event().GetModifiers() & + other_event->event_->Event().GetType() == + WebInputEvent::Type::kPointerRawUpdate && + ((event_->Event().GetModifiers() & blink::WebInputEvent::Modifiers::kRelativeMotionEvent) == - (other_event->Event().GetModifiers() & + (other_event->event_->Event().GetModifiers() & blink::WebInputEvent::Modifiers::kRelativeMotionEvent)); } @@ -89,15 +90,15 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, QueuedWebInputEvent* other_event = static_cast<QueuedWebInputEvent*>(other_task); - if (other_event->Event().GetType() == + if (other_event->event_->Event().GetType() == blink::WebInputEvent::Type::kTouchScrollStarted) { return HandleTouchScrollStartQueued(); } - if (!Event().IsSameEventClass(other_event->Event())) + if (!event_->Event().IsSameEventClass(other_event->event_->Event())) return FilterResult::KeepIterating; - if (!CanCoalesceWith(*other_event)) { + if (!event_->CanCoalesceWith(*other_event->event_)) { // Two pointerevents may not be able to coalesce but we should continue // looking further down the queue if both of them were rawupdate or move // events and only their pointer_type, id, or event_type was different. @@ -117,11 +118,11 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, if (other_event->callback_) { blocking_coalesced_callbacks_.push_back( std::make_pair(std::move(other_event->callback_), - other_event->latency_info().trace_id())); + other_event->event_->latency_info().trace_id())); } known_by_scheduler_count_ += other_event->known_by_scheduler_count_; - CoalesceWith(*other_event); + event_->CoalesceWith(*other_event->event_); // The newest event (|other_item|) always wins when updating fields. originally_cancelable_ = other_event->originally_cancelable_; @@ -135,12 +136,12 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, HandledEventCallback callback = base::BindOnce(&QueuedWebInputEvent::HandledEvent, base::Unretained(this), base::RetainedRef(queue)); - if (!queue->HandleEventOnMainThread(*this, attribution(), + if (!queue->HandleEventOnMainThread(*event_, attribution(), std::move(callback))) { // The |callback| won't be run, so our stored |callback_| should run // indicating error. HandledEvent(queue, blink::mojom::InputEventResultState::kNotConsumed, - latency_info(), nullptr, base::nullopt); + event_->latency_info(), nullptr, base::nullopt); } } @@ -171,7 +172,7 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, // events processed. for (size_t i = 0; i < known_by_scheduler_count_; ++i) { queue->main_thread_scheduler_->DidHandleInputEventOnMainThread( - Event(), + event_->Event(), ack_result == blink::mojom::InputEventResultState::kConsumed ? blink::WebInputEventResult::kHandledApplication : blink::WebInputEventResult::kNotHandled); @@ -183,14 +184,20 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, blink::WebInputEventAttribution attribution() const { return attribution_; } + const blink::WebInputEvent& Event() const { return event_->Event(); } + + blink::WebCoalescedInputEvent* mutable_coalesced_event() { + return event_.get(); + } + private: FilterResult HandleTouchScrollStartQueued() { // A TouchScrollStart will queued after this touch move which will make all // previous touch moves that are queued uncancelable. - switch (Event().GetType()) { + switch (event_->Event().GetType()) { case blink::WebInputEvent::Type::kTouchMove: { blink::WebTouchEvent* touch_event = - static_cast<blink::WebTouchEvent*>(EventPointer()); + static_cast<blink::WebTouchEvent*>(event_->EventPointer()); if (touch_event->dispatch_type == blink::WebInputEvent::DispatchType::kBlocking) { touch_event->dispatch_type = @@ -206,6 +213,8 @@ class QueuedWebInputEvent : public blink::WebCoalescedInputEvent, } } + std::unique_ptr<blink::WebCoalescedInputEvent> event_; + // Contains the pending callbacks to be called, along with their associated // trace_ids. base::circular_deque<std::pair<HandledEventCallback, int64_t>> @@ -246,20 +255,19 @@ MainThreadEventQueue::MainThreadEventQueue( raf_fallback_timer_.SetTaskRunner(main_task_runner); event_predictor_ = std::make_unique<InputEventPrediction>( - base::FeatureList::IsEnabled(features::kResamplingInputEvents)); + base::FeatureList::IsEnabled(blink::features::kResamplingInputEvents)); } MainThreadEventQueue::~MainThreadEventQueue() {} void MainThreadEventQueue::HandleEvent( - ui::WebScopedInputEvent event, - const ui::LatencyInfo& latency, + std::unique_ptr<blink::WebCoalescedInputEvent> event, InputEventDispatchType original_dispatch_type, blink::mojom::InputEventResultState ack_result, const blink::WebInputEventAttribution& attribution, HandledEventCallback callback) { TRACE_EVENT2("input", "MainThreadEventQueue::HandleEvent", "dispatch_type", - original_dispatch_type, "event_type", event->GetType()); + original_dispatch_type, "event_type", event->Event().GetType()); DCHECK(original_dispatch_type == DISPATCH_TYPE_BLOCKING || original_dispatch_type == DISPATCH_TYPE_NON_BLOCKING); DCHECK(ack_result == blink::mojom::InputEventResultState::kSetNonBlocking || @@ -270,13 +278,15 @@ void MainThreadEventQueue::HandleEvent( bool is_blocking = original_dispatch_type == DISPATCH_TYPE_BLOCKING && ack_result != blink::mojom::InputEventResultState::kSetNonBlocking; - bool is_wheel = event->GetType() == blink::WebInputEvent::Type::kMouseWheel; - bool is_touch = blink::WebInputEvent::IsTouchEventType(event->GetType()); + bool is_wheel = + event->Event().GetType() == blink::WebInputEvent::Type::kMouseWheel; + bool is_touch = + blink::WebInputEvent::IsTouchEventType(event->Event().GetType()); bool originally_cancelable = false; if (is_touch) { blink::WebTouchEvent* touch_event = - static_cast<blink::WebTouchEvent*>(event.get()); + static_cast<blink::WebTouchEvent*>(event->EventPointer()); originally_cancelable = touch_event->dispatch_type == blink::WebInputEvent::DispatchType::kBlocking; @@ -313,7 +323,7 @@ void MainThreadEventQueue::HandleEvent( if (is_wheel) { blink::WebMouseWheelEvent* wheel_event = - static_cast<blink::WebMouseWheelEvent*>(event.get()); + static_cast<blink::WebMouseWheelEvent*>(event->EventPointer()); originally_cancelable = wheel_event->dispatch_type == blink::WebInputEvent::DispatchType::kBlocking; if (!is_blocking) { @@ -331,26 +341,33 @@ void MainThreadEventQueue::HandleEvent( } if (has_pointerrawupdate_handlers_) { - if (event->GetType() == WebInputEvent::Type::kMouseMove) { - ui::WebScopedInputEvent raw_event(new blink::WebPointerEvent( - WebInputEvent::Type::kPointerRawUpdate, - *(static_cast<blink::WebMouseEvent*>(event.get())))); + if (event->Event().GetType() == WebInputEvent::Type::kMouseMove) { + std::unique_ptr<blink::WebCoalescedInputEvent> raw_event = + std::make_unique<blink::WebCoalescedInputEvent>( + std::make_unique<blink::WebPointerEvent>( + WebInputEvent::Type::kPointerRawUpdate, + *(static_cast<blink::WebMouseEvent*>(event->EventPointer()))), + event->latency_info()); std::unique_ptr<QueuedWebInputEvent> raw_queued_event( - new QueuedWebInputEvent(std::move(raw_event), latency, false, + new QueuedWebInputEvent(std::move(raw_event), false, HandledEventCallback(), false, attribution)); QueueEvent(std::move(raw_queued_event)); - } else if (event->GetType() == WebInputEvent::Type::kTouchMove) { + } else if (event->Event().GetType() == WebInputEvent::Type::kTouchMove) { const blink::WebTouchEvent& touch_event = - *static_cast<const blink::WebTouchEvent*>(event.get()); + *static_cast<const blink::WebTouchEvent*>(event->EventPointer()); for (unsigned i = 0; i < touch_event.touches_length; ++i) { const blink::WebTouchPoint& touch_point = touch_event.touches[i]; if (touch_point.state == blink::WebTouchPoint::State::kStateMoved) { - ui::WebScopedInputEvent raw_event( - new blink::WebPointerEvent(touch_event, touch_point)); - raw_event->SetType(WebInputEvent::Type::kPointerRawUpdate); + std::unique_ptr<blink::WebCoalescedInputEvent> raw_event = + std::make_unique<blink::WebCoalescedInputEvent>( + std::make_unique<blink::WebPointerEvent>(touch_event, + touch_point), + event->latency_info()); + raw_event->EventPointer()->SetType( + WebInputEvent::Type::kPointerRawUpdate); std::unique_ptr<QueuedWebInputEvent> raw_queued_event( - new QueuedWebInputEvent(std::move(raw_event), latency, false, + new QueuedWebInputEvent(std::move(raw_event), false, HandledEventCallback(), false, attribution)); QueueEvent(std::move(raw_queued_event)); @@ -359,15 +376,21 @@ void MainThreadEventQueue::HandleEvent( } } + ui::LatencyInfo cloned_latency_info; + + // Clone the latency info if we are calling the callback. + if (callback) + cloned_latency_info = event->latency_info(); + std::unique_ptr<QueuedWebInputEvent> queued_event(new QueuedWebInputEvent( - std::move(event), latency, originally_cancelable, - std::move(event_callback), IsForwardedAndSchedulerKnown(ack_result), - attribution)); + std::move(event), originally_cancelable, std::move(event_callback), + IsForwardedAndSchedulerKnown(ack_result), attribution)); QueueEvent(std::move(queued_event)); if (callback) - std::move(callback).Run(ack_result, latency, nullptr, base::nullopt); + std::move(callback).Run(ack_result, cloned_latency_info, nullptr, + base::nullopt); } void MainThreadEventQueue::QueueClosure(base::OnceClosure closure) { @@ -621,7 +644,8 @@ void MainThreadEventQueue::HandleEventResampling( base::TimeTicks frame_time) { if (item->IsWebInputEvent() && allow_raf_aligned_input_ && event_predictor_) { QueuedWebInputEvent* event = static_cast<QueuedWebInputEvent*>(item.get()); - event_predictor_->HandleEvents(*event, frame_time); + event_predictor_->HandleEvents(*event->mutable_coalesced_event(), + frame_time); } } diff --git a/chromium/content/renderer/input/main_thread_event_queue.h b/chromium/content/renderer/input/main_thread_event_queue.h index 8f338767dbc..02efe76b16d 100644 --- a/chromium/content/renderer/input/main_thread_event_queue.h +++ b/chromium/content/renderer/input/main_thread_event_queue.h @@ -90,8 +90,7 @@ class CONTENT_EXPORT MainThreadEventQueue // Called once the compositor has handled |event| and indicated that it is // a non-blocking event to be queued to the main thread. - void HandleEvent(ui::WebScopedInputEvent event, - const ui::LatencyInfo& latency, + void HandleEvent(std::unique_ptr<blink::WebCoalescedInputEvent> event, InputEventDispatchType dispatch_type, blink::mojom::InputEventResultState ack_result, const blink::WebInputEventAttribution& attribution, diff --git a/chromium/content/renderer/input/main_thread_event_queue_unittest.cc b/chromium/content/renderer/input/main_thread_event_queue_unittest.cc index 69894a688df..67207dfd5c0 100644 --- a/chromium/content/renderer/input/main_thread_event_queue_unittest.cc +++ b/chromium/content/renderer/input/main_thread_event_queue_unittest.cc @@ -17,13 +17,16 @@ #include "base/test/scoped_feature_list.h" #include "base/test/test_simple_task_runner.h" #include "build/build_config.h" -#include "content/common/input/synthetic_web_input_event_builders.h" #include "content/renderer/input/main_thread_event_queue.h" #include "content/renderer/render_thread_impl.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" #include "third_party/blink/public/common/input/web_input_event_attribution.h" #include "third_party/blink/public/platform/scheduler/test/web_mock_thread_scheduler.h" +using blink::SyntheticWebMouseEventBuilder; +using blink::SyntheticWebMouseWheelEventBuilder; +using blink::SyntheticWebTouchEvent; using blink::WebInputEvent; using blink::WebMouseEvent; using blink::WebMouseWheelEvent; @@ -198,9 +201,11 @@ class MainThreadEventQueueTest : public testing::Test, blink::mojom::InputEventResultState ack_result) { base::AutoReset<bool> in_handle_event(&handler_callback_->handling_event_, true); - queue_->HandleEvent( - event.Clone(), ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING, ack_result, - blink::WebInputEventAttribution(), handler_callback_->GetCallback()); + queue_->HandleEvent(std::make_unique<blink::WebCoalescedInputEvent>( + event.Clone(), ui::LatencyInfo()), + DISPATCH_TYPE_BLOCKING, ack_result, + blink::WebInputEventAttribution(), + handler_callback_->GetCallback()); } void RunClosure(unsigned closure_id) { @@ -370,8 +375,6 @@ TEST_F(MainThreadEventQueueTest, NonBlockingWheel) { handled_tasks_[0]->taskAsEvent()->GetCoalescedEventsPointers(); const WebMouseWheelEvent* coalesced_wheel_event0 = static_cast<const WebMouseWheelEvent*>(coalesced_events[0].get()); - coalesced_event.dispatch_type = - WebInputEvent::DispatchType::kListenersNonBlockingPassive; EXPECT_TRUE(Equal(coalesced_event, *coalesced_wheel_event0)); coalesced_event = kEvents[1]; @@ -399,8 +402,6 @@ TEST_F(MainThreadEventQueueTest, NonBlockingWheel) { handled_tasks_[1]->taskAsEvent()->GetCoalescedEventsPointers(); const WebMouseWheelEvent* coalesced_wheel_event0 = static_cast<const WebMouseWheelEvent*>(coalesced_events[0].get()); - coalesced_event.dispatch_type = - WebInputEvent::DispatchType::kListenersNonBlockingPassive; EXPECT_TRUE(Equal(coalesced_event, *coalesced_wheel_event0)); coalesced_event = kEvents[3]; @@ -444,9 +445,10 @@ TEST_F(MainThreadEventQueueTest, NonBlockingTouch) { handled_tasks_.at(0)->taskAsEvent()->Event().GetType()); const WebTouchEvent* last_touch_event = static_cast<const WebTouchEvent*>( handled_tasks_.at(0)->taskAsEvent()->EventPointer()); - kEvents[0].dispatch_type = + SyntheticWebTouchEvent non_blocking_touch = kEvents[0]; + non_blocking_touch.dispatch_type = WebInputEvent::DispatchType::kListenersNonBlockingPassive; - EXPECT_TRUE(Equal(kEvents[0], *last_touch_event)); + EXPECT_TRUE(Equal(non_blocking_touch, *last_touch_event)); { EXPECT_EQ(1u, handled_tasks_[0]->taskAsEvent()->CoalescedEventSize()); @@ -462,9 +464,10 @@ TEST_F(MainThreadEventQueueTest, NonBlockingTouch) { handled_tasks_.at(1)->taskAsEvent()->Event().GetType()); last_touch_event = static_cast<const WebTouchEvent*>( handled_tasks_.at(1)->taskAsEvent()->EventPointer()); - kEvents[1].dispatch_type = + non_blocking_touch = kEvents[1]; + non_blocking_touch.dispatch_type = WebInputEvent::DispatchType::kListenersNonBlockingPassive; - EXPECT_TRUE(Equal(kEvents[1], *last_touch_event)); + EXPECT_TRUE(Equal(non_blocking_touch, *last_touch_event)); { EXPECT_EQ(1u, handled_tasks_[1]->taskAsEvent()->CoalescedEventSize()); @@ -493,8 +496,6 @@ TEST_F(MainThreadEventQueueTest, NonBlockingTouch) { handled_tasks_[2]->taskAsEvent()->GetCoalescedEventsPointers(); const WebTouchEvent* coalesced_touch_event0 = static_cast<const WebTouchEvent*>(coalesced_events[0].get()); - coalesced_event.dispatch_type = - WebInputEvent::DispatchType::kListenersNonBlockingPassive; EXPECT_TRUE(Equal(coalesced_event, *coalesced_touch_event0)); coalesced_event = kEvents[3]; @@ -1493,4 +1494,103 @@ TEST_F(MainThreadEventQueueTest, UnbufferedDispatchMouseEvent) { EXPECT_FALSE(needs_main_frame_); } +// This test verifies that the events marked with kRelativeMotionEvent modifier +// are not coalesced with other events. During pointer lock, +// kRelativeMotionEvent is sent to the Renderer only to update the new screen +// position. Events of this kind shouldn't be dispatched or coalesced. +TEST_F(MainThreadEventQueueTest, PointerEventsWithRelativeMotionCoalescing) { + WebMouseEvent mouse_move = SyntheticWebMouseEventBuilder::Build( + WebInputEvent::Type::kMouseMove, 10, 10, 0); + + EXPECT_FALSE(main_task_runner_->HasPendingTask()); + EXPECT_EQ(0u, event_queue().size()); + + // Non blocking events are not reported to the scheduler. + EXPECT_CALL(thread_scheduler_, + DidHandleInputEventOnMainThread(testing::_, testing::_)) + .Times(0); + + queue_->HasPointerRawUpdateEventHandlers(true); + + // Inject two mouse move events. For each event injected, there will be two + // events in the queue. One for kPointerRawUpdate and another kMouseMove + // event. + HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking); + EXPECT_EQ(2u, event_queue().size()); + // When another event of the same kind is injected, it is coalesced with the + // previous event, hence queue size doesn't change. + HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking); + EXPECT_EQ(2u, event_queue().size()); + + // Inject a kRelativeMotionEvent, which cannot be coalesced. Thus, the queue + // size should increase. + WebMouseEvent fake_mouse_move = SyntheticWebMouseEventBuilder::Build( + WebInputEvent::Type::kMouseMove, 10, 10, + blink::WebInputEvent::Modifiers::kRelativeMotionEvent); + HandleEvent(fake_mouse_move, + blink::mojom::InputEventResultState::kSetNonBlocking); + EXPECT_EQ(4u, event_queue().size()); + + // Lastly inject another mouse move event. Since it cannot be coalesced with + // previous event, which is a kRelativeMotionEvent, expect the queue size to + // increase again. + HandleEvent(mouse_move, blink::mojom::InputEventResultState::kSetNonBlocking); + EXPECT_EQ(6u, event_queue().size()); + + RunPendingTasksWithSimulatedRaf(); + EXPECT_EQ(0u, event_queue().size()); + EXPECT_FALSE(needs_main_frame_); + EXPECT_FALSE(main_task_runner_->HasPendingTask()); + + // For the 4 events injected, verify that the queue size should be 6, that is + // 3 kPointerRawUpdate events and 3 kMouseMove events. + EXPECT_EQ(6u, handled_tasks_.size()); + { + // The first event should have a |CoalescedEventSize| of 2, since two events + // of the same kind are coalesced. + EXPECT_EQ(WebInputEvent::Type::kPointerRawUpdate, + handled_tasks_.at(0)->taskAsEvent()->Event().GetType()); + EXPECT_EQ(2u, handled_tasks_.at(0)->taskAsEvent()->CoalescedEventSize()); + } + { + // The second event is a kRelativeMotionEvent, it cannot be coalesced, so + // the |CoalescedEventSize| should be 1. + EXPECT_EQ(WebInputEvent::Type::kPointerRawUpdate, + handled_tasks_.at(1)->taskAsEvent()->Event().GetType()); + EXPECT_EQ(1u, handled_tasks_.at(1)->taskAsEvent()->CoalescedEventSize()); + EXPECT_EQ(blink::WebInputEvent::Modifiers::kRelativeMotionEvent, + handled_tasks_.at(1)->taskAsEvent()->Event().GetModifiers()); + } + { + // The third event cannot be coalesced with the previous kPointerRawUpdate, + // so |CoalescedEventSize| should be 1. + EXPECT_EQ(WebInputEvent::Type::kPointerRawUpdate, + handled_tasks_.at(2)->taskAsEvent()->Event().GetType()); + EXPECT_EQ(1u, handled_tasks_.at(2)->taskAsEvent()->CoalescedEventSize()); + } + { + // The fourth event should have a |CoalescedEventSize| of 2, since two + // events of the same kind are coalesced. + EXPECT_EQ(WebInputEvent::Type::kMouseMove, + handled_tasks_.at(3)->taskAsEvent()->Event().GetType()); + EXPECT_EQ(2u, handled_tasks_.at(3)->taskAsEvent()->CoalescedEventSize()); + } + { + // The fifth event is a kRelativeMotionEvent, it cannot be coalesced, so + // the |CoalescedEventSize| should be 1. + EXPECT_EQ(WebInputEvent::Type::kMouseMove, + handled_tasks_.at(4)->taskAsEvent()->Event().GetType()); + EXPECT_EQ(1u, handled_tasks_.at(4)->taskAsEvent()->CoalescedEventSize()); + EXPECT_EQ(blink::WebInputEvent::Modifiers::kRelativeMotionEvent, + handled_tasks_.at(4)->taskAsEvent()->Event().GetModifiers()); + } + { + // The sixth event cannot be coalesced with the previous kMouseMove, + // so |CoalescedEventSize| should be 1. + EXPECT_EQ(WebInputEvent::Type::kMouseMove, + handled_tasks_.at(5)->taskAsEvent()->Event().GetType()); + EXPECT_EQ(1u, handled_tasks_.at(5)->taskAsEvent()->CoalescedEventSize()); + } +} + } // namespace content diff --git a/chromium/content/renderer/input/render_widget_input_handler.cc b/chromium/content/renderer/input/render_widget_input_handler.cc deleted file mode 100644 index a3ce13879aa..00000000000 --- a/chromium/content/renderer/input/render_widget_input_handler.cc +++ /dev/null @@ -1,730 +0,0 @@ -// Copyright 2015 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. - -#include "content/renderer/input/render_widget_input_handler.h" - -#include <stddef.h> -#include <stdint.h> -#include <utility> - -#include "base/auto_reset.h" -#include "base/command_line.h" -#include "base/metrics/histogram_macros.h" -#include "build/build_config.h" -#include "cc/metrics/event_metrics.h" -#include "cc/paint/element_id.h" -#include "cc/trees/latency_info_swap_promise_monitor.h" -#include "components/viz/common/surfaces/frame_sink_id.h" -#include "content/public/common/content_switches.h" -#include "content/public/renderer/render_frame.h" -#include "content/renderer/ime_event_guard.h" -#include "content/renderer/input/render_widget_input_handler_delegate.h" -#include "content/renderer/render_frame_proxy.h" -#include "content/renderer/render_thread_impl.h" -#include "content/renderer/render_widget.h" -#include "services/tracing/public/cpp/perfetto/flow_event_utils.h" -#include "services/tracing/public/cpp/perfetto/macros.h" -#include "third_party/blink/public/common/input/web_gesture_device.h" -#include "third_party/blink/public/common/input/web_gesture_event.h" -#include "third_party/blink/public/common/input/web_input_event_attribution.h" -#include "third_party/blink/public/common/input/web_keyboard_event.h" -#include "third_party/blink/public/common/input/web_mouse_wheel_event.h" -#include "third_party/blink/public/common/input/web_pointer_event.h" -#include "third_party/blink/public/common/input/web_touch_event.h" -#include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h" -#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" -#include "third_party/blink/public/web/web_document.h" -#include "third_party/blink/public/web/web_frame_widget.h" -#include "third_party/blink/public/web/web_local_frame.h" -#include "third_party/blink/public/web/web_node.h" -#include "ui/events/blink/blink_event_util.h" -#include "ui/events/blink/web_input_event_traits.h" -#include "ui/gfx/geometry/dip_util.h" -#include "ui/gfx/geometry/point_conversions.h" -#include "ui/latency/latency_info.h" - -#if defined(OS_ANDROID) -#include <android/keycodes.h> -#endif - -using blink::WebGestureEvent; -using blink::WebInputEvent; -using blink::WebInputEventResult; -using blink::WebKeyboardEvent; -using blink::WebMouseEvent; -using blink::WebMouseWheelEvent; -using blink::WebPointerEvent; -using blink::WebTouchEvent; -using blink::WebTouchPoint; -using perfetto::protos::pbzero::ChromeLatencyInfo; -using perfetto::protos::pbzero::TrackEvent; -using ui::DidOverscrollParams; - -namespace content { - -namespace { - -int64_t GetEventLatencyMicros(base::TimeTicks event_timestamp, - base::TimeTicks now) { - return (now - event_timestamp).InMicroseconds(); -} - -void LogInputEventLatencyUma(const WebInputEvent& event, base::TimeTicks now) { - UMA_HISTOGRAM_CUSTOM_COUNTS("Event.AggregatedLatency.Renderer2", - GetEventLatencyMicros(event.TimeStamp(), now), 1, - 10000000, 100); -} - -void LogPassiveEventListenersUma(WebInputEventResult result, - WebInputEvent::DispatchType dispatch_type) { - // This enum is backing a histogram. Do not remove or reorder members. - enum ListenerEnum { - PASSIVE_LISTENER_UMA_ENUM_PASSIVE, - PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE, - PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED, - PASSIVE_LISTENER_UMA_ENUM_CANCELABLE, - PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED, - PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING, - PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_MAIN_THREAD_RESPONSIVENESS_DEPRECATED, - PASSIVE_LISTENER_UMA_ENUM_COUNT - }; - - ListenerEnum enum_value; - switch (dispatch_type) { - case WebInputEvent::DispatchType::kListenersForcedNonBlockingDueToFling: - enum_value = PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING_DUE_TO_FLING; - break; - case WebInputEvent::DispatchType::kListenersNonBlockingPassive: - enum_value = PASSIVE_LISTENER_UMA_ENUM_PASSIVE; - break; - case WebInputEvent::DispatchType::kEventNonBlocking: - enum_value = PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE; - break; - case WebInputEvent::DispatchType::kBlocking: - if (result == WebInputEventResult::kHandledApplication) - enum_value = PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED; - else if (result == WebInputEventResult::kHandledSuppressed) - enum_value = PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED; - else - enum_value = PASSIVE_LISTENER_UMA_ENUM_CANCELABLE; - break; - default: - NOTREACHED(); - return; - } - - UMA_HISTOGRAM_ENUMERATION("Event.PassiveListeners", enum_value, - PASSIVE_LISTENER_UMA_ENUM_COUNT); -} - -void LogAllPassiveEventListenersUma(const WebInputEvent& input_event, - WebInputEventResult result) { - // TODO(dtapuska): Use the input_event.timeStampSeconds as the start - // ideally this should be when the event was sent by the compositor to the - // renderer. https://crbug.com/565348. - if (input_event.GetType() == WebInputEvent::Type::kTouchStart || - input_event.GetType() == WebInputEvent::Type::kTouchMove || - input_event.GetType() == WebInputEvent::Type::kTouchEnd) { - const WebTouchEvent& touch = static_cast<const WebTouchEvent&>(input_event); - - LogPassiveEventListenersUma(result, touch.dispatch_type); - } else if (input_event.GetType() == WebInputEvent::Type::kMouseWheel) { - LogPassiveEventListenersUma( - result, - static_cast<const WebMouseWheelEvent&>(input_event).dispatch_type); - } -} - -blink::WebCoalescedInputEvent GetCoalescedWebPointerEventForTouch( - const WebPointerEvent& pointer_event, - const std::vector<std::unique_ptr<WebInputEvent>>& coalesced_events, - const std::vector<std::unique_ptr<WebInputEvent>>& predicted_events, - const ui::LatencyInfo& latency) { - std::vector<std::unique_ptr<WebInputEvent>> related_pointer_events; - for (const std::unique_ptr<WebInputEvent>& event : coalesced_events) { - DCHECK(WebInputEvent::IsTouchEventType(event->GetType())); - const WebTouchEvent& touch_event = - static_cast<const WebTouchEvent&>(*event); - for (unsigned i = 0; i < touch_event.touches_length; ++i) { - if (touch_event.touches[i].id == pointer_event.id && - touch_event.touches[i].state != - WebTouchPoint::State::kStateStationary) { - related_pointer_events.emplace_back(std::make_unique<WebPointerEvent>( - touch_event, touch_event.touches[i])); - } - } - } - std::vector<std::unique_ptr<WebInputEvent>> predicted_pointer_events; - for (const std::unique_ptr<WebInputEvent>& event : predicted_events) { - DCHECK(WebInputEvent::IsTouchEventType(event->GetType())); - const WebTouchEvent& touch_event = - static_cast<const WebTouchEvent&>(*event); - for (unsigned i = 0; i < touch_event.touches_length; ++i) { - if (touch_event.touches[i].id == pointer_event.id && - touch_event.touches[i].state != - WebTouchPoint::State::kStateStationary) { - predicted_pointer_events.emplace_back(std::make_unique<WebPointerEvent>( - touch_event, touch_event.touches[i])); - } - } - } - - return blink::WebCoalescedInputEvent( - pointer_event.Clone(), std::move(related_pointer_events), - std::move(predicted_pointer_events), latency); -} - -viz::FrameSinkId GetRemoteFrameSinkId(const blink::WebHitTestResult& result) { - const blink::WebNode& node = result.GetNode(); - DCHECK(!node.IsNull()); - blink::WebFrame* result_frame = blink::WebFrame::FromFrameOwnerElement(node); - if (!result_frame || !result_frame->IsWebRemoteFrame()) - return viz::FrameSinkId(); - - blink::WebRemoteFrame* remote_frame = result_frame->ToWebRemoteFrame(); - if (remote_frame->IsIgnoredForHitTest() || !result.ContentBoxContainsPoint()) - return viz::FrameSinkId(); - - return RenderFrameProxy::FromWebFrame(remote_frame)->frame_sink_id(); -} - -blink::mojom::InputEventResultState GetAckResult( - WebInputEventResult processed) { - return processed == WebInputEventResult::kNotHandled - ? blink::mojom::InputEventResultState::kNotConsumed - : blink::mojom::InputEventResultState::kConsumed; -} - -} // namespace - -// This class should be placed on the stack when handling an input event. It -// stores information from callbacks from blink while handling an input event -// and allows them to be returned in the InputEventAck result. -class RenderWidgetInputHandler::HandlingState { - public: - HandlingState(base::WeakPtr<RenderWidgetInputHandler> input_handler_param, - blink::WebInputEvent::Type type) - : event_type(type), input_handler(std::move(input_handler_param)) { - previous_was_handling_input = input_handler->handling_input_event_; - previous_state = input_handler->handling_input_state_; - input_handler->handling_input_event_ = true; - input_handler->handling_input_state_ = this; - } - - ~HandlingState() { - // Unwinding the HandlingState on the stack might result in an - // input_handler_ that got destroyed. i.e. via a nested event loop. - if (!input_handler) - return; - input_handler->handling_input_event_ = previous_was_handling_input; - DCHECK_EQ(input_handler->handling_input_state_, this); - input_handler->handling_input_state_ = previous_state; - } - - // Used to intercept overscroll notifications while an event is being - // handled. If the event causes overscroll, the overscroll metadata can be - // bundled in the event ack, saving an IPC. Note that we must continue - // supporting overscroll IPC notifications due to fling animation updates. - blink::mojom::DidOverscrollParamsPtr event_overscroll; - - base::Optional<cc::TouchAction> touch_action; - - // Used to hold a sequence of parameters corresponding to scroll gesture - // events that should be injected once the current input event is done - // being processed. - std::unique_ptr< - std::vector<RenderWidgetInputHandler::InjectScrollGestureParams>> - injected_scroll_params; - - // Type of the input event we are currently handling. - blink::WebInputEvent::Type event_type; - - private: - HandlingState* previous_state; - bool previous_was_handling_input; - base::WeakPtr<RenderWidgetInputHandler> input_handler; -}; - -RenderWidgetInputHandler::RenderWidgetInputHandler( - RenderWidgetInputHandlerDelegate* delegate, - RenderWidget* widget) - : delegate_(delegate), widget_(widget) { - DCHECK(delegate); - DCHECK(widget); - delegate->SetInputHandler(this); -} - -RenderWidgetInputHandler::~RenderWidgetInputHandler() = default; - -blink::WebHitTestResult RenderWidgetInputHandler::GetHitTestResultAtPoint( - const gfx::PointF& point) { - gfx::PointF point_in_pixel(point); - if (widget_->compositor_deps()->IsUseZoomForDSFEnabled()) { - point_in_pixel = gfx::ConvertPointToPixel( - widget_->GetOriginalScreenInfo().device_scale_factor, point_in_pixel); - } - return widget_->GetWebWidget()->HitTestResultAt(point_in_pixel); -} - -viz::FrameSinkId RenderWidgetInputHandler::GetFrameSinkIdAtPoint( - const gfx::PointF& point, - gfx::PointF* local_point) { - blink::WebHitTestResult result = GetHitTestResultAtPoint(point); - - blink::WebNode result_node = result.GetNode(); - *local_point = gfx::PointF(point); - - // TODO(crbug.com/797828): When the node is null the caller may - // need to do extra checks. Like maybe update the layout and then - // call the hit-testing API. Either way it might be better to have - // a DCHECK for the node rather than a null check here. - if (result_node.IsNull()) { - return widget_->GetFrameSinkId(); - } - - viz::FrameSinkId frame_sink_id = GetRemoteFrameSinkId(result); - if (frame_sink_id.is_valid()) { - *local_point = gfx::PointF(result.LocalPointWithoutContentBoxOffset()); - if (widget_->compositor_deps()->IsUseZoomForDSFEnabled()) { - *local_point = gfx::ConvertPointToDIP( - widget_->GetOriginalScreenInfo().device_scale_factor, *local_point); - } - return frame_sink_id; - } - - // Return the FrameSinkId for the current widget if the point did not hit - // test to a remote frame, or the point is outside of the remote frame's - // content box, or the remote frame doesn't have a valid FrameSinkId yet. - return widget_->GetFrameSinkId(); -} - -WebInputEventResult RenderWidgetInputHandler::HandleTouchEvent( - const blink::WebCoalescedInputEvent& coalesced_event) { - const WebInputEvent& input_event = coalesced_event.Event(); - - if (input_event.GetType() == WebInputEvent::Type::kTouchScrollStarted) { - WebPointerEvent pointer_event = - WebPointerEvent::CreatePointerCausesUaActionEvent( - blink::WebPointerProperties::PointerType::kUnknown, - input_event.TimeStamp()); - return widget_->GetWebWidget()->HandleInputEvent( - blink::WebCoalescedInputEvent(pointer_event, - coalesced_event.latency_info())); - } - - const WebTouchEvent touch_event = - static_cast<const WebTouchEvent&>(input_event); - for (unsigned i = 0; i < touch_event.touches_length; ++i) { - const WebTouchPoint& touch_point = touch_event.touches[i]; - if (touch_point.state != blink::WebTouchPoint::State::kStateStationary) { - const WebPointerEvent& pointer_event = - WebPointerEvent(touch_event, touch_point); - const blink::WebCoalescedInputEvent& coalesced_pointer_event = - GetCoalescedWebPointerEventForTouch( - pointer_event, coalesced_event.GetCoalescedEventsPointers(), - coalesced_event.GetPredictedEventsPointers(), - coalesced_event.latency_info()); - widget_->GetWebWidget()->HandleInputEvent(coalesced_pointer_event); - } - } - return widget_->GetWebWidget()->DispatchBufferedTouchEvents(); -} - -void RenderWidgetInputHandler::HandleInputEvent( - const blink::WebCoalescedInputEvent& coalesced_event, - HandledEventCallback callback) { - const WebInputEvent& input_event = coalesced_event.Event(); - - // Keep a WeakPtr to this RenderWidgetInputHandler to detect if executing the - // input event destroyed the associated RenderWidget (and this handler). - base::WeakPtr<RenderWidgetInputHandler> weak_self = - weak_ptr_factory_.GetWeakPtr(); - HandlingState handling_state(weak_self, input_event.GetType()); - -#if defined(OS_ANDROID) - ImeEventGuard guard(widget_->AsWeakPtr()); -#endif - - base::TimeTicks start_time; - if (base::TimeTicks::IsHighResolution()) - start_time = base::TimeTicks::Now(); - - TRACE_EVENT1("renderer,benchmark,rail", - "RenderWidgetInputHandler::OnHandleInputEvent", "event", - WebInputEvent::GetName(input_event.GetType())); - int64_t trace_id = coalesced_event.latency_info().trace_id(); - TRACE_EVENT("input,benchmark", "LatencyInfo.Flow", - [trace_id](perfetto::EventContext ctx) { - ChromeLatencyInfo* info = - ctx.event()->set_chrome_latency_info(); - info->set_trace_id(trace_id); - info->set_step(ChromeLatencyInfo::STEP_HANDLE_INPUT_EVENT_MAIN); - tracing::FillFlowEvent(ctx, TrackEvent::LegacyEvent::FLOW_INOUT, - trace_id); - }); - - // If we don't have a high res timer, these metrics won't be accurate enough - // to be worth collecting. Note that this does introduce some sampling bias. - if (!start_time.is_null()) - LogInputEventLatencyUma(input_event, start_time); - - ui::LatencyInfo swap_latency_info(coalesced_event.latency_info()); - swap_latency_info.AddLatencyNumber( - ui::LatencyComponentType::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT); - cc::LatencyInfoSwapPromiseMonitor swap_promise_monitor( - &swap_latency_info, widget_->layer_tree_host()->GetSwapPromiseManager(), - nullptr); - auto scoped_event_metrics_monitor = - widget_->layer_tree_host()->GetScopedEventMetricsMonitor( - cc::EventMetrics::Create(input_event.GetTypeAsUiEventType(), - input_event.TimeStamp(), - input_event.GetScrollInputType())); - - bool prevent_default = false; - bool show_virtual_keyboard_for_mouse = false; - if (WebInputEvent::IsMouseEventType(input_event.GetType())) { - const WebMouseEvent& mouse_event = - static_cast<const WebMouseEvent&>(input_event); - TRACE_EVENT2("renderer", "HandleMouseMove", "x", - mouse_event.PositionInWidget().x(), "y", - mouse_event.PositionInWidget().y()); - - prevent_default = delegate_->WillHandleMouseEvent(mouse_event); - - // Reset the last known cursor if mouse has left this widget. So next - // time that the mouse enters we always set the cursor accordingly. - if (mouse_event.GetType() == WebInputEvent::Type::kMouseLeave) - current_cursor_.reset(); - - if (mouse_event.button == WebPointerProperties::Button::kLeft && - mouse_event.GetType() == WebInputEvent::Type::kMouseUp) { - show_virtual_keyboard_for_mouse = true; - } - } - - if (WebInputEvent::IsKeyboardEventType(input_event.GetType())) { -#if defined(OS_ANDROID) - // The DPAD_CENTER key on Android has a dual semantic: (1) in the general - // case it should behave like a select key (i.e. causing a click if a button - // is focused). However, if a text field is focused (2), its intended - // behavior is to just show the IME and don't propagate the key. - // A typical use case is a web form: the DPAD_CENTER should bring up the IME - // when clicked on an input text field and cause the form submit if clicked - // when the submit button is focused, but not vice-versa. - // The UI layer takes care of translating DPAD_CENTER into a RETURN key, - // but at this point we have to swallow the event for the scenario (2). - const WebKeyboardEvent& key_event = - static_cast<const WebKeyboardEvent&>(input_event); - if (key_event.native_key_code == AKEYCODE_DPAD_CENTER && - widget_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE) { - // Show the keyboard on keyup (not keydown) to match the behavior of - // Android's TextView. - if (key_event.GetType() == WebInputEvent::Type::kKeyUp) - widget_->ShowVirtualKeyboardOnElementFocus(); - // Prevent default for both keydown and keyup (letting the keydown go - // through to the web app would cause compatibility problems since - // DPAD_CENTER is also used as a "confirm" button). - prevent_default = true; - } -#endif - } - - if (WebInputEvent::IsGestureEventType(input_event.GetType())) { - const WebGestureEvent& gesture_event = - static_cast<const WebGestureEvent&>(input_event); - prevent_default = - prevent_default || delegate_->WillHandleGestureEvent(gesture_event); - } - - WebInputEventResult processed = prevent_default - ? WebInputEventResult::kHandledSuppressed - : WebInputEventResult::kNotHandled; - if (input_event.GetType() != WebInputEvent::Type::kChar || - !suppress_next_char_events_) { - suppress_next_char_events_ = false; - if (processed == WebInputEventResult::kNotHandled && - widget_->GetWebWidget()) { - if (delegate_->SupportsBufferedTouchEvents() && - WebInputEvent::IsTouchEventType(input_event.GetType())) - processed = HandleTouchEvent(coalesced_event); - else - processed = widget_->GetWebWidget()->HandleInputEvent(coalesced_event); - } - - // The associated RenderWidget (and this RenderWidgetInputHandler) could - // have been destroyed. If it was return early before accessing any more of - // this class. - if (!weak_self) { - if (callback) { - std::move(callback).Run(GetAckResult(processed), swap_latency_info, - std::move(handling_state.event_overscroll), - handling_state.touch_action); - } - return; - } - } - - // Handling |input_event| is finished and further down, we might start - // handling injected scroll events. So, stop monitoring EventMetrics for - // |input_event| to avoid nested monitors. - scoped_event_metrics_monitor = nullptr; - - LogAllPassiveEventListenersUma(input_event, processed); - - // If this RawKeyDown event corresponds to a browser keyboard shortcut and - // it's not processed by webkit, then we need to suppress the upcoming Char - // events. - bool is_keyboard_shortcut = - input_event.GetType() == WebInputEvent::Type::kRawKeyDown && - static_cast<const WebKeyboardEvent&>(input_event).is_browser_shortcut; - if (processed == WebInputEventResult::kNotHandled && is_keyboard_shortcut) - suppress_next_char_events_ = true; - - // The handling of some input events on the main thread may require injecting - // scroll gestures back into blink, e.g., a mousedown on a scrollbar. We - // do this here so that we can attribute latency information from the mouse as - // a scroll interaction, instead of just classifying as mouse input. - if (handling_state.injected_scroll_params && - handling_state.injected_scroll_params->size()) { - HandleInjectedScrollGestures( - std::move(*handling_state.injected_scroll_params), input_event, - coalesced_event.latency_info()); - } - - // Send gesture scroll events and their dispositions to the compositor thread, - // so that they can be used to produce the elastic overscroll effect. - if (input_event.GetType() == WebInputEvent::Type::kGestureScrollBegin || - input_event.GetType() == WebInputEvent::Type::kGestureScrollEnd || - input_event.GetType() == WebInputEvent::Type::kGestureScrollUpdate) { - const WebGestureEvent& gesture_event = - static_cast<const WebGestureEvent&>(input_event); - if (gesture_event.SourceDevice() == blink::WebGestureDevice::kTouchpad || - gesture_event.SourceDevice() == blink::WebGestureDevice::kTouchscreen) { - gfx::Vector2dF latest_overscroll_delta = - handling_state.event_overscroll - ? handling_state.event_overscroll->latest_overscroll_delta - : gfx::Vector2dF(); - cc::OverscrollBehavior overscroll_behavior = - handling_state.event_overscroll - ? handling_state.event_overscroll->overscroll_behavior - : cc::OverscrollBehavior(); - delegate_->ObserveGestureEventAndResult( - gesture_event, latest_overscroll_delta, overscroll_behavior, - processed != WebInputEventResult::kNotHandled); - } - } - - if (callback) { - std::move(callback).Run(GetAckResult(processed), swap_latency_info, - std::move(handling_state.event_overscroll), - handling_state.touch_action); - } else { - DCHECK(!handling_state.event_overscroll) - << "Unexpected overscroll for un-acked event"; - } - - // Show the virtual keyboard if enabled and a user gesture triggers a focus - // change. - if ((processed != WebInputEventResult::kNotHandled && - input_event.GetType() == WebInputEvent::Type::kTouchEnd) || - show_virtual_keyboard_for_mouse) { - delegate_->ShowVirtualKeyboard(); - } - - if (!prevent_default && - WebInputEvent::IsKeyboardEventType(input_event.GetType())) - delegate_->OnDidHandleKeyEvent(); - -// TODO(rouslan): Fix ChromeOS and Windows 8 behavior of autofill popup with -// virtual keyboard. -#if !defined(OS_ANDROID) - // Virtual keyboard is not supported, so react to focus change immediately. - if ((processed != WebInputEventResult::kNotHandled && - input_event.GetType() == WebInputEvent::Type::kMouseDown) || - input_event.GetType() == WebInputEvent::Type::kGestureTap) { - delegate_->FocusChangeComplete(); - } -#endif - - // Ensure all injected scrolls were handled or queue up - any remaining - // injected scrolls at this point would not be processed. - DCHECK(!handling_state.injected_scroll_params || - (handling_state.injected_scroll_params)->empty()); -} - -void RenderWidgetInputHandler::DidOverscrollFromBlink( - const gfx::Vector2dF& overscrollDelta, - const gfx::Vector2dF& accumulatedOverscroll, - const gfx::PointF& position, - const gfx::Vector2dF& velocity, - const cc::OverscrollBehavior& behavior) { - blink::mojom::DidOverscrollParamsPtr params = - blink::mojom::DidOverscrollParams::New( - accumulatedOverscroll, overscrollDelta, velocity, position, behavior); - - // If we're currently handling an event, stash the overscroll data such that - // it can be bundled in the event ack. - if (handling_input_state_) { - handling_input_state_->event_overscroll = std::move(params); - return; - } - - delegate_->OnDidOverscroll(std::move(params)); -} - -void RenderWidgetInputHandler::InjectGestureScrollEvent( - blink::WebGestureDevice device, - const gfx::Vector2dF& delta, - ui::ScrollGranularity granularity, - cc::ElementId scrollable_area_element_id, - WebInputEvent::Type injected_type) { - DCHECK(ui::IsGestureScroll(injected_type)); - // If we're currently handling an input event, cache the appropriate - // parameters so we can dispatch the events directly once blink finishes - // handling the event. - // Otherwise, queue the event on the main thread event queue. - // The latter may occur when scrollbar scrolls are injected due to - // autoscroll timer - i.e. not within the handling of a mouse event. - // We don't always just enqueue events, since events queued to the - // MainThreadEventQueue in the middle of dispatch (which we are) won't - // be dispatched until the next time the queue gets to run. The side effect - // of that would be an extra frame of latency if we're injecting a scroll - // during the handling of a rAF aligned input event, such as mouse move. - if (handling_input_state_) { - // Multiple gestures may be injected during the dispatch of a single - // input event (e.g. Begin/Update). Create a vector and append to the - // end of it - the gestures will subsequently be injected in order. - if (!handling_input_state_->injected_scroll_params) { - handling_input_state_->injected_scroll_params = - std::make_unique<std::vector<InjectScrollGestureParams>>(); - } - - InjectScrollGestureParams params{device, delta, granularity, - scrollable_area_element_id, injected_type}; - handling_input_state_->injected_scroll_params->push_back(params); - } else { - base::TimeTicks now = base::TimeTicks::Now(); - std::unique_ptr<WebGestureEvent> gesture_event = - WebGestureEvent::GenerateInjectedScrollGesture( - injected_type, now, device, gfx::PointF(0, 0), delta, granularity); - if (injected_type == WebInputEvent::Type::kGestureScrollBegin) { - gesture_event->data.scroll_begin.scrollable_area_element_id = - scrollable_area_element_id.GetStableId(); - } - - ui::LatencyInfo latency_info; - ui::WebScopedInputEvent web_scoped_gesture_event(gesture_event.release()); - // TODO(acomminos): If/when we add support for gesture event attribution on - // the impl thread, have the caller provide attribution. - blink::WebInputEventAttribution attribution; - - widget_->GetInputEventQueue()->HandleEvent( - std::move(web_scoped_gesture_event), latency_info, - DISPATCH_TYPE_NON_BLOCKING, - blink::mojom::InputEventResultState::kNotConsumed, attribution, - HandledEventCallback()); - } -} - -void RenderWidgetInputHandler::HandleInjectedScrollGestures( - std::vector<InjectScrollGestureParams> injected_scroll_params, - const WebInputEvent& input_event, - const ui::LatencyInfo& original_latency_info) { - DCHECK(injected_scroll_params.size()); - - base::TimeTicks original_timestamp; - bool found_original_component = original_latency_info.FindLatency( - ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, &original_timestamp); - DCHECK(found_original_component); - - gfx::PointF position = ui::PositionInWidgetFromInputEvent(input_event); - for (const InjectScrollGestureParams& params : injected_scroll_params) { - // Set up a new LatencyInfo for the injected scroll - this is the original - // LatencyInfo for the input event that was being handled when the scroll - // was injected. This new LatencyInfo will have a modified type, and an - // additional scroll update component. Also set up a SwapPromiseMonitor that - // will cause the LatencyInfo to be sent up with the compositor frame, if - // the GSU causes a commit. This allows end to end latency to be logged for - // the injected scroll, annotated with the correct type. - ui::LatencyInfo scrollbar_latency_info(original_latency_info); - - // Currently only scrollbar is supported - if this DCHECK hits due to a - // new type being injected, please modify the type passed to - // |set_source_event_type()|. - DCHECK(params.device == blink::WebGestureDevice::kScrollbar); - scrollbar_latency_info.set_source_event_type( - ui::SourceEventType::SCROLLBAR); - scrollbar_latency_info.AddLatencyNumber( - ui::LatencyComponentType::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT); - - if (params.type == WebInputEvent::Type::kGestureScrollUpdate) { - if (input_event.GetType() != WebInputEvent::Type::kGestureScrollUpdate) { - scrollbar_latency_info.AddLatencyNumberWithTimestamp( - last_injected_gesture_was_begin_ - ? ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT - : ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, - original_timestamp); - } else { - // If we're injecting a GSU in response to a GSU (touch drags of the - // scrollbar thumb in Blink handles GSUs, and reverses them with - // injected GSUs), the LatencyInfo will already have the appropriate - // SCROLL_UPDATE component set. - DCHECK( - scrollbar_latency_info.FindLatency( - ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, - nullptr) || - scrollbar_latency_info.FindLatency( - ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT, - nullptr)); - } - } - - std::unique_ptr<WebGestureEvent> gesture_event = - WebGestureEvent::GenerateInjectedScrollGesture( - params.type, input_event.TimeStamp(), params.device, position, - params.scroll_delta, params.granularity); - if (params.type == WebInputEvent::Type::kGestureScrollBegin) { - gesture_event->data.scroll_begin.scrollable_area_element_id = - params.scrollable_area_element_id.GetStableId(); - last_injected_gesture_was_begin_ = true; - } else { - last_injected_gesture_was_begin_ = false; - } - - { - cc::LatencyInfoSwapPromiseMonitor swap_promise_monitor( - &scrollbar_latency_info, - widget_->layer_tree_host()->GetSwapPromiseManager(), nullptr); - auto scoped_event_metrics_monitor = - widget_->layer_tree_host()->GetScopedEventMetricsMonitor( - cc::EventMetrics::Create(gesture_event->GetTypeAsUiEventType(), - gesture_event->TimeStamp(), - gesture_event->GetScrollInputType())); - widget_->GetWebWidget()->HandleInputEvent(blink::WebCoalescedInputEvent( - *gesture_event, scrollbar_latency_info)); - } - } -} - -bool RenderWidgetInputHandler::DidChangeCursor(const ui::Cursor& cursor) { - if (current_cursor_.has_value() && current_cursor_.value() == cursor) - return false; - current_cursor_ = cursor; - return true; -} - -bool RenderWidgetInputHandler::ProcessTouchAction( - cc::TouchAction touch_action) { - if (!handling_input_state_) - return false; - // Ignore setTouchAction calls that result from synthetic touch events (eg. - // when blink is emulating touch with mouse). - if (handling_input_state_->event_type != WebInputEvent::Type::kTouchStart) - return false; - - handling_input_state_->touch_action = touch_action; - return true; -} - -} // namespace content diff --git a/chromium/content/renderer/input/render_widget_input_handler.h b/chromium/content/renderer/input/render_widget_input_handler.h deleted file mode 100644 index 289cb9ccc0a..00000000000 --- a/chromium/content/renderer/input/render_widget_input_handler.h +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2015 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 CONTENT_RENDERER_INPUT_RENDER_WIDGET_INPUT_HANDLER_H_ -#define CONTENT_RENDERER_INPUT_RENDER_WIDGET_INPUT_HANDLER_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/optional.h" -#include "base/time/time.h" -#include "content/common/input/input_event_dispatch_type.h" -#include "content/renderer/input/main_thread_event_queue.h" -#include "third_party/blink/public/common/input/web_coalesced_input_event.h" -#include "third_party/blink/public/common/input/web_gesture_event.h" -#include "third_party/blink/public/web/web_hit_test_result.h" -#include "ui/base/cursor/cursor.h" -#include "ui/base/ui_base_types.h" -#include "ui/events/blink/did_overscroll_params.h" -#include "ui/events/types/scroll_types.h" - -namespace cc { -struct ElementId; -struct OverscrollBehavior; -} - -namespace ui { -class LatencyInfo; -} - -namespace viz { -class FrameSinkId; -} - -namespace content { - -class RenderWidget; -class RenderWidgetInputHandlerDelegate; - -// RenderWidgetInputHandler is an IPC-agnostic input handling class. -// IPC transport code should live in RenderWidget or RenderWidgetMusConnection. -class CONTENT_EXPORT RenderWidgetInputHandler { - public: - RenderWidgetInputHandler(RenderWidgetInputHandlerDelegate* delegate, - RenderWidget* widget); - virtual ~RenderWidgetInputHandler(); - - // Hit test the given point to find out the frame underneath and - // returns the FrameSinkId for that frame. |local_point| returns the point - // in the coordinate space of the FrameSinkId that was hit. - viz::FrameSinkId GetFrameSinkIdAtPoint(const gfx::PointF& point, - gfx::PointF* local_point); - - // Handle input events from the input event provider. - virtual void HandleInputEvent( - const blink::WebCoalescedInputEvent& coalesced_event, - HandledEventCallback callback); - - // Handle overscroll from Blink. - void DidOverscrollFromBlink(const gfx::Vector2dF& overscrollDelta, - const gfx::Vector2dF& accumulatedOverscroll, - const gfx::PointF& position, - const gfx::Vector2dF& velocity, - const cc::OverscrollBehavior& behavior); - - void InjectGestureScrollEvent(blink::WebGestureDevice device, - const gfx::Vector2dF& delta, - ui::ScrollGranularity granularity, - cc::ElementId scrollable_area_element_id, - blink::WebInputEvent::Type injected_type); - - bool handling_input_event() const { return handling_input_event_; } - void set_handling_input_event(bool handling_input_event) { - handling_input_event_ = handling_input_event; - } - - // Process the touch action, returning whether the action should be relayed - // to the browser. - bool ProcessTouchAction(cc::TouchAction touch_action); - - // Process the new cursor and returns true if it has changed from the last - // cursor. - bool DidChangeCursor(const ui::Cursor& cursor); - - // Do a hit test for a given point in viewport coordinate. - blink::WebHitTestResult GetHitTestResultAtPoint(const gfx::PointF& point); - - private: - class HandlingState; - struct InjectScrollGestureParams { - blink::WebGestureDevice device; - gfx::Vector2dF scroll_delta; - ui::ScrollGranularity granularity; - cc::ElementId scrollable_area_element_id; - blink::WebInputEvent::Type type; - }; - - blink::WebInputEventResult HandleTouchEvent( - const blink::WebCoalescedInputEvent& coalesced_event); - - void HandleInjectedScrollGestures( - std::vector<InjectScrollGestureParams> injected_scroll_params, - const WebInputEvent& input_event, - const ui::LatencyInfo& original_latency_info); - - RenderWidgetInputHandlerDelegate* const delegate_; - - RenderWidget* const widget_; - - // Are we currently handling an input event? - bool handling_input_event_ = false; - - // Current state from HandleInputEvent. This variable is stack allocated - // and is not owned. - HandlingState* handling_input_state_ = nullptr; - - // We store the current cursor object so we can avoid spamming SetCursor - // messages. - base::Optional<ui::Cursor> current_cursor_; - - // Indicates if the next sequence of Char events should be suppressed or not. - bool suppress_next_char_events_ = false; - - // Whether the last injected scroll gesture was a GestureScrollBegin. Used to - // determine which GestureScrollUpdate is the first in a gesture sequence for - // latency classification. - bool last_injected_gesture_was_begin_ = false; - - base::WeakPtrFactory<RenderWidgetInputHandler> weak_ptr_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(RenderWidgetInputHandler); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_INPUT_RENDER_WIDGET_INPUT_HANDLER_H_ diff --git a/chromium/content/renderer/input/render_widget_input_handler_delegate.h b/chromium/content/renderer/input/render_widget_input_handler_delegate.h deleted file mode 100644 index 69686ad2cf4..00000000000 --- a/chromium/content/renderer/input/render_widget_input_handler_delegate.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2015 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 CONTENT_RENDERER_INPUT_RENDER_WIDGET_INPUT_HANDLER_DELEGATE_H_ -#define CONTENT_RENDERER_INPUT_RENDER_WIDGET_INPUT_HANDLER_DELEGATE_H_ - -#include <memory> - -#include "content/common/content_export.h" -#include "third_party/blink/public/mojom/input/input_handler.mojom.h" -#include "third_party/blink/public/platform/web_input_event_result.h" - -namespace blink { -class WebGestureEvent; -class WebMouseEvent; -} - -namespace gfx { -class Vector2dF; -} - -namespace content { - -class RenderWidgetInputHandler; - -// Consumers of RenderWidgetInputHandler implement this delegate in order to -// transport input handling information across processes. -class CONTENT_EXPORT RenderWidgetInputHandlerDelegate { - public: - // Called when animations due to focus change have completed (if any). - virtual void FocusChangeComplete() = 0; - - // Called to forward a gesture event to the compositor thread, to effect - // the elastic overscroll effect. - virtual void ObserveGestureEventAndResult( - const blink::WebGestureEvent& gesture_event, - const gfx::Vector2dF& unused_delta, - const cc::OverscrollBehavior& overscroll_behavior, - bool event_processed) = 0; - - // Notifies that a key event was just handled. - virtual void OnDidHandleKeyEvent() = 0; - - // Notifies that an overscroll was completed from Blink. - virtual void OnDidOverscroll(blink::mojom::DidOverscrollParamsPtr params) = 0; - - // Notifies the delegate of the |input_handler| managing it. - virtual void SetInputHandler(RenderWidgetInputHandler* input_handler) = 0; - - // Call this if virtual keyboard should be displayed, e.g. after a tap on an - // input field on mobile. Note that we do this just by setting a bit in - // text input state and update it to the browser such that browser process can - // be up to date when showing virtual keyboard. - virtual void ShowVirtualKeyboard() = 0; - - // Send an update of text input state to the browser process. - virtual void UpdateTextInputState() = 0; - - // Clear the text input state. - virtual void ClearTextInputState() = 0; - - // Notifies that a gesture event is about to be handled. - // Returns true if no further handling is needed. In that case, the event - // won't be sent to WebKit. - virtual bool WillHandleGestureEvent(const blink::WebGestureEvent& event) = 0; - - // Notifies that a mouse event is about to be handled. - // Returns true if no further handling is needed. In that case, the event - // won't be sent to WebKit or trigger DidHandleMouseEvent(). - virtual bool WillHandleMouseEvent(const blink::WebMouseEvent& event) = 0; - - // Whether buffered touch events should be supported or not. - virtual bool SupportsBufferedTouchEvents() = 0; - - protected: - virtual ~RenderWidgetInputHandlerDelegate() = default; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_INPUT_RENDER_WIDGET_INPUT_HANDLER_DELEGATE_H_ diff --git a/chromium/content/renderer/input/synchronous_compositor_proxy.cc b/chromium/content/renderer/input/synchronous_compositor_proxy.cc index d95fa790edb..97595a7bcc4 100644 --- a/chromium/content/renderer/input/synchronous_compositor_proxy.cc +++ b/chromium/content/renderer/input/synchronous_compositor_proxy.cc @@ -98,10 +98,10 @@ void SynchronousCompositorProxy::DidActivatePendingTree() { SendAsyncRendererStateIfNeeded(); } -mojom::SyncCompositorCommonRendererParamsPtr +blink::mojom::SyncCompositorCommonRendererParamsPtr SynchronousCompositorProxy::PopulateNewCommonParams() { - mojom::SyncCompositorCommonRendererParamsPtr params = - mojom::SyncCompositorCommonRendererParams::New(); + blink::mojom::SyncCompositorCommonRendererParamsPtr params = + blink::mojom::SyncCompositorCommonRendererParams::New(); params->version = ++version_; params->total_scroll_offset = total_scroll_offset_; params->max_scroll_offset = max_scroll_offset_; @@ -116,7 +116,7 @@ SynchronousCompositorProxy::PopulateNewCommonParams() { } void SynchronousCompositorProxy::DemandDrawHwAsync( - mojom::SyncCompositorDemandDrawHwParamsPtr params) { + blink::mojom::SyncCompositorDemandDrawHwParamsPtr params) { DemandDrawHw( std::move(params), base::BindOnce(&SynchronousCompositorProxy::SendDemandDrawHwAsyncReply, @@ -124,7 +124,7 @@ void SynchronousCompositorProxy::DemandDrawHwAsync( } void SynchronousCompositorProxy::DemandDrawHw( - mojom::SyncCompositorDemandDrawHwParamsPtr params, + blink::mojom::SyncCompositorDemandDrawHwParamsPtr params, DemandDrawHwCallback callback) { invalidate_needs_draw_ = false; hardware_draw_reply_ = std::move(callback); @@ -145,7 +145,9 @@ void SynchronousCompositorProxy::DemandDrawHw( } void SynchronousCompositorProxy::WillSkipDraw() { - layer_tree_frame_sink_->WillSkipDraw(); + if (layer_tree_frame_sink_) { + layer_tree_frame_sink_->WillSkipDraw(); + } } struct SynchronousCompositorProxy::SharedMemoryWithSize { @@ -173,7 +175,7 @@ void SynchronousCompositorProxy::ZeroSharedMemory() { } void SynchronousCompositorProxy::DemandDrawSw( - mojom::SyncCompositorDemandDrawSwParamsPtr params, + blink::mojom::SyncCompositorDemandDrawSwParamsPtr params, DemandDrawSwCallback callback) { invalidate_needs_draw_ = false; software_draw_reply_ = std::move(callback); @@ -198,7 +200,7 @@ void SynchronousCompositorProxy::DemandDrawSw( } void SynchronousCompositorProxy::DoDemandDrawSw( - mojom::SyncCompositorDemandDrawSwParamsPtr params) { + blink::mojom::SyncCompositorDemandDrawSwParamsPtr params) { DCHECK(layer_tree_frame_sink_); DCHECK(software_draw_shm_->zeroed); software_draw_shm_->zeroed = false; @@ -227,7 +229,7 @@ void SynchronousCompositorProxy::SubmitCompositorFrame( base::Optional<viz::HitTestRegionList> hit_test_region_list) { // Verify that exactly one of these is true. DCHECK(hardware_draw_reply_.is_null() ^ software_draw_reply_.is_null()); - mojom::SyncCompositorCommonRendererParamsPtr common_renderer_params = + blink::mojom::SyncCompositorCommonRendererParamsPtr common_renderer_params = PopulateNewCommonParams(); if (hardware_draw_reply_) { @@ -304,7 +306,7 @@ void SynchronousCompositorProxy::SetSharedMemory( base::WritableSharedMemoryRegion shm_region, SetSharedMemoryCallback callback) { bool success = false; - mojom::SyncCompositorCommonRendererParamsPtr common_renderer_params; + blink::mojom::SyncCompositorCommonRendererParamsPtr common_renderer_params; if (shm_region.IsValid()) { base::WritableSharedMemoryMapping shm_mapping = shm_region.Map(); if (shm_mapping.IsValid()) { @@ -315,7 +317,8 @@ void SynchronousCompositorProxy::SetSharedMemory( } } if (!common_renderer_params) { - common_renderer_params = mojom::SyncCompositorCommonRendererParams::New(); + common_renderer_params = + blink::mojom::SyncCompositorCommonRendererParams::New(); } std::move(callback).Run(success, std::move(common_renderer_params)); } @@ -333,7 +336,7 @@ uint32_t SynchronousCompositorProxy::NextMetadataVersion() { } void SynchronousCompositorProxy::SendDemandDrawHwAsyncReply( - mojom::SyncCompositorCommonRendererParamsPtr, + blink::mojom::SyncCompositorCommonRendererParamsPtr, uint32_t layer_tree_frame_sink_id, uint32_t metadata_version, base::Optional<viz::CompositorFrame> frame, @@ -343,7 +346,7 @@ void SynchronousCompositorProxy::SendDemandDrawHwAsyncReply( } void SynchronousCompositorProxy::SendBeginFrameResponse( - mojom::SyncCompositorCommonRendererParamsPtr param) { + blink::mojom::SyncCompositorCommonRendererParamsPtr param) { control_host_->BeginFrameResponse(std::move(param)); } @@ -361,9 +364,10 @@ void SynchronousCompositorProxy::LayerTreeFrameSinkCreated() { } void SynchronousCompositorProxy::BindChannel( - mojo::PendingRemote<mojom::SynchronousCompositorControlHost> control_host, - mojo::PendingAssociatedRemote<mojom::SynchronousCompositorHost> host, - mojo::PendingAssociatedReceiver<mojom::SynchronousCompositor> + mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost> + control_host, + mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost> host, + mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor> compositor_request) { // Reset bound mojo channels before rebinding new variants as the // associated RenderWidgetHost may be reused. diff --git a/chromium/content/renderer/input/synchronous_compositor_proxy.h b/chromium/content/renderer/input/synchronous_compositor_proxy.h index 703fb153e96..1841bdae369 100644 --- a/chromium/content/renderer/input/synchronous_compositor_proxy.h +++ b/chromium/content/renderer/input/synchronous_compositor_proxy.h @@ -13,12 +13,12 @@ #include "base/memory/writable_shared_memory_region.h" #include "base/optional.h" #include "components/viz/common/frame_timing_details_map.h" -#include "content/common/input/synchronous_compositor.mojom.h" -#include "content/renderer/android/synchronous_layer_tree_frame_sink.h" +#include "content/renderer/input/synchronous_layer_tree_frame_sink.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h" +#include "third_party/blink/public/mojom/input/synchronous_compositor.mojom.h" #include "third_party/blink/public/platform/input/synchronous_input_handler_proxy.h" #include "ui/gfx/geometry/scroll_offset.h" #include "ui/gfx/geometry/size_f.h" @@ -29,11 +29,9 @@ class CompositorFrame; namespace content { -class SynchronousLayerTreeFrameSink; - class SynchronousCompositorProxy : public blink::SynchronousInputHandler, public SynchronousLayerTreeFrameSinkClient, - public mojom::SynchronousCompositor { + public blink::mojom::SynchronousCompositor { public: SynchronousCompositorProxy( blink::SynchronousInputHandlerProxy* input_handler_proxy); @@ -41,9 +39,11 @@ class SynchronousCompositorProxy : public blink::SynchronousInputHandler, void Init(); void BindChannel( - mojo::PendingRemote<mojom::SynchronousCompositorControlHost> control_host, - mojo::PendingAssociatedRemote<mojom::SynchronousCompositorHost> host, - mojo::PendingAssociatedReceiver<mojom::SynchronousCompositor> + mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost> + control_host, + mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost> + host, + mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor> compositor_request); // blink::SynchronousInputHandler overrides. @@ -67,16 +67,16 @@ class SynchronousCompositorProxy : public blink::SynchronousInputHandler, void SetLayerTreeFrameSink( SynchronousLayerTreeFrameSink* layer_tree_frame_sink); - mojom::SyncCompositorCommonRendererParamsPtr PopulateNewCommonParams(); + blink::mojom::SyncCompositorCommonRendererParamsPtr PopulateNewCommonParams(); - // mojom::SynchronousCompositor overrides. + // blink::mojom::SynchronousCompositor overrides. void DemandDrawHwAsync( - mojom::SyncCompositorDemandDrawHwParamsPtr draw_params) final; - void DemandDrawHw(mojom::SyncCompositorDemandDrawHwParamsPtr params, + blink::mojom::SyncCompositorDemandDrawHwParamsPtr draw_params) final; + void DemandDrawHw(blink::mojom::SyncCompositorDemandDrawHwParamsPtr params, DemandDrawHwCallback callback) final; void SetSharedMemory(base::WritableSharedMemoryRegion shm_region, SetSharedMemoryCallback callback) final; - void DemandDrawSw(mojom::SyncCompositorDemandDrawSwParamsPtr params, + void DemandDrawSw(blink::mojom::SyncCompositorDemandDrawSwParamsPtr params, DemandDrawSwCallback callback) final; void WillSkipDraw() final; void ZeroSharedMemory() final; @@ -93,9 +93,10 @@ class SynchronousCompositorProxy : public blink::SynchronousInputHandler, protected: void SendAsyncRendererStateIfNeeded(); void LayerTreeFrameSinkCreated(); - void SendBeginFrameResponse(mojom::SyncCompositorCommonRendererParamsPtr); + void SendBeginFrameResponse( + blink::mojom::SyncCompositorCommonRendererParamsPtr); void SendDemandDrawHwAsyncReply( - mojom::SyncCompositorCommonRendererParamsPtr, + blink::mojom::SyncCompositorCommonRendererParamsPtr, uint32_t layer_tree_frame_sink_id, uint32_t metadata_version, base::Optional<viz::CompositorFrame>, @@ -108,16 +109,16 @@ class SynchronousCompositorProxy : public blink::SynchronousInputHandler, bool begin_frame_paused_ = false; private: - void DoDemandDrawSw(mojom::SyncCompositorDemandDrawSwParamsPtr params); + void DoDemandDrawSw(blink::mojom::SyncCompositorDemandDrawSwParamsPtr params); uint32_t NextMetadataVersion(); void HostDisconnected(); struct SharedMemoryWithSize; blink::SynchronousInputHandlerProxy* const input_handler_proxy_; - mojo::Remote<mojom::SynchronousCompositorControlHost> control_host_; - mojo::AssociatedRemote<mojom::SynchronousCompositorHost> host_; - mojo::AssociatedReceiver<mojom::SynchronousCompositor> receiver_{this}; + mojo::Remote<blink::mojom::SynchronousCompositorControlHost> control_host_; + mojo::AssociatedRemote<blink::mojom::SynchronousCompositorHost> host_; + mojo::AssociatedReceiver<blink::mojom::SynchronousCompositor> receiver_{this}; const bool use_in_process_zero_copy_software_draw_; const bool viz_frame_submission_enabled_; diff --git a/chromium/content/renderer/input/synchronous_compositor_registry.h b/chromium/content/renderer/input/synchronous_compositor_registry.h index 5d57d4242c6..a476b28e036 100644 --- a/chromium/content/renderer/input/synchronous_compositor_registry.h +++ b/chromium/content/renderer/input/synchronous_compositor_registry.h @@ -5,16 +5,15 @@ #ifndef CONTENT_RENDERER_INPUT_SYNCHRONOUS_COMPOSITOR_REGISTRY_H_ #define CONTENT_RENDERER_INPUT_SYNCHRONOUS_COMPOSITOR_REGISTRY_H_ +#include "content/renderer/input/synchronous_layer_tree_frame_sink.h" + namespace content { -class SynchronousLayerTreeFrameSink; class SynchronousCompositorRegistry { public: virtual void RegisterLayerTreeFrameSink( - int routing_id, SynchronousLayerTreeFrameSink* layer_tree_frame_sink) = 0; virtual void UnregisterLayerTreeFrameSink( - int routing_id, SynchronousLayerTreeFrameSink* layer_tree_frame_sink) = 0; protected: diff --git a/chromium/content/renderer/input/synchronous_layer_tree_frame_sink.h b/chromium/content/renderer/input/synchronous_layer_tree_frame_sink.h new file mode 100644 index 00000000000..83d8ee558b0 --- /dev/null +++ b/chromium/content/renderer/input/synchronous_layer_tree_frame_sink.h @@ -0,0 +1,58 @@ +// 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 CONTENT_RENDERER_INPUT_SYNCHRONOUS_LAYER_TREE_FRAME_SINK_H_ +#define CONTENT_RENDERER_INPUT_SYNCHRONOUS_LAYER_TREE_FRAME_SINK_H_ + +#include "cc/trees/layer_tree_frame_sink.h" +#include "components/viz/common/frame_timing_details_map.h" +#include "components/viz/common/hit_test/hit_test_region_list.h" +#include "components/viz/common/quads/compositor_frame.h" + +namespace content { + +// This class represents the client interface for the frame sink +// created for the synchronous compositor. +class SynchronousLayerTreeFrameSinkClient { + public: + virtual void DidActivatePendingTree() = 0; + virtual void Invalidate(bool needs_draw) = 0; + virtual void SubmitCompositorFrame( + uint32_t layer_tree_frame_sink_id, + base::Optional<viz::CompositorFrame> frame, + base::Optional<viz::HitTestRegionList> hit_test_region_list) = 0; + virtual void SetNeedsBeginFrames(bool needs_begin_frames) = 0; + virtual void SinkDestroyed() = 0; + + protected: + virtual ~SynchronousLayerTreeFrameSinkClient() {} +}; + +// This class represents the interface for the frame sink for the synchronous +// compositor. +class SynchronousLayerTreeFrameSink : public cc::LayerTreeFrameSink { + public: + using cc::LayerTreeFrameSink::LayerTreeFrameSink; + + virtual void SetSyncClient( + SynchronousLayerTreeFrameSinkClient* compositor) = 0; + virtual void DidPresentCompositorFrame( + const viz::FrameTimingDetailsMap& timing_details) = 0; + virtual void BeginFrame(const viz::BeginFrameArgs& args) = 0; + virtual void SetBeginFrameSourcePaused(bool paused) = 0; + virtual void SetMemoryPolicy(size_t bytes_limit) = 0; + virtual void ReclaimResources( + uint32_t layer_tree_frame_sink_id, + const std::vector<viz::ReturnedResource>& resources) = 0; + virtual void DemandDrawHw( + const gfx::Size& viewport_size, + const gfx::Rect& viewport_rect_for_tile_priority, + const gfx::Transform& transform_for_tile_priority) = 0; + virtual void DemandDrawSw(SkCanvas* canvas) = 0; + virtual void WillSkipDraw() = 0; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_INPUT_SYNCHRONOUS_LAYER_TREE_FRAME_SINK_H_ diff --git a/chromium/content/renderer/input/widget_input_handler_impl.cc b/chromium/content/renderer/input/widget_input_handler_impl.cc index d27b93ea269..ce94586fade 100644 --- a/chromium/content/renderer/input/widget_input_handler_impl.cc +++ b/chromium/content/renderer/input/widget_input_handler_impl.cc @@ -8,17 +8,17 @@ #include "base/bind.h" #include "base/check.h" -#include "content/common/input/ime_text_span_conversions.h" #include "content/common/input_messages.h" #include "content/renderer/ime_event_guard.h" +#include "content/renderer/input/frame_input_handler_impl.h" #include "content/renderer/input/widget_input_handler_manager.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_widget.h" +#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h" #include "third_party/blink/public/common/input/web_coalesced_input_event.h" #include "third_party/blink/public/common/input/web_keyboard_event.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" -#include "third_party/blink/public/web/web_ime_text_span.h" #include "third_party/blink/public/web/web_local_frame.h" namespace content { @@ -49,21 +49,9 @@ WidgetInputHandlerImpl::WidgetInputHandlerImpl( WidgetInputHandlerImpl::~WidgetInputHandlerImpl() {} -void WidgetInputHandlerImpl::SetAssociatedReceiver( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver) { - scoped_refptr<base::SingleThreadTaskRunner> task_runner; - if (content::RenderThreadImpl::current()) { - blink::scheduler::WebThreadScheduler* scheduler = - content::RenderThreadImpl::current()->GetWebMainThreadScheduler(); - task_runner = scheduler->DeprecatedDefaultTaskRunner(); - } - associated_receiver_.Bind(std::move(receiver), std::move(task_runner)); - associated_receiver_.set_disconnect_handler( - base::BindOnce(&WidgetInputHandlerImpl::Release, base::Unretained(this))); -} - void WidgetInputHandlerImpl::SetReceiver( - mojo::PendingReceiver<mojom::WidgetInputHandler> interface_receiver) { + mojo::PendingReceiver<blink::mojom::WidgetInputHandler> + interface_receiver) { scoped_refptr<base::SingleThreadTaskRunner> task_runner; if (content::RenderThreadImpl::current()) { blink::scheduler::WebThreadScheduler* scheduler = @@ -103,17 +91,16 @@ void WidgetInputHandlerImpl::ImeSetComposition( const gfx::Range& range, int32_t start, int32_t end) { - RunOnMainThread( - base::BindOnce(&RenderWidget::OnImeSetComposition, render_widget_, text, - ConvertUiImeTextSpansToBlinkImeTextSpans(ime_text_spans), - range, start, end)); + RunOnMainThread(base::BindOnce(&RenderWidget::OnImeSetComposition, + render_widget_, text, ime_text_spans, range, + start, end)); } static void ImeCommitTextOnMainThread( base::WeakPtr<RenderWidget> render_widget, scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner, const base::string16& text, - const std::vector<blink::WebImeTextSpan>& ime_text_spans, + const std::vector<ui::ImeTextSpan>& ime_text_spans, const gfx::Range& range, int32_t relative_cursor_position, WidgetInputHandlerImpl::ImeCommitTextCallback callback) { @@ -130,8 +117,7 @@ void WidgetInputHandlerImpl::ImeCommitText( ImeCommitTextCallback callback) { RunOnMainThread( base::BindOnce(&ImeCommitTextOnMainThread, render_widget_, - base::ThreadTaskRunnerHandle::Get(), text, - ConvertUiImeTextSpansToBlinkImeTextSpans(ime_text_spans), + base::ThreadTaskRunnerHandle::Get(), text, ime_text_spans, range, relative_cursor_position, std::move(callback))); } @@ -153,14 +139,14 @@ void WidgetInputHandlerImpl::RequestCompositionUpdates(bool immediate_request, } void WidgetInputHandlerImpl::DispatchEvent( - std::unique_ptr<content::InputEvent> event, + std::unique_ptr<blink::WebCoalescedInputEvent> event, DispatchEventCallback callback) { TRACE_EVENT0("input", "WidgetInputHandlerImpl::DispatchEvent"); input_handler_manager_->DispatchEvent(std::move(event), std::move(callback)); } void WidgetInputHandlerImpl::DispatchNonBlockingEvent( - std::unique_ptr<content::InputEvent> event) { + std::unique_ptr<blink::WebCoalescedInputEvent> event) { TRACE_EVENT0("input", "WidgetInputHandlerImpl::DispatchNonBlockingEvent"); input_handler_manager_->DispatchEvent(std::move(event), DispatchEventCallback()); @@ -187,14 +173,24 @@ void WidgetInputHandlerImpl::InputWasProcessed() { } void WidgetInputHandlerImpl::AttachSynchronousCompositor( - mojo::PendingRemote<mojom::SynchronousCompositorControlHost> control_host, - mojo::PendingAssociatedRemote<mojom::SynchronousCompositorHost> host, - mojo::PendingAssociatedReceiver<mojom::SynchronousCompositor> + mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost> + control_host, + mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost> host, + mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor> compositor_receiver) { input_handler_manager_->AttachSynchronousCompositor( std::move(control_host), std::move(host), std::move(compositor_receiver)); } +void WidgetInputHandlerImpl::GetFrameWidgetInputHandler( + mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetInputHandler> + frame_receiver) { + mojo::MakeSelfOwnedAssociatedReceiver( + std::make_unique<FrameInputHandlerImpl>( + render_widget_, main_thread_task_runner_, input_event_queue_), + std::move(frame_receiver)); +} + void WidgetInputHandlerImpl::RunOnMainThread(base::OnceClosure closure) { if (input_event_queue_) { input_event_queue_->QueueClosure(base::BindOnce( @@ -217,7 +213,6 @@ void WidgetInputHandlerImpl::Release() { if (!main_thread_task_runner_->BelongsToCurrentThread()) { // Close the binding on the compositor thread first before telling the main // thread to delete this object. - associated_receiver_.reset(); receiver_.reset(); main_thread_task_runner_->PostTask( FROM_HERE, base::BindOnce(&WidgetInputHandlerImpl::Release, diff --git a/chromium/content/renderer/input/widget_input_handler_impl.h b/chromium/content/renderer/input/widget_input_handler_impl.h index 86d288b5967..61d239d0bc0 100644 --- a/chromium/content/renderer/input/widget_input_handler_impl.h +++ b/chromium/content/renderer/input/widget_input_handler_impl.h @@ -7,9 +7,10 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" -#include "content/common/input/input_handler.mojom.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" +#include "third_party/blink/public/common/input/web_coalesced_input_event.h" +#include "third_party/blink/public/mojom/input/input_handler.mojom.h" namespace content { class MainThreadEventQueue; @@ -20,7 +21,7 @@ class WidgetInputHandlerManager; // interface. If threaded compositing is used this thread will live on // the compositor thread and proxy events to the main thread. This // is done so that events stay in order relative to other events. -class WidgetInputHandlerImpl : public mojom::WidgetInputHandler { +class WidgetInputHandlerImpl : public blink::mojom::WidgetInputHandler { public: WidgetInputHandlerImpl( scoped_refptr<WidgetInputHandlerManager> manager, @@ -30,10 +31,10 @@ class WidgetInputHandlerImpl : public mojom::WidgetInputHandler { ~WidgetInputHandlerImpl() override; void SetAssociatedReceiver( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> + mojo::PendingAssociatedReceiver<blink::mojom::WidgetInputHandler> interface_receiver); - void SetReceiver( - mojo::PendingReceiver<mojom::WidgetInputHandler> interface_receiver); + void SetReceiver(mojo::PendingReceiver<blink::mojom::WidgetInputHandler> + interface_receiver); void SetFocus(bool focused) override; void MouseCaptureLost() override; @@ -54,15 +55,21 @@ class WidgetInputHandlerImpl : public mojom::WidgetInputHandler { void RequestTextInputStateUpdate() override; void RequestCompositionUpdates(bool immediate_request, bool monitor_request) override; - void DispatchEvent(std::unique_ptr<content::InputEvent>, + void DispatchEvent(std::unique_ptr<blink::WebCoalescedInputEvent>, DispatchEventCallback callback) override; - void DispatchNonBlockingEvent(std::unique_ptr<content::InputEvent>) override; + void DispatchNonBlockingEvent( + std::unique_ptr<blink::WebCoalescedInputEvent>) override; void WaitForInputProcessed(WaitForInputProcessedCallback callback) override; void AttachSynchronousCompositor( - mojo::PendingRemote<mojom::SynchronousCompositorControlHost> control_host, - mojo::PendingAssociatedRemote<mojom::SynchronousCompositorHost> host, - mojo::PendingAssociatedReceiver<mojom::SynchronousCompositor> + mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost> + control_host, + mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost> + host, + mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor> compositor_receiver) override; + void GetFrameWidgetInputHandler( + mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetInputHandler> + interface_request) override; void InputWasProcessed(); private: @@ -80,9 +87,7 @@ class WidgetInputHandlerImpl : public mojom::WidgetInputHandler { // killed before we actually fully process the input. WaitForInputProcessedCallback input_processed_ack_; - mojo::Receiver<mojom::WidgetInputHandler> receiver_{this}; - mojo::AssociatedReceiver<mojom::WidgetInputHandler> associated_receiver_{ - this}; + mojo::Receiver<blink::mojom::WidgetInputHandler> receiver_{this}; base::WeakPtrFactory<WidgetInputHandlerImpl> weak_ptr_factory_{this}; diff --git a/chromium/content/renderer/input/widget_input_handler_manager.cc b/chromium/content/renderer/input/widget_input_handler_manager.cc index 4c606edf453..1464a8835b2 100644 --- a/chromium/content/renderer/input/widget_input_handler_manager.cc +++ b/chromium/content/renderer/input/widget_input_handler_manager.cc @@ -10,6 +10,7 @@ #include "base/check_op.h" #include "base/metrics/histogram_macros.h" #include "base/notreached.h" +#include "cc/base/features.h" #include "content/common/input_messages.h" #include "content/renderer/ime_event_guard.h" #include "content/renderer/input/widget_input_handler_impl.h" @@ -51,11 +52,12 @@ blink::mojom::DidOverscrollParamsPtr ToDidOverscrollParams( overscroll_params->overscroll_behavior); } -void CallCallback(mojom::WidgetInputHandler::DispatchEventCallback callback, - blink::mojom::InputEventResultState result_state, - const ui::LatencyInfo& latency_info, - blink::mojom::DidOverscrollParamsPtr overscroll_params, - base::Optional<cc::TouchAction> touch_action) { +void CallCallback( + blink::mojom::WidgetInputHandler::DispatchEventCallback callback, + blink::mojom::InputEventResultState result_state, + const ui::LatencyInfo& latency_info, + blink::mojom::DidOverscrollParamsPtr overscroll_params, + base::Optional<cc::TouchAction> touch_action) { ui::LatencyInfo::TraceIntermediateFlowEvents( {latency_info}, ChromeLatencyInfo::STEP_HANDLED_INPUT_EVENT_IMPL); std::move(callback).Run( @@ -81,9 +83,11 @@ blink::mojom::InputEventResultState InputEventDispositionToAck( return blink::mojom::InputEventResultState::kSetNonBlocking; case blink::InputHandlerProxy::DID_HANDLE_SHOULD_BUBBLE: return blink::mojom::InputEventResultState::kConsumedShouldBubble; + case blink::InputHandlerProxy::REQUIRES_MAIN_THREAD_HIT_TEST: + default: + NOTREACHED(); + return blink::mojom::InputEventResultState::kUnknown; } - NOTREACHED(); - return blink::mojom::InputEventResultState::kUnknown; } } // namespace @@ -114,7 +118,6 @@ class SynchronousCompositorProxyRegistry SynchronousCompositorProxy* proxy() { return proxy_.get(); } void RegisterLayerTreeFrameSink( - int routing_id, SynchronousLayerTreeFrameSink* layer_tree_frame_sink) override { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); DCHECK_EQ(nullptr, sink_); @@ -124,7 +127,6 @@ class SynchronousCompositorProxyRegistry } void UnregisterLayerTreeFrameSink( - int routing_id, SynchronousLayerTreeFrameSink* layer_tree_frame_sink) override { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); DCHECK_EQ(layer_tree_frame_sink, sink_); @@ -198,37 +200,19 @@ void WidgetInputHandlerManager::InitInputHandler() { WidgetInputHandlerManager::~WidgetInputHandlerManager() = default; -void WidgetInputHandlerManager::AddAssociatedInterface( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host) { - if (compositor_task_runner_) { - associated_host_ = mojo::SharedRemote<mojom::WidgetInputHandlerHost>( - std::move(host), compositor_task_runner_); - // Mojo channel bound on compositor thread. - compositor_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&WidgetInputHandlerManager::BindAssociatedChannel, this, - std::move(receiver))); - } else { - associated_host_ = - mojo::SharedRemote<mojom::WidgetInputHandlerHost>(std::move(host)); - // Mojo channel bound on main thread. - BindAssociatedChannel(std::move(receiver)); - } -} - void WidgetInputHandlerManager::AddInterface( - mojo::PendingReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host) { + mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver, + mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host) { if (compositor_task_runner_) { - host_ = mojo::SharedRemote<mojom::WidgetInputHandlerHost>( + host_ = mojo::SharedRemote<blink::mojom::WidgetInputHandlerHost>( std::move(host), compositor_task_runner_); // Mojo channel bound on compositor thread. compositor_task_runner_->PostTask( FROM_HERE, base::BindOnce(&WidgetInputHandlerManager::BindChannel, this, std::move(receiver))); } else { - host_ = mojo::SharedRemote<mojom::WidgetInputHandlerHost>(std::move(host)); + host_ = mojo::SharedRemote<blink::mojom::WidgetInputHandlerHost>( + std::move(host)); // Mojo channel bound on main thread. BindChannel(std::move(receiver)); } @@ -243,12 +227,11 @@ void WidgetInputHandlerManager::WillShutdown() { } void WidgetInputHandlerManager::DispatchNonBlockingEventToMainThread( - ui::WebScopedInputEvent event, - const ui::LatencyInfo& latency_info, + std::unique_ptr<blink::WebCoalescedInputEvent> event, const blink::WebInputEventAttribution& attribution) { DCHECK(input_event_queue_); input_event_queue_->HandleEvent( - std::move(event), latency_info, DISPATCH_TYPE_NON_BLOCKING, + std::move(event), DISPATCH_TYPE_NON_BLOCKING, blink::mojom::InputEventResultState::kSetNonBlocking, attribution, HandledEventCallback()); } @@ -256,7 +239,11 @@ void WidgetInputHandlerManager::DispatchNonBlockingEventToMainThread( void WidgetInputHandlerManager::FindScrollTargetOnMainThread( const gfx::PointF& point, ElementAtPointCallback callback) { + TRACE_EVENT2("input", + "WidgetInputHandlerManager::FindScrollTargetOnMainThread", + "point.x", point.x(), "point.y", point.y()); DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); + DCHECK(base::FeatureList::IsEnabled(::features::kScrollUnification)); uint64_t element_id = render_widget_->GetHitTestResultAtPoint(point).GetScrollableContainerId(); @@ -270,7 +257,7 @@ void WidgetInputHandlerManager::DidAnimateForInput() { } void WidgetInputHandlerManager::DidStartScrollingViewport() { - mojom::WidgetInputHandlerHost* host = GetWidgetInputHandlerHost(); + blink::mojom::WidgetInputHandlerHost* host = GetWidgetInputHandlerHost(); if (!host) return; host->DidStartScrollingViewport(); @@ -281,27 +268,28 @@ void WidgetInputHandlerManager::GenerateScrollBeginAndSendToMainThread( const blink::WebInputEventAttribution& attribution) { DCHECK_EQ(update_event.GetType(), blink::WebInputEvent::Type::kGestureScrollUpdate); - blink::WebGestureEvent scroll_begin = - ui::ScrollBeginFromScrollUpdate(update_event); + std::unique_ptr<blink::WebCoalescedInputEvent> event = + std::make_unique<blink::WebCoalescedInputEvent>( + ui::ScrollBeginFromScrollUpdate(update_event).Clone(), + ui::LatencyInfo()); - DispatchNonBlockingEventToMainThread(scroll_begin.Clone(), ui::LatencyInfo(), - attribution); + DispatchNonBlockingEventToMainThread(std::move(event), attribution); } -void WidgetInputHandlerManager::SetWhiteListedTouchAction( +void WidgetInputHandlerManager::SetAllowedTouchAction( cc::TouchAction touch_action, uint32_t unique_touch_event_id, blink::InputHandlerProxy::EventDisposition event_disposition) { - white_listed_touch_action_ = touch_action; + allowed_touch_action_ = touch_action; } void WidgetInputHandlerManager::ProcessTouchAction( cc::TouchAction touch_action) { - if (mojom::WidgetInputHandlerHost* host = GetWidgetInputHandlerHost()) + if (blink::mojom::WidgetInputHandlerHost* host = GetWidgetInputHandlerHost()) host->SetTouchActionFromMain(touch_action); } -mojom::WidgetInputHandlerHost* +blink::mojom::WidgetInputHandlerHost* WidgetInputHandlerManager::GetWidgetInputHandlerHost() { if (associated_host_) return associated_host_.get(); @@ -311,9 +299,10 @@ WidgetInputHandlerManager::GetWidgetInputHandlerHost() { } void WidgetInputHandlerManager::AttachSynchronousCompositor( - mojo::PendingRemote<mojom::SynchronousCompositorControlHost> control_host, - mojo::PendingAssociatedRemote<mojom::SynchronousCompositorHost> host, - mojo::PendingAssociatedReceiver<mojom::SynchronousCompositor> + mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost> + control_host, + mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost> host, + mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor> compositor_request) { #if defined(OS_ANDROID) DCHECK(synchronous_compositor_registry_); @@ -353,22 +342,11 @@ void WidgetInputHandlerManager::LogInputTimingUMA() { } void WidgetInputHandlerManager::DispatchEvent( - std::unique_ptr<content::InputEvent> event, - mojom::WidgetInputHandler::DispatchEventCallback callback) { - if (!event || !event->web_event) { - // Call |callback| if it was available indicating this event wasn't - // handled. - if (callback) { - std::move(callback).Run( - blink::mojom::InputEventResultSource::kMainThread, ui::LatencyInfo(), - blink::mojom::InputEventResultState::kNotConsumed, nullptr, nullptr); - } - return; - } - + std::unique_ptr<blink::WebCoalescedInputEvent> event, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback) { bool event_is_move = - event->web_event->GetType() == WebInputEvent::Type::kMouseMove || - event->web_event->GetType() == WebInputEvent::Type::kPointerMove; + event->Event().GetType() == WebInputEvent::Type::kMouseMove || + event->Event().GetType() == WebInputEvent::Type::kPointerMove; if (!event_is_move) LogInputTimingUMA(); @@ -394,7 +372,7 @@ void WidgetInputHandlerManager::DispatchEvent( // platform timestamp in this process. Instead use the time that the event is // received as the event's timestamp. if (!base::TimeTicks::IsConsistentAcrossProcesses()) { - event->web_event->SetTimeStamp(base::TimeTicks::Now()); + event->EventPointer()->SetTimeStamp(base::TimeTicks::Now()); } if (uses_input_handler_) { @@ -417,14 +395,13 @@ void WidgetInputHandlerManager::DispatchEvent( // either ACK the event as handled to the browser or forward it to the main // thread. input_handler_proxy_->HandleInputEventWithLatencyInfo( - std::move(event->web_event), event->latency_info, + std::move(event), base::BindOnce( &WidgetInputHandlerManager::DidHandleInputEventSentToCompositor, this, std::move(callback))); } else { DCHECK(!input_handler_proxy_); - DispatchDirectlyToWidget(std::move(event->web_event), event->latency_info, - std::move(callback)); + DispatchDirectlyToWidget(std::move(event), std::move(callback)); } } @@ -473,15 +450,19 @@ static void WaitForInputProcessedFromMain( auto redraw_complete_callback = base::BindOnce( &WidgetInputHandlerManager::InputWasProcessed, manager->AsWeakPtr()); - // We consider all observable effects of an input gesture to be processed + // Since wheel-events can kick off animations, we can not consider + // all observable effects of an input gesture to be processed // when the CompositorFrame caused by that input has been produced, send, and - // displayed. RequestPresentation will force a a commit and redraw and - // callback when the CompositorFrame has been displayed in the display - // service. Some examples of non-trivial effects that require waiting that - // long: committing NonFastScrollRegions to the compositor, sending - // touch-action rects to the browser, and sending updated surface information - // to the display compositor for up-to-date OOPIF hit-testing. - render_widget->RequestPresentation(std::move(redraw_complete_callback)); + // displayed. Therefore, explicitly request the presentation *after* any + // ongoing scroll-animation ends. After the scroll-animation ends (if any), + // the call will force a commit and redraw and callback when the + // CompositorFrame has been displayed in the display service. Some examples of + // non-trivial effects that require waiting that long: committing + // NonFastScrollRegions to the compositor, sending touch-action rects to the + // browser, and sending updated surface information to the display compositor + // for up-to-date OOPIF hit-testing. + render_widget->RequestPresentationAfterScrollAnimationEnd( + std::move(redraw_complete_callback)); } void WidgetInputHandlerManager::WaitForInputProcessed( @@ -492,9 +473,9 @@ void WidgetInputHandlerManager::WaitForInputProcessed( input_processed_callback_ = std::move(callback); // We mustn't touch render_widget_ from the impl thread so post all the setup - // to the main thread. - main_thread_task_runner_->PostTask( - FROM_HERE, + // to the main thread. Make sure the callback runs after all the queued events + // are dispatched. + input_event_queue_->QueueClosure( base::BindOnce(&WaitForInputProcessedFromMain, render_widget_)); } @@ -549,20 +530,8 @@ void WidgetInputHandlerManager::InitOnInputHandlingThread( #endif } -void WidgetInputHandlerManager::BindAssociatedChannel( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver) { - if (!receiver.is_valid()) - return; - // Don't pass the |input_event_queue_| on if we don't have a - // |compositor_task_runner_| as events might get out of order. - WidgetInputHandlerImpl* handler = new WidgetInputHandlerImpl( - this, main_thread_task_runner_, - compositor_task_runner_ ? input_event_queue_ : nullptr, render_widget_); - handler->SetAssociatedReceiver(std::move(receiver)); -} - void WidgetInputHandlerManager::BindChannel( - mojo::PendingReceiver<mojom::WidgetInputHandler> receiver) { + mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver) { if (!receiver.is_valid()) return; // Don't pass the |input_event_queue_| on if we don't have a @@ -574,9 +543,8 @@ void WidgetInputHandlerManager::BindChannel( } void WidgetInputHandlerManager::DispatchDirectlyToWidget( - const ui::WebScopedInputEvent& event, - const ui::LatencyInfo& latency, - mojom::WidgetInputHandler::DispatchEventCallback callback) { + std::unique_ptr<blink::WebCoalescedInputEvent> event, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback) { // This path should only be taken by non-frame RenderWidgets that don't use a // compositor (e.g. popups, plugins). Events bounds for a frame RenderWidget // must be passed through the InputHandlerProxy first. @@ -586,9 +554,10 @@ void WidgetInputHandlerManager::DispatchDirectlyToWidget( // was just recreated for a provisional frame. if (!render_widget_ || render_widget_->IsForProvisionalFrame()) { if (callback) { - std::move(callback).Run( - blink::mojom::InputEventResultSource::kMainThread, latency, - blink::mojom::InputEventResultState::kNotConsumed, nullptr, nullptr); + std::move(callback).Run(blink::mojom::InputEventResultSource::kMainThread, + event->latency_info(), + blink::mojom::InputEventResultState::kNotConsumed, + nullptr, nullptr); } return; } @@ -597,15 +566,41 @@ void WidgetInputHandlerManager::DispatchDirectlyToWidget( base::BindOnce(&WidgetInputHandlerManager::DidHandleInputEventSentToMain, this, std::move(callback)); - blink::WebCoalescedInputEvent coalesced_event(*event, latency); - render_widget_->HandleInputEvent(coalesced_event, std::move(send_callback)); + render_widget_->HandleInputEvent(*event, std::move(send_callback)); +} + +void WidgetInputHandlerManager::FindScrollTargetReply( + std::unique_ptr<blink::WebCoalescedInputEvent> event, + blink::mojom::WidgetInputHandler::DispatchEventCallback browser_callback, + uint64_t hit_test_result) { + TRACE_EVENT1("input", "WidgetInputHandlerManager::FindScrollTargetReply", + "hit_test_result", hit_test_result); + DCHECK(InputThreadTaskRunner()->BelongsToCurrentThread()); + DCHECK(base::FeatureList::IsEnabled(::features::kScrollUnification)); + + // If the input_handler was destroyed in the mean time just ACK the event as + // unconsumed to the browser and drop further handling. + if (!input_handler_proxy_) { + std::move(browser_callback) + .Run(blink::mojom::InputEventResultSource::kMainThread, + ui::LatencyInfo(), + blink::mojom::InputEventResultState::kNotConsumed, nullptr, + nullptr); + return; + } + + input_handler_proxy_->ContinueScrollBeginAfterMainThreadHitTest( + std::move(event), + base::BindOnce( + &WidgetInputHandlerManager::DidHandleInputEventSentToCompositor, this, + std::move(browser_callback)), + hit_test_result); } void WidgetInputHandlerManager::DidHandleInputEventSentToCompositor( - mojom::WidgetInputHandler::DispatchEventCallback callback, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback, blink::InputHandlerProxy::EventDisposition event_disposition, - ui::WebScopedInputEvent input_event, - const ui::LatencyInfo& latency_info, + std::unique_ptr<blink::WebCoalescedInputEvent> event, std::unique_ptr<blink::InputHandlerProxy::DidOverscrollParams> overscroll_params, const blink::WebInputEventAttribution& attribution) { @@ -615,18 +610,47 @@ void WidgetInputHandlerManager::DidHandleInputEventSentToCompositor( DCHECK(InputThreadTaskRunner()->BelongsToCurrentThread()); ui::LatencyInfo::TraceIntermediateFlowEvents( - {latency_info}, ChromeLatencyInfo::STEP_DID_HANDLE_INPUT_AND_OVERSCROLL); + {event->latency_info()}, + ChromeLatencyInfo::STEP_DID_HANDLE_INPUT_AND_OVERSCROLL); + + if (event_disposition == + blink::InputHandlerProxy::REQUIRES_MAIN_THREAD_HIT_TEST) { + TRACE_EVENT_INSTANT0("input", "PostingHitTestToMainThread", + TRACE_EVENT_SCOPE_THREAD); + // TODO(bokan): We're going to need to perform a hit test on the main thread + // before we can continue handling the event. This is the critical path of a + // scroll so we should probably ensure the scheduler can prioritize it + // accordingly. https://crbug.com/1082618. + DCHECK(base::FeatureList::IsEnabled(::features::kScrollUnification)); + DCHECK_EQ(event->Event().GetType(), + blink::WebInputEvent::Type::kGestureScrollBegin); + DCHECK(input_handler_proxy_); + + gfx::PointF event_position = + static_cast<const blink::WebGestureEvent&>(event->Event()) + .PositionInWidget(); + + ElementAtPointCallback result_callback = base::BindOnce( + &WidgetInputHandlerManager::FindScrollTargetReply, this->AsWeakPtr(), + std::move(event), std::move(callback)); + + main_thread_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&WidgetInputHandlerManager::FindScrollTargetOnMainThread, + this, event_position, std::move(result_callback))); + return; + } blink::mojom::InputEventResultState ack_state = InputEventDispositionToAck(event_disposition); if (ack_state == blink::mojom::InputEventResultState::kConsumed) { main_thread_scheduler_->DidHandleInputEventOnCompositorThread( - *input_event, blink::scheduler::WebThreadScheduler::InputEventState:: - EVENT_CONSUMED_BY_COMPOSITOR); + event->Event(), blink::scheduler::WebThreadScheduler::InputEventState:: + EVENT_CONSUMED_BY_COMPOSITOR); } else if (MainThreadEventQueue::IsForwardedAndSchedulerKnown(ack_state)) { main_thread_scheduler_->DidHandleInputEventOnCompositorThread( - *input_event, blink::scheduler::WebThreadScheduler::InputEventState:: - EVENT_FORWARDED_TO_MAIN_THREAD); + event->Event(), blink::scheduler::WebThreadScheduler::InputEventState:: + EVENT_FORWARDED_TO_MAIN_THREAD); } if (ack_state == blink::mojom::InputEventResultState::kSetNonBlocking || @@ -634,27 +658,27 @@ void WidgetInputHandlerManager::DidHandleInputEventSentToCompositor( blink::mojom::InputEventResultState::kSetNonBlockingDueToFling || ack_state == blink::mojom::InputEventResultState::kNotConsumed) { DCHECK(!overscroll_params); - DCHECK(!latency_info.coalesced()); + DCHECK(!event->latency_info().coalesced()); InputEventDispatchType dispatch_type = callback.is_null() ? DISPATCH_TYPE_NON_BLOCKING : DISPATCH_TYPE_BLOCKING; HandledEventCallback handled_event = base::BindOnce( &WidgetInputHandlerManager::DidHandleInputEventSentToMain, this, std::move(callback)); - input_event_queue_->HandleEvent(std::move(input_event), latency_info, - dispatch_type, ack_state, attribution, - std::move(handled_event)); + input_event_queue_->HandleEvent(std::move(event), dispatch_type, ack_state, + attribution, std::move(handled_event)); return; } if (callback) { std::move(callback).Run( - blink::mojom::InputEventResultSource::kCompositorThread, latency_info, - ack_state, ToDidOverscrollParams(overscroll_params.get()), nullptr); + blink::mojom::InputEventResultSource::kCompositorThread, + event->latency_info(), ack_state, + ToDidOverscrollParams(overscroll_params.get()), nullptr); } } void WidgetInputHandlerManager::DidHandleInputEventSentToMain( - mojom::WidgetInputHandler::DispatchEventCallback callback, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback, blink::mojom::InputEventResultState ack_state, const ui::LatencyInfo& latency_info, blink::mojom::DidOverscrollParamsPtr overscroll_params, @@ -669,10 +693,10 @@ void WidgetInputHandlerManager::DidHandleInputEventSentToMain( {latency_info}, ChromeLatencyInfo::STEP_HANDLED_INPUT_EVENT_MAIN_OR_IMPL); if (!touch_action.has_value()) { - TRACE_EVENT_INSTANT0("input", "Using white_listed_touch_action", + TRACE_EVENT_INSTANT0("input", "Using allowed_touch_action", TRACE_EVENT_SCOPE_THREAD); - touch_action = white_listed_touch_action_; - white_listed_touch_action_.reset(); + touch_action = allowed_touch_action_; + allowed_touch_action_.reset(); } // This method is called from either the main thread or the compositor thread. bool is_compositor_thread = compositor_task_runner_ && diff --git a/chromium/content/renderer/input/widget_input_handler_manager.h b/chromium/content/renderer/input/widget_input_handler_manager.h index d5d95972da8..18bed414154 100644 --- a/chromium/content/renderer/input/widget_input_handler_manager.h +++ b/chromium/content/renderer/input/widget_input_handler_manager.h @@ -9,11 +9,11 @@ #include "base/single_thread_task_runner.h" #include "build/build_config.h" #include "content/common/content_export.h" -#include "content/common/input/input_handler.mojom.h" #include "content/renderer/render_frame_impl.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/shared_remote.h" +#include "third_party/blink/public/mojom/input/input_handler.mojom.h" #include "third_party/blink/public/platform/input/input_handler_proxy.h" #include "third_party/blink/public/platform/input/input_handler_proxy_client.h" @@ -67,18 +67,15 @@ class CONTENT_EXPORT WidgetInputHandlerManager final scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, blink::scheduler::WebThreadScheduler* main_thread_scheduler, bool needs_input_handler); - void AddAssociatedInterface( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host); - void AddInterface(mojo::PendingReceiver<mojom::WidgetInputHandler> receiver, - mojo::PendingRemote<mojom::WidgetInputHandlerHost> host); + void AddInterface( + mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver, + mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host); // InputHandlerProxyClient overrides. void WillShutdown() override; void DispatchNonBlockingEventToMainThread( - ui::WebScopedInputEvent event, - const ui::LatencyInfo& latency_info, + std::unique_ptr<blink::WebCoalescedInputEvent> event, const blink::WebInputEventAttribution& attribution) override; void DidAnimateForInput() override; @@ -86,7 +83,7 @@ class CONTENT_EXPORT WidgetInputHandlerManager final void GenerateScrollBeginAndSendToMainThread( const blink::WebGestureEvent& update_event, const blink::WebInputEventAttribution& attribution) override; - void SetWhiteListedTouchAction( + void SetAllowedTouchAction( cc::TouchAction touch_action, uint32_t unique_touch_event_id, blink::InputHandlerProxy::EventDisposition event_disposition) override; @@ -95,17 +92,20 @@ class CONTENT_EXPORT WidgetInputHandlerManager final const blink::WebGestureEvent& gesture_event, const cc::InputHandlerScrollResult& scroll_result); - void DispatchEvent(std::unique_ptr<content::InputEvent> event, - mojom::WidgetInputHandler::DispatchEventCallback callback); + void DispatchEvent( + std::unique_ptr<blink::WebCoalescedInputEvent> event, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback); void ProcessTouchAction(cc::TouchAction touch_action); - mojom::WidgetInputHandlerHost* GetWidgetInputHandlerHost(); + blink::mojom::WidgetInputHandlerHost* GetWidgetInputHandlerHost(); void AttachSynchronousCompositor( - mojo::PendingRemote<mojom::SynchronousCompositorControlHost> control_host, - mojo::PendingAssociatedRemote<mojom::SynchronousCompositorHost> host, - mojo::PendingAssociatedReceiver<mojom::SynchronousCompositor> + mojo::PendingRemote<blink::mojom::SynchronousCompositorControlHost> + control_host, + mojo::PendingAssociatedRemote<blink::mojom::SynchronousCompositorHost> + host, + mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor> compositor_request); #if defined(OS_ANDROID) @@ -153,9 +153,8 @@ class CONTENT_EXPORT WidgetInputHandlerManager final void InitOnInputHandlingThread( const base::WeakPtr<cc::InputHandler>& input_handler, bool sync_compositing); - void BindAssociatedChannel( - mojo::PendingAssociatedReceiver<mojom::WidgetInputHandler> receiver); - void BindChannel(mojo::PendingReceiver<mojom::WidgetInputHandler> receiver); + void BindChannel( + mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver); // This method skips the input handler proxy and sends the event directly to // the RenderWidget (main thread). Should only be used by non-frame @@ -164,9 +163,15 @@ class CONTENT_EXPORT WidgetInputHandlerManager final // InputHandlerProxy by calling DispatchEvent which will re-route to the main // thread if needed. void DispatchDirectlyToWidget( - const ui::WebScopedInputEvent& event, - const ui::LatencyInfo& latency, - mojom::WidgetInputHandler::DispatchEventCallback callback); + std::unique_ptr<blink::WebCoalescedInputEvent> event, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback); + + // Used to return a result from FindScrollTargetOnMainThread. Will be called + // on the input handling thread. + void FindScrollTargetReply( + std::unique_ptr<blink::WebCoalescedInputEvent> event, + blink::mojom::WidgetInputHandler::DispatchEventCallback browser_callback, + uint64_t hit_test_result); // This method is the callback used by the compositor input handler to // communicate back whether the event was successfully handled on the @@ -176,10 +181,9 @@ class CONTENT_EXPORT WidgetInputHandlerManager final // on the input handling thread (i.e. if a compositor thread exists, it'll be // called from it). void DidHandleInputEventSentToCompositor( - mojom::WidgetInputHandler::DispatchEventCallback callback, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback, blink::InputHandlerProxy::EventDisposition event_disposition, - ui::WebScopedInputEvent input_event, - const ui::LatencyInfo& latency_info, + std::unique_ptr<blink::WebCoalescedInputEvent> event, std::unique_ptr<blink::InputHandlerProxy::DidOverscrollParams> overscroll_params, const blink::WebInputEventAttribution& attribution); @@ -189,7 +193,7 @@ class CONTENT_EXPORT WidgetInputHandlerManager final // called on either thread as non-blocking events sent to the main thread // will be ACKed immediately when added to the main thread event queue. void DidHandleInputEventSentToMain( - mojom::WidgetInputHandler::DispatchEventCallback callback, + blink::mojom::WidgetInputHandler::DispatchEventCallback callback, blink::mojom::InputEventResultState ack_state, const ui::LatencyInfo& latency_info, blink::mojom::DidOverscrollParamsPtr overscroll_params, @@ -216,18 +220,18 @@ class CONTENT_EXPORT WidgetInputHandlerManager final // The WidgetInputHandlerHost is bound on the compositor task runner // but class can be called on the compositor and main thread. - mojo::SharedRemote<mojom::WidgetInputHandlerHost> host_; + mojo::SharedRemote<blink::mojom::WidgetInputHandlerHost> host_; // Host that was passed as part of the FrameInputHandler associated // channel. - mojo::SharedRemote<mojom::WidgetInputHandlerHost> associated_host_; + mojo::SharedRemote<blink::mojom::WidgetInputHandlerHost> associated_host_; // Any thread can access these variables. scoped_refptr<MainThreadEventQueue> input_event_queue_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; - base::Optional<cc::TouchAction> white_listed_touch_action_; + base::Optional<cc::TouchAction> allowed_touch_action_; // Callback used to respond to the WaitForInputProcessed Mojo message. This // callback is set from and must be invoked from the Mojo-bound thread (i.e. |