mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-26 17:07:47 +01:00
views: Add support for accelerators (issue #2102)
This commit is contained in:
parent
e4867b5afb
commit
bd1b80198f
@ -63,6 +63,18 @@ typedef struct _cef_browser_view_t {
|
||||
///
|
||||
struct _cef_browser_t* (CEF_CALLBACK *get_browser)(
|
||||
struct _cef_browser_view_t* self);
|
||||
|
||||
///
|
||||
// Sets whether accelerators registered with cef_window_t::SetAccelerator are
|
||||
// triggered before or after the event is sent to the cef_browser_t. If
|
||||
// |prefer_accelerators| is true (1) then the matching accelerator will be
|
||||
// triggered immediately and the event will not be sent to the cef_browser_t.
|
||||
// If |prefer_accelerators| is false (0) then the matching accelerator will
|
||||
// only be triggered if the event is not handled by web content or by
|
||||
// cef_keyboard_handler_t. The default value is false (0).
|
||||
///
|
||||
void (CEF_CALLBACK *set_prefer_accelerators)(struct _cef_browser_view_t* self,
|
||||
int prefer_accelerators);
|
||||
} cef_browser_view_t;
|
||||
|
||||
|
||||
|
@ -269,6 +269,27 @@ typedef struct _cef_window_t {
|
||||
///
|
||||
void (CEF_CALLBACK *send_mouse_events)(struct _cef_window_t* self,
|
||||
cef_mouse_button_type_t button, int mouse_down, int mouse_up);
|
||||
|
||||
///
|
||||
// Set the keyboard accelerator for the specified |command_id|. |key_code| can
|
||||
// be any virtual key or character value. cef_window_delegate_t::OnAccelerator
|
||||
// will be called if the keyboard combination is triggered while this window
|
||||
// has focus.
|
||||
///
|
||||
void (CEF_CALLBACK *set_accelerator)(struct _cef_window_t* self,
|
||||
int command_id, int key_code, int shift_pressed, int ctrl_pressed,
|
||||
int alt_pressed);
|
||||
|
||||
///
|
||||
// Remove the keyboard accelerator for the specified |command_id|.
|
||||
///
|
||||
void (CEF_CALLBACK *remove_accelerator)(struct _cef_window_t* self,
|
||||
int command_id);
|
||||
|
||||
///
|
||||
// Remove all keyboard accelerators.
|
||||
///
|
||||
void (CEF_CALLBACK *remove_all_accelerators)(struct _cef_window_t* self);
|
||||
} cef_window_t;
|
||||
|
||||
|
||||
|
@ -103,6 +103,22 @@ typedef struct _cef_window_delegate_t {
|
||||
///
|
||||
int (CEF_CALLBACK *can_close)(struct _cef_window_delegate_t* self,
|
||||
struct _cef_window_t* window);
|
||||
|
||||
///
|
||||
// Called when a keyboard accelerator registered with
|
||||
// cef_window_t::SetAccelerator is triggered. Return true (1) if the
|
||||
// accelerator was handled or false (0) otherwise.
|
||||
///
|
||||
int (CEF_CALLBACK *on_accelerator)(struct _cef_window_delegate_t* self,
|
||||
struct _cef_window_t* window, int command_id);
|
||||
|
||||
///
|
||||
// Called after all other controls in the window have had a chance to handle
|
||||
// the event. |event| contains information about the keyboard event. Return
|
||||
// true (1) if the keyboard event was handled or false (0) otherwise.
|
||||
///
|
||||
int (CEF_CALLBACK *on_key_event)(struct _cef_window_delegate_t* self,
|
||||
struct _cef_window_t* window, const struct _cef_key_event_t* event);
|
||||
} cef_window_delegate_t;
|
||||
|
||||
|
||||
|
@ -74,6 +74,18 @@ class CefBrowserView : public CefView {
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual CefRefPtr<CefBrowser> GetBrowser() =0;
|
||||
|
||||
///
|
||||
// Sets whether accelerators registered with CefWindow::SetAccelerator are
|
||||
// triggered before or after the event is sent to the CefBrowser. If
|
||||
// |prefer_accelerators| is true then the matching accelerator will be
|
||||
// triggered immediately and the event will not be sent to the CefBrowser. If
|
||||
// |prefer_accelerators| is false then the matching accelerator will only be
|
||||
// triggered if the event is not handled by web content or by
|
||||
// CefKeyboardHandler. The default value is false.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual void SetPreferAccelerators(bool prefer_accelerators) =0;
|
||||
};
|
||||
|
||||
#endif // CEF_INCLUDE_VIEWS_CEF_BROWSER_VIEW_H_
|
||||
|
@ -289,6 +289,30 @@ class CefWindow : public CefPanel {
|
||||
virtual void SendMouseEvents(cef_mouse_button_type_t button,
|
||||
bool mouse_down,
|
||||
bool mouse_up) =0;
|
||||
///
|
||||
// Set the keyboard accelerator for the specified |command_id|. |key_code| can
|
||||
// be any virtual key or character value. CefWindowDelegate::OnAccelerator
|
||||
// will be called if the keyboard combination is triggered while this window
|
||||
// has focus.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual void SetAccelerator(int command_id,
|
||||
int key_code,
|
||||
bool shift_pressed,
|
||||
bool ctrl_pressed,
|
||||
bool alt_pressed) =0;
|
||||
|
||||
///
|
||||
// Remove the keyboard accelerator for the specified |command_id|.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual void RemoveAccelerator(int command_id) =0;
|
||||
|
||||
///
|
||||
// Remove all keyboard accelerators.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual void RemoveAllAccelerators() =0;
|
||||
};
|
||||
|
||||
#endif // CEF_INCLUDE_VIEWS_CEF_WINDOW_H_
|
||||
|
@ -95,6 +95,24 @@ class CefWindowDelegate : public CefPanelDelegate {
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool CanClose(CefRefPtr<CefWindow> window) { return true; }
|
||||
|
||||
///
|
||||
// Called when a keyboard accelerator registered with
|
||||
// CefWindow::SetAccelerator is triggered. Return true if the accelerator was
|
||||
// handled or false otherwise.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool OnAccelerator(CefRefPtr<CefWindow> window,
|
||||
int command_id) { return false; }
|
||||
|
||||
///
|
||||
// Called after all other controls in the window have had a chance to
|
||||
// handle the event. |event| contains information about the keyboard event.
|
||||
// Return true if the keyboard event was handled or false otherwise.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool OnKeyEvent(CefRefPtr<CefWindow> window,
|
||||
const CefKeyEvent& event) { return false; }
|
||||
};
|
||||
|
||||
#endif // CEF_INCLUDE_VIEWS_CEF_WINDOW_DELEGATE_H_
|
||||
|
@ -216,7 +216,8 @@ void CefBrowserPlatformDelegateViews::ViewText(const std::string& text) {
|
||||
|
||||
void CefBrowserPlatformDelegateViews::HandleKeyboardEvent(
|
||||
const content::NativeWebKeyboardEvent& event) {
|
||||
native_delegate_->HandleKeyboardEvent(event);
|
||||
// The BrowserView will handle accelerators.
|
||||
browser_view_->HandleKeyboardEvent(event);
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateViews::HandleExternalProtocol(const GURL& url) {
|
||||
|
@ -5,9 +5,14 @@
|
||||
#include "libcef/browser/views/browser_view_impl.h"
|
||||
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
#include "libcef/browser/browser_util.h"
|
||||
#include "libcef/browser/context.h"
|
||||
#include "libcef/browser/views/window_impl.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
#include "content/public/browser/native_web_keyboard_event.h"
|
||||
#include "ui/content_accelerators/accelerator_util.h"
|
||||
|
||||
// static
|
||||
CefRefPtr<CefBrowserView> CefBrowserView::CreateBrowserView(
|
||||
CefRefPtr<CefClient> client,
|
||||
@ -75,11 +80,45 @@ void CefBrowserViewImpl::BrowserDestroyed(CefBrowserHostImpl* browser) {
|
||||
root_view()->SetWebContents(nullptr);
|
||||
}
|
||||
|
||||
void CefBrowserViewImpl::HandleKeyboardEvent(
|
||||
const content::NativeWebKeyboardEvent& event) {
|
||||
if (!root_view())
|
||||
return;
|
||||
|
||||
views::FocusManager* focus_manager = root_view()->GetFocusManager();
|
||||
if (!focus_manager)
|
||||
return;
|
||||
|
||||
if (HandleAccelerator(event, focus_manager))
|
||||
return;
|
||||
|
||||
// Give the CefWindowDelegate a chance to handle the event.
|
||||
CefRefPtr<CefWindow> window =
|
||||
view_util::GetWindowFor(root_view()->GetWidget());
|
||||
CefWindowImpl* window_impl = static_cast<CefWindowImpl*>(window.get());
|
||||
if (window_impl) {
|
||||
CefKeyEvent cef_event;
|
||||
if (browser_util::GetCefKeyEvent(event, cef_event) &&
|
||||
window_impl->OnKeyEvent(cef_event)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Proceed with default native handling.
|
||||
unhandled_keyboard_event_handler_.HandleKeyboardEvent(event, focus_manager);
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> CefBrowserViewImpl::GetBrowser() {
|
||||
CEF_REQUIRE_VALID_RETURN(nullptr);
|
||||
return browser_;
|
||||
}
|
||||
|
||||
void CefBrowserViewImpl::SetPreferAccelerators(bool prefer_accelerators) {
|
||||
CEF_REQUIRE_VALID_RETURN_VOID();
|
||||
if (root_view())
|
||||
root_view()->set_allow_accelerators(prefer_accelerators);
|
||||
}
|
||||
|
||||
void CefBrowserViewImpl::SetBackgroundColor(cef_color_t color) {
|
||||
CEF_REQUIRE_VALID_RETURN_VOID();
|
||||
ParentClass::SetBackgroundColor(color);
|
||||
@ -167,3 +206,39 @@ CefBrowserViewView* CefBrowserViewImpl::CreateRootView() {
|
||||
void CefBrowserViewImpl::InitializeRootView() {
|
||||
static_cast<CefBrowserViewView*>(root_view())->Initialize();
|
||||
}
|
||||
|
||||
bool CefBrowserViewImpl::HandleAccelerator(
|
||||
const content::NativeWebKeyboardEvent& event,
|
||||
views::FocusManager* focus_manager) {
|
||||
// Previous calls to TranslateMessage can generate Char events as well as
|
||||
// RawKeyDown events, even if the latter triggered an accelerator. In these
|
||||
// cases, we discard the Char events.
|
||||
if (event.type() == blink::WebInputEvent::Char && ignore_next_char_event_) {
|
||||
ignore_next_char_event_ = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// It's necessary to reset this flag, because a RawKeyDown event may not
|
||||
// always generate a Char event.
|
||||
ignore_next_char_event_ = false;
|
||||
|
||||
if (event.type() == blink::WebInputEvent::RawKeyDown) {
|
||||
ui::Accelerator accelerator =
|
||||
ui::GetAcceleratorFromNativeWebKeyboardEvent(event);
|
||||
|
||||
// This is tricky: we want to set ignore_next_char_event_ if
|
||||
// ProcessAccelerator returns true. But ProcessAccelerator might delete
|
||||
// |this| if the accelerator is a "close tab" one. So we speculatively
|
||||
// set the flag and fix it if no event was handled.
|
||||
ignore_next_char_event_ = true;
|
||||
|
||||
if (focus_manager->ProcessAccelerator(accelerator))
|
||||
return true;
|
||||
|
||||
// ProcessAccelerator didn't handle the accelerator, so we know both
|
||||
// that |this| is still valid, and that we didn't want to set the flag.
|
||||
ignore_next_char_event_ = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "libcef/browser/views/view_impl.h"
|
||||
#include "libcef/browser/views/browser_view_view.h"
|
||||
|
||||
#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
|
||||
|
||||
class CefBrowserViewImpl :
|
||||
public CefViewImpl<CefBrowserViewView, CefBrowserView,
|
||||
CefBrowserViewDelegate>,
|
||||
@ -41,8 +43,13 @@ class CefBrowserViewImpl :
|
||||
void BrowserCreated(CefBrowserHostImpl* browser);
|
||||
void BrowserDestroyed(CefBrowserHostImpl* browser);
|
||||
|
||||
// Called to handle accelerators when the event is unhandled by the web
|
||||
// content and the browser client.
|
||||
void HandleKeyboardEvent(const content::NativeWebKeyboardEvent& event);
|
||||
|
||||
// CefBrowserView methods:
|
||||
CefRefPtr<CefBrowser> GetBrowser() override;
|
||||
void SetPreferAccelerators(bool prefer_accelerators) override;
|
||||
|
||||
// CefView methods:
|
||||
CefRefPtr<CefBrowserView> AsBrowserView() override { return this; }
|
||||
@ -75,10 +82,20 @@ class CefBrowserViewImpl :
|
||||
CefBrowserViewView* CreateRootView() override;
|
||||
void InitializeRootView() override;
|
||||
|
||||
std::unique_ptr<CefBrowserHostImpl::CreateParams> pending_browser_create_params_;
|
||||
// Logic extracted from UnhandledKeyboardEventHandler::HandleKeyboardEvent for
|
||||
// the handling of accelerators. Returns true if the event was handled by the
|
||||
// accelerator.
|
||||
bool HandleAccelerator(const content::NativeWebKeyboardEvent& event,
|
||||
views::FocusManager* focus_manager);
|
||||
|
||||
std::unique_ptr<CefBrowserHostImpl::CreateParams>
|
||||
pending_browser_create_params_;
|
||||
|
||||
CefRefPtr<CefBrowserHostImpl> browser_;
|
||||
|
||||
views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
|
||||
bool ignore_next_char_event_ = false;
|
||||
|
||||
IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefBrowserViewImpl);
|
||||
DISALLOW_COPY_AND_ASSIGN(CefBrowserViewImpl);
|
||||
};
|
||||
|
@ -35,6 +35,7 @@ CEF_BUTTON_IMPL_T class CefButtonImpl : public CEF_VIEW_IMPL_D {
|
||||
|
||||
// CefView methods:
|
||||
CefRefPtr<CefButton> AsButton() override { return this; }
|
||||
void SetFocusable(bool focusable) override;
|
||||
|
||||
protected:
|
||||
// Create a new implementation object.
|
||||
@ -68,4 +69,11 @@ CEF_BUTTON_IMPL_T void CEF_BUTTON_IMPL_D::SetAccessibleName(
|
||||
ParentClass::root_view()->SetAccessibleName(name);
|
||||
}
|
||||
|
||||
CEF_BUTTON_IMPL_T void CEF_BUTTON_IMPL_D::SetFocusable(
|
||||
bool focusable) {
|
||||
CEF_REQUIRE_VALID_RETURN_VOID();
|
||||
ParentClass::root_view()->set_request_focus_on_press(focusable);
|
||||
ParentClass::SetFocusable(focusable);
|
||||
}
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_VIEWS_BUTTON_IMPL_H_
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "libcef/browser/views/window_impl.h"
|
||||
|
||||
#include "libcef/browser/browser_util.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
#include "libcef/browser/views/display_impl.h"
|
||||
#include "libcef/browser/views/fill_layout_impl.h"
|
||||
@ -17,6 +18,7 @@
|
||||
|
||||
#if defined(USE_AURA)
|
||||
#include "ui/aura/test/ui_controls_factory_aura.h"
|
||||
#include "ui/aura/window.h"
|
||||
#include "ui/base/test/ui_controls_aura.h"
|
||||
#if defined(OS_LINUX)
|
||||
#include "ui/views/test/ui_controls_factory_desktop_aurax11.h"
|
||||
@ -48,6 +50,58 @@ void InitializeUITesting() {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_AURA)
|
||||
|
||||
// This class forwards KeyEvents to the CefWindowImpl associated with a widget.
|
||||
// This allows KeyEvents to be processed after all other targets.
|
||||
// Events originating from CefBrowserView will instead be delivered via
|
||||
// CefBrowserViewImpl::HandleKeyboardEvent.
|
||||
class CefUnhandledKeyEventHandler : public ui::EventHandler {
|
||||
public:
|
||||
CefUnhandledKeyEventHandler(CefWindowImpl* window_impl,
|
||||
views::Widget* widget)
|
||||
: window_impl_(window_impl),
|
||||
widget_(widget),
|
||||
window_(widget->GetNativeWindow()) {
|
||||
DCHECK(window_);
|
||||
window_->AddPostTargetHandler(this);
|
||||
}
|
||||
|
||||
~CefUnhandledKeyEventHandler() override {
|
||||
window_->RemovePostTargetHandler(this);
|
||||
}
|
||||
|
||||
// Implementation of ui::EventHandler:
|
||||
void OnKeyEvent(ui::KeyEvent* event) override {
|
||||
// Give the FocusManager a chance to handle accelerators first.
|
||||
// Widget::OnKeyEvent would normally call this after all EventHandlers have
|
||||
// had a shot but we don't want to wait.
|
||||
if (widget_->GetFocusManager() &&
|
||||
!widget_->GetFocusManager()->OnKeyEvent(*event)) {
|
||||
event->StopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
CefKeyEvent cef_event;
|
||||
if (browser_util::GetCefKeyEvent(*event, cef_event) &&
|
||||
window_impl_->OnKeyEvent(cef_event)) {
|
||||
event->StopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Members are guaranteed to outlive this object.
|
||||
CefWindowImpl* window_impl_;
|
||||
views::Widget* widget_;
|
||||
|
||||
// |window_| is the event target that is associated with this class.
|
||||
aura::Window* window_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefUnhandledKeyEventHandler);
|
||||
};
|
||||
|
||||
#endif // defined(USE_AURA)
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
@ -315,6 +369,12 @@ bool CefWindowImpl::CanWidgetClose() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void CefWindowImpl::OnWindowClosing() {
|
||||
#if defined(USE_AURA)
|
||||
unhandled_key_event_handler_.reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CefWindowImpl::OnWindowViewDeleted() {
|
||||
CancelMenu();
|
||||
|
||||
@ -337,6 +397,27 @@ void CefWindowImpl::MenuClosed(CefRefPtr<CefMenuModelImpl> source) {
|
||||
menu_runner_.reset(nullptr);
|
||||
}
|
||||
|
||||
// Will only be called if CanHandleAccelerators() returns true.
|
||||
bool CefWindowImpl::AcceleratorPressed(const ui::Accelerator& accelerator) {
|
||||
for (const auto& entry : accelerator_map_) {
|
||||
if (entry.second == accelerator)
|
||||
return delegate()->OnAccelerator(this, entry.first);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CefWindowImpl::CanHandleAccelerators() const {
|
||||
if (delegate() && widget_)
|
||||
return widget_->IsActive();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CefWindowImpl::OnKeyEvent(const CefKeyEvent& event) {
|
||||
if (delegate())
|
||||
return delegate()->OnKeyEvent(this, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void CefWindowImpl::ShowMenu(views::MenuButton* menu_button,
|
||||
CefRefPtr<CefMenuModel> menu_model,
|
||||
const CefPoint& screen_point,
|
||||
@ -474,6 +555,67 @@ void CefWindowImpl::SendMouseEvents(cef_mouse_button_type_t button,
|
||||
ui_controls::SendMouseEvents(type, state);
|
||||
}
|
||||
|
||||
void CefWindowImpl::SetAccelerator(int command_id,
|
||||
int key_code,
|
||||
bool shift_pressed,
|
||||
bool ctrl_pressed,
|
||||
bool alt_pressed) {
|
||||
CEF_REQUIRE_VALID_RETURN_VOID();
|
||||
if (!widget_)
|
||||
return;
|
||||
|
||||
AcceleratorMap::const_iterator it = accelerator_map_.find(command_id);
|
||||
if (it != accelerator_map_.end())
|
||||
RemoveAccelerator(command_id);
|
||||
|
||||
int modifiers = 0;
|
||||
if (shift_pressed)
|
||||
modifiers |= ui::EF_SHIFT_DOWN;
|
||||
if (ctrl_pressed)
|
||||
modifiers |= ui::EF_CONTROL_DOWN;
|
||||
if (alt_pressed)
|
||||
modifiers |= ui::EF_ALT_DOWN;
|
||||
ui::Accelerator accelerator(static_cast<ui::KeyboardCode>(key_code),
|
||||
modifiers);
|
||||
|
||||
accelerator_map_.insert(std::make_pair(command_id, accelerator));
|
||||
|
||||
views::FocusManager* focus_manager = widget_->GetFocusManager();
|
||||
DCHECK(focus_manager);
|
||||
focus_manager->RegisterAccelerator(
|
||||
accelerator, ui::AcceleratorManager::kNormalPriority, this);
|
||||
}
|
||||
|
||||
void CefWindowImpl::RemoveAccelerator(int command_id) {
|
||||
CEF_REQUIRE_VALID_RETURN_VOID();
|
||||
if (!widget_)
|
||||
return;
|
||||
|
||||
AcceleratorMap::iterator it = accelerator_map_.find(command_id);
|
||||
if (it == accelerator_map_.end())
|
||||
return;
|
||||
|
||||
ui::Accelerator accelerator = it->second;
|
||||
|
||||
accelerator_map_.erase(it);
|
||||
|
||||
views::FocusManager* focus_manager = widget_->GetFocusManager();
|
||||
DCHECK(focus_manager);
|
||||
focus_manager->UnregisterAccelerator(accelerator, this);
|
||||
}
|
||||
|
||||
void CefWindowImpl::RemoveAllAccelerators() {
|
||||
CEF_REQUIRE_VALID_RETURN_VOID();
|
||||
if (!widget_)
|
||||
return;
|
||||
|
||||
accelerator_map_.clear();
|
||||
|
||||
views::FocusManager* focus_manager = widget_->GetFocusManager();
|
||||
DCHECK(focus_manager);
|
||||
focus_manager->UnregisterAccelerators(this);
|
||||
}
|
||||
|
||||
CefWindowImpl::CefWindowImpl(CefRefPtr<CefWindowDelegate> delegate)
|
||||
: ParentClass(delegate),
|
||||
widget_(nullptr),
|
||||
@ -495,6 +637,11 @@ void CefWindowImpl::CreateWidget() {
|
||||
widget_ = root_view()->GetWidget();
|
||||
DCHECK(widget_);
|
||||
|
||||
#if defined(USE_AURA)
|
||||
unhandled_key_event_handler_ =
|
||||
base::MakeUnique<CefUnhandledKeyEventHandler>(this, widget_);
|
||||
#endif
|
||||
|
||||
// The Widget and root View are owned by the native window. Therefore don't
|
||||
// keep an owned reference.
|
||||
std::unique_ptr<views::View> view_ptr = view_util::PassOwnership(this);
|
||||
|
@ -6,6 +6,8 @@
|
||||
#define CEF_LIBCEF_BROWSER_VIEWS_WINDOW_IMPL_H_
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "include/views/cef_window.h"
|
||||
#include "include/views/cef_window_delegate.h"
|
||||
|
||||
@ -13,6 +15,7 @@
|
||||
#include "libcef/browser/views/panel_impl.h"
|
||||
#include "libcef/browser/views/window_view.h"
|
||||
|
||||
#include "ui/base/accelerators/accelerator.h"
|
||||
#include "ui/views/controls/menu/menu_runner.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
|
||||
@ -23,7 +26,8 @@ class MenuButton;
|
||||
class CefWindowImpl :
|
||||
public CefPanelImpl<CefWindowView, CefWindow, CefWindowDelegate>,
|
||||
public CefWindowView::Delegate,
|
||||
public CefMenuModelImpl::Observer {
|
||||
public CefMenuModelImpl::Observer,
|
||||
public ui::AcceleratorTarget {
|
||||
public:
|
||||
typedef CefPanelImpl<CefWindowView, CefWindow, CefWindowDelegate> ParentClass;
|
||||
|
||||
@ -70,6 +74,13 @@ class CefWindowImpl :
|
||||
void SendMouseEvents(cef_mouse_button_type_t button,
|
||||
bool mouse_down,
|
||||
bool mouse_up) override;
|
||||
void SetAccelerator(int command_id,
|
||||
int key_code,
|
||||
bool shift_pressed,
|
||||
bool ctrl_pressed,
|
||||
bool alt_pressed) override;
|
||||
void RemoveAccelerator(int command_id) override;
|
||||
void RemoveAllAccelerators() override;
|
||||
|
||||
// CefViewAdapter methods:
|
||||
void Detach() override;
|
||||
@ -91,6 +102,7 @@ class CefWindowImpl :
|
||||
|
||||
// CefWindowView::Delegate methods:
|
||||
bool CanWidgetClose() override;
|
||||
void OnWindowClosing() override;
|
||||
void OnWindowViewDeleted() override;
|
||||
|
||||
// CefMenuModelImpl::Observer methods:
|
||||
@ -101,6 +113,14 @@ class CefWindowImpl :
|
||||
void GetDebugInfo(base::DictionaryValue* info,
|
||||
bool include_children) override;
|
||||
|
||||
// ui::AcceleratorTarget methods:
|
||||
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
|
||||
bool CanHandleAccelerators() const override;
|
||||
|
||||
// Called for key events that have not been handled by other controls in the
|
||||
// window. Returns true if the event was handled.
|
||||
bool OnKeyEvent(const CefKeyEvent& event);
|
||||
|
||||
void ShowMenu(views::MenuButton* menu_button,
|
||||
CefRefPtr<CefMenuModel> menu_model,
|
||||
const CefPoint& screen_point,
|
||||
@ -128,6 +148,15 @@ class CefWindowImpl :
|
||||
CefRefPtr<CefMenuModelImpl> menu_model_;
|
||||
std::unique_ptr<views::MenuRunner> menu_runner_;
|
||||
|
||||
// Map of command_id to accelerator.
|
||||
typedef std::map<int, ui::Accelerator> AcceleratorMap;
|
||||
AcceleratorMap accelerator_map_;
|
||||
|
||||
#if defined(USE_AURA)
|
||||
// Native widget's handler to receive events after the event target.
|
||||
std::unique_ptr<ui::EventHandler> unhandled_key_event_handler_;
|
||||
#endif
|
||||
|
||||
IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefWindowImpl);
|
||||
DISALLOW_COPY_AND_ASSIGN(CefWindowImpl);
|
||||
};
|
||||
|
@ -368,6 +368,10 @@ gfx::ImageSkia CefWindowView::GetWindowAppIcon() {
|
||||
GetForced1xScaleRepresentation(GetDisplay().device_scale_factor());
|
||||
}
|
||||
|
||||
void CefWindowView::WindowClosing() {
|
||||
window_delegate_->OnWindowClosing();
|
||||
}
|
||||
|
||||
views::View* CefWindowView::GetContentsView() {
|
||||
// |this| will be the "Contents View" hosted by the Widget via ClientView and
|
||||
// RootView.
|
||||
|
@ -29,6 +29,9 @@ class CefWindowView :
|
||||
// Returns true to signal that the Widget can be closed.
|
||||
virtual bool CanWidgetClose() = 0;
|
||||
|
||||
// Called when the underlying platform window is closing.
|
||||
virtual void OnWindowClosing() = 0;
|
||||
|
||||
// Called when the WindowView is about to be deleted.
|
||||
virtual void OnWindowViewDeleted() = 0;
|
||||
|
||||
@ -58,6 +61,7 @@ class CefWindowView :
|
||||
base::string16 GetWindowTitle() const override;
|
||||
gfx::ImageSkia GetWindowIcon() override;
|
||||
gfx::ImageSkia GetWindowAppIcon() override;
|
||||
void WindowClosing() override;
|
||||
views::View* GetContentsView() override;
|
||||
views::ClientView* CreateClientView(views::Widget* widget) override;
|
||||
views::NonClientFrameView* CreateNonClientFrameView(
|
||||
|
@ -92,6 +92,19 @@ cef_browser_t* CEF_CALLBACK browser_view_get_browser(
|
||||
return CefBrowserCppToC::Wrap(_retval);
|
||||
}
|
||||
|
||||
void CEF_CALLBACK browser_view_set_prefer_accelerators(
|
||||
struct _cef_browser_view_t* self, int prefer_accelerators) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefBrowserViewCppToC::Get(self)->SetPreferAccelerators(
|
||||
prefer_accelerators?true:false);
|
||||
}
|
||||
|
||||
cef_browser_view_t* CEF_CALLBACK browser_view_as_browser_view(
|
||||
struct _cef_view_t* self) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
@ -905,6 +918,7 @@ int CEF_CALLBACK browser_view_convert_point_from_view(struct _cef_view_t* self,
|
||||
|
||||
CefBrowserViewCppToC::CefBrowserViewCppToC() {
|
||||
GetStruct()->get_browser = browser_view_get_browser;
|
||||
GetStruct()->set_prefer_accelerators = browser_view_set_prefer_accelerators;
|
||||
GetStruct()->base.as_browser_view = browser_view_as_browser_view;
|
||||
GetStruct()->base.as_button = browser_view_as_button;
|
||||
GetStruct()->base.as_panel = browser_view_as_panel;
|
||||
|
@ -518,6 +518,48 @@ void CEF_CALLBACK window_send_mouse_events(struct _cef_window_t* self,
|
||||
mouse_up?true:false);
|
||||
}
|
||||
|
||||
void CEF_CALLBACK window_set_accelerator(struct _cef_window_t* self,
|
||||
int command_id, int key_code, int shift_pressed, int ctrl_pressed,
|
||||
int alt_pressed) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefWindowCppToC::Get(self)->SetAccelerator(
|
||||
command_id,
|
||||
key_code,
|
||||
shift_pressed?true:false,
|
||||
ctrl_pressed?true:false,
|
||||
alt_pressed?true:false);
|
||||
}
|
||||
|
||||
void CEF_CALLBACK window_remove_accelerator(struct _cef_window_t* self,
|
||||
int command_id) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefWindowCppToC::Get(self)->RemoveAccelerator(
|
||||
command_id);
|
||||
}
|
||||
|
||||
void CEF_CALLBACK window_remove_all_accelerators(struct _cef_window_t* self) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefWindowCppToC::Get(self)->RemoveAllAccelerators();
|
||||
}
|
||||
|
||||
struct _cef_window_t* CEF_CALLBACK window_as_window(struct _cef_panel_t* self) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
@ -1550,6 +1592,9 @@ CefWindowCppToC::CefWindowCppToC() {
|
||||
GetStruct()->send_key_press = window_send_key_press;
|
||||
GetStruct()->send_mouse_move = window_send_mouse_move;
|
||||
GetStruct()->send_mouse_events = window_send_mouse_events;
|
||||
GetStruct()->set_accelerator = window_set_accelerator;
|
||||
GetStruct()->remove_accelerator = window_remove_accelerator;
|
||||
GetStruct()->remove_all_accelerators = window_remove_all_accelerators;
|
||||
GetStruct()->base.as_window = window_as_window;
|
||||
GetStruct()->base.set_to_fill_layout = window_set_to_fill_layout;
|
||||
GetStruct()->base.set_to_box_layout = window_set_to_box_layout;
|
||||
|
@ -153,6 +153,59 @@ int CEF_CALLBACK window_delegate_can_close(struct _cef_window_delegate_t* self,
|
||||
return _retval;
|
||||
}
|
||||
|
||||
int CEF_CALLBACK window_delegate_on_accelerator(
|
||||
struct _cef_window_delegate_t* self, cef_window_t* window,
|
||||
int command_id) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
// Verify param: window; type: refptr_diff
|
||||
DCHECK(window);
|
||||
if (!window)
|
||||
return 0;
|
||||
|
||||
// Execute
|
||||
bool _retval = CefWindowDelegateCppToC::Get(self)->OnAccelerator(
|
||||
CefWindowCToCpp::Wrap(window),
|
||||
command_id);
|
||||
|
||||
// Return type: bool
|
||||
return _retval;
|
||||
}
|
||||
|
||||
int CEF_CALLBACK window_delegate_on_key_event(
|
||||
struct _cef_window_delegate_t* self, cef_window_t* window,
|
||||
const struct _cef_key_event_t* event) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
// Verify param: window; type: refptr_diff
|
||||
DCHECK(window);
|
||||
if (!window)
|
||||
return 0;
|
||||
// Verify param: event; type: struct_byref_const
|
||||
DCHECK(event);
|
||||
if (!event)
|
||||
return 0;
|
||||
|
||||
// Translate param: event; type: struct_byref_const
|
||||
CefKeyEvent eventObj;
|
||||
if (event)
|
||||
eventObj.Set(*event, false);
|
||||
|
||||
// Execute
|
||||
bool _retval = CefWindowDelegateCppToC::Get(self)->OnKeyEvent(
|
||||
CefWindowCToCpp::Wrap(window),
|
||||
eventObj);
|
||||
|
||||
// Return type: bool
|
||||
return _retval;
|
||||
}
|
||||
|
||||
cef_size_t CEF_CALLBACK window_delegate_get_preferred_size(
|
||||
struct _cef_view_delegate_t* self, cef_view_t* view) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
@ -301,6 +354,8 @@ CefWindowDelegateCppToC::CefWindowDelegateCppToC() {
|
||||
GetStruct()->can_maximize = window_delegate_can_maximize;
|
||||
GetStruct()->can_minimize = window_delegate_can_minimize;
|
||||
GetStruct()->can_close = window_delegate_can_close;
|
||||
GetStruct()->on_accelerator = window_delegate_on_accelerator;
|
||||
GetStruct()->on_key_event = window_delegate_on_key_event;
|
||||
GetStruct()->base.base.get_preferred_size =
|
||||
window_delegate_get_preferred_size;
|
||||
GetStruct()->base.base.get_minimum_size = window_delegate_get_minimum_size;
|
||||
|
@ -81,6 +81,18 @@ CefRefPtr<CefBrowser> CefBrowserViewCToCpp::GetBrowser() {
|
||||
return CefBrowserCToCpp::Wrap(_retval);
|
||||
}
|
||||
|
||||
void CefBrowserViewCToCpp::SetPreferAccelerators(bool prefer_accelerators) {
|
||||
cef_browser_view_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, set_prefer_accelerators))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
_struct->set_prefer_accelerators(_struct,
|
||||
prefer_accelerators);
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowserView> CefBrowserViewCToCpp::AsBrowserView() {
|
||||
cef_view_t* _struct = reinterpret_cast<cef_view_t*>(GetStruct());
|
||||
if (CEF_MEMBER_MISSING(_struct, as_browser_view))
|
||||
|
@ -32,6 +32,7 @@ class CefBrowserViewCToCpp
|
||||
|
||||
// CefBrowserView methods.
|
||||
CefRefPtr<CefBrowser> GetBrowser() OVERRIDE;
|
||||
void SetPreferAccelerators(bool prefer_accelerators) OVERRIDE;
|
||||
|
||||
// CefView methods.
|
||||
CefRefPtr<CefBrowserView> AsBrowserView() OVERRIDE;
|
||||
|
@ -505,6 +505,46 @@ void CefWindowCToCpp::SendMouseEvents(cef_mouse_button_type_t button,
|
||||
mouse_up);
|
||||
}
|
||||
|
||||
void CefWindowCToCpp::SetAccelerator(int command_id, int key_code,
|
||||
bool shift_pressed, bool ctrl_pressed, bool alt_pressed) {
|
||||
cef_window_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, set_accelerator))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
_struct->set_accelerator(_struct,
|
||||
command_id,
|
||||
key_code,
|
||||
shift_pressed,
|
||||
ctrl_pressed,
|
||||
alt_pressed);
|
||||
}
|
||||
|
||||
void CefWindowCToCpp::RemoveAccelerator(int command_id) {
|
||||
cef_window_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, remove_accelerator))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
_struct->remove_accelerator(_struct,
|
||||
command_id);
|
||||
}
|
||||
|
||||
void CefWindowCToCpp::RemoveAllAccelerators() {
|
||||
cef_window_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, remove_all_accelerators))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
_struct->remove_all_accelerators(_struct);
|
||||
}
|
||||
|
||||
CefRefPtr<CefWindow> CefWindowCToCpp::AsWindow() {
|
||||
cef_panel_t* _struct = reinterpret_cast<cef_panel_t*>(GetStruct());
|
||||
if (CEF_MEMBER_MISSING(_struct, as_window))
|
||||
|
@ -68,6 +68,10 @@ class CefWindowCToCpp
|
||||
void SendMouseMove(int screen_x, int screen_y) OVERRIDE;
|
||||
void SendMouseEvents(cef_mouse_button_type_t button, bool mouse_down,
|
||||
bool mouse_up) OVERRIDE;
|
||||
void SetAccelerator(int command_id, int key_code, bool shift_pressed,
|
||||
bool ctrl_pressed, bool alt_pressed) OVERRIDE;
|
||||
void RemoveAccelerator(int command_id) OVERRIDE;
|
||||
void RemoveAllAccelerators() OVERRIDE;
|
||||
|
||||
// CefPanel methods.
|
||||
CefRefPtr<CefWindow> AsWindow() OVERRIDE;
|
||||
|
@ -151,6 +151,50 @@ bool CefWindowDelegateCToCpp::CanClose(CefRefPtr<CefWindow> window) {
|
||||
return _retval?true:false;
|
||||
}
|
||||
|
||||
bool CefWindowDelegateCToCpp::OnAccelerator(CefRefPtr<CefWindow> window,
|
||||
int command_id) {
|
||||
cef_window_delegate_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, on_accelerator))
|
||||
return false;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: window; type: refptr_diff
|
||||
DCHECK(window.get());
|
||||
if (!window.get())
|
||||
return false;
|
||||
|
||||
// Execute
|
||||
int _retval = _struct->on_accelerator(_struct,
|
||||
CefWindowCppToC::Wrap(window),
|
||||
command_id);
|
||||
|
||||
// Return type: bool
|
||||
return _retval?true:false;
|
||||
}
|
||||
|
||||
bool CefWindowDelegateCToCpp::OnKeyEvent(CefRefPtr<CefWindow> window,
|
||||
const CefKeyEvent& event) {
|
||||
cef_window_delegate_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, on_key_event))
|
||||
return false;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: window; type: refptr_diff
|
||||
DCHECK(window.get());
|
||||
if (!window.get())
|
||||
return false;
|
||||
|
||||
// Execute
|
||||
int _retval = _struct->on_key_event(_struct,
|
||||
CefWindowCppToC::Wrap(window),
|
||||
&event);
|
||||
|
||||
// Return type: bool
|
||||
return _retval?true:false;
|
||||
}
|
||||
|
||||
CefSize CefWindowDelegateCToCpp::GetPreferredSize(CefRefPtr<CefView> view) {
|
||||
cef_view_delegate_t* _struct = reinterpret_cast<cef_view_delegate_t*>(
|
||||
GetStruct());
|
||||
|
@ -40,6 +40,9 @@ class CefWindowDelegateCToCpp
|
||||
bool CanMaximize(CefRefPtr<CefWindow> window) override;
|
||||
bool CanMinimize(CefRefPtr<CefWindow> window) override;
|
||||
bool CanClose(CefRefPtr<CefWindow> window) override;
|
||||
bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) override;
|
||||
bool OnKeyEvent(CefRefPtr<CefWindow> window,
|
||||
const CefKeyEvent& event) override;
|
||||
|
||||
// CefPanelDelegate methods.
|
||||
|
||||
|
@ -462,6 +462,12 @@ void ClientHandler::OnDraggableRegionsChanged(
|
||||
NotifyDraggableRegions(regions);
|
||||
}
|
||||
|
||||
void ClientHandler::OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
NotifyTakeFocus(next);
|
||||
}
|
||||
|
||||
bool ClientHandler::OnRequestGeolocationPermission(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const CefString& requesting_url,
|
||||
@ -990,6 +996,18 @@ void ClientHandler::NotifyDraggableRegions(
|
||||
delegate_->OnSetDraggableRegions(regions);
|
||||
}
|
||||
|
||||
void ClientHandler::NotifyTakeFocus(bool next) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
// Execute this method on the main thread.
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&ClientHandler::NotifyTakeFocus, this, next));
|
||||
return;
|
||||
}
|
||||
|
||||
if (delegate_)
|
||||
delegate_->OnTakeFocus(next);
|
||||
}
|
||||
|
||||
void ClientHandler::BuildTestMenu(CefRefPtr<CefMenuModel> model) {
|
||||
if (model->GetCount() > 0)
|
||||
model->AddSeparator();
|
||||
|
@ -30,6 +30,7 @@ class ClientHandler : public CefClient,
|
||||
public CefDisplayHandler,
|
||||
public CefDownloadHandler,
|
||||
public CefDragHandler,
|
||||
public CefFocusHandler,
|
||||
public CefGeolocationHandler,
|
||||
public CefKeyboardHandler,
|
||||
public CefLifeSpanHandler,
|
||||
@ -70,6 +71,9 @@ class ClientHandler : public CefClient,
|
||||
virtual void OnSetDraggableRegions(
|
||||
const std::vector<CefDraggableRegion>& regions) = 0;
|
||||
|
||||
// Set focus to the next/previous control.
|
||||
virtual void OnTakeFocus(bool next) {}
|
||||
|
||||
protected:
|
||||
virtual ~Delegate() {}
|
||||
};
|
||||
@ -99,6 +103,9 @@ class ClientHandler : public CefClient,
|
||||
CefRefPtr<CefDragHandler> GetDragHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
CefRefPtr<CefFocusHandler> GetFocusHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
CefRefPtr<CefGeolocationHandler> GetGeolocationHandler() OVERRIDE {
|
||||
return this;
|
||||
}
|
||||
@ -168,11 +175,13 @@ class ClientHandler : public CefClient,
|
||||
bool OnDragEnter(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefDragData> dragData,
|
||||
CefDragHandler::DragOperationsMask mask) OVERRIDE;
|
||||
|
||||
void OnDraggableRegionsChanged(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const std::vector<CefDraggableRegion>& regions) OVERRIDE;
|
||||
|
||||
// CefFocusHandler methods
|
||||
void OnTakeFocus(CefRefPtr<CefBrowser> browser, bool next) OVERRIDE;
|
||||
|
||||
// CefGeolocationHandler methods
|
||||
bool OnRequestGeolocationPermission(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
@ -323,6 +332,7 @@ class ClientHandler : public CefClient,
|
||||
bool canGoForward);
|
||||
void NotifyDraggableRegions(
|
||||
const std::vector<CefDraggableRegion>& regions);
|
||||
void NotifyTakeFocus(bool next);
|
||||
|
||||
// Test context menu creation.
|
||||
void BuildTestMenu(CefRefPtr<CefMenuModel> model);
|
||||
|
@ -329,6 +329,18 @@ void RootWindowViews::OnSetDraggableRegions(
|
||||
window_->SetDraggableRegions(regions);
|
||||
}
|
||||
|
||||
void RootWindowViews::OnTakeFocus(bool next) {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
// Execute this method on the UI thread.
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(&RootWindowViews::OnTakeFocus, this, next));
|
||||
return;
|
||||
}
|
||||
|
||||
if (window_)
|
||||
window_->TakeFocus(next);
|
||||
}
|
||||
|
||||
void RootWindowViews::CreateClientHandler(const std::string& url) {
|
||||
DCHECK(!client_handler_);
|
||||
|
||||
|
@ -73,6 +73,7 @@ class RootWindowViews : public RootWindow,
|
||||
bool canGoForward) OVERRIDE;
|
||||
void OnSetDraggableRegions(
|
||||
const std::vector<CefDraggableRegion>& regions) OVERRIDE;
|
||||
void OnTakeFocus(bool next) OVERRIDE;
|
||||
|
||||
private:
|
||||
void CreateClientHandler(const std::string& url);
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#if !defined(OS_WIN)
|
||||
#define VK_RETURN 0x0D
|
||||
#define VK_MENU 0x12 // ALT key.
|
||||
#endif
|
||||
|
||||
namespace client {
|
||||
@ -204,6 +205,21 @@ void ViewsWindow::SetDraggableRegions(
|
||||
window_->SetDraggableRegions(window_regions);
|
||||
}
|
||||
|
||||
void ViewsWindow::TakeFocus(bool next) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!window_ || !with_controls_)
|
||||
return;
|
||||
|
||||
if (next) {
|
||||
// Focus is moving forwards (tab). Give focus to the URL textfield.
|
||||
window_->GetViewForID(ID_URL_TEXTFIELD)->RequestFocus();
|
||||
} else {
|
||||
// Focus is moving backwards (tab+shift). Give focus to the menu button.
|
||||
window_->GetViewForID(ID_MENU_BUTTON)->RequestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewsWindow::OnPopupBrowserViewCreated(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
CefRefPtr<CefBrowserView> popup_browser_view,
|
||||
@ -345,6 +361,9 @@ void ViewsWindow::OnWindowCreated(CefRefPtr<CefWindow> window) {
|
||||
if (with_controls_) {
|
||||
// Add the BrowserView and other controls to the Window.
|
||||
AddControls();
|
||||
|
||||
// Add keyboard accelerators to the Window.
|
||||
AddAccelerators();
|
||||
} else {
|
||||
// Add the BrowserView as the only child of the Window.
|
||||
window_->AddChildView(browser_view_);
|
||||
@ -386,6 +405,33 @@ bool ViewsWindow::IsFrameless(CefRefPtr<CefWindow> window) {
|
||||
return frameless_;
|
||||
}
|
||||
|
||||
bool ViewsWindow::OnAccelerator(CefRefPtr<CefWindow> window, int command_id) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (command_id == ID_QUIT) {
|
||||
delegate_->OnExit();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ViewsWindow::OnKeyEvent(CefRefPtr<CefWindow> window,
|
||||
const CefKeyEvent& event) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!window_ || !with_controls_)
|
||||
return false;
|
||||
|
||||
if (event.type == KEYEVENT_RAWKEYDOWN && event.windows_key_code == VK_MENU) {
|
||||
// ALT key is pressed. Give focus to the menu button.
|
||||
window_->GetViewForID(ID_MENU_BUTTON)->RequestFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CefSize ViewsWindow::GetMinimumSize(CefRefPtr<CefView> view) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
@ -420,7 +466,7 @@ void ViewsWindow::CreateMenuModel() {
|
||||
menu_model_ = CefMenuModel::CreateMenuModel(this);
|
||||
|
||||
// Create the test menu.
|
||||
CefRefPtr<CefMenuModel> test_menu = menu_model_->AddSubMenu(0, "Tests");
|
||||
CefRefPtr<CefMenuModel> test_menu = menu_model_->AddSubMenu(0, "&Tests");
|
||||
test_menu->AddItem(ID_TESTS_GETSOURCE, "Get Source");
|
||||
test_menu->AddItem(ID_TESTS_GETTEXT, "Get Text");
|
||||
test_menu->AddItem(ID_TESTS_WINDOW_NEW, "New Window");
|
||||
@ -436,7 +482,10 @@ void ViewsWindow::CreateMenuModel() {
|
||||
test_menu->AddItem(ID_TESTS_PRINT_TO_PDF, "Print to PDF");
|
||||
test_menu->AddItem(ID_TESTS_OTHER_TESTS, "Other Tests");
|
||||
|
||||
menu_model_->AddItem(ID_QUIT, "Exit");
|
||||
menu_model_->AddItem(ID_QUIT, "E&xit");
|
||||
|
||||
// Show the accelerator shortcut text in the menu.
|
||||
menu_model_->SetAcceleratorAt(1, 'X', false, false, true);
|
||||
}
|
||||
|
||||
CefRefPtr<CefLabelButton> ViewsWindow::CreateBrowseButton(
|
||||
@ -473,6 +522,8 @@ void ViewsWindow::AddControls() {
|
||||
menu_button->SetImage(CEF_BUTTON_STATE_NORMAL, LoadImageIcon("menu_icon"));
|
||||
// Override the default minimum size.
|
||||
menu_button->SetMinimumSize(CefSize(0, 0));
|
||||
// Menu button must be focusable for keyboard access to work.
|
||||
menu_button->SetFocusable(true);
|
||||
|
||||
// Create the top panel.
|
||||
CefRefPtr<CefPanel> top_panel = CefPanel::CreatePanel(NULL);
|
||||
@ -524,6 +575,15 @@ void ViewsWindow::AddControls() {
|
||||
minimum_window_size_ = CefSize(min_width, min_height);
|
||||
}
|
||||
|
||||
void ViewsWindow::AddAccelerators() {
|
||||
// Trigger accelerators without first forwarding to web content.
|
||||
browser_view_->SetPreferAccelerators(true);
|
||||
|
||||
// Specify the accelerators to handle. OnAccelerator will be called when the
|
||||
// accelerator is triggered.
|
||||
window_->SetAccelerator(ID_QUIT, 'X', false, false, true);
|
||||
}
|
||||
|
||||
void ViewsWindow::EnableView(int id, bool enable) {
|
||||
if (!window_)
|
||||
return;
|
||||
|
@ -83,6 +83,7 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
bool canGoBack,
|
||||
bool canGoForward);
|
||||
void SetDraggableRegions(const std::vector<CefDraggableRegion>& regions);
|
||||
void TakeFocus(bool next);
|
||||
|
||||
// CefBrowserViewDelegate methods:
|
||||
bool OnPopupBrowserViewCreated(
|
||||
@ -111,6 +112,9 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
void OnWindowDestroyed(CefRefPtr<CefWindow> window) OVERRIDE;
|
||||
bool IsFrameless(CefRefPtr<CefWindow> window) OVERRIDE;
|
||||
bool CanClose(CefRefPtr<CefWindow> window) OVERRIDE;
|
||||
bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) OVERRIDE;
|
||||
bool OnKeyEvent(CefRefPtr<CefWindow> window,
|
||||
const CefKeyEvent& event) OVERRIDE;
|
||||
|
||||
// CefViewDelegate methods:
|
||||
CefSize GetMinimumSize(CefRefPtr<CefView> view) override;
|
||||
@ -131,6 +135,9 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
// Add controls to the Window.
|
||||
void AddControls();
|
||||
|
||||
// Add keyboard accelerators to the Window.
|
||||
void AddAccelerators();
|
||||
|
||||
// Enable or disable a view by |id|.
|
||||
void EnableView(int id, bool enable);
|
||||
|
||||
|
@ -250,10 +250,13 @@ void LabelButtonClick(CefRefPtr<CefWaitableEvent> event,
|
||||
bool with_button_text,
|
||||
bool with_button_image,
|
||||
bool with_window_frame) {
|
||||
TestWindowDelegate::RunTest(event,
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created =
|
||||
base::Bind(RunLabelButtonClick, with_button_frame, with_button_text,
|
||||
with_button_image),
|
||||
!with_window_frame, false);
|
||||
with_button_image);
|
||||
config.frameless = !with_window_frame;
|
||||
config.close_window = false;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void LabelButtonClickFramedWithTextWithImageFramedWindowImpl(
|
||||
@ -465,10 +468,13 @@ void MenuButtonClick(CefRefPtr<CefWaitableEvent> event,
|
||||
bool with_button_menu_marker,
|
||||
bool with_button_image,
|
||||
bool with_window_frame) {
|
||||
TestWindowDelegate::RunTest(event,
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created =
|
||||
base::Bind(RunMenuButtonClick, with_button_frame, with_button_text,
|
||||
with_button_menu_marker, with_button_image),
|
||||
!with_window_frame, false);
|
||||
with_button_menu_marker, with_button_image);
|
||||
config.frameless = !with_window_frame;
|
||||
config.close_window = false;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void MenuButtonClickFramedWithTextWithMarkerWithImageFramedWindowImpl(
|
||||
|
@ -133,8 +133,9 @@ void RunScrollViewLayout(bool with_delegate,
|
||||
|
||||
void ScrollViewLayout(CefRefPtr<CefWaitableEvent> event,
|
||||
bool with_delegate) {
|
||||
TestWindowDelegate::RunTest(event,
|
||||
base::Bind(RunScrollViewLayout, with_delegate), false);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunScrollViewLayout, with_delegate);
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void ScrollViewLayoutWithDelegateImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
|
@ -23,13 +23,9 @@ const int TestWindowDelegate::kWSize = 400;
|
||||
|
||||
// static
|
||||
void TestWindowDelegate::RunTest(CefRefPtr<CefWaitableEvent> event,
|
||||
const WindowTest& window_test,
|
||||
bool frameless,
|
||||
bool close_window,
|
||||
int window_size) {
|
||||
const Config& config) {
|
||||
CefWindow::CreateTopLevelWindow(
|
||||
new TestWindowDelegate(event, window_test, frameless, close_window,
|
||||
window_size));
|
||||
new TestWindowDelegate(event, config));
|
||||
}
|
||||
|
||||
void TestWindowDelegate::OnWindowCreated(CefRefPtr<CefWindow> window) {
|
||||
@ -60,22 +56,22 @@ void TestWindowDelegate::OnWindowCreated(CefRefPtr<CefWindow> window) {
|
||||
// Size will come from GetPreferredSize() on initial Window creation.
|
||||
EXPECT_TRUE(got_get_preferred_size_);
|
||||
CefRect client_bounds = window->GetClientAreaBoundsInScreen();
|
||||
if (frameless_) {
|
||||
EXPECT_EQ(window_size_, client_bounds.width);
|
||||
EXPECT_EQ(window_size_, client_bounds.height);
|
||||
if (config_.frameless) {
|
||||
EXPECT_EQ(config_.window_size, client_bounds.width);
|
||||
EXPECT_EQ(config_.window_size, client_bounds.height);
|
||||
} else {
|
||||
// Client area bounds calculation might have off-by-one errors on Windows
|
||||
// due to non-client frame size being calculated internally in pixels and
|
||||
// then converted to DIPs. See http://crbug.com/602692.
|
||||
EXPECT_TRUE(abs(client_bounds.width - window_size_) <= 1);
|
||||
EXPECT_TRUE(abs(client_bounds.height - window_size_) <= 1);
|
||||
EXPECT_TRUE(abs(client_bounds.width - config_.window_size) <= 1);
|
||||
EXPECT_TRUE(abs(client_bounds.height - config_.window_size) <= 1);
|
||||
}
|
||||
|
||||
// Run the requested test.
|
||||
if (!window_test_.is_null())
|
||||
window_test_.Run(window);
|
||||
// Run the callback.
|
||||
if (!config_.on_window_created.is_null())
|
||||
config_.on_window_created.Run(window);
|
||||
|
||||
if (close_window_) {
|
||||
if (config_.close_window) {
|
||||
// Close the window asynchronously.
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(&TestWindowDelegate::OnCloseWindow, this));
|
||||
@ -97,6 +93,10 @@ void TestWindowDelegate::OnWindowDestroyed(CefRefPtr<CefWindow> window) {
|
||||
EXPECT_FALSE(window->IsVisible());
|
||||
EXPECT_FALSE(window->IsDrawn());
|
||||
|
||||
// Run the callback.
|
||||
if (!config_.on_window_destroyed.is_null())
|
||||
config_.on_window_destroyed.Run(window);
|
||||
|
||||
window_ = nullptr;
|
||||
|
||||
// Don't execute the timeout callback.
|
||||
@ -104,24 +104,32 @@ void TestWindowDelegate::OnWindowDestroyed(CefRefPtr<CefWindow> window) {
|
||||
}
|
||||
|
||||
bool TestWindowDelegate::IsFrameless(CefRefPtr<CefWindow> window) {
|
||||
return frameless_;
|
||||
return config_.frameless;
|
||||
}
|
||||
|
||||
CefSize TestWindowDelegate::GetPreferredSize(CefRefPtr<CefView> view) {
|
||||
got_get_preferred_size_ = true;
|
||||
return CefSize(window_size_, window_size_);
|
||||
return CefSize(config_.window_size, config_.window_size);
|
||||
}
|
||||
|
||||
bool TestWindowDelegate::OnAccelerator(CefRefPtr<CefWindow> window,
|
||||
int command_id) {
|
||||
if (!config_.on_accelerator.is_null())
|
||||
return config_.on_accelerator.Run(window_, command_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TestWindowDelegate::OnKeyEvent(CefRefPtr<CefWindow> window,
|
||||
const CefKeyEvent& event) {
|
||||
if (!config_.on_key_event.is_null())
|
||||
return config_.on_key_event.Run(window_, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
TestWindowDelegate::TestWindowDelegate(CefRefPtr<CefWaitableEvent> event,
|
||||
const WindowTest& window_test,
|
||||
bool frameless,
|
||||
bool close_window,
|
||||
int window_size)
|
||||
const Config& config)
|
||||
: event_(event),
|
||||
window_test_(window_test),
|
||||
frameless_(frameless),
|
||||
close_window_(close_window),
|
||||
window_size_(window_size),
|
||||
config_(config),
|
||||
weak_ptr_factory_(this) {
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,21 @@ class TestWindowDelegate : public CefWindowDelegate {
|
||||
static const int kWSize;
|
||||
|
||||
// Test execution callback.
|
||||
typedef base::Callback<void(CefRefPtr<CefWindow>)> WindowTest;
|
||||
typedef base::Callback<void(CefRefPtr<CefWindow>)> OnWindowCreatedCallback;
|
||||
typedef base::Callback<void(CefRefPtr<CefWindow>)> OnWindowDestroyedCallback;
|
||||
typedef base::Callback<bool(CefRefPtr<CefWindow>,int)> OnAcceleratorCallback;
|
||||
typedef base::Callback<bool(CefRefPtr<CefWindow>,const CefKeyEvent&)>
|
||||
OnKeyEventCallback;
|
||||
|
||||
struct Config {
|
||||
OnWindowCreatedCallback on_window_created;
|
||||
OnWindowDestroyedCallback on_window_destroyed;
|
||||
OnAcceleratorCallback on_accelerator;
|
||||
OnKeyEventCallback on_key_event;
|
||||
bool frameless = false;
|
||||
bool close_window = true;
|
||||
int window_size = kWSize;
|
||||
};
|
||||
|
||||
// Creates a Window with a new TestWindowDelegate instance and executes
|
||||
// |window_test| after the Window is created. |event| will be signaled once
|
||||
@ -23,33 +37,27 @@ class TestWindowDelegate : public CefWindowDelegate {
|
||||
// immediately after |window_test| returns. Otherwise, the caller is
|
||||
// responsible for closing the Window passed to |window_test|.
|
||||
static void RunTest(CefRefPtr<CefWaitableEvent> event,
|
||||
const WindowTest& window_test,
|
||||
bool frameless = false,
|
||||
bool close_window = true,
|
||||
int window_size = kWSize);
|
||||
const Config& config);
|
||||
|
||||
// CefWindowDelegate methods:
|
||||
void OnWindowCreated(CefRefPtr<CefWindow> window) override;
|
||||
void OnWindowDestroyed(CefRefPtr<CefWindow> window) override;
|
||||
bool IsFrameless(CefRefPtr<CefWindow> window) override;
|
||||
CefSize GetPreferredSize(CefRefPtr<CefView> view) override;
|
||||
bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) override;
|
||||
bool OnKeyEvent(CefRefPtr<CefWindow> window,
|
||||
const CefKeyEvent& event) override;
|
||||
|
||||
private:
|
||||
TestWindowDelegate(CefRefPtr<CefWaitableEvent> event,
|
||||
const WindowTest& window_test,
|
||||
bool frameless,
|
||||
bool close_window,
|
||||
int window_size);
|
||||
const Config& config);
|
||||
~TestWindowDelegate() override;
|
||||
|
||||
void OnCloseWindow();
|
||||
void OnTimeoutWindow();
|
||||
|
||||
CefRefPtr<CefWaitableEvent> event_;
|
||||
WindowTest window_test_;
|
||||
bool frameless_;
|
||||
bool close_window_;
|
||||
int window_size_;
|
||||
Config config_;
|
||||
|
||||
CefRefPtr<CefWindow> window_;
|
||||
|
||||
|
@ -278,8 +278,10 @@ void RunTextfieldKeyEvent(CefRefPtr<CefWindow> window) {
|
||||
}
|
||||
|
||||
void TextfieldKeyEventImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event,
|
||||
base::Bind(RunTextfieldKeyEvent), false, false);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunTextfieldKeyEvent);
|
||||
config.close_window = false;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -14,6 +14,10 @@
|
||||
|
||||
#define WINDOW_TEST_ASYNC(name) UI_THREAD_TEST_ASYNC(ViewsWindowTest, name)
|
||||
|
||||
#if !defined(OS_WIN)
|
||||
#define VK_MENU 0x12 // ALT key.
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
// Window state change delay in MS.
|
||||
@ -33,11 +37,14 @@ void ExpectCloseRects(const CefRect& expected,
|
||||
}
|
||||
|
||||
void WindowCreateImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, TestWindowDelegate::WindowTest(), false);
|
||||
TestWindowDelegate::Config config;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void WindowCreateFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, TestWindowDelegate::WindowTest(), true);
|
||||
TestWindowDelegate::Config config;
|
||||
config.frameless = true;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void RunWindowShowHide(CefRefPtr<CefWindow> window) {
|
||||
@ -52,11 +59,16 @@ void RunWindowShowHide(CefRefPtr<CefWindow> window) {
|
||||
}
|
||||
|
||||
void WindowShowHideImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, base::Bind(RunWindowShowHide), false);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowShowHide);
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void WindowShowHideFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, base::Bind(RunWindowShowHide), true);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowShowHide);
|
||||
config.frameless = true;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
const int kWPanel1ID = 1;
|
||||
@ -180,11 +192,16 @@ void RunWindowLayoutAndCoords(CefRefPtr<CefWindow> window) {
|
||||
}
|
||||
|
||||
void WindowLayoutAndCoordsImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, base::Bind(RunWindowLayoutAndCoords), false);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowLayoutAndCoords);
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void WindowLayoutAndCoordsFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, base::Bind(RunWindowLayoutAndCoords), true);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowLayoutAndCoords);
|
||||
config.frameless = true;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void VerifyRestore(CefRefPtr<CefWindow> window) {
|
||||
@ -223,13 +240,18 @@ void RunWindowMaximize(CefRefPtr<CefWindow> window) {
|
||||
}
|
||||
|
||||
void WindowMaximizeImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, base::Bind(RunWindowMaximize), false,
|
||||
false);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowMaximize);
|
||||
config.close_window = false;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void WindowMaximizeFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, base::Bind(RunWindowMaximize), true,
|
||||
false);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowMaximize);
|
||||
config.frameless = true;
|
||||
config.close_window = false;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void VerifyMinimize(CefRefPtr<CefWindow> window) {
|
||||
@ -260,13 +282,18 @@ void RunWindowMinimize(CefRefPtr<CefWindow> window) {
|
||||
}
|
||||
|
||||
void WindowMinimizeImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, base::Bind(RunWindowMinimize), false,
|
||||
false);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowMinimize);
|
||||
config.close_window = false;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void WindowMinimizeFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, base::Bind(RunWindowMinimize), true,
|
||||
false);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowMinimize);
|
||||
config.frameless = true;
|
||||
config.close_window = false;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void VerifyFullscreenExit(CefRefPtr<CefWindow> window) {
|
||||
@ -307,13 +334,18 @@ void RunWindowFullscreen(CefRefPtr<CefWindow> window) {
|
||||
}
|
||||
|
||||
void WindowFullscreenImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, base::Bind(RunWindowFullscreen), false,
|
||||
false);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowFullscreen);
|
||||
config.close_window = false;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void WindowFullscreenFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, base::Bind(RunWindowFullscreen), true,
|
||||
false);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowFullscreen);
|
||||
config.frameless = true;
|
||||
config.close_window = false;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void RunWindowIcon(CefRefPtr<CefWindow> window) {
|
||||
@ -333,11 +365,113 @@ void RunWindowIcon(CefRefPtr<CefWindow> window) {
|
||||
}
|
||||
|
||||
void WindowIconImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, base::Bind(RunWindowIcon), false);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowIcon);
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
void WindowIconFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
TestWindowDelegate::RunTest(event, base::Bind(RunWindowIcon), true);
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowIcon);
|
||||
config.frameless = true;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
const int kChar = 'A';
|
||||
const int kCloseWindowId = 2;
|
||||
bool got_accelerator;
|
||||
int got_key_event_alt_count;
|
||||
bool got_key_event_char;
|
||||
|
||||
void TriggerAccelerator(CefRefPtr<CefWindow> window) {
|
||||
window->SendKeyPress(kChar, EVENTFLAG_ALT_DOWN);
|
||||
}
|
||||
|
||||
bool OnKeyEvent(CefRefPtr<CefWindow> window, const CefKeyEvent& event) {
|
||||
if (event.type != KEYEVENT_RAWKEYDOWN)
|
||||
return false;
|
||||
|
||||
if (event.windows_key_code == VK_MENU) {
|
||||
// First we get the ALT key press in all cases.
|
||||
EXPECT_FALSE(got_key_event_char);
|
||||
if (got_key_event_alt_count == 0)
|
||||
EXPECT_FALSE(got_accelerator);
|
||||
else
|
||||
EXPECT_TRUE(got_accelerator);
|
||||
|
||||
EXPECT_EQ(event.modifiers, EVENTFLAG_ALT_DOWN);
|
||||
got_key_event_alt_count++;
|
||||
} else if (event.windows_key_code == kChar) {
|
||||
// Then we get the char key press with the ALT modifier if the accelerator
|
||||
// isn't registered.
|
||||
EXPECT_TRUE(got_accelerator);
|
||||
EXPECT_EQ(got_key_event_alt_count, 2);
|
||||
EXPECT_FALSE(got_key_event_char);
|
||||
|
||||
EXPECT_EQ(event.modifiers, EVENTFLAG_ALT_DOWN);
|
||||
got_key_event_char = true;
|
||||
|
||||
// Call this method just to make sure it doesn't crash.
|
||||
window->RemoveAllAccelerators();
|
||||
|
||||
// End the test by closing the Window.
|
||||
window->Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) {
|
||||
EXPECT_FALSE(got_accelerator);
|
||||
EXPECT_EQ(got_key_event_alt_count, 1);
|
||||
EXPECT_FALSE(got_key_event_char);
|
||||
|
||||
EXPECT_EQ(kCloseWindowId, command_id);
|
||||
got_accelerator = true;
|
||||
|
||||
// Remove the accelerator.
|
||||
window->RemoveAccelerator(kCloseWindowId);
|
||||
|
||||
// Now send the event without the accelerator registered. Should result in a
|
||||
// call to OnKeyEvent.
|
||||
TriggerAccelerator(window);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RunWindowAccelerator(CefRefPtr<CefWindow> window) {
|
||||
window->SetAccelerator(kCloseWindowId, kChar, false, false, true);
|
||||
window->Show();
|
||||
|
||||
CefPostDelayedTask(TID_UI, base::Bind(TriggerAccelerator, window),
|
||||
kStateDelayMS);
|
||||
}
|
||||
|
||||
void VerifyWindowAccelerator(CefRefPtr<CefWindow> window) {
|
||||
EXPECT_TRUE(got_accelerator);
|
||||
EXPECT_EQ(got_key_event_alt_count, 2);
|
||||
EXPECT_TRUE(got_key_event_char);
|
||||
}
|
||||
|
||||
// Expected order of events:
|
||||
// 1. OnKeyEvent for ALT key press.
|
||||
// 2. OnAccelerator for ALT+Char key press (with accelerator registered).
|
||||
// 3. OnKeyEvent for ALT key press.
|
||||
// 4. OnKeyEvent for ALT+Char key press (without accelerator registered).
|
||||
void WindowAcceleratorImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
got_accelerator = false;
|
||||
got_key_event_alt_count = 0;
|
||||
got_key_event_char = false;
|
||||
|
||||
TestWindowDelegate::Config config;
|
||||
config.on_window_created = base::Bind(RunWindowAccelerator);
|
||||
config.on_window_destroyed = base::Bind(VerifyWindowAccelerator);
|
||||
config.on_accelerator = base::Bind(OnAccelerator);
|
||||
config.on_key_event = base::Bind(OnKeyEvent);
|
||||
config.close_window = false;
|
||||
TestWindowDelegate::RunTest(event, config);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -359,3 +493,4 @@ WINDOW_TEST_ASYNC(WindowFullscreen);
|
||||
WINDOW_TEST_ASYNC(WindowFullscreenFrameless);
|
||||
WINDOW_TEST_ASYNC(WindowIcon);
|
||||
WINDOW_TEST_ASYNC(WindowIconFrameless);
|
||||
WINDOW_TEST_ASYNC(WindowAccelerator);
|
||||
|
Loading…
x
Reference in New Issue
Block a user