mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
views: Add support for accelerators (issue #2102)
This commit is contained in:
@@ -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);
|
||||
|
Reference in New Issue
Block a user