diff options
Diffstat (limited to 'src/core/render_widget_host_view_qt.cpp')
-rw-r--r-- | src/core/render_widget_host_view_qt.cpp | 563 |
1 files changed, 330 insertions, 233 deletions
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index fbb4c5bd6..888043fda 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -1,47 +1,8 @@ - -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "render_widget_host_view_qt.h" -#include "browser_accessibility_manager_qt.h" -#include "common/qt_messages.h" #include "qtwebenginecoreglobal_p.h" #include "render_widget_host_view_qt_delegate.h" #include "render_widget_host_view_qt_delegate_client.h" @@ -51,27 +12,33 @@ #include "web_contents_adapter_client.h" #include "web_event_factory.h" -#include "base/threading/thread_task_runner_handle.h" #include "components/viz/common/features.h" #include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/surfaces/frame_sink_id_allocator.h" #include "components/viz/host/host_frame_sink_manager.h" #include "content/browser/compositor/image_transport_factory.h" -#include "content/browser/frame_host/frame_tree.h" -#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/browser/renderer_host/render_frame_host_impl.h" +#include "content/browser/renderer_host/frame_tree.h" +#include "content/browser/renderer_host/frame_tree_node.h" +#include "content/browser/renderer_host/cursor_manager.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_widget_host_input_event_router.h" +#include "content/browser/renderer_host/ui_events_helper.h" #include "content/common/content_switches_internal.h" #include "content/common/cursors/webcursor.h" -#include "content/common/input_messages.h" +#include "content/public/browser/web_contents.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/cursor/cursor.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/display/display_util.h" #include "ui/events/blink/blink_event_util.h" #include "ui/events/event.h" #include "ui/events/gesture_detection/gesture_configuration.h" #include "ui/events/gesture_detection/gesture_provider_config_helper.h" +#include "ui/events/keycodes/dom/dom_keyboard_layout_map.h" #include "ui/gfx/image/image_skia.h" #if defined(USE_OZONE) @@ -79,13 +46,17 @@ #endif #if defined(USE_AURA) +#include "ui/wm/core/cursor_util.h" #include "ui/base/cursor/cursor_size.h" -#include "ui/base/cursor/cursors_aura.h" -#include "ui/base/resource/resource_bundle.h" +#endif + +#if defined(Q_OS_MACOS) +#include "ui/resources/grit/ui_resources.h" #endif #include <QGuiApplication> #include <QPixmap> +#include <QScopeGuard> #include <QScreen> #include <QWindow> @@ -119,6 +90,31 @@ static inline ui::GestureProvider::Config QtGestureProviderConfig() { return config; } +extern display::Display toDisplayDisplay(int id, const QScreen *screen); + +static display::ScreenInfos screenInfosFromQtForUpdate(QScreen *currentScreen) +{ + display::ScreenInfo screenInfo; + const auto &screens = qApp->screens(); + if (screens.isEmpty()) { + screenInfo.device_scale_factor = qGuiApp->devicePixelRatio(); + return display::ScreenInfos(screenInfo); + } + + Q_ASSERT(qApp->primaryScreen() == screens.first()); + display::ScreenInfos result; + for (int i = 0; i < screens.length(); ++i) { + display::DisplayUtil::DisplayToScreenInfo(&screenInfo, toDisplayDisplay(i, screens.at(i))); + result.screen_infos.push_back(screenInfo); + if (currentScreen == screens.at(i)) + result.current_display_id = i; + } + + Q_ASSERT(result.current_display_id != display::kInvalidDisplayId); + + return result; +} + // An minimal override to support progressing flings class FlingingCompositor : public ui::Compositor { @@ -148,7 +144,7 @@ public: RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget) : content::RenderWidgetHostViewBase::RenderWidgetHostViewBase(widget) - , m_taskRunner(base::ThreadTaskRunnerHandle::Get()) + , m_taskRunner(base::SingleThreadTaskRunner::GetCurrentDefault()) , m_gestureProvider(QtGestureProviderConfig(), this) , m_frameSinkId(host()->GetFrameSinkId()) , m_delegateClient(new RenderWidgetHostViewQtDelegateClient(this)) @@ -178,13 +174,12 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget if (host()->delegate() && host()->delegate()->GetInputEventRouter()) host()->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(GetFrameSinkId(), this); + m_cursorManager.reset(new content::CursorManager(this)); + m_touchSelectionControllerClient.reset(new TouchSelectionControllerClientQt(this)); - ui::TouchSelectionController::Config config; - config.max_tap_duration = base::TimeDelta::FromMilliseconds(ui::GestureConfiguration::GetInstance()->long_press_time_in_ms()); - config.tap_slop = ui::GestureConfiguration::GetInstance()->max_touch_move_in_pixels_for_click(); - config.enable_longpress_drag_selection = false; - m_touchSelectionController.reset(new ui::TouchSelectionController(m_touchSelectionControllerClient.get(), config)); + resetTouchSelectionController(); + host()->render_frame_metadata_provider()->AddObserver(this); host()->render_frame_metadata_provider()->ReportAllFrameSubmissionsForTesting(true); host()->SetView(this); @@ -199,8 +194,14 @@ RenderWidgetHostViewQt::~RenderWidgetHostViewQt() if (text_input_manager_) text_input_manager_->RemoveObserver(this); + if (host()->delegate()) + m_touchSelectionControllerClient->resetControls(); + m_touchSelectionController.reset(); m_touchSelectionControllerClient.reset(); + + host()->render_frame_metadata_provider()->RemoveObserver(this); + host()->ViewDestroyed(); } void RenderWidgetHostViewQt::setDelegate(RenderWidgetHostViewQtDelegate* delegate) @@ -224,21 +225,51 @@ void RenderWidgetHostViewQt::setAdapterClient(WebContentsAdapterClient *adapterC m_adapterClient = nullptr; }); } -void RenderWidgetHostViewQt::InitAsChild(gfx::NativeView) +void RenderWidgetHostViewQt::OnInputEventAck(blink::mojom::InputEventResultSource, + blink::mojom::InputEventResultState state, + const blink::WebInputEvent &event) { + if (event.GetType() == blink::WebInputEvent::Type::kMouseWheel) + WheelEventAck(static_cast<const blink::WebMouseWheelEvent &>(event), state); } -void RenderWidgetHostViewQt::InitAsPopup(content::RenderWidgetHostView*, const gfx::Rect& rect) +// static +// Called when new child/guest renderframes created. +void RenderWidgetHostViewQt::registerInputEventObserver(content::WebContents *webContents, + content::RenderFrameHost *rfh) { - m_delegate->initAsPopup(toQt(rect)); + if (static_cast<content::RenderFrameHostImpl *>(rfh)->is_local_root_subframe()) { + content::WebContents *parent = webContents->GetOutermostWebContents(); + QtWebEngineCore::RenderWidgetHostViewQt *mainRwhv = + static_cast<QtWebEngineCore::RenderWidgetHostViewQt *>( + parent->GetRenderWidgetHostView()); + // Child (originAgentCluster) or guest (pdf) frame that is embedded into the main frame + content::RenderWidgetHost *childFrame = rfh->GetRenderWidgetHost(); + childFrame->AddInputEventObserver(mainRwhv); + + if (webContents->IsInnerWebContentsForGuest()) { + // The frame which holds the actual PDF content inside the guest + content::RenderWidgetHost *guestFrame = webContents->GetRenderViewHost()->GetWidget(); + guestFrame->AddInputEventObserver(mainRwhv); + } + } } -void RenderWidgetHostViewQt::InitAsFullscreen(content::RenderWidgetHostView*) +void RenderWidgetHostViewQt::InitAsChild(gfx::NativeView) { } +void RenderWidgetHostViewQt::InitAsPopup(content::RenderWidgetHostView*, const gfx::Rect& rect, const gfx::Rect& anchorRect) +{ + Q_UNUSED(anchorRect); + m_delegate->initAsPopup(toQt(rect)); +} + void RenderWidgetHostViewQt::SetSize(const gfx::Size &sizeInDips) { + if (!m_delegate) + return; + m_delegate->resize(sizeInDips.width(), sizeInDips.height()); } @@ -260,22 +291,16 @@ gfx::NativeView RenderWidgetHostViewQt::GetNativeView() return gfx::NativeView(); } -gfx::NativeViewAccessible RenderWidgetHostViewQt::GetNativeViewAccessible() +content::WebContentsAccessibility *RenderWidgetHostViewQt::GetWebContentsAccessibility() { - return 0; + if (!m_webContentsAccessibility) + m_webContentsAccessibility.reset(new WebContentsAccessibilityQt(this)); + return m_webContentsAccessibility.get(); } -content::BrowserAccessibilityManager* RenderWidgetHostViewQt::CreateBrowserAccessibilityManager(content::BrowserAccessibilityDelegate* delegate, bool for_root_frame) +QObject *WebContentsAccessibilityQt::accessibilityParentObject() const { - Q_UNUSED(for_root_frame); // FIXME -#if QT_CONFIG(accessibility) - return new content::BrowserAccessibilityManagerQt( - m_adapterClient->accessibilityParentObject(), - content::BrowserAccessibilityManagerQt::GetEmptyDocument(), - delegate); -#else - return 0; -#endif // QT_CONFIG(accessibility) + return m_rwhv->m_adapterClient->accessibilityParentObject(); } // Set focus to the associated View component. @@ -296,6 +321,11 @@ bool RenderWidgetHostViewQt::IsMouseLocked() return m_isMouseLocked; } +viz::FrameSinkId RenderWidgetHostViewQt::GetRootFrameSinkId() +{ + return m_uiCompositor->frame_sink_id(); +} + bool RenderWidgetHostViewQt::IsSurfaceAvailableForCopy() { return m_delegatedFrameHost->CanCopyFromCompositingSurface(); @@ -308,8 +338,9 @@ void RenderWidgetHostViewQt::CopyFromSurface(const gfx::Rect &src_rect, m_delegatedFrameHost->CopyFromCompositingSurface(src_rect, output_size, std::move(callback)); } -void RenderWidgetHostViewQt::Show() +void RenderWidgetHostViewQt::ShowWithVisibility(content::PageVisibilityState page_visibility) { + Q_ASSERT(page_visibility != content::PageVisibilityState::kHidden); if (m_delegate) m_delegate->show(); else @@ -336,6 +367,9 @@ gfx::Rect RenderWidgetHostViewQt::GetViewBounds() void RenderWidgetHostViewQt::UpdateBackgroundColor() { + if (!m_delegate) + return; + DCHECK(GetBackgroundColor()); SkColor color = *GetBackgroundColor(); @@ -346,11 +380,8 @@ void RenderWidgetHostViewQt::UpdateBackgroundColor() m_rootLayer->SetColor(color); m_uiCompositor->SetBackgroundColor(color); - content::RenderViewHost *rvh = content::RenderViewHost::From(host()); if (color == SK_ColorTRANSPARENT) host()->owner_delegate()->SetBackgroundOpaque(false); - else - host()->Send(new RenderViewObserverQt_SetBackgroundColor(rvh->GetRoutingID(), color)); } // Return value indicates whether the mouse is locked successfully or not. @@ -381,18 +412,82 @@ void RenderWidgetHostViewQt::UnlockMouse() host()->LostMouseLock(); } -void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor) +bool RenderWidgetHostViewQt::updateCursorFromResource(ui::mojom::CursorType type) +{ + int resourceId; + // GetCursorDataFor only knows hotspots for 1x and 2x cursor images, in physical pixels. + qreal hotspotDpr = GetScreenInfo().device_scale_factor <= 1.0f ? 1.0f : 2.0f; + qreal hotX; + qreal hotY; + +#if defined(USE_AURA) + gfx::Point hotspot; + if (!wm::GetCursorDataFor(ui::CursorSize::kNormal, type, hotspotDpr, &resourceId, &hotspot)) + return false; + hotX = hotspot.x(); + hotY = hotspot.y(); +#elif defined(Q_OS_MACOS) + // See chromium/content/common/cursors/webcursor_mac.mm + switch (type) { + case ui::mojom::CursorType::kVerticalText: + // TODO: [NSCursor IBeamCursorForVerticalLayout] + return false; + case ui::mojom::CursorType::kCell: + resourceId = IDR_CELL_CURSOR; + hotX = 7; + hotY = 7; + break; + case ui::mojom::CursorType::kContextMenu: + // TODO: [NSCursor contextualMenuCursor] + return false; + case ui::mojom::CursorType::kZoomIn: + resourceId = IDR_ZOOMIN_CURSOR; + hotX = 7; + hotY = 7; + break; + case ui::mojom::CursorType::kZoomOut: + resourceId = IDR_ZOOMOUT_CURSOR; + hotX = 7; + hotY = 7; + break; + default: + Q_UNREACHABLE(); + return false; + } +#else + Q_UNREACHABLE(); + return false; +#endif + + const gfx::ImageSkia *imageSkia = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resourceId); + if (!imageSkia) + return false; + + QImage imageQt = toQImage(imageSkia->GetRepresentation(GetScreenInfo().device_scale_factor)); + + // Convert hotspot coordinates into device-independent pixels. + hotX /= hotspotDpr; + hotY /= hotspotDpr; + +#if defined(Q_OS_LINUX) + // QTBUG-68571: On Linux (xcb, wayland, eglfs), hotspot coordinates must be in physical pixels. + qreal imageDpr = imageQt.devicePixelRatio(); + hotX *= imageDpr; + hotY *= imageDpr; +#endif + + m_delegate->updateCursor(QCursor(QPixmap::fromImage(std::move(imageQt)), qRound(hotX), qRound(hotY))); + return true; +} + +void RenderWidgetHostViewQt::UpdateCursor(const ui::Cursor &webCursor) { DisplayCursor(webCursor); } -void RenderWidgetHostViewQt::DisplayCursor(const content::WebCursor &webCursor) +void RenderWidgetHostViewQt::DisplayCursor(const ui::Cursor &cursorInfo) { - const ui::Cursor &cursorInfo = webCursor.cursor(); Qt::CursorShape shape = Qt::ArrowCursor; -#if defined(USE_AURA) - ui::mojom::CursorType auraType = ui::mojom::CursorType::kNull; -#endif switch (cursorInfo.type()) { case ui::mojom::CursorType::kNull: case ui::mojom::CursorType::kPointer: @@ -468,31 +563,19 @@ void RenderWidgetHostViewQt::DisplayCursor(const content::WebCursor &webCursor) case ui::mojom::CursorType::kAlias: shape = Qt::DragLinkCursor; break; -#if defined(USE_AURA) case ui::mojom::CursorType::kVerticalText: - auraType = ui::mojom::CursorType::kVerticalText; - break; case ui::mojom::CursorType::kCell: - auraType = ui::mojom::CursorType::kCell; - break; case ui::mojom::CursorType::kContextMenu: - auraType = ui::mojom::CursorType::kContextMenu; - break; case ui::mojom::CursorType::kZoomIn: - auraType = ui::mojom::CursorType::kZoomIn; - break; case ui::mojom::CursorType::kZoomOut: - auraType = ui::mojom::CursorType::kZoomOut; - break; -#else - case ui::mojom::CursorType::kVerticalText: - case ui::mojom::CursorType::kCell: - case ui::mojom::CursorType::kContextMenu: - case ui::mojom::CursorType::kZoomIn: - case ui::mojom::CursorType::kZoomOut: - // FIXME: Support on OS X + if (updateCursorFromResource(cursorInfo.type())) + return; break; -#endif + case ui::mojom::CursorType::kEastWestNoResize: + case ui::mojom::CursorType::kNorthEastSouthWestNoResize: + case ui::mojom::CursorType::kNorthSouthNoResize: + case ui::mojom::CursorType::kNorthWestSouthEastNoResize: + // Use forbidden cursor matching webcursor_mac.mm and win_cursor_factory.cc case ui::mojom::CursorType::kNoDrop: case ui::mojom::CursorType::kNotAllowed: shape = Qt::ForbiddenCursor; @@ -514,36 +597,14 @@ void RenderWidgetHostViewQt::DisplayCursor(const content::WebCursor &webCursor) } break; } -#if defined(USE_AURA) - if (auraType != ui::mojom::CursorType::kNull) { - int resourceId; - gfx::Point hotspot; - // GetCursorDataFor only knows hotspots for 1x and 2x cursor images, in physical pixels. - qreal hotspotDpr = m_screenInfo.device_scale_factor <= 1.0f ? 1.0f : 2.0f; - if (ui::GetCursorDataFor(ui::CursorSize::kNormal, auraType, hotspotDpr, &resourceId, &hotspot)) { - if (const gfx::ImageSkia *imageSkia = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resourceId)) { - QImage imageQt = toQImage(imageSkia->GetRepresentation(m_screenInfo.device_scale_factor)); - - // Convert hotspot coordinates into device-independent pixels. - qreal hotX = hotspot.x() / hotspotDpr; - qreal hotY = hotspot.y() / hotspotDpr; - -#if defined(Q_OS_LINUX) - // QTBUG-68571: On Linux (xcb, wayland, eglfs), hotspot coordinates must be in physical pixels. - qreal imageDpr = imageQt.devicePixelRatio(); - hotX *= imageDpr; - hotY *= imageDpr; -#endif - - m_delegate->updateCursor(QCursor(QPixmap::fromImage(std::move(imageQt)), qRound(hotX), qRound(hotY))); - return; - } - } - } -#endif m_delegate->updateCursor(QCursor(shape)); } +content::CursorManager *RenderWidgetHostViewQt::GetCursorManager() +{ + return m_cursorManager.get(); +} + void RenderWidgetHostViewQt::SetIsLoading(bool) { // We use WebContentsDelegateQt::LoadingStateChanged to notify about loading state. @@ -554,7 +615,9 @@ void RenderWidgetHostViewQt::ImeCancelComposition() qApp->inputMethod()->reset(); } -void RenderWidgetHostViewQt::ImeCompositionRangeChanged(const gfx::Range&, const std::vector<gfx::Rect>&) +void RenderWidgetHostViewQt::ImeCompositionRangeChanged(const gfx::Range &, + const absl::optional<std::vector<gfx::Rect>> &, + const absl::optional<std::vector<gfx::Rect>> &) { // FIXME: not implemented? QT_NOT_YET_IMPLEMENTED @@ -565,25 +628,32 @@ void RenderWidgetHostViewQt::RenderProcessGone() Destroy(); } -void RenderWidgetHostViewQt::Destroy() +bool RenderWidgetHostViewQt::TransformPointToCoordSpaceForView(const gfx::PointF &point, + content::RenderWidgetHostViewBase *target_view, + gfx::PointF *transformed_point) { - delete this; + if (target_view == this) { + *transformed_point = point; + return true; + } + + return target_view->TransformPointToLocalCoordSpace(point, GetCurrentSurfaceId(), transformed_point); } -void RenderWidgetHostViewQt::SetTooltipText(const base::string16 &tooltip_text) +void RenderWidgetHostViewQt::Destroy() { - DisplayTooltipText(tooltip_text); + delete this; } -void RenderWidgetHostViewQt::DisplayTooltipText(const base::string16 &tooltip_text) +void RenderWidgetHostViewQt::UpdateTooltipUnderCursor(const std::u16string &tooltip_text) { - if (m_adapterClient) - m_adapterClient->setToolTip(toQt(tooltip_text)); + UpdateTooltip(tooltip_text); } -void RenderWidgetHostViewQt::GetScreenInfo(content::ScreenInfo *results) +void RenderWidgetHostViewQt::UpdateTooltip(const std::u16string &tooltip_text) { - *results = m_screenInfo; + if (host()->delegate() && m_adapterClient) + m_adapterClient->setToolTip(toQt(tooltip_text)); } gfx::Rect RenderWidgetHostViewQt::GetBoundsInRootWindow() @@ -597,31 +667,29 @@ void RenderWidgetHostViewQt::OnUpdateTextInputStateCalled(content::TextInputMana Q_UNUSED(updated_view); Q_UNUSED(did_update_state); - const content::TextInputState *state = text_input_manager_->GetTextInputState(); + const ui::mojom::TextInputState *state = text_input_manager_->GetTextInputState(); if (!state) { - m_delegate->inputMethodStateChanged(false /*editorVisible*/, false /*passwordInput*/); - m_delegate->setInputMethodHints(Qt::ImhNone); + // Do not reset input method state here because an editable node might be still focused and + // this would hide the virtual keyboard if a child of the focused node is removed. return; } ui::TextInputType type = getTextInputType(); -#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) m_delegate->setInputMethodHints(toQtInputMethodHints(getTextInputType()) | Qt::ImhNoPredictiveText | Qt::ImhNoTextHandles | Qt::ImhNoEditMenu); -#else - m_delegate->setInputMethodHints(toQtInputMethodHints(getTextInputType()) | Qt::ImhNoPredictiveText); -#endif QString surroundingText = toQt(state->value); // Remove IME composition text from the surrounding text - if (state->composition_start != -1 && state->composition_end != -1) - surroundingText.remove(state->composition_start, - state->composition_end - state->composition_start); + if (state->composition.has_value()) + surroundingText.remove(state->composition->start(), + state->composition->end() - state->composition->start()); delegateClient()->setSurroundingText(surroundingText); // In case of text selection, the update is expected in RenderWidgetHostViewQt::selectionChanged(). if (GetSelectedText().empty()) { - // At this point it is unknown whether the text input state has been updated due to a text selection. - // Keep the cursor position updated for cursor movements too. - delegateClient()->setCursorPosition(state->selection_start); + if (state->composition.has_value()) { + delegateClient()->setCursorPosition(state->composition->start()); + } else { + delegateClient()->setCursorPosition(state->selection.start()); + } m_delegate->inputMethodStateChanged(type != ui::TEXT_INPUT_TYPE_NONE, type == ui::TEXT_INPUT_TYPE_PASSWORD); } @@ -631,7 +699,7 @@ void RenderWidgetHostViewQt::OnUpdateTextInputStateCalled(content::TextInputMana } // Ignore selection change triggered by ime composition unless it clears an actual text selection - if (state->composition_start != -1 && delegateClient()->isPreviousSelectionEmpty()) { + if (state->composition.has_value() && delegateClient()->isPreviousSelectionEmpty()) { m_imState = 0; return; } @@ -658,15 +726,22 @@ void RenderWidgetHostViewQt::OnTextSelectionChanged(content::TextInputManager *t Q_UNUSED(text_input_manager); Q_UNUSED(updated_view); - const content::TextInputManager::TextSelection *selection = GetTextInputManager()->GetTextSelection(updated_view); - if (!selection) - return; + // We obtain the TextSelection from focused RWH which is obtained from the + // frame tree. + content::RenderWidgetHostViewBase *focused_view = + GetFocusedWidget() ? GetFocusedWidget()->GetView() : nullptr; + + if (!focused_view) + return; #if defined(USE_OZONE) - if (!selection->selected_text().empty() && selection->user_initiated()) { - // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard. - ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kSelection); - clipboard_writer.WriteText(selection->selected_text()); + if (ui::Clipboard::IsSupportedClipboardBuffer(ui::ClipboardBuffer::kSelection)) { + const content::TextInputManager::TextSelection *selection = GetTextInputManager()->GetTextSelection(focused_view); + if (selection->selected_text().length() && selection->user_initiated()) { + // Set the ClipboardBuffer::kSelection to the ui::Clipboard. + ui::ScopedClipboardWriter clipboard_writer(ui::ClipboardBuffer::kSelection); + clipboard_writer.WriteText(selection->selected_text()); + } } #endif // defined(USE_OZONE) @@ -690,16 +765,16 @@ void RenderWidgetHostViewQt::OnGestureEvent(const ui::GestureEventData& gesture) if (m_touchSelectionController && m_touchSelectionControllerClient) { switch (event.GetType()) { - case blink::WebInputEvent::kGestureLongPress: + case blink::WebInputEvent::Type::kGestureLongPress: m_touchSelectionController->HandleLongPressEvent(event.TimeStamp(), event.PositionInWidget()); break; - case blink::WebInputEvent::kGestureTap: + case blink::WebInputEvent::Type::kGestureTap: m_touchSelectionController->HandleTapEvent(event.PositionInWidget(), event.data.tap.tap_count); break; - case blink::WebInputEvent::kGestureScrollBegin: + case blink::WebInputEvent::Type::kGestureScrollBegin: m_touchSelectionControllerClient->onScrollBegin(); break; - case blink::WebInputEvent::kGestureScrollEnd: + case blink::WebInputEvent::Type::kGestureScrollEnd: m_touchSelectionControllerClient->onScrollEnd(); break; default: @@ -707,7 +782,8 @@ void RenderWidgetHostViewQt::OnGestureEvent(const ui::GestureEventData& gesture) } } - host()->ForwardGestureEvent(event); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteGestureEvent(this, &event, ui::LatencyInfo()); } void RenderWidgetHostViewQt::DidStopFlinging() @@ -725,12 +801,7 @@ viz::ScopedSurfaceIdAllocator RenderWidgetHostViewQt::DidUpdateVisualProperties( void RenderWidgetHostViewQt::OnDidUpdateVisualPropertiesComplete(const cc::RenderFrameMetadata &metadata) { - synchronizeVisualProperties(metadata.local_surface_id_allocation); -} - -void RenderWidgetHostViewQt::OnDidFirstVisuallyNonEmptyPaint() -{ - m_adapterClient->didFirstVisuallyNonEmptyPaint(); + synchronizeVisualProperties(metadata.local_surface_id); } Compositor::Id RenderWidgetHostViewQt::compositorId() @@ -741,17 +812,18 @@ Compositor::Id RenderWidgetHostViewQt::compositorId() void RenderWidgetHostViewQt::notifyShown() { // Handle possible frame eviction: - if (!m_dfhLocalSurfaceIdAllocator.HasValidLocalSurfaceIdAllocation()) + if (!m_dfhLocalSurfaceIdAllocator.HasValidLocalSurfaceId()) m_dfhLocalSurfaceIdAllocator.GenerateId(); if (m_visible) return; m_visible = true; - host()->WasShown(base::nullopt); + host()->WasShown(nullptr); m_delegatedFrameHost->AttachToCompositor(m_uiCompositor.get()); - m_delegatedFrameHost->WasShown(GetLocalSurfaceIdAllocation().local_surface_id(), - toGfx(delegateClient()->viewRectInDips().size()), base::nullopt); + m_delegatedFrameHost->WasShown(GetLocalSurfaceId(), + toGfx(delegateClient()->viewRectInDips().size()), + nullptr); } void RenderWidgetHostViewQt::notifyHidden() @@ -764,10 +836,11 @@ void RenderWidgetHostViewQt::notifyHidden() m_delegatedFrameHost->DetachFromCompositor(); } -void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) { - Q_UNUSED(touch); - const bool eventConsumed = ack_result == content::INPUT_EVENT_ACK_STATE_CONSUMED; - m_gestureProvider.OnTouchEventAck(touch.event.unique_touch_event_id, eventConsumed, /*fixme: ?? */false); +void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, blink::mojom::InputEventResultState ack_result) +{ + const bool eventConsumed = (ack_result == blink::mojom::InputEventResultState::kConsumed); + const bool isSetBlocking = content::InputEventResultStateIsSetBlocking(ack_result); + m_gestureProvider.OnTouchEventAck(touch.event.unique_touch_event_id, eventConsumed, isSetBlocking); } void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEvent) @@ -775,11 +848,11 @@ void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEve auto result = m_gestureProvider.OnTouchEvent(motionEvent); if (!result.succeeded) return; - blink::WebTouchEvent touchEvent = ui::CreateWebTouchEventFromMotionEvent(motionEvent, result.moved_beyond_slop_region, false /*hovering, FIXME ?*/); - host()->ForwardTouchEventWithLatencyInfo(touchEvent, CreateLatencyInfo(touchEvent)); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteTouchEvent(this, &touchEvent, CreateLatencyInfo(touchEvent)); } bool RenderWidgetHostViewQt::isPopup() const @@ -789,21 +862,17 @@ bool RenderWidgetHostViewQt::isPopup() const bool RenderWidgetHostViewQt::updateScreenInfo() { - content::ScreenInfo oldScreenInfo = m_screenInfo; - QScreen *screen = m_delegate->window() ? m_delegate->window()->screen() : nullptr; - - if (screen) { - m_screenInfo.device_scale_factor = screen->devicePixelRatio(); - m_screenInfo.depth_per_component = 8; - m_screenInfo.depth = screen->depth(); - m_screenInfo.is_monochrome = (m_screenInfo.depth == 1); - m_screenInfo.rect = toGfx(screen->geometry()); - m_screenInfo.available_rect = toGfx(screen->availableGeometry()); - } else { - m_screenInfo.device_scale_factor = qGuiApp->devicePixelRatio(); - } - return (m_screenInfo != oldScreenInfo); + QWindow *window = m_delegate->Window(); + if (!window) + return false; + + display::ScreenInfos newScreenInfos = screenInfosFromQtForUpdate(window->screen()); + if (screen_infos_ == newScreenInfos) + return false; + + screen_infos_ = std::move(newScreenInfos); + return true; } void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *event) @@ -812,8 +881,9 @@ void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *event) Q_ASSERT(m_pendingWheelEvents.isEmpty()); blink::WebMouseWheelEvent webEvent = WebEventFactory::toWebWheelEvent(event); m_wheelAckPending = (webEvent.phase != blink::WebMouseWheelEvent::kPhaseEnded); - GetMouseWheelPhaseHandler()->AddPhaseIfNeededAndScheduleEndEvent(webEvent, false); - host()->ForwardWheelEvent(webEvent); + GetMouseWheelPhaseHandler()->AddPhaseIfNeededAndScheduleEndEvent(webEvent, true); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(this, &webEvent, ui::LatencyInfo()); return; } if (!m_pendingWheelEvents.isEmpty()) { @@ -824,7 +894,7 @@ void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *event) m_pendingWheelEvents.append(WebEventFactory::toWebWheelEvent(event)); } -void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &event, content::InputEventAckState /*ack_result*/) +void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &event, blink::mojom::InputEventResultState /*ack_result*/) { if (event.phase == blink::WebMouseWheelEvent::kPhaseEnded) return; @@ -833,19 +903,22 @@ void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &even while (!m_pendingWheelEvents.isEmpty() && !m_wheelAckPending) { blink::WebMouseWheelEvent webEvent = m_pendingWheelEvents.takeFirst(); m_wheelAckPending = (webEvent.phase != blink::WebMouseWheelEvent::kPhaseEnded); - m_mouseWheelPhaseHandler.AddPhaseIfNeededAndScheduleEndEvent(webEvent, false); - host()->ForwardWheelEvent(webEvent); + m_mouseWheelPhaseHandler.AddPhaseIfNeededAndScheduleEndEvent(webEvent, true); + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) + host()->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(this, &webEvent, ui::LatencyInfo()); } } -void RenderWidgetHostViewQt::GestureEventAck(const blink::WebGestureEvent &event, content::InputEventAckState ack_result) +void RenderWidgetHostViewQt::GestureEventAck(const blink::WebGestureEvent &event, + blink::mojom::InputEventResultState ack_result, + blink::mojom::ScrollResultDataPtr scroll_result_data) { // Forward unhandled scroll events back as wheel events - if (event.GetType() != blink::WebInputEvent::kGestureScrollUpdate) + if (event.GetType() != blink::WebInputEvent::Type::kGestureScrollUpdate) return; switch (ack_result) { - case content::INPUT_EVENT_ACK_STATE_NOT_CONSUMED: - case content::INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: + case blink::mojom::InputEventResultState::kNotConsumed: + case blink::mojom::InputEventResultState::kNoConsumerExists: WebEventFactory::sendUnhandledWheelEvent(event, delegate()); break; default: @@ -858,26 +931,13 @@ content::MouseWheelPhaseHandler *RenderWidgetHostViewQt::GetMouseWheelPhaseHandl return &m_mouseWheelPhaseHandler; } -content::RenderFrameHost *RenderWidgetHostViewQt::getFocusedFrameHost() -{ - content::RenderViewHostImpl *viewHost = content::RenderViewHostImpl::From(host()); - if (!viewHost) - return nullptr; - - content::FrameTreeNode *focusedFrame = viewHost->GetDelegate()->GetFrameTree()->GetFocusedFrame(); - if (!focusedFrame) - return nullptr; - - return focusedFrame->current_frame_host(); -} - -content::mojom::FrameInputHandler *RenderWidgetHostViewQt::getFrameInputHandler() +blink::mojom::FrameWidgetInputHandler *RenderWidgetHostViewQt::getFrameWidgetInputHandler() { - content::RenderFrameHostImpl *frameHost = static_cast<content::RenderFrameHostImpl *>(getFocusedFrameHost()); - if (!frameHost) + auto *focused_widget = GetFocusedWidget(); + if (!focused_widget) return nullptr; - return frameHost->GetFrameInputHandler(); + return focused_widget->GetFrameWidgetInputHandler(); } ui::TextInputType RenderWidgetHostViewQt::getTextInputType() const @@ -898,20 +958,32 @@ const viz::FrameSinkId &RenderWidgetHostViewQt::GetFrameSinkId() const return m_delegatedFrameHost->frame_sink_id(); } -const viz::LocalSurfaceIdAllocation &RenderWidgetHostViewQt::GetLocalSurfaceIdAllocation() const +const viz::LocalSurfaceId &RenderWidgetHostViewQt::GetLocalSurfaceId() const +{ + return m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceId(); +} + +void RenderWidgetHostViewQt::FocusedNodeChanged(bool is_editable_node, const gfx::Rect& node_bounds_in_screen) +{ + Q_UNUSED(node_bounds_in_screen); + if (!is_editable_node) { + m_delegate->inputMethodStateChanged(false /*editorVisible*/, false /*passwordInput*/); + m_delegate->setInputMethodHints(Qt::ImhNone); + } +} + +base::flat_map<std::string, std::string> RenderWidgetHostViewQt::GetKeyboardLayoutMap() { - return m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation(); + return ui::GenerateDomKeyboardLayoutMap(); } void RenderWidgetHostViewQt::TakeFallbackContentFrom(content::RenderWidgetHostView *view) { DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)->IsRenderWidgetHostViewChildFrame()); RenderWidgetHostViewQt *viewQt = static_cast<RenderWidgetHostViewQt *>(view); - base::Optional<SkColor> color = viewQt->GetBackgroundColor(); - if (color) - SetBackgroundColor(*color); + CopyBackgroundColorIfPresentFrom(*viewQt); + m_delegatedFrameHost->TakeFallbackContentFrom(viewQt->m_delegatedFrameHost.get()); - host()->GetContentRenderingTimeoutFrom(viewQt->host()); } void RenderWidgetHostViewQt::EnsureSurfaceSynchronizedForWebTest() @@ -928,10 +1000,9 @@ void RenderWidgetHostViewQt::ResetFallbackToFirstNavigationSurface() { } -void RenderWidgetHostViewQt::OnRenderFrameMetadataChangedAfterActivation() +void RenderWidgetHostViewQt::OnRenderFrameMetadataChangedAfterActivation(base::TimeTicks activation_time) { - content::RenderWidgetHostViewBase::OnRenderFrameMetadataChangedAfterActivation(); - + Q_UNUSED(activation_time); const cc::RenderFrameMetadata &metadata = host()->render_frame_metadata_provider()->LastRenderFrameMetadata(); if (metadata.selection.start != m_selectionStart || metadata.selection.end != m_selectionEnd) { m_selectionStart = metadata.selection.start; @@ -939,17 +1010,22 @@ void RenderWidgetHostViewQt::OnRenderFrameMetadataChangedAfterActivation() m_touchSelectionControllerClient->UpdateClientSelectionBounds(m_selectionStart, m_selectionEnd); } - gfx::Vector2dF scrollOffset = metadata.root_scroll_offset.value_or(gfx::Vector2dF()); - gfx::SizeF contentsSize = metadata.root_layer_size; + gfx::PointF scrollOffset = gfx::PointF(); + if (metadata.root_scroll_offset.has_value()) + scrollOffset = gfx::ScalePoint(metadata.root_scroll_offset.value(), + 1 / metadata.device_scale_factor); std::swap(m_lastScrollOffset, scrollOffset); - std::swap(m_lastContentsSize, contentsSize); if (m_adapterClient && scrollOffset != m_lastScrollOffset) m_adapterClient->updateScrollPosition(toQt(m_lastScrollOffset)); + + gfx::SizeF contentsSize = + gfx::ScaleSize(metadata.root_layer_size, 1 / metadata.device_scale_factor); + std::swap(m_lastContentsSize, contentsSize); if (m_adapterClient && contentsSize != m_lastContentsSize) m_adapterClient->updateContentsSize(toQt(m_lastContentsSize)); } -void RenderWidgetHostViewQt::synchronizeVisualProperties(const base::Optional<viz::LocalSurfaceIdAllocation> &childSurfaceId) +void RenderWidgetHostViewQt::synchronizeVisualProperties(const absl::optional<viz::LocalSurfaceId> &childSurfaceId) { if (childSurfaceId) m_dfhLocalSurfaceIdAllocator.UpdateFromChild(*childSurfaceId); @@ -961,17 +1037,28 @@ void RenderWidgetHostViewQt::synchronizeVisualProperties(const base::Optional<vi m_rootLayer->SetBounds(gfx::Rect(gfx::Point(), viewSizeInPixels)); m_uiCompositorLocalSurfaceIdAllocator.GenerateId(); m_uiCompositor->SetScaleAndSize( - m_screenInfo.device_scale_factor, + GetScreenInfo().device_scale_factor, viewSizeInPixels, - m_uiCompositorLocalSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation()); + m_uiCompositorLocalSurfaceIdAllocator.GetCurrentLocalSurfaceId()); m_delegatedFrameHost->EmbedSurface( - m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(), + m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceId(), viewSizeInDips, cc::DeadlinePolicy::UseDefaultDeadline()); host()->SynchronizeVisualProperties(); } +void RenderWidgetHostViewQt::resetTouchSelectionController() +{ + Q_ASSERT(m_touchSelectionControllerClient); + m_touchSelectionControllerClient->resetControls(); + ui::TouchSelectionController::Config config; + config.max_tap_duration = base::Milliseconds(ui::GestureConfiguration::GetInstance()->long_press_time_in_ms()); + config.tap_slop = ui::GestureConfiguration::GetInstance()->max_touch_move_in_pixels_for_click(); + config.enable_longpress_drag_selection = false; + m_touchSelectionController.reset(new ui::TouchSelectionController(m_touchSelectionControllerClient.get(), config)); +} + std::unique_ptr<content::SyntheticGestureTarget> RenderWidgetHostViewQt::CreateSyntheticGestureTarget() { return nullptr; @@ -982,4 +1069,14 @@ ui::Compositor *RenderWidgetHostViewQt::GetCompositor() return m_uiCompositor.get(); } +absl::optional<content::DisplayFeature> RenderWidgetHostViewQt::GetDisplayFeature() +{ + return absl::nullopt; +} + +void RenderWidgetHostViewQt::SetDisplayFeatureForTesting(const content::DisplayFeature *) +{ + NOTIMPLEMENTED(); +} + } // namespace QtWebEngineCore |