alloy: Add touch handle and quick menu support for OSR (fixes issue #3268)

The client is responsible for rendering both as no default implementation
is currently available for OSR.
This commit is contained in:
JohnKarel 2022-05-27 12:03:31 +03:00 committed by Marshall Greenblatt
parent 771e5c7c0c
commit d9b764860a
41 changed files with 2166 additions and 52 deletions

View File

@ -416,6 +416,8 @@ static_library("libcef_static") {
"libcef/browser/alloy/alloy_content_browser_client.h",
"libcef/browser/alloy/alloy_download_util.cc",
"libcef/browser/alloy/alloy_download_util.h",
"libcef/browser/alloy/alloy_web_contents_view_delegate.cc",
"libcef/browser/alloy/alloy_web_contents_view_delegate.h",
"libcef/browser/alloy/browser_platform_delegate_alloy.cc",
"libcef/browser/alloy/browser_platform_delegate_alloy.h",
"libcef/browser/alloy/chrome_browser_process_alloy.cc",
@ -636,6 +638,10 @@ static_library("libcef_static") {
"libcef/browser/osr/render_widget_host_view_osr.h",
"libcef/browser/osr/synthetic_gesture_target_osr.cc",
"libcef/browser/osr/synthetic_gesture_target_osr.h",
"libcef/browser/osr/touch_handle_drawable_osr.cc",
"libcef/browser/osr/touch_handle_drawable_osr.h",
"libcef/browser/osr/touch_selection_controller_client_osr.cc",
"libcef/browser/osr/touch_selection_controller_client_osr.h",
"libcef/browser/osr/video_consumer_osr.cc",
"libcef/browser/osr/video_consumer_osr.h",
"libcef/browser/osr/web_contents_view_osr.cc",

View File

@ -8,7 +8,7 @@
# by hand. See the translator.README.txt file in the tools directory for
# more information.
#
# $hash=5f2e9bf79ec768c0eb978ff5e1dd0178701dcc21$
# $hash=7ee0c6a789cc0574798332fe7c7cc10f862280af$
#
{
@ -416,6 +416,8 @@
'libcef_dll/cpptoc/run_context_menu_callback_cpptoc.h',
'libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc',
'libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h',
'libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.cc',
'libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.h',
'libcef_dll/cpptoc/sslinfo_cpptoc.cc',
'libcef_dll/cpptoc/sslinfo_cpptoc.h',
'libcef_dll/cpptoc/sslstatus_cpptoc.cc',
@ -722,6 +724,8 @@
'libcef_dll/ctocpp/run_context_menu_callback_ctocpp.h',
'libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc',
'libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h',
'libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.cc',
'libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.h',
'libcef_dll/ctocpp/sslinfo_ctocpp.cc',
'libcef_dll/ctocpp/sslinfo_ctocpp.h',
'libcef_dll/ctocpp/sslstatus_ctocpp.cc',

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=d007b3dc26f3f049bf67623da8fae59dc75a193b$
// $hash=d9498ae2e32ec124df3dd2c3017bcf415d4205f8$
//
#ifndef CEF_INCLUDE_CAPI_CEF_CONTEXT_MENU_HANDLER_CAPI_H_
@ -74,6 +74,29 @@ typedef struct _cef_run_context_menu_callback_t {
void(CEF_CALLBACK* cancel)(struct _cef_run_context_menu_callback_t* self);
} cef_run_context_menu_callback_t;
///
// Callback structure used for continuation of custom quick menu display.
///
typedef struct _cef_run_quick_menu_callback_t {
///
// Base structure.
///
cef_base_ref_counted_t base;
///
// Complete quick menu display by selecting the specified |command_id| and
// |event_flags|.
///
void(CEF_CALLBACK* cont)(struct _cef_run_quick_menu_callback_t* self,
int command_id,
cef_event_flags_t event_flags);
///
// Cancel quick menu display.
///
void(CEF_CALLBACK* cancel)(struct _cef_run_quick_menu_callback_t* self);
} cef_run_quick_menu_callback_t;
///
// Implement this structure to handle context menu events. The functions of this
// structure will be called on the UI thread.
@ -133,16 +156,56 @@ typedef struct _cef_context_menu_handler_t {
///
// Called when the context menu is dismissed irregardless of whether the menu
// was NULL or a command was selected.
// was canceled or a command was selected.
///
void(CEF_CALLBACK* on_context_menu_dismissed)(
struct _cef_context_menu_handler_t* self,
struct _cef_browser_t* browser,
struct _cef_frame_t* frame);
///
// Called to allow custom display of the quick menu for a windowless browser.
// |location| is the top left corner of the selected region. |size| is the
// size of the selected region. |edit_state_flags| is a combination of flags
// that represent the state of the quick menu. Return true (1) if the menu
// will be handled and execute |callback| either synchronously or
// asynchronously with the selected command ID. Return false (0) to cancel the
// menu.
///
int(CEF_CALLBACK* run_quick_menu)(
struct _cef_context_menu_handler_t* self,
struct _cef_browser_t* browser,
struct _cef_frame_t* frame,
const cef_point_t* location,
const cef_size_t* size,
cef_quick_menu_edit_state_flags_t edit_state_flags,
struct _cef_run_quick_menu_callback_t* callback);
///
// Called to execute a command selected from the quick menu for a windowless
// browser. Return true (1) if the command was handled or false (0) for the
// default implementation. See cef_menu_id_t for command IDs that have default
// implementations.
///
int(CEF_CALLBACK* on_quick_menu_command)(
struct _cef_context_menu_handler_t* self,
struct _cef_browser_t* browser,
struct _cef_frame_t* frame,
int command_id,
cef_event_flags_t event_flags);
///
// Called when the quick menu for a windowless browser is dismissed
// irregardless of whether the menu was canceled or a command was selected.
///
void(CEF_CALLBACK* on_quick_menu_dismissed)(
struct _cef_context_menu_handler_t* self,
struct _cef_browser_t* browser,
struct _cef_frame_t* frame);
} cef_context_menu_handler_t;
///
// Provides information about the context menu state. The ethods of this
// Provides information about the context menu state. The functions of this
// structure can only be accessed on browser process the UI thread.
///
typedef struct _cef_context_menu_params_t {

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=7fc75c41ce47a5e715471b9bb82c848d6cf25472$
// $hash=b0688a7d24b67b74a62841be60217a8e48c7228e$
//
#ifndef CEF_INCLUDE_CAPI_CEF_RENDER_HANDLER_CAPI_H_
@ -161,6 +161,25 @@ typedef struct _cef_render_handler_t {
cef_rect_t const* dirtyRects,
void* shared_handle);
///
// Called to retrieve the size of the touch handle for the specified
// |orientation|.
///
void(CEF_CALLBACK* get_touch_handle_size)(
struct _cef_render_handler_t* self,
struct _cef_browser_t* browser,
cef_horizontal_alignment_t orientation,
cef_size_t* size);
///
// Called when touch handle state is updated. The client is responsible for
// rendering the touch handles.
///
void(CEF_CALLBACK* on_touch_handle_state_changed)(
struct _cef_render_handler_t* self,
struct _cef_browser_t* browser,
const struct _cef_touch_handle_state_t* state);
///
// Called when the user starts dragging content in the web view. Contextual
// information about the dragged content is supplied by |drag_data|. (|x|,

View File

@ -42,13 +42,13 @@
// way that may cause binary incompatibility with other builds. The universal
// hash value will change if any platform is affected whereas the platform hash
// values will change only if that particular platform is affected.
#define CEF_API_HASH_UNIVERSAL "b6255e15aa977a7214cf28e4e1a2372b454838d4"
#define CEF_API_HASH_UNIVERSAL "eb7cc5b2fb5c87d0f580e8df1bb609729fc731d0"
#if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "b262c3a2cbd2632de1bfed887da8b8114c9ecbf5"
#define CEF_API_HASH_PLATFORM "b61f8f06751ed7231b2036b71d714d074feadf5b"
#elif defined(OS_MAC)
#define CEF_API_HASH_PLATFORM "fd6d3d83442fe31ad26d5648755e0cf2e14a7fc7"
#define CEF_API_HASH_PLATFORM "d4ac1390d4c202e26633a0c95a560171ad05e4fe"
#elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "d686964de5e01eed900d78d5f8a7da9f8fc3a777"
#define CEF_API_HASH_PLATFORM "0d9fe8afb1b67a6098e08f7fe6d0ac7e70ce29e6"
#endif
#ifdef __cplusplus

View File

@ -51,14 +51,12 @@ class CefContextMenuParams;
/*--cef(source=library)--*/
class CefRunContextMenuCallback : public virtual CefBaseRefCounted {
public:
typedef cef_event_flags_t EventFlags;
///
// Complete context menu display by selecting the specified |command_id| and
// |event_flags|.
///
/*--cef(capi_name=cont)--*/
virtual void Continue(int command_id, EventFlags event_flags) = 0;
virtual void Continue(int command_id, cef_event_flags_t event_flags) = 0;
///
// Cancel context menu display.
@ -67,6 +65,26 @@ class CefRunContextMenuCallback : public virtual CefBaseRefCounted {
virtual void Cancel() = 0;
};
///
// Callback interface used for continuation of custom quick menu display.
///
/*--cef(source=library)--*/
class CefRunQuickMenuCallback : public virtual CefBaseRefCounted {
public:
///
// Complete quick menu display by selecting the specified |command_id| and
// |event_flags|.
///
/*--cef(capi_name=cont)--*/
virtual void Continue(int command_id, cef_event_flags_t event_flags) = 0;
///
// Cancel quick menu display.
///
/*--cef()--*/
virtual void Cancel() = 0;
};
///
// Implement this interface to handle context menu events. The methods of this
// class will be called on the UI thread.
@ -75,6 +93,7 @@ class CefRunContextMenuCallback : public virtual CefBaseRefCounted {
class CefContextMenuHandler : public virtual CefBaseRefCounted {
public:
typedef cef_event_flags_t EventFlags;
typedef cef_quick_menu_edit_state_flags_t QuickMenuEditStateFlags;
///
// Called before a context menu is displayed. |params| provides information
@ -126,15 +145,55 @@ class CefContextMenuHandler : public virtual CefBaseRefCounted {
///
// Called when the context menu is dismissed irregardless of whether the menu
// was empty or a command was selected.
// was canceled or a command was selected.
///
/*--cef()--*/
virtual void OnContextMenuDismissed(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame) {}
///
// Called to allow custom display of the quick menu for a windowless browser.
// |location| is the top left corner of the selected region. |size| is the
// size of the selected region. |edit_state_flags| is a combination of flags
// that represent the state of the quick menu. Return true if the menu will be
// handled and execute |callback| either synchronously or asynchronously with
// the selected command ID. Return false to cancel the menu.
///
/*--cef()--*/
virtual bool RunQuickMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefPoint& location,
const CefSize& size,
QuickMenuEditStateFlags edit_state_flags,
CefRefPtr<CefRunQuickMenuCallback> callback) {
return false;
}
///
// Called to execute a command selected from the quick menu for a windowless
// browser. Return true if the command was handled or false for the default
// implementation. See cef_menu_id_t for command IDs that have default
// implementations.
///
/*--cef()--*/
virtual bool OnQuickMenuCommand(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int command_id,
EventFlags event_flags) {
return false;
}
///
// Called when the quick menu for a windowless browser is dismissed
// irregardless of whether the menu was canceled or a command was selected.
///
/*--cef()--*/
virtual void OnQuickMenuDismissed(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame) {}
};
///
// Provides information about the context menu state. The ethods of this class
// Provides information about the context menu state. The methods of this class
// can only be accessed on browser process the UI thread.
///
/*--cef(source=library)--*/

View File

@ -163,6 +163,23 @@ class CefRenderHandler : public virtual CefBaseRefCounted {
const RectList& dirtyRects,
void* shared_handle) {}
///
// Called to retrieve the size of the touch handle for the specified
// |orientation|.
///
/*--cef()--*/
virtual void GetTouchHandleSize(CefRefPtr<CefBrowser> browser,
cef_horizontal_alignment_t orientation,
CefSize& size) {}
///
// Called when touch handle state is updated. The client is responsible for
// rendering the touch handles.
///
/*--cef()--*/
virtual void OnTouchHandleStateChanged(CefRefPtr<CefBrowser> browser,
const CefTouchHandleState& state) {}
///
// Called when the user starts dragging content in the web view. Contextual
// information about the dragged content is supplied by |drag_data|.

View File

@ -1996,6 +1996,17 @@ typedef enum {
CM_EDITFLAG_CAN_EDIT_RICHLY = 1 << 8,
} cef_context_menu_edit_state_flags_t;
///
// Supported quick menu state bit flags.
///
typedef enum {
QM_EDITFLAG_NONE = 0,
QM_EDITFLAG_CAN_ELLIPSIS = 1 << 0,
QM_EDITFLAG_CAN_CUT = 1 << 1,
QM_EDITFLAG_CAN_COPY = 1 << 2,
QM_EDITFLAG_CAN_PASTE = 1 << 3,
} cef_quick_menu_edit_state_flags_t;
///
// Key event types.
///
@ -3230,6 +3241,52 @@ typedef enum {
CEF_SHOW_STATE_FULLSCREEN,
} cef_show_state_t;
///
// Values indicating what state of the touch handle is set.
///
typedef enum {
CEF_THS_FLAG_NONE = 0,
CEF_THS_FLAG_ENABLED = 1 << 0,
CEF_THS_FLAG_ORIENTATION = 1 << 1,
CEF_THS_FLAG_ORIGIN = 1 << 2,
CEF_THS_FLAG_ALPHA = 1 << 3,
} cef_touch_handle_state_flags_t;
typedef struct _cef_touch_handle_state_t {
///
// Touch handle id. Increments for each new touch handle.
///
int touch_handle_id;
///
// Combination of cef_touch_handle_state_flags_t values indicating what state
// is set.
///
uint32_t flags;
///
// Enabled state. Only set if |flags| contains CEF_THS_FLAG_ENABLED.
///
int enabled;
///
// Orientation state. Only set if |flags| contains CEF_THS_FLAG_ORIENTATION.
///
cef_horizontal_alignment_t orientation;
int mirror_vertical;
int mirror_horizontal;
///
// Origin state. Only set if |flags| contains CEF_THS_FLAG_ORIGIN.
///
cef_point_t origin;
///
// Alpha state. Only set if |flags| contains CEF_THS_FLAG_ALPHA.
///
float alpha;
} cef_touch_handle_state_t;
#ifdef __cplusplus
}
#endif

View File

@ -820,6 +820,25 @@ class CefTime : public CefStructBase<CefTimeTraits> {
}
};
struct CefTouchHandleStateTraits {
typedef cef_touch_handle_state_t struct_type;
static inline void init(struct_type* s) {}
static inline void clear(struct_type* s) {}
static inline void set(const struct_type* src,
struct_type* target,
bool copy) {
*target = *src;
}
};
///
// Class representing the state of a touch handle.
///
typedef CefStructBase<CefTouchHandleStateTraits> CefTouchHandleState;
struct CefCookieTraits {
typedef cef_cookie_t struct_type;

View File

@ -1119,12 +1119,6 @@ bool AlloyBrowserHostImpl::TakeFocus(content::WebContents* source,
return false;
}
bool AlloyBrowserHostImpl::HandleContextMenu(
content::RenderFrameHost& render_frame_host,
const content::ContextMenuParams& params) {
return HandleContextMenu(web_contents(), params);
}
void AlloyBrowserHostImpl::CanDownload(
const GURL& url,
const std::string& request_method,
@ -1255,8 +1249,7 @@ void AlloyBrowserHostImpl::RunFileChooser(
params);
}
bool AlloyBrowserHostImpl::HandleContextMenu(
content::WebContents* web_contents,
bool AlloyBrowserHostImpl::ShowContextMenu(
const content::ContextMenuParams& params) {
CEF_REQUIRE_UIT();
if (!menu_manager_.get() && platform_delegate_) {

View File

@ -172,8 +172,7 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
void OnSetFocus(cef_focus_source_t source) override;
bool HandleContextMenu(content::WebContents* web_contents,
const content::ContextMenuParams& params);
bool ShowContextMenu(const content::ContextMenuParams& params);
enum DestructionState {
DESTRUCTION_STATE_NONE = 0,
@ -209,8 +208,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
bool proceed,
bool* proceed_to_fire_unload) override;
bool TakeFocus(content::WebContents* source, bool reverse) override;
bool HandleContextMenu(content::RenderFrameHost& render_frame_host,
const content::ContextMenuParams& params) override;
void CanDownload(const GURL& url,
const std::string& request_method,
base::OnceCallback<void(bool)> callback) override;

View File

@ -12,6 +12,7 @@
#include "libcef/browser/alloy/alloy_browser_context.h"
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
#include "libcef/browser/alloy/alloy_browser_main.h"
#include "libcef/browser/alloy/alloy_web_contents_view_delegate.h"
#include "libcef/browser/browser_context.h"
#include "libcef/browser/browser_frame.h"
#include "libcef/browser/browser_info.h"
@ -1458,6 +1459,12 @@ std::string AlloyContentBrowserClient::GetReducedUserAgent() {
return embedder_support::GetReducedUserAgent();
}
std::unique_ptr<content::WebContentsViewDelegate>
AlloyContentBrowserClient::GetWebContentsViewDelegate(
content::WebContents* web_contents) {
return std::make_unique<AlloyWebContentsViewDelegate>(web_contents);
}
blink::UserAgentMetadata AlloyContentBrowserClient::GetUserAgentMetadata() {
blink::UserAgentMetadata metadata;

View File

@ -235,6 +235,8 @@ class AlloyContentBrowserClient : public content::ContentBrowserClient {
std::string GetUserAgent() override;
std::string GetFullUserAgent() override;
std::string GetReducedUserAgent() override;
std::unique_ptr<content::WebContentsViewDelegate> GetWebContentsViewDelegate(
content::WebContents* web_contents) override;
blink::UserAgentMetadata GetUserAgentMetadata() override;
base::flat_set<std::string> GetPluginMimeTypesWithExternalHandlers(
content::BrowserContext* browser_context) override;

View File

@ -0,0 +1,22 @@
// Copyright 2022 The Chromium Embedded Framework 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 "libcef/browser/alloy/alloy_web_contents_view_delegate.h"
#include "content/public/browser/web_contents.h"
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
AlloyWebContentsViewDelegate::AlloyWebContentsViewDelegate(
content::WebContents* web_contents)
: web_contents_(web_contents) {}
void AlloyWebContentsViewDelegate::ShowContextMenu(
content::RenderFrameHost& render_frame_host,
const content::ContextMenuParams& params) {
if (auto browser =
AlloyBrowserHostImpl::GetBrowserForContents(web_contents_)) {
browser->ShowContextMenu(params);
}
}

View File

@ -0,0 +1,33 @@
// Copyright 2022 The Chromium Embedded Framework 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 CEF_LIBCEF_BROWSER_ALLOY_ALLOY_WEB_CONTENTS_VIEW_DELEGATE_H_
#define CEF_LIBCEF_BROWSER_ALLOY_ALLOY_WEB_CONTENTS_VIEW_DELEGATE_H_
#pragma once
#include "include/internal/cef_ptr.h"
#include "content/public/browser/web_contents_view_delegate.h"
namespace content {
class WebContents;
}
class AlloyWebContentsViewDelegate : public content::WebContentsViewDelegate {
public:
explicit AlloyWebContentsViewDelegate(content::WebContents* web_contents);
AlloyWebContentsViewDelegate(const AlloyWebContentsViewDelegate&) = delete;
AlloyWebContentsViewDelegate& operator=(const AlloyWebContentsViewDelegate&) =
delete;
// WebContentsViewDelegate methods:
void ShowContextMenu(content::RenderFrameHost& render_frame_host,
const content::ContextMenuParams& params) override;
private:
content::WebContents* const web_contents_;
};
#endif // CEF_LIBCEF_BROWSER_ALLOY_ALLOY_WEB_CONTENTS_VIEW_DELEGATE_H_

View File

@ -69,8 +69,7 @@ bool CefMimeHandlerViewGuestDelegate::HandleContextMenu(
AlloyBrowserHostImpl::GetBrowserForContents(owner_web_contents_);
DCHECK(owner_browser);
return owner_browser->HandleContextMenu(
content::WebContents::FromRenderFrameHost(&render_frame_host), params);
return owner_browser->ShowContextMenu(params);
}
} // namespace extensions

View File

@ -9,6 +9,7 @@
#include "libcef/browser/image_impl.h"
#include "libcef/browser/osr/osr_accessibility_util.h"
#include "libcef/browser/osr/render_widget_host_view_osr.h"
#include "libcef/browser/osr/touch_selection_controller_client_osr.h"
#include "libcef/browser/osr/web_contents_view_osr.h"
#include "libcef/browser/views/view_util.h"
#include "libcef/common/drag_data_impl.h"

View File

@ -13,7 +13,7 @@ class CefWebContentsViewOSR;
namespace content {
class RenderWidgetHostImpl;
}
} // namespace content
// Base implementation of windowless browser functionality.
class CefBrowserPlatformDelegateOsr

View File

@ -6,12 +6,12 @@
#include "libcef/browser/osr/render_widget_host_view_osr.h"
#include <stdint.h>
#include <utility>
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
#include "libcef/browser/osr/osr_util.h"
#include "libcef/browser/osr/synthetic_gesture_target_osr.h"
#include "libcef/browser/osr/touch_selection_controller_client_osr.h"
#include "libcef/browser/osr/video_consumer_osr.h"
#include "libcef/browser/thread_util.h"
@ -51,6 +51,7 @@
#include "ui/events/gesture_detection/motion_event.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/touch_selection/touch_selection_controller.h"
namespace {
@ -179,6 +180,18 @@ ui::ImeTextSpan::UnderlineStyle GetImeUnderlineStyle(
} // namespace
// Logic copied from RenderWidgetHostViewAura::CreateSelectionController.
void CefRenderWidgetHostViewOSR::CreateSelectionController() {
ui::TouchSelectionController::Config tsc_config;
tsc_config.max_tap_duration = base::Milliseconds(
ui::GestureConfiguration::GetInstance()->long_press_time_in_ms());
tsc_config.tap_slop = ui::GestureConfiguration::GetInstance()
->max_touch_move_in_pixels_for_click();
tsc_config.enable_longpress_drag_selection = false;
selection_controller_ = std::make_unique<ui::TouchSelectionController>(
selection_controller_client_.get(), tsc_config);
}
CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
SkColor background_color,
bool use_shared_texture,
@ -260,6 +273,10 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
if (!render_widget_host_->is_hidden())
Show();
}
selection_controller_client_ =
std::make_unique<CefTouchSelectionControllerClientOSR>(this);
CreateSelectionController();
}
CefRenderWidgetHostViewOSR::~CefRenderWidgetHostViewOSR() {
@ -392,8 +409,13 @@ void CefRenderWidgetHostViewOSR::Hide() {
is_showing_ = false;
if (browser_impl_.get())
if (browser_impl_) {
browser_impl_->CancelContextMenu();
}
if (selection_controller_client_) {
selection_controller_client_->CloseQuickMenuAndHideHandles();
}
if (video_consumer_) {
video_consumer_->SetActive(false);
@ -424,6 +446,11 @@ void CefRenderWidgetHostViewOSR::EnsureSurfaceSynchronizedForWebTest() {
absl::nullopt);
}
content::TouchSelectionControllerClientManager*
CefRenderWidgetHostViewOSR::GetTouchSelectionControllerClientManager() {
return selection_controller_client_.get();
}
gfx::Rect CefRenderWidgetHostViewOSR::GetViewBounds() {
if (IsPopupWidget())
return popup_position_;
@ -948,6 +975,14 @@ void CefRenderWidgetHostViewOSR::OnRenderFrameMetadataChangedAfterActivation(
weak_ptr_factory_.GetWeakPtr()));
}
}
if (metadata.selection.start != selection_start_ ||
metadata.selection.end != selection_end_) {
selection_start_ = metadata.selection.start;
selection_end_ = metadata.selection.end;
selection_controller_client_->UpdateClientSelectionBounds(selection_start_,
selection_end_);
}
}
std::unique_ptr<viz::HostDisplayClient>
@ -1091,6 +1126,10 @@ void CefRenderWidgetHostViewOSR::SendKeyEvent(
TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::SendKeyEvent");
content::RenderWidgetHostImpl* target_host = render_widget_host_;
if (selection_controller_client_) {
selection_controller_client_->CloseQuickMenuAndHideHandles();
}
// If there are multiple widgets on the page (such as when there are
// out-of-process iframes), pick the one that should process this event.
if (render_widget_host_ && render_widget_host_->delegate()) {
@ -1114,12 +1153,16 @@ void CefRenderWidgetHostViewOSR::SendMouseEvent(
const blink::WebMouseEvent& event) {
TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::SendMouseEvent");
if (!IsPopupWidget()) {
if (browser_impl_.get() &&
if (browser_impl_ &&
event.GetType() == blink::WebMouseEvent::Type::kMouseDown &&
event.button != blink::WebPointerProperties::Button::kRight) {
browser_impl_->CancelContextMenu();
}
if (selection_controller_client_) {
selection_controller_client_->CloseQuickMenuAndHideHandles();
}
if (popup_host_view_) {
if (popup_host_view_->popup_position_.Contains(
event.PositionInWidget().x(), event.PositionInWidget().y())) {
@ -1179,8 +1222,13 @@ void CefRenderWidgetHostViewOSR::SendMouseWheelEvent(
TRACE_EVENT0("cef", "CefRenderWidgetHostViewOSR::SendMouseWheelEvent");
if (!IsPopupWidget()) {
if (browser_impl_.get())
if (browser_impl_) {
browser_impl_->CancelContextMenu();
}
if (selection_controller_client_) {
selection_controller_client_->CloseQuickMenuAndHideHandles();
}
if (popup_host_view_) {
if (popup_host_view_->popup_position_.Contains(
@ -1274,6 +1322,11 @@ void CefRenderWidgetHostViewOSR::SendTouchEvent(const CefTouchEvent& event) {
if (!pointer_state_.OnTouch(event))
return;
if (selection_controller_->WillHandleTouchEvent(pointer_state_)) {
pointer_state_.CleanupRemovedTouchPoints(event);
return;
}
ui::FilteredGestureProvider::TouchHandlingResult result =
gesture_provider_.OnTouchEvent(pointer_state_);
@ -1334,8 +1387,13 @@ void CefRenderWidgetHostViewOSR::SetFocus(bool focus) {
widget->GotFocus();
widget->SetActive(true);
} else {
if (browser_impl_.get())
if (browser_impl_) {
browser_impl_->CancelContextMenu();
}
if (selection_controller_client_) {
selection_controller_client_->CloseQuickMenuAndHideHandles();
}
widget->SetActive(false);
widget->LostFocus();
@ -1480,6 +1538,13 @@ ui::Layer* CefRenderWidgetHostViewOSR::GetRootLayer() const {
return root_layer_.get();
}
ui::TextInputType CefRenderWidgetHostViewOSR::GetTextInputType() {
if (text_input_manager_ && text_input_manager_->GetTextInputState())
return text_input_manager_->GetTextInputState()->type;
return ui::TEXT_INPUT_TYPE_NONE;
}
void CefRenderWidgetHostViewOSR::SetFrameRate() {
CefRefPtr<AlloyBrowserHostImpl> browser;
if (parent_host_view_) {

View File

@ -32,6 +32,7 @@
#include "third_party/blink/public/mojom/widget/record_content_to_visible_time_request.mojom-forward.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/compositor/compositor.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/gesture_detection/filtered_gesture_provider.h"
@ -47,18 +48,23 @@
#include "ui/gfx/win/window_impl.h"
#endif
namespace ui {
class TouchSelectionController;
} // namespace ui
namespace content {
class BackingStore;
class CursorManager;
class DelegatedFrameHost;
class DelegatedFrameHostClient;
class RenderWidgetHost;
class RenderWidgetHostImpl;
class RenderWidgetHostViewGuest;
class BackingStore;
class CursorManager;
} // namespace content
class CefCopyFrameGenerator;
class CefSoftwareOutputDeviceOSR;
class CefTouchSelectionControllerClientOSR;
class CefVideoConsumerOSR;
class CefWebContentsViewOSR;
@ -118,6 +124,8 @@ class CefRenderWidgetHostViewOSR
void Hide() override;
bool IsShowing() override;
void EnsureSurfaceSynchronizedForWebTest() override;
content::TouchSelectionControllerClientManager*
GetTouchSelectionControllerClientManager() override;
gfx::Rect GetViewBounds() override;
void SetBackgroundColor(SkColor color) override;
absl::optional<SkColor> GetBackgroundColor() override;
@ -290,6 +298,16 @@ class CefRenderWidgetHostViewOSR
// content::DelegatedFrameHostClient::InvalidateLocalSurfaceIdOnEviction.
void InvalidateLocalSurfaceId();
ui::TouchSelectionController* selection_controller() const {
return selection_controller_.get();
}
CefTouchSelectionControllerClientOSR* selection_controller_client() const {
return selection_controller_client_.get();
}
ui::TextInputType GetTextInputType();
private:
void SetFrameRate();
bool SetScreenInfo();
@ -302,6 +320,9 @@ class CefRenderWidgetHostViewOSR
void CancelWidget();
// Helper function to create a selection controller.
void CreateSelectionController();
void OnScrollOffsetChanged();
void AddGuestHostView(CefRenderWidgetHostViewOSR* guest_host);
@ -342,6 +363,14 @@ class CefRenderWidgetHostViewOSR
// opaqueness changes.
void UpdateBackgroundColorFromRenderer(SkColor color);
// The last selection bounds reported to the view.
gfx::SelectionBound selection_start_;
gfx::SelectionBound selection_end_;
std::unique_ptr<CefTouchSelectionControllerClientOSR>
selection_controller_client_;
std::unique_ptr<ui::TouchSelectionController> selection_controller_;
// The background color of the web content.
SkColor background_color_;

View File

@ -0,0 +1,128 @@
// Copyright 2022 The Chromium Embedded Framework Authors.
// Portions 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 "libcef/browser/osr/touch_handle_drawable_osr.h"
#include <cmath>
#include "libcef/browser/osr/render_widget_host_view_osr.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
namespace {
// Copied from touch_handle_drawable_aura.cc
// The distance by which a handle image is offset from the focal point (i.e.
// text baseline) downwards.
constexpr int kSelectionHandleVerticalVisualOffset = 2;
// The padding around the selection handle image can be used to extend the
// handle so that touch events near the selection handle image are
// targeted to the selection handle.
constexpr int kSelectionHandlePadding = 0;
} // namespace
int CefTouchHandleDrawableOSR::counter_ = 0;
CefTouchHandleDrawableOSR::CefTouchHandleDrawableOSR(
CefRenderWidgetHostViewOSR* rwhv)
: rwhv_(rwhv), id_(counter_++) {}
void CefTouchHandleDrawableOSR::SetEnabled(bool enabled) {
if (enabled == enabled_)
return;
enabled_ = enabled;
CefTouchHandleState touch_handle_state;
touch_handle_state.touch_handle_id = id_;
touch_handle_state.flags = CEF_THS_FLAG_ENABLED;
touch_handle_state.enabled = enabled_;
TouchHandleStateChanged(touch_handle_state);
}
void CefTouchHandleDrawableOSR::SetOrientation(
ui::TouchHandleOrientation orientation,
bool mirror_vertical,
bool mirror_horizontal) {
if (orientation == orientation_)
return;
orientation_ = orientation;
CefSize size;
auto browser = rwhv_->browser_impl();
auto handler = browser->GetClient()->GetRenderHandler();
handler->GetTouchHandleSize(
browser.get(), static_cast<cef_horizontal_alignment_t>(orientation_),
size);
const gfx::Size& image_size = gfx::Size(size.width, size.height);
int handle_width = image_size.width() + 2 * kSelectionHandlePadding;
int handle_height = image_size.height() + 2 * kSelectionHandlePadding;
relative_bounds_ =
gfx::RectF(-kSelectionHandlePadding,
kSelectionHandleVerticalVisualOffset - kSelectionHandlePadding,
handle_width, handle_height);
CefTouchHandleState touch_handle_state;
touch_handle_state.touch_handle_id = id_;
touch_handle_state.flags = CEF_THS_FLAG_ORIENTATION;
touch_handle_state.orientation =
static_cast<cef_horizontal_alignment_t>(orientation_);
touch_handle_state.mirror_vertical = mirror_vertical;
touch_handle_state.mirror_horizontal = mirror_horizontal;
TouchHandleStateChanged(touch_handle_state);
}
void CefTouchHandleDrawableOSR::SetOrigin(const gfx::PointF& position) {
if (position == origin_position_)
return;
origin_position_ = position;
CefTouchHandleState touch_handle_state;
touch_handle_state.touch_handle_id = id_;
touch_handle_state.flags = CEF_THS_FLAG_ORIGIN;
touch_handle_state.origin = {static_cast<int>(std::round(position.x())),
static_cast<int>(std::round(position.y()))};
TouchHandleStateChanged(touch_handle_state);
}
void CefTouchHandleDrawableOSR::SetAlpha(float alpha) {
if (alpha == alpha_)
return;
alpha_ = alpha;
CefTouchHandleState touch_handle_state;
touch_handle_state.touch_handle_id = id_;
touch_handle_state.flags = CEF_THS_FLAG_ALPHA;
touch_handle_state.alpha = alpha_;
TouchHandleStateChanged(touch_handle_state);
}
gfx::RectF CefTouchHandleDrawableOSR::GetVisibleBounds() const {
gfx::RectF bounds = relative_bounds_;
bounds.Offset(origin_position_.x(), origin_position_.y());
bounds.Inset(gfx::InsetsF::TLBR(
kSelectionHandlePadding,
kSelectionHandlePadding + kSelectionHandleVerticalVisualOffset,
kSelectionHandlePadding, kSelectionHandlePadding));
return bounds;
}
float CefTouchHandleDrawableOSR::GetDrawableHorizontalPaddingRatio() const {
return 0.0f;
}
void CefTouchHandleDrawableOSR::TouchHandleStateChanged(
const CefTouchHandleState& state) {
auto browser = rwhv_->browser_impl();
auto handler = browser->GetClient()->GetRenderHandler();
handler->OnTouchHandleStateChanged(browser.get(), state);
}

View File

@ -0,0 +1,59 @@
// Copyright 2022 The Chromium Embedded Framework Authors.
// Portions 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 CEF_LIBCEF_BROWSER_OSR_TOUCH_HANDLE_DRAWABLE_OSR_H_
#define CEF_LIBCEF_BROWSER_OSR_TOUCH_HANDLE_DRAWABLE_OSR_H_
#include "include/internal/cef_types_wrappers.h"
#include "base/memory/raw_ptr.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/touch_selection/touch_handle.h"
#include "ui/touch_selection/touch_handle_orientation.h"
#include "ui/touch_selection/ui_touch_selection_export.h"
class CefRenderWidgetHostViewOSR;
// Copied from TouchHandleDrawableAura.
class CefTouchHandleDrawableOSR : public ui::TouchHandleDrawable {
public:
explicit CefTouchHandleDrawableOSR(CefRenderWidgetHostViewOSR* rwhv);
CefTouchHandleDrawableOSR(const CefTouchHandleDrawableOSR&) = delete;
CefTouchHandleDrawableOSR& operator=(const CefTouchHandleDrawableOSR&) =
delete;
private:
// TouchHandleDrawable:
void SetEnabled(bool enabled) override;
void SetOrientation(ui::TouchHandleOrientation orientation,
bool mirror_vertical,
bool mirror_horizontal) override;
void SetOrigin(const gfx::PointF& position) override;
void SetAlpha(float alpha) override;
gfx::RectF GetVisibleBounds() const override;
float GetDrawableHorizontalPaddingRatio() const override;
// Pass the current touch handle state to the CefRenderHandler.
void TouchHandleStateChanged(const CefTouchHandleState& state);
raw_ptr<CefRenderWidgetHostViewOSR> rwhv_;
float alpha_ = 0.f;
static int counter_;
bool enabled_ = false;
int id_;
ui::TouchHandleOrientation orientation_ =
ui::TouchHandleOrientation::UNDEFINED;
// Origin position of the handle set via SetOrigin, in coordinate space of
// selection controller client (i.e. handle's parent).
gfx::PointF origin_position_;
// Handle bounds relative to the focal position.
gfx::RectF relative_bounds_ = gfx::RectF(0.0F, 0.0F, 24.0F, 24.0F);
};
#endif

View File

@ -0,0 +1,525 @@
// Copyright 2022 The Chromium Embedded Framework Authors.
// Portions 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 "libcef/browser/osr/touch_selection_controller_client_osr.h"
#include <cmath>
#include <set>
#include "libcef/browser/osr/render_widget_host_view_osr.h"
#include "libcef/browser/osr/touch_handle_drawable_osr.h"
#include "base/bind.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/context_menu_params.h"
#include "content/public/browser/render_view_host.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
#include "ui/base/pointer/touch_editing_controller.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
namespace {
// Delay before showing the quick menu, in milliseconds.
constexpr int kQuickMenuDelayInMs = 100;
constexpr cef_quick_menu_edit_state_flags_t kMenuCommands[] = {
QM_EDITFLAG_CAN_ELLIPSIS, QM_EDITFLAG_CAN_CUT, QM_EDITFLAG_CAN_COPY,
QM_EDITFLAG_CAN_PASTE};
constexpr int kInvalidCommandId = -1;
constexpr cef_event_flags_t kEmptyEventFlags =
static_cast<cef_event_flags_t>(0);
class CefRunQuickMenuCallbackImpl : public CefRunQuickMenuCallback {
public:
using Callback = base::OnceCallback<void(int, int)>;
explicit CefRunQuickMenuCallbackImpl(Callback callback)
: callback_(std::move(callback)) {}
CefRunQuickMenuCallbackImpl(const CefRunQuickMenuCallbackImpl&) = delete;
CefRunQuickMenuCallbackImpl& operator=(const CefRunQuickMenuCallbackImpl&) =
delete;
~CefRunQuickMenuCallbackImpl() {
if (!callback_.is_null()) {
// The callback is still pending. Cancel it now.
if (CEF_CURRENTLY_ON_UIT()) {
RunNow(std::move(callback_), kInvalidCommandId, kEmptyEventFlags);
} else {
CEF_POST_TASK(CEF_UIT,
base::BindOnce(&CefRunQuickMenuCallbackImpl::RunNow,
std::move(callback_), kInvalidCommandId,
kEmptyEventFlags));
}
}
}
void Continue(int command_id, cef_event_flags_t event_flags) override {
if (CEF_CURRENTLY_ON_UIT()) {
if (!callback_.is_null()) {
RunNow(std::move(callback_), command_id, event_flags);
}
} else {
CEF_POST_TASK(CEF_UIT,
base::BindOnce(&CefRunQuickMenuCallbackImpl::Continue, this,
command_id, event_flags));
}
}
void Cancel() override { Continue(kInvalidCommandId, kEmptyEventFlags); }
void Disconnect() { callback_.Reset(); }
private:
static void RunNow(Callback callback,
int command_id,
cef_event_flags_t event_flags) {
CEF_REQUIRE_UIT();
std::move(callback).Run(command_id, event_flags);
}
Callback callback_;
IMPLEMENT_REFCOUNTING(CefRunQuickMenuCallbackImpl);
};
} // namespace
CefTouchSelectionControllerClientOSR::CefTouchSelectionControllerClientOSR(
CefRenderWidgetHostViewOSR* rwhv)
: rwhv_(rwhv),
internal_client_(rwhv),
active_client_(&internal_client_),
active_menu_client_(this),
quick_menu_timer_(
FROM_HERE,
base::Milliseconds(kQuickMenuDelayInMs),
base::BindRepeating(
&CefTouchSelectionControllerClientOSR::ShowQuickMenu,
base::Unretained(this))),
weak_ptr_factory_(this) {
DCHECK(rwhv_);
}
CefTouchSelectionControllerClientOSR::~CefTouchSelectionControllerClientOSR() {
for (auto& observer : observers_)
observer.OnManagerWillDestroy(this);
}
void CefTouchSelectionControllerClientOSR::CloseQuickMenuAndHideHandles() {
CloseQuickMenu();
rwhv_->selection_controller()->HideAndDisallowShowingAutomatically();
}
void CefTouchSelectionControllerClientOSR::OnWindowMoved() {
UpdateQuickMenu();
}
void CefTouchSelectionControllerClientOSR::OnTouchDown() {
touch_down_ = true;
UpdateQuickMenu();
}
void CefTouchSelectionControllerClientOSR::OnTouchUp() {
touch_down_ = false;
UpdateQuickMenu();
}
void CefTouchSelectionControllerClientOSR::OnScrollStarted() {
scroll_in_progress_ = true;
rwhv_->selection_controller()->SetTemporarilyHidden(true);
UpdateQuickMenu();
}
void CefTouchSelectionControllerClientOSR::OnScrollCompleted() {
scroll_in_progress_ = false;
active_client_->DidScroll();
rwhv_->selection_controller()->SetTemporarilyHidden(false);
UpdateQuickMenu();
}
bool CefTouchSelectionControllerClientOSR::HandleContextMenu(
const content::ContextMenuParams& params) {
if ((params.source_type == ui::MENU_SOURCE_LONG_PRESS ||
params.source_type == ui::MENU_SOURCE_LONG_TAP) &&
params.is_editable && params.selection_text.empty() &&
IsQuickMenuAvailable()) {
quick_menu_requested_ = true;
UpdateQuickMenu();
return true;
}
const bool from_touch = params.source_type == ui::MENU_SOURCE_LONG_PRESS ||
params.source_type == ui::MENU_SOURCE_LONG_TAP ||
params.source_type == ui::MENU_SOURCE_TOUCH;
if (from_touch && !params.selection_text.empty())
return true;
rwhv_->selection_controller()->HideAndDisallowShowingAutomatically();
return false;
}
void CefTouchSelectionControllerClientOSR::DidStopFlinging() {
OnScrollCompleted();
}
void CefTouchSelectionControllerClientOSR::UpdateClientSelectionBounds(
const gfx::SelectionBound& start,
const gfx::SelectionBound& end) {
UpdateClientSelectionBounds(start, end, &internal_client_, this);
}
void CefTouchSelectionControllerClientOSR::UpdateClientSelectionBounds(
const gfx::SelectionBound& start,
const gfx::SelectionBound& end,
ui::TouchSelectionControllerClient* client,
ui::TouchSelectionMenuClient* menu_client) {
if (client != active_client_ &&
(start.type() == gfx::SelectionBound::EMPTY || !start.visible()) &&
(end.type() == gfx::SelectionBound::EMPTY || !end.visible()) &&
(manager_selection_start_.type() != gfx::SelectionBound::EMPTY ||
manager_selection_end_.type() != gfx::SelectionBound::EMPTY)) {
return;
}
active_client_ = client;
active_menu_client_ = menu_client;
manager_selection_start_ = start;
manager_selection_end_ = end;
// Notify TouchSelectionController if anything should change here. Only
// update if the client is different and not making a change to empty, or
// is the same client.
GetTouchSelectionController()->OnSelectionBoundsChanged(start, end);
}
void CefTouchSelectionControllerClientOSR::InvalidateClient(
ui::TouchSelectionControllerClient* client) {
DCHECK(client != &internal_client_);
if (client == active_client_) {
active_client_ = &internal_client_;
active_menu_client_ = this;
}
}
ui::TouchSelectionController*
CefTouchSelectionControllerClientOSR::GetTouchSelectionController() {
return rwhv_->selection_controller();
}
void CefTouchSelectionControllerClientOSR::AddObserver(
TouchSelectionControllerClientManager::Observer* observer) {
observers_.AddObserver(observer);
}
void CefTouchSelectionControllerClientOSR::RemoveObserver(
TouchSelectionControllerClientManager::Observer* observer) {
observers_.RemoveObserver(observer);
}
bool CefTouchSelectionControllerClientOSR::IsQuickMenuAvailable() const {
DCHECK(active_menu_client_);
const auto is_enabled = [this](cef_quick_menu_edit_state_flags_t command) {
return active_menu_client_->IsCommandIdEnabled(command);
};
return std::any_of(std::cbegin(kMenuCommands), std::cend(kMenuCommands),
is_enabled);
}
void CefTouchSelectionControllerClientOSR::CloseQuickMenu() {
if (!quick_menu_running_)
return;
quick_menu_running_ = false;
auto browser = rwhv_->browser_impl();
if (auto handler = browser->client()->GetContextMenuHandler()) {
handler->OnQuickMenuDismissed(browser.get(), browser->GetFocusedFrame());
}
}
void CefTouchSelectionControllerClientOSR::ShowQuickMenu() {
auto browser = rwhv_->browser_impl();
if (auto handler = browser->client()->GetContextMenuHandler()) {
gfx::RectF rect =
rwhv_->selection_controller()->GetVisibleRectBetweenBounds();
gfx::PointF origin = rect.origin();
gfx::PointF bottom_right = rect.bottom_right();
auto client_bounds = gfx::RectF(rwhv_->GetViewBounds());
origin.SetToMax(client_bounds.origin());
bottom_right.SetToMin(client_bounds.bottom_right());
if (origin.x() > bottom_right.x() || origin.y() > bottom_right.y())
return;
gfx::Vector2dF diagonal = bottom_right - origin;
gfx::SizeF size(diagonal.x(), diagonal.y());
int quickmenuflags = 0;
for (const auto& command : kMenuCommands) {
if (active_menu_client_->IsCommandIdEnabled(command)) {
quickmenuflags |= command;
}
}
CefRefPtr<CefRunQuickMenuCallbackImpl> callbackImpl(
new CefRunQuickMenuCallbackImpl(base::BindOnce(
&CefTouchSelectionControllerClientOSR::ExecuteCommand,
weak_ptr_factory_.GetWeakPtr())));
quick_menu_running_ = true;
if (!handler->RunQuickMenu(
browser, browser->GetFocusedFrame(),
{static_cast<int>(std::round(origin.x())),
static_cast<int>(std::round(origin.y()))},
{static_cast<int>(std::round(size.width())),
static_cast<int>(std::round(size.height()))},
static_cast<CefContextMenuHandler::QuickMenuEditStateFlags>(
quickmenuflags),
callbackImpl)) {
callbackImpl->Disconnect();
CloseQuickMenu();
}
}
}
void CefTouchSelectionControllerClientOSR::UpdateQuickMenu() {
// Hide the quick menu if there is any. This should happen even if the menu
// should be shown again, in order to update its location or content.
if (quick_menu_running_) {
CloseQuickMenu();
} else {
quick_menu_timer_.Stop();
}
// Start timer to show quick menu if necessary.
if (ShouldShowQuickMenu()) {
quick_menu_timer_.Reset();
}
}
bool CefTouchSelectionControllerClientOSR::SupportsAnimation() const {
return false;
}
bool CefTouchSelectionControllerClientOSR::InternalClient::SupportsAnimation()
const {
NOTREACHED();
return false;
}
void CefTouchSelectionControllerClientOSR::SetNeedsAnimate() {
NOTREACHED();
}
void CefTouchSelectionControllerClientOSR::InternalClient::SetNeedsAnimate() {
NOTREACHED();
}
void CefTouchSelectionControllerClientOSR::MoveCaret(
const gfx::PointF& position) {
active_client_->MoveCaret(position);
}
void CefTouchSelectionControllerClientOSR::InternalClient::MoveCaret(
const gfx::PointF& position) {
if (auto host_delegate = rwhv_->host()->delegate()) {
host_delegate->MoveCaret(gfx::ToRoundedPoint(position));
}
}
void CefTouchSelectionControllerClientOSR::MoveRangeSelectionExtent(
const gfx::PointF& extent) {
active_client_->MoveRangeSelectionExtent(extent);
}
void CefTouchSelectionControllerClientOSR::InternalClient::
MoveRangeSelectionExtent(const gfx::PointF& extent) {
if (auto host_delegate = rwhv_->host()->delegate()) {
host_delegate->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
}
}
void CefTouchSelectionControllerClientOSR::SelectBetweenCoordinates(
const gfx::PointF& base,
const gfx::PointF& extent) {
active_client_->SelectBetweenCoordinates(base, extent);
}
void CefTouchSelectionControllerClientOSR::InternalClient::
SelectBetweenCoordinates(const gfx::PointF& base,
const gfx::PointF& extent) {
if (auto host_delegate = rwhv_->host()->delegate()) {
host_delegate->SelectRange(gfx::ToRoundedPoint(base),
gfx::ToRoundedPoint(extent));
}
}
void CefTouchSelectionControllerClientOSR::OnSelectionEvent(
ui::SelectionEventType event) {
// This function (implicitly) uses active_menu_client_, so we don't go to the
// active view for this.
switch (event) {
case ui::SELECTION_HANDLES_SHOWN:
quick_menu_requested_ = true;
[[fallthrough]];
case ui::INSERTION_HANDLE_SHOWN:
UpdateQuickMenu();
break;
case ui::SELECTION_HANDLES_CLEARED:
case ui::INSERTION_HANDLE_CLEARED:
quick_menu_requested_ = false;
UpdateQuickMenu();
break;
case ui::SELECTION_HANDLE_DRAG_STARTED:
case ui::INSERTION_HANDLE_DRAG_STARTED:
handle_drag_in_progress_ = true;
UpdateQuickMenu();
break;
case ui::SELECTION_HANDLE_DRAG_STOPPED:
case ui::INSERTION_HANDLE_DRAG_STOPPED:
handle_drag_in_progress_ = false;
UpdateQuickMenu();
break;
case ui::SELECTION_HANDLES_MOVED:
case ui::INSERTION_HANDLE_MOVED:
UpdateQuickMenu();
break;
case ui::INSERTION_HANDLE_TAPPED:
quick_menu_requested_ = !quick_menu_requested_;
UpdateQuickMenu();
break;
}
}
void CefTouchSelectionControllerClientOSR::InternalClient::OnSelectionEvent(
ui::SelectionEventType event) {
NOTREACHED();
}
void CefTouchSelectionControllerClientOSR::OnDragUpdate(
const ui::TouchSelectionDraggable::Type type,
const gfx::PointF& position) {}
void CefTouchSelectionControllerClientOSR::InternalClient::OnDragUpdate(
const ui::TouchSelectionDraggable::Type type,
const gfx::PointF& position) {
NOTREACHED();
}
std::unique_ptr<ui::TouchHandleDrawable>
CefTouchSelectionControllerClientOSR::CreateDrawable() {
return std::make_unique<CefTouchHandleDrawableOSR>(rwhv_);
}
void CefTouchSelectionControllerClientOSR::DidScroll() {}
std::unique_ptr<ui::TouchHandleDrawable>
CefTouchSelectionControllerClientOSR::InternalClient::CreateDrawable() {
NOTREACHED();
return nullptr;
}
void CefTouchSelectionControllerClientOSR::InternalClient::DidScroll() {
NOTREACHED();
}
bool CefTouchSelectionControllerClientOSR::IsCommandIdEnabled(
int command_id) const {
bool editable = rwhv_->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
bool readable = rwhv_->GetTextInputType() != ui::TEXT_INPUT_TYPE_PASSWORD;
bool has_selection = !rwhv_->GetSelectedText().empty();
switch (command_id) {
case QM_EDITFLAG_CAN_ELLIPSIS:
return true; // Always allowed to show the ellipsis button.
case QM_EDITFLAG_CAN_CUT:
return editable && readable && has_selection;
case QM_EDITFLAG_CAN_COPY:
return readable && has_selection;
case QM_EDITFLAG_CAN_PASTE: {
std::u16string result;
ui::DataTransferEndpoint data_dst = ui::DataTransferEndpoint(
ui::EndpointType::kDefault, /*notify_if_restricted=*/false);
ui::Clipboard::GetForCurrentThread()->ReadText(
ui::ClipboardBuffer::kCopyPaste, &data_dst, &result);
return editable && !result.empty();
}
default:
return false;
}
}
void CefTouchSelectionControllerClientOSR::ExecuteCommand(int command_id,
int event_flags) {
if (command_id == kInvalidCommandId) {
return;
}
if (command_id != QM_EDITFLAG_CAN_ELLIPSIS) {
rwhv_->selection_controller()->HideAndDisallowShowingAutomatically();
}
content::RenderWidgetHostDelegate* host_delegate = rwhv_->host()->delegate();
if (!host_delegate) {
return;
}
auto browser = rwhv_->browser_impl();
if (auto handler = browser->client()->GetContextMenuHandler()) {
if (handler->OnQuickMenuCommand(
browser.get(), browser->GetFocusedFrame(), command_id,
static_cast<cef_event_flags_t>(event_flags))) {
return;
}
}
switch (command_id) {
case QM_EDITFLAG_CAN_CUT:
host_delegate->Cut();
break;
case QM_EDITFLAG_CAN_COPY:
host_delegate->Copy();
break;
case QM_EDITFLAG_CAN_PASTE:
host_delegate->Paste();
break;
case QM_EDITFLAG_CAN_ELLIPSIS:
CloseQuickMenu();
RunContextMenu();
break;
default:
// Invalid command, do nothing.
// Also reached when callback is destroyed/cancelled.
break;
}
}
void CefTouchSelectionControllerClientOSR::RunContextMenu() {
const gfx::RectF anchor_rect =
rwhv_->selection_controller()->GetVisibleRectBetweenBounds();
const gfx::PointF anchor_point =
gfx::PointF(anchor_rect.CenterPoint().x(), anchor_rect.y());
rwhv_->host()->ShowContextMenuAtPoint(gfx::ToRoundedPoint(anchor_point),
ui::MENU_SOURCE_TOUCH_EDIT_MENU);
// Hide selection handles after getting rect-between-bounds from touch
// selection controller; otherwise, rect would be empty and the above
// calculations would be invalid.
rwhv_->selection_controller()->HideAndDisallowShowingAutomatically();
}
bool CefTouchSelectionControllerClientOSR::ShouldShowQuickMenu() {
return quick_menu_requested_ && !touch_down_ && !scroll_in_progress_ &&
!handle_drag_in_progress_ && IsQuickMenuAvailable();
}
std::u16string CefTouchSelectionControllerClientOSR::GetSelectedText() {
return rwhv_->GetSelectedText();
}

View File

@ -0,0 +1,156 @@
// Copyright 2022 The Chromium Embedded Framework Authors.
// Portions 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 CEF_LIBCEF_BROWSER_OSR_TOUCH_SELECTION_CONTROLLER_CLIENT_OSR_H_
#define CEF_LIBCEF_BROWSER_OSR_TOUCH_SELECTION_CONTROLLER_CLIENT_OSR_H_
#include <memory>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/timer/timer.h"
#include "content/common/content_export.h"
#include "content/public/browser/touch_selection_controller_client_manager.h"
#include "ui/touch_selection/touch_selection_controller.h"
#include "ui/touch_selection/touch_selection_menu_runner.h"
namespace content {
struct ContextMenuParams;
}
class CefRenderWidgetHostViewOSR;
// An implementation of |TouchSelectionControllerClient| to be used in OSR's
// implementation of touch selection for contents.
// Copied from TouchSelectionControllerClientAura.
class CefTouchSelectionControllerClientOSR
: public ui::TouchSelectionControllerClient,
public ui::TouchSelectionMenuClient,
public content::TouchSelectionControllerClientManager {
public:
explicit CefTouchSelectionControllerClientOSR(
CefRenderWidgetHostViewOSR* rwhv);
CefTouchSelectionControllerClientOSR(
const CefTouchSelectionControllerClientOSR&) = delete;
CefTouchSelectionControllerClientOSR& operator=(
const CefTouchSelectionControllerClientOSR&) = delete;
~CefTouchSelectionControllerClientOSR() override;
void CloseQuickMenuAndHideHandles();
void OnWindowMoved();
// Called on first touch down/last touch up to hide/show the quick menu.
void OnTouchDown();
void OnTouchUp();
// Called when touch scroll starts/completes to hide/show touch handles and
// the quick menu.
void OnScrollStarted();
void OnScrollCompleted();
// Gives an opportunity to the client to handle context menu request and show
// the quick menu instead, if appropriate. Returns |true| to indicate that no
// further handling is needed.
// TODO(mohsen): This is to match Chrome on Android behavior. However, it is
// better not to send context menu request from the renderer in this case and
// instead decide in the client about showing the quick menu in response to
// selection events. (http://crbug.com/548245)
bool HandleContextMenu(const content::ContextMenuParams& params);
void UpdateClientSelectionBounds(const gfx::SelectionBound& start,
const gfx::SelectionBound& end);
// TouchSelectionControllerClientManager.
void DidStopFlinging() override;
void UpdateClientSelectionBounds(
const gfx::SelectionBound& start,
const gfx::SelectionBound& end,
ui::TouchSelectionControllerClient* client,
ui::TouchSelectionMenuClient* menu_client) override;
void InvalidateClient(ui::TouchSelectionControllerClient* client) override;
ui::TouchSelectionController* GetTouchSelectionController() override;
void AddObserver(
TouchSelectionControllerClientManager::Observer* observer) override;
void RemoveObserver(
TouchSelectionControllerClientManager::Observer* observer) override;
private:
class EnvEventObserver;
bool IsQuickMenuAvailable() const;
void CloseQuickMenu();
void ShowQuickMenu();
void UpdateQuickMenu();
// ui::TouchSelectionControllerClient:
bool SupportsAnimation() const override;
void SetNeedsAnimate() override;
void MoveCaret(const gfx::PointF& position) override;
void MoveRangeSelectionExtent(const gfx::PointF& extent) override;
void SelectBetweenCoordinates(const gfx::PointF& base,
const gfx::PointF& extent) override;
void OnSelectionEvent(ui::SelectionEventType event) override;
void OnDragUpdate(const ui::TouchSelectionDraggable::Type type,
const gfx::PointF& position) override;
std::unique_ptr<ui::TouchHandleDrawable> CreateDrawable() override;
void DidScroll() override;
// ui::TouchSelectionMenuClient:
bool IsCommandIdEnabled(int command_id) const override;
void ExecuteCommand(int command_id, int event_flags) override;
void RunContextMenu() override;
bool ShouldShowQuickMenu() override;
std::u16string GetSelectedText() override;
// Not owned, non-null for the lifetime of this object.
raw_ptr<CefRenderWidgetHostViewOSR> rwhv_;
class InternalClient final : public ui::TouchSelectionControllerClient {
public:
explicit InternalClient(CefRenderWidgetHostViewOSR* rwhv) : rwhv_(rwhv) {}
~InternalClient() final {}
bool SupportsAnimation() const final;
void SetNeedsAnimate() final;
void MoveCaret(const gfx::PointF& position) final;
void MoveRangeSelectionExtent(const gfx::PointF& extent) final;
void SelectBetweenCoordinates(const gfx::PointF& base,
const gfx::PointF& extent) final;
void OnSelectionEvent(ui::SelectionEventType event) final;
void OnDragUpdate(const ui::TouchSelectionDraggable::Type type,
const gfx::PointF& position) final;
std::unique_ptr<ui::TouchHandleDrawable> CreateDrawable() final;
void DidScroll() override;
private:
raw_ptr<CefRenderWidgetHostViewOSR> rwhv_;
} internal_client_;
// Keep track of which client interface to use.
raw_ptr<TouchSelectionControllerClient> active_client_;
raw_ptr<TouchSelectionMenuClient> active_menu_client_;
gfx::SelectionBound manager_selection_start_;
gfx::SelectionBound manager_selection_end_;
base::ObserverList<TouchSelectionControllerClientManager::Observer>
observers_;
base::RetainingOneShotTimer quick_menu_timer_;
bool quick_menu_requested_ = false;
bool quick_menu_running_ = false;
bool touch_down_ = false;
bool scroll_in_progress_ = false;
bool handle_drag_in_progress_ = false;
base::WeakPtrFactory<CefTouchSelectionControllerClientOSR> weak_ptr_factory_;
};
#endif

View File

@ -7,6 +7,7 @@
#include "libcef/browser/alloy/alloy_browser_host_impl.h"
#include "libcef/browser/osr/render_widget_host_view_osr.h"
#include "libcef/browser/osr/touch_selection_controller_client_osr.h"
#include "libcef/common/drag_data_impl.h"
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
@ -148,6 +149,22 @@ bool CefWebContentsViewOSR::CloseTabAfterEventTrackingIfNeeded() {
}
#endif // BUILDFLAG(IS_MAC)
void CefWebContentsViewOSR::ShowContextMenu(
content::RenderFrameHost& render_frame_host,
const content::ContextMenuParams& params) {
auto selection_controller_client = GetSelectionControllerClient();
if (selection_controller_client &&
selection_controller_client->HandleContextMenu(params)) {
// Context menu display, if any, will be handled via
// AlloyWebContentsViewDelegate::ShowContextMenu.
return;
}
if (auto browser = GetBrowser()) {
browser->ShowContextMenu(params);
}
}
void CefWebContentsViewOSR::StartDragging(
const content::DropData& drop_data,
blink::DragOperationsMask allowed_ops,
@ -186,3 +203,9 @@ AlloyBrowserHostImpl* CefWebContentsViewOSR::GetBrowser() const {
return view->browser_impl().get();
return nullptr;
}
CefTouchSelectionControllerClientOSR*
CefWebContentsViewOSR::GetSelectionControllerClient() const {
CefRenderWidgetHostViewOSR* view = GetView();
return view ? view->selection_controller_client() : nullptr;
}

View File

@ -18,6 +18,7 @@ class WebContentsViewDelegate;
class AlloyBrowserHostImpl;
class CefRenderWidgetHostViewOSR;
class CefTouchSelectionControllerClientOSR;
// An implementation of WebContentsView for off-screen rendering.
class CefWebContentsViewOSR : public content::WebContentsView,
@ -66,6 +67,8 @@ class CefWebContentsViewOSR : public content::WebContentsView,
#endif
// RenderViewHostDelegateView methods.
void ShowContextMenu(content::RenderFrameHost& render_frame_host,
const content::ContextMenuParams& params) override;
void StartDragging(const content::DropData& drop_data,
blink::DragOperationsMask allowed_ops,
const gfx::ImageSkia& image,
@ -82,6 +85,7 @@ class CefWebContentsViewOSR : public content::WebContentsView,
private:
CefRenderWidgetHostViewOSR* GetView() const;
AlloyBrowserHostImpl* GetBrowser() const;
CefTouchSelectionControllerClientOSR* GetSelectionControllerClient() const;
const SkColor background_color_;
const bool use_shared_texture_;

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=a689271e9c27cfd0d6f6fadb8bb624898f165934$
// $hash=1531579b642c3009765e7ef273887c423e552b36$
//
#include "libcef_dll/cpptoc/context_menu_handler_cpptoc.h"
@ -18,6 +18,7 @@
#include "libcef_dll/ctocpp/frame_ctocpp.h"
#include "libcef_dll/ctocpp/menu_model_ctocpp.h"
#include "libcef_dll/ctocpp/run_context_menu_callback_ctocpp.h"
#include "libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.h"
#include "libcef_dll/shutdown_checker.h"
namespace {
@ -167,6 +168,112 @@ void CEF_CALLBACK context_menu_handler_on_context_menu_dismissed(
CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame));
}
int CEF_CALLBACK context_menu_handler_run_quick_menu(
struct _cef_context_menu_handler_t* self,
cef_browser_t* browser,
struct _cef_frame_t* frame,
const cef_point_t* location,
const cef_size_t* size,
cef_quick_menu_edit_state_flags_t edit_state_flags,
cef_run_quick_menu_callback_t* callback) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return 0;
// Verify param: frame; type: refptr_diff
DCHECK(frame);
if (!frame)
return 0;
// Verify param: location; type: simple_byref_const
DCHECK(location);
if (!location)
return 0;
// Verify param: size; type: simple_byref_const
DCHECK(size);
if (!size)
return 0;
// Verify param: callback; type: refptr_diff
DCHECK(callback);
if (!callback)
return 0;
// Translate param: location; type: simple_byref_const
CefPoint locationVal = location ? *location : CefPoint();
// Translate param: size; type: simple_byref_const
CefSize sizeVal = size ? *size : CefSize();
// Execute
bool _retval = CefContextMenuHandlerCppToC::Get(self)->RunQuickMenu(
CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame), locationVal,
sizeVal, edit_state_flags, CefRunQuickMenuCallbackCToCpp::Wrap(callback));
// Return type: bool
return _retval;
}
int CEF_CALLBACK context_menu_handler_on_quick_menu_command(
struct _cef_context_menu_handler_t* self,
cef_browser_t* browser,
struct _cef_frame_t* frame,
int command_id,
cef_event_flags_t event_flags) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return 0;
// Verify param: frame; type: refptr_diff
DCHECK(frame);
if (!frame)
return 0;
// Execute
bool _retval = CefContextMenuHandlerCppToC::Get(self)->OnQuickMenuCommand(
CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame), command_id,
event_flags);
// Return type: bool
return _retval;
}
void CEF_CALLBACK context_menu_handler_on_quick_menu_dismissed(
struct _cef_context_menu_handler_t* self,
cef_browser_t* browser,
struct _cef_frame_t* frame) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return;
// Verify param: frame; type: refptr_diff
DCHECK(frame);
if (!frame)
return;
// Execute
CefContextMenuHandlerCppToC::Get(self)->OnQuickMenuDismissed(
CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame));
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
@ -179,6 +286,11 @@ CefContextMenuHandlerCppToC::CefContextMenuHandlerCppToC() {
context_menu_handler_on_context_menu_command;
GetStruct()->on_context_menu_dismissed =
context_menu_handler_on_context_menu_dismissed;
GetStruct()->run_quick_menu = context_menu_handler_run_quick_menu;
GetStruct()->on_quick_menu_command =
context_menu_handler_on_quick_menu_command;
GetStruct()->on_quick_menu_dismissed =
context_menu_handler_on_quick_menu_dismissed;
}
// DESTRUCTOR - Do not edit by hand.

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=17fc7e8f42e6c518405f2aba5e849c98bf8122ce$
// $hash=6671ca3d639065c49adfc8ceac4c58833344d558$
//
#include "libcef_dll/cpptoc/render_handler_cpptoc.h"
@ -329,6 +329,73 @@ render_handler_on_accelerated_paint(struct _cef_render_handler_t* self,
CefBrowserCToCpp::Wrap(browser), type, dirtyRectsList, shared_handle);
}
void CEF_CALLBACK
render_handler_get_touch_handle_size(struct _cef_render_handler_t* self,
cef_browser_t* browser,
cef_horizontal_alignment_t orientation,
cef_size_t* size) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return;
// Verify param: size; type: simple_byref
DCHECK(size);
if (!size)
return;
// Translate param: size; type: simple_byref
CefSize sizeVal = size ? *size : CefSize();
// Execute
CefRenderHandlerCppToC::Get(self)->GetTouchHandleSize(
CefBrowserCToCpp::Wrap(browser), orientation, sizeVal);
// Restore param: size; type: simple_byref
if (size)
*size = sizeVal;
}
void CEF_CALLBACK render_handler_on_touch_handle_state_changed(
struct _cef_render_handler_t* self,
cef_browser_t* browser,
const struct _cef_touch_handle_state_t* state) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return;
// Verify param: state; type: struct_byref_const
DCHECK(state);
if (!state)
return;
if (!template_util::has_valid_size(state)) {
NOTREACHED() << "invalid state->[base.]size";
return;
}
// Translate param: state; type: struct_byref_const
CefTouchHandleState stateObj;
if (state)
stateObj.Set(*state, false);
// Execute
CefRenderHandlerCppToC::Get(self)->OnTouchHandleStateChanged(
CefBrowserCToCpp::Wrap(browser), stateObj);
}
int CEF_CALLBACK
render_handler_start_dragging(struct _cef_render_handler_t* self,
cef_browser_t* browser,
@ -509,6 +576,9 @@ CefRenderHandlerCppToC::CefRenderHandlerCppToC() {
GetStruct()->on_popup_size = render_handler_on_popup_size;
GetStruct()->on_paint = render_handler_on_paint;
GetStruct()->on_accelerated_paint = render_handler_on_accelerated_paint;
GetStruct()->get_touch_handle_size = render_handler_get_touch_handle_size;
GetStruct()->on_touch_handle_state_changed =
render_handler_on_touch_handle_state_changed;
GetStruct()->start_dragging = render_handler_start_dragging;
GetStruct()->update_drag_cursor = render_handler_update_drag_cursor;
GetStruct()->on_scroll_offset_changed =

View File

@ -0,0 +1,83 @@
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=51e850e2768a6ec8ec7d764830d27138334d82ac$
//
#include "libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.h"
#include "libcef_dll/shutdown_checker.h"
namespace {
// MEMBER FUNCTIONS - Body may be edited by hand.
void CEF_CALLBACK
run_quick_menu_callback_cont(struct _cef_run_quick_menu_callback_t* self,
int command_id,
cef_event_flags_t event_flags) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefRunQuickMenuCallbackCppToC::Get(self)->Continue(command_id, event_flags);
}
void CEF_CALLBACK
run_quick_menu_callback_cancel(struct _cef_run_quick_menu_callback_t* self) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefRunQuickMenuCallbackCppToC::Get(self)->Cancel();
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
CefRunQuickMenuCallbackCppToC::CefRunQuickMenuCallbackCppToC() {
GetStruct()->cont = run_quick_menu_callback_cont;
GetStruct()->cancel = run_quick_menu_callback_cancel;
}
// DESTRUCTOR - Do not edit by hand.
CefRunQuickMenuCallbackCppToC::~CefRunQuickMenuCallbackCppToC() {
shutdown_checker::AssertNotShutdown();
}
template <>
CefRefPtr<CefRunQuickMenuCallback> CefCppToCRefCounted<
CefRunQuickMenuCallbackCppToC,
CefRunQuickMenuCallback,
cef_run_quick_menu_callback_t>::UnwrapDerived(CefWrapperType type,
cef_run_quick_menu_callback_t*
s) {
NOTREACHED() << "Unexpected class type: " << type;
return nullptr;
}
template <>
CefWrapperType
CefCppToCRefCounted<CefRunQuickMenuCallbackCppToC,
CefRunQuickMenuCallback,
cef_run_quick_menu_callback_t>::kWrapperType =
WT_RUN_QUICK_MENU_CALLBACK;

View File

@ -0,0 +1,38 @@
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=b641fe8119fa5ab3e3a635105ca25985dec40bd0$
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_RUN_QUICK_MENU_CALLBACK_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_RUN_QUICK_MENU_CALLBACK_CPPTOC_H_
#pragma once
#if !defined(BUILDING_CEF_SHARED)
#error This file can be included DLL-side only
#endif
#include "include/capi/cef_context_menu_handler_capi.h"
#include "include/cef_context_menu_handler.h"
#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed DLL-side only.
class CefRunQuickMenuCallbackCppToC
: public CefCppToCRefCounted<CefRunQuickMenuCallbackCppToC,
CefRunQuickMenuCallback,
cef_run_quick_menu_callback_t> {
public:
CefRunQuickMenuCallbackCppToC();
virtual ~CefRunQuickMenuCallbackCppToC();
};
#endif // CEF_LIBCEF_DLL_CPPTOC_RUN_QUICK_MENU_CALLBACK_CPPTOC_H_

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=7b91234844f040546245a09f4724142efdf929ff$
// $hash=7f280440c705606151f40b5c50d62483e75ab0ba$
//
#include "libcef_dll/ctocpp/context_menu_handler_ctocpp.h"
@ -18,6 +18,7 @@
#include "libcef_dll/cpptoc/frame_cpptoc.h"
#include "libcef_dll/cpptoc/menu_model_cpptoc.h"
#include "libcef_dll/cpptoc/run_context_menu_callback_cpptoc.h"
#include "libcef_dll/cpptoc/run_quick_menu_callback_cpptoc.h"
#include "libcef_dll/shutdown_checker.h"
// VIRTUAL METHODS - Body may be edited by hand.
@ -169,6 +170,103 @@ void CefContextMenuHandlerCToCpp::OnContextMenuDismissed(
CefFrameCppToC::Wrap(frame));
}
NO_SANITIZE("cfi-icall")
bool CefContextMenuHandlerCToCpp::RunQuickMenu(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefPoint& location,
const CefSize& size,
QuickMenuEditStateFlags edit_state_flags,
CefRefPtr<CefRunQuickMenuCallback> callback) {
shutdown_checker::AssertNotShutdown();
cef_context_menu_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, run_quick_menu))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return false;
// Verify param: frame; type: refptr_diff
DCHECK(frame.get());
if (!frame.get())
return false;
// Verify param: callback; type: refptr_diff
DCHECK(callback.get());
if (!callback.get())
return false;
// Execute
int _retval = _struct->run_quick_menu(
_struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame),
&location, &size, edit_state_flags,
CefRunQuickMenuCallbackCppToC::Wrap(callback));
// Return type: bool
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall")
bool CefContextMenuHandlerCToCpp::OnQuickMenuCommand(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int command_id,
EventFlags event_flags) {
shutdown_checker::AssertNotShutdown();
cef_context_menu_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_quick_menu_command))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return false;
// Verify param: frame; type: refptr_diff
DCHECK(frame.get());
if (!frame.get())
return false;
// Execute
int _retval = _struct->on_quick_menu_command(
_struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame),
command_id, event_flags);
// Return type: bool
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall")
void CefContextMenuHandlerCToCpp::OnQuickMenuDismissed(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame) {
shutdown_checker::AssertNotShutdown();
cef_context_menu_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_quick_menu_dismissed))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return;
// Verify param: frame; type: refptr_diff
DCHECK(frame.get());
if (!frame.get())
return;
// Execute
_struct->on_quick_menu_dismissed(_struct, CefBrowserCppToC::Wrap(browser),
CefFrameCppToC::Wrap(frame));
}
// CONSTRUCTOR - Do not edit by hand.
CefContextMenuHandlerCToCpp::CefContextMenuHandlerCToCpp() {}

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=3dba1df692cc69ba3aab91b989cceb9a7d363858$
// $hash=49b3f96c2cd6e36844e0edd0737e4d9b3e79e625$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_CONTEXT_MENU_HANDLER_CTOCPP_H_
@ -51,6 +51,18 @@ class CefContextMenuHandlerCToCpp
EventFlags event_flags) override;
void OnContextMenuDismissed(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame) override;
bool RunQuickMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefPoint& location,
const CefSize& size,
QuickMenuEditStateFlags edit_state_flags,
CefRefPtr<CefRunQuickMenuCallback> callback) override;
bool OnQuickMenuCommand(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int command_id,
EventFlags event_flags) override;
void OnQuickMenuDismissed(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame) override;
};
#endif // CEF_LIBCEF_DLL_CTOCPP_CONTEXT_MENU_HANDLER_CTOCPP_H_

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=8d30c4f8cf47bac2f9f728de876abb759b38041f$
// $hash=6d01f6d66ba97afef1d9c21ab31115e91bc134c6$
//
#include "libcef_dll/ctocpp/render_handler_ctocpp.h"
@ -265,6 +265,51 @@ void CefRenderHandlerCToCpp::OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,
delete[] dirtyRectsList;
}
NO_SANITIZE("cfi-icall")
void CefRenderHandlerCToCpp::GetTouchHandleSize(
CefRefPtr<CefBrowser> browser,
cef_horizontal_alignment_t orientation,
CefSize& size) {
shutdown_checker::AssertNotShutdown();
cef_render_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_touch_handle_size))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return;
// Execute
_struct->get_touch_handle_size(_struct, CefBrowserCppToC::Wrap(browser),
orientation, &size);
}
NO_SANITIZE("cfi-icall")
void CefRenderHandlerCToCpp::OnTouchHandleStateChanged(
CefRefPtr<CefBrowser> browser,
const CefTouchHandleState& state) {
shutdown_checker::AssertNotShutdown();
cef_render_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_touch_handle_state_changed))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return;
// Execute
_struct->on_touch_handle_state_changed(
_struct, CefBrowserCppToC::Wrap(browser), &state);
}
NO_SANITIZE("cfi-icall")
bool CefRenderHandlerCToCpp::StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=de430ab07ee4a1ba234c17ae560813a0aeeef5da$
// $hash=f33de5a4c65bc08dcc3161a3b862be2b1fa95546$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_RENDER_HANDLER_CTOCPP_H_
@ -57,6 +57,11 @@ class CefRenderHandlerCToCpp
PaintElementType type,
const RectList& dirtyRects,
void* shared_handle) override;
void GetTouchHandleSize(CefRefPtr<CefBrowser> browser,
cef_horizontal_alignment_t orientation,
CefSize& size) override;
void OnTouchHandleStateChanged(CefRefPtr<CefBrowser> browser,
const CefTouchHandleState& state) override;
bool StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
DragOperationsMask allowed_ops,

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=f77743d285768c21bd89b9955d47176ef52f1e1a$
// $hash=427fe84b74eec6346d7da729cba2fdf52d1c0fd7$
//
#include "libcef_dll/ctocpp/run_context_menu_callback_ctocpp.h"
@ -19,7 +19,7 @@
NO_SANITIZE("cfi-icall")
void CefRunContextMenuCallbackCToCpp::Continue(int command_id,
EventFlags event_flags) {
cef_event_flags_t event_flags) {
shutdown_checker::AssertNotShutdown();
cef_run_context_menu_callback_t* _struct = GetStruct();

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=9b70c0c42b514b6d44f4fff612eaf4d3fb62ef06$
// $hash=ffa640e35d08dd0f9b8c0ea291db190947826915$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_RUN_CONTEXT_MENU_CALLBACK_CTOCPP_H_
@ -35,7 +35,7 @@ class CefRunContextMenuCallbackCToCpp
virtual ~CefRunContextMenuCallbackCToCpp();
// CefRunContextMenuCallback methods.
void Continue(int command_id, EventFlags event_flags) override;
void Continue(int command_id, cef_event_flags_t event_flags) override;
void Cancel() override;
};

View File

@ -0,0 +1,73 @@
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=c0d516016a14eeed0c73bde99e2495ae691c2326$
//
#include "libcef_dll/ctocpp/run_quick_menu_callback_ctocpp.h"
#include "libcef_dll/shutdown_checker.h"
// VIRTUAL METHODS - Body may be edited by hand.
NO_SANITIZE("cfi-icall")
void CefRunQuickMenuCallbackCToCpp::Continue(int command_id,
cef_event_flags_t event_flags) {
shutdown_checker::AssertNotShutdown();
cef_run_quick_menu_callback_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, cont))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
_struct->cont(_struct, command_id, event_flags);
}
NO_SANITIZE("cfi-icall") void CefRunQuickMenuCallbackCToCpp::Cancel() {
shutdown_checker::AssertNotShutdown();
cef_run_quick_menu_callback_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, cancel))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
_struct->cancel(_struct);
}
// CONSTRUCTOR - Do not edit by hand.
CefRunQuickMenuCallbackCToCpp::CefRunQuickMenuCallbackCToCpp() {}
// DESTRUCTOR - Do not edit by hand.
CefRunQuickMenuCallbackCToCpp::~CefRunQuickMenuCallbackCToCpp() {
shutdown_checker::AssertNotShutdown();
}
template <>
cef_run_quick_menu_callback_t* CefCToCppRefCounted<
CefRunQuickMenuCallbackCToCpp,
CefRunQuickMenuCallback,
cef_run_quick_menu_callback_t>::UnwrapDerived(CefWrapperType type,
CefRunQuickMenuCallback* c) {
NOTREACHED() << "Unexpected class type: " << type;
return nullptr;
}
template <>
CefWrapperType
CefCToCppRefCounted<CefRunQuickMenuCallbackCToCpp,
CefRunQuickMenuCallback,
cef_run_quick_menu_callback_t>::kWrapperType =
WT_RUN_QUICK_MENU_CALLBACK;

View File

@ -0,0 +1,42 @@
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=519977d5976a7486e0fda9d9b9b0d6fd0fd9b44f$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_RUN_QUICK_MENU_CALLBACK_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_RUN_QUICK_MENU_CALLBACK_CTOCPP_H_
#pragma once
#if !defined(WRAPPING_CEF_SHARED)
#error This file can be included wrapper-side only
#endif
#include "include/capi/cef_context_menu_handler_capi.h"
#include "include/cef_context_menu_handler.h"
#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed wrapper-side only.
class CefRunQuickMenuCallbackCToCpp
: public CefCToCppRefCounted<CefRunQuickMenuCallbackCToCpp,
CefRunQuickMenuCallback,
cef_run_quick_menu_callback_t> {
public:
CefRunQuickMenuCallbackCToCpp();
virtual ~CefRunQuickMenuCallbackCToCpp();
// CefRunQuickMenuCallback methods.
void Continue(int command_id, cef_event_flags_t event_flags) override;
void Cancel() override;
};
#endif // CEF_LIBCEF_DLL_CTOCPP_RUN_QUICK_MENU_CALLBACK_CTOCPP_H_

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=7a247cc26167ddbc4fbe23ed939fa9e39c48a09c$
// $hash=98d509772d772e85d47d53e3df21f7317799c19e$
//
#ifndef CEF_LIBCEF_DLL_WRAPPER_TYPES_H_
@ -121,6 +121,7 @@ enum CefWrapperType {
WT_RESPONSE_FILTER,
WT_RUN_CONTEXT_MENU_CALLBACK,
WT_RUN_FILE_DIALOG_CALLBACK,
WT_RUN_QUICK_MENU_CALLBACK,
WT_SSLINFO,
WT_SSLSTATUS,
WT_SCHEME_HANDLER_FACTORY,

View File

@ -27,12 +27,10 @@ namespace {
const char kTestUrl[] = "http://tests/osrtest";
// this html should render on a 600 x 400 window with a little vertical
// offset with scrollbar.
// default osr widget size
// Must be both large enough for the drag/drop region to be visible and small
// enough for a little vertical offset with scrollbar.
const int kOsrWidth = 600;
const int kOsrHeight = 400;
const int kOsrHeight = 450;
// bounding client rects for edit box and navigate button
#if defined(OS_WIN)
@ -48,6 +46,10 @@ const CefRect kExpandedSelectRect(462, 42, 79, 334);
// word to be written into edit box
const char kKeyTestWord[] = "done";
constexpr uint32_t kAllTouchHandleFlags =
(CEF_THS_FLAG_ENABLED | CEF_THS_FLAG_ORIENTATION | CEF_THS_FLAG_ORIGIN |
CEF_THS_FLAG_ALPHA);
#if defined(OS_LINUX)
// From ui/events/keycodes/keyboard_codes_posix.h
@ -126,6 +128,9 @@ enum OSRTestType {
// Right click will trigger a context menu, and on destroying the test, it
// should not crash
OSR_TEST_CONTEXT_MENU,
// In certain scenarios, the quick menu should be shown instead of the context
// menu
OSR_TEST_QUICK_MENU,
// clicking on dropdown box, PET_POPUP OnPaint is triggered
OSR_TEST_POPUP_PAINT,
// clicking on dropdown box, a popup will show up
@ -609,6 +614,16 @@ class OSRTestHandler : public RoutingTestHandler,
1);
}
break;
case OSR_TEST_QUICK_MENU:
if (StartTest()) {
CefTouchEvent touch_event_pressed;
touch_event_pressed.type = CEF_TET_PRESSED;
const CefRect& expected_rect = GetElementBounds("quickmenu");
touch_event_pressed.x = MiddleX(expected_rect);
touch_event_pressed.y = MiddleY(expected_rect);
browser->GetHost()->SendTouchEvent(touch_event_pressed);
}
break;
case OSR_TEST_CLICK_LEFT:
if (StartTest()) {
CefMouseEvent mouse_event;
@ -856,6 +871,10 @@ class OSRTestHandler : public RoutingTestHandler,
mouse_event.x = MiddleX(dragdiv);
mouse_event.y = MiddleY(dragdiv);
mouse_event.modifiers = 0;
// The div drag point must be visible.
EXPECT_LT(mouse_event.y, kOsrHeight);
browser->GetHost()->SendMouseMoveEvent(mouse_event, false);
// click on the element to drag
mouse_event.modifiers = EVENTFLAG_LEFT_MOUSE_BUTTON;
@ -1317,6 +1336,211 @@ class OSRTestHandler : public RoutingTestHandler,
}
}
bool RunContextMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model,
CefRefPtr<CefRunContextMenuCallback> callback) override {
if (!started())
return false;
EXPECT_UI_THREAD();
auto current_browser = GetBrowser();
EXPECT_TRUE(current_browser->IsSame(browser));
EXPECT_EQ(current_browser->GetFocusedFrame()->GetIdentifier(),
frame->GetIdentifier());
if (test_type_ == OSR_TEST_QUICK_MENU) {
EXPECT_EQ(2U, got_touch_handle_enabled_ct_);
EXPECT_EQ(2U, got_touch_handle_size_ct_);
EXPECT_TRUE(got_quick_menu_);
EXPECT_TRUE(got_quick_menu_command_);
EXPECT_TRUE(got_quick_menu_dismissed_);
EXPECT_EQ(2U, got_touch_handle_disabled_ct_);
EXPECT_FALSE(got_context_menu_);
got_context_menu_.yes();
// Got all expected callbacks.
DestroySucceededTestSoon();
// Cancel the menu immediately.
callback->Cancel();
return true;
}
return false;
}
bool RunQuickMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefPoint& location,
const CefSize& size,
QuickMenuEditStateFlags edit_state_flags,
CefRefPtr<CefRunQuickMenuCallback> callback) override {
if (!started())
return false;
EXPECT_UI_THREAD();
auto current_browser = GetBrowser();
EXPECT_TRUE(current_browser->IsSame(browser));
EXPECT_EQ(current_browser->GetFocusedFrame()->GetIdentifier(),
frame->GetIdentifier());
EXPECT_EQ(OSR_TEST_QUICK_MENU, test_type_);
EXPECT_GT(location.x, 0);
EXPECT_GT(location.y, 0);
EXPECT_GT(size.width, 0);
EXPECT_GT(size.height, 0);
EXPECT_EQ(static_cast<QuickMenuEditStateFlags>(QM_EDITFLAG_CAN_ELLIPSIS |
QM_EDITFLAG_CAN_COPY),
edit_state_flags);
EXPECT_TRUE(callback.get());
EXPECT_EQ(2U, got_touch_handle_enabled_ct_);
EXPECT_EQ(2U, got_touch_handle_size_ct_);
EXPECT_FALSE(got_quick_menu_);
EXPECT_FALSE(got_quick_menu_command_);
EXPECT_FALSE(got_quick_menu_dismissed_);
EXPECT_EQ(0U, got_touch_handle_disabled_ct_);
EXPECT_FALSE(got_context_menu_);
got_quick_menu_.yes();
// Proceed to OnQuickMenuCommand.
callback->Continue(QM_EDITFLAG_CAN_ELLIPSIS,
static_cast<cef_event_flags_t>(EVENTFLAG_SHIFT_DOWN));
return true;
}
bool OnQuickMenuCommand(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int command_id,
EventFlags event_flags) override {
EXPECT_UI_THREAD();
auto current_browser = GetBrowser();
EXPECT_TRUE(current_browser->IsSame(browser));
EXPECT_EQ(current_browser->GetFocusedFrame()->GetIdentifier(),
frame->GetIdentifier());
EXPECT_EQ(OSR_TEST_QUICK_MENU, test_type_);
// Values passed to Continue() in RunQuickMenu.
EXPECT_EQ(QM_EDITFLAG_CAN_ELLIPSIS, command_id);
EXPECT_EQ(EVENTFLAG_SHIFT_DOWN, event_flags);
EXPECT_EQ(2U, got_touch_handle_enabled_ct_);
EXPECT_EQ(2U, got_touch_handle_size_ct_);
EXPECT_TRUE(got_quick_menu_);
EXPECT_FALSE(got_quick_menu_command_);
EXPECT_FALSE(got_quick_menu_dismissed_);
EXPECT_EQ(0U, got_touch_handle_disabled_ct_);
EXPECT_FALSE(got_context_menu_);
got_quick_menu_command_.yes();
// Proceed to OnQuickMenuDismissed and RunContextMenu.
return false;
}
void OnQuickMenuDismissed(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame) override {
EXPECT_UI_THREAD();
auto current_browser = GetBrowser();
EXPECT_TRUE(current_browser->IsSame(browser));
EXPECT_EQ(current_browser->GetFocusedFrame()->GetIdentifier(),
frame->GetIdentifier());
EXPECT_EQ(OSR_TEST_QUICK_MENU, test_type_);
EXPECT_EQ(2U, got_touch_handle_enabled_ct_);
EXPECT_EQ(2U, got_touch_handle_size_ct_);
EXPECT_TRUE(got_quick_menu_);
EXPECT_TRUE(got_quick_menu_command_);
EXPECT_FALSE(got_quick_menu_dismissed_);
EXPECT_EQ(0U, got_touch_handle_disabled_ct_);
EXPECT_FALSE(got_context_menu_);
EXPECT_EQ(kAllTouchHandleFlags, touch_handle_flags_);
got_quick_menu_dismissed_.yes();
}
void GetTouchHandleSize(CefRefPtr<CefBrowser> browser,
cef_horizontal_alignment_t orientation,
CefSize& size) override {
size = CefSize(24, 24);
got_touch_handle_size_ct_++;
}
void OnTouchHandleStateChanged(CefRefPtr<CefBrowser> browser,
const CefTouchHandleState& state) override {
if (!started())
return;
EXPECT_UI_THREAD();
auto current_browser = GetBrowser();
EXPECT_TRUE(current_browser->IsSame(browser));
if (test_type_ == OSR_TEST_QUICK_MENU) {
if (state.flags & CEF_THS_FLAG_ENABLED) {
EXPECT_EQ(state.orientation, 0);
EXPECT_EQ(state.origin.x, 0);
EXPECT_EQ(state.origin.y, 0);
EXPECT_EQ(state.alpha, 0);
if (state.enabled) {
got_touch_handle_enabled_ct_++;
EXPECT_FALSE(got_quick_menu_);
EXPECT_FALSE(got_quick_menu_command_);
EXPECT_FALSE(got_quick_menu_dismissed_);
EXPECT_EQ(0U, got_touch_handle_disabled_ct_);
EXPECT_FALSE(got_context_menu_);
touch_handle_flags_ |= CEF_THS_FLAG_ENABLED;
} else {
got_touch_handle_disabled_ct_++;
EXPECT_EQ(2U, got_touch_handle_enabled_ct_);
EXPECT_EQ(2U, got_touch_handle_size_ct_);
EXPECT_TRUE(got_quick_menu_);
EXPECT_TRUE(got_quick_menu_command_);
EXPECT_TRUE(got_quick_menu_dismissed_);
EXPECT_FALSE(got_context_menu_);
}
}
if (state.flags & CEF_THS_FLAG_ORIENTATION) {
EXPECT_EQ(state.enabled, false);
EXPECT_GE(state.orientation, 0);
EXPECT_EQ(state.origin.x, 0);
EXPECT_EQ(state.origin.y, 0);
EXPECT_EQ(state.alpha, 0);
touch_handle_flags_ |= CEF_THS_FLAG_ORIENTATION;
}
if (state.flags & CEF_THS_FLAG_ORIGIN) {
EXPECT_EQ(state.enabled, false);
EXPECT_EQ(state.orientation, 0);
EXPECT_GT(state.origin.x, 0);
EXPECT_GT(state.origin.y, 0);
EXPECT_EQ(state.alpha, 0);
touch_handle_flags_ |= CEF_THS_FLAG_ORIGIN;
}
if (state.flags & CEF_THS_FLAG_ALPHA) {
EXPECT_EQ(state.enabled, false);
EXPECT_EQ(state.orientation, 0);
EXPECT_EQ(state.origin.x, 0);
EXPECT_EQ(state.origin.y, 0);
EXPECT_GE(state.alpha, 0);
touch_handle_flags_ |= CEF_THS_FLAG_ALPHA;
}
}
}
// OSRTestHandler functions
void CreateOSRBrowser(const CefString& url) {
CefWindowInfo windowInfo;
@ -1418,6 +1642,17 @@ class OSRTestHandler : public RoutingTestHandler,
EXPECT_FALSE(got_system_focus_event_);
}
if (test_type_ == OSR_TEST_QUICK_MENU) {
EXPECT_EQ(2U, got_touch_handle_enabled_ct_);
EXPECT_EQ(2U, got_touch_handle_size_ct_);
EXPECT_TRUE(got_quick_menu_);
EXPECT_TRUE(got_quick_menu_command_);
EXPECT_TRUE(got_quick_menu_dismissed_);
EXPECT_EQ(2U, got_touch_handle_disabled_ct_);
EXPECT_TRUE(got_context_menu_);
EXPECT_EQ(kAllTouchHandleFlags, touch_handle_flags_);
}
RoutingTestHandler::DestroyTest();
}
@ -1509,6 +1744,15 @@ class OSRTestHandler : public RoutingTestHandler,
TrackCallback got_initial_text_selection_event_;
TrackCallback got_virtual_keyboard_event_;
uint32_t touch_handle_flags_ = 0U;
size_t got_touch_handle_enabled_ct_ = 0U;
size_t got_touch_handle_size_ct_ = 0U;
TrackCallback got_quick_menu_;
TrackCallback got_quick_menu_command_;
TrackCallback got_quick_menu_dismissed_;
size_t got_touch_handle_disabled_ct_ = 0U;
TrackCallback got_context_menu_;
typedef std::map<std::string, CefRect> ElementBoundsMap;
ElementBoundsMap element_bounds_;
@ -1562,6 +1806,8 @@ OSR_TEST(Scrolling, OSR_TEST_SCROLLING, 1.0f)
OSR_TEST(Scrolling2x, OSR_TEST_SCROLLING, 2.0f)
OSR_TEST(ContextMenu, OSR_TEST_CONTEXT_MENU, 1.0f)
OSR_TEST(ContextMenu2x, OSR_TEST_CONTEXT_MENU, 2.0f)
OSR_TEST(QuickMenu, OSR_TEST_QUICK_MENU, 1.0f)
OSR_TEST(QuickMenu2x, OSR_TEST_CONTEXT_MENU, 2.0f)
OSR_TEST(PopupPaint, OSR_TEST_POPUP_PAINT, 1.0f)
OSR_TEST(PopupPaint2x, OSR_TEST_POPUP_PAINT, 2.0f)
OSR_TEST(PopupShow, OSR_TEST_POPUP_SHOW, 1.0f)

View File

@ -57,6 +57,7 @@
elems.push(getElementBounds('LI11'));
elems.push(getElementBounds('LI11select'));
elems.push(getElementBounds('email'));
elems.push(getElementBounds('quickmenu'));
elems.push(getElementBounds('editbox'));
elems.push(getElementBounds('btnnavigate'));
elems.push(getElementBounds('dropdiv'));
@ -176,6 +177,7 @@
trigger show a tooltip</li>
<li id='LI11' onclick='selectText(event)'>SELECTED_TEXT_RANGE</li>
<li><input id='email' type='text' size=10 inputmode='email'></li>
<li id="quickmenu">Long touch press should trigger quick menu</li>
</ol>
<div class="dropdiv" id="dropdiv" ondrop="drop(event)" ondragover="allowDrop(event)">