Commit 745816be authored by mazda@chromium.org's avatar mazda@chromium.org

Add ShellAcceleratorController that manages global keyboard accelerators.

- Create ShellAcceleratorController that manages global keyboard accelerators and also processes several accelerators as a target.
- Create ShellAcceleratorFilter, which is used by DesktopEventFilter to handle accelerators.
- Add a function to Shell for accessing ShellAcceleratorController.

The 1st attempt (http://crrev.com/110637) broke aura_shell_unittests and this fixes it.
The differences are
- moving ShellAcceleratorFilter to Shell from DesktopEventFilter, and
- adding the ShellAcceleratorFilter in Shell initialization code to DesktopEventFilter.

BUG=97255
TEST=Manual, aura_shell_unittests succeeds.


Review URL: http://codereview.chromium.org/8561012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111100 0039d316-1c4b-4281-b951-d872f2087c98
parent 0f83a23a
......@@ -26,10 +26,7 @@
#include "ui/base/hit_test.h"
#include "ui/gfx/compositor/compositor.h"
#include "ui/gfx/compositor/layer.h"
#include "ui/gfx/compositor/layer_animation_sequence.h"
#include "ui/gfx/compositor/layer_animator.h"
#include "ui/gfx/compositor/screen_rotation.h"
#include "ui/gfx/interpolated_transform.h"
#ifdef USE_WEBKIT_COMPOSITOR
#include "ui/gfx/compositor/compositor_cc.h"
......@@ -99,50 +96,6 @@ void GetEventFiltersToNotify(Window* target, EventFilters* filters) {
}
}
#if !defined(NDEBUG)
bool MaybeFullScreen(DesktopHost* host, KeyEvent* event) {
if (event->key_code() == ui::VKEY_F11) {
host->ToggleFullScreen();
return true;
}
return false;
}
bool MaybeRotate(Desktop* desktop, KeyEvent* event) {
if ((event->flags() & ui::EF_CONTROL_DOWN) &&
event->key_code() == ui::VKEY_HOME) {
static int i = 0;
int delta = 0;
switch (i) {
case 0: delta = 90; break;
case 1: delta = 90; break;
case 2: delta = 90; break;
case 3: delta = 90; break;
case 4: delta = -90; break;
case 5: delta = -90; break;
case 6: delta = -90; break;
case 7: delta = -90; break;
case 8: delta = -90; break;
case 9: delta = 180; break;
case 10: delta = 180; break;
case 11: delta = 90; break;
case 12: delta = 180; break;
case 13: delta = 180; break;
}
i = (i + 1) % 14;
desktop->layer()->GetAnimator()->set_preemption_strategy(
ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
scoped_ptr<ui::LayerAnimationSequence> screen_rotation(
new ui::LayerAnimationSequence(new ui::ScreenRotation(delta)));
screen_rotation->AddObserver(desktop);
desktop->layer()->GetAnimator()->ScheduleAnimation(
screen_rotation.release());
return true;
}
return false;
}
#endif
} // namespace
Desktop* Desktop::instance_ = NULL;
......@@ -285,14 +238,6 @@ bool Desktop::DispatchMouseEvent(MouseEvent* event) {
}
bool Desktop::DispatchKeyEvent(KeyEvent* event) {
#if !defined(NDEBUG)
// TODO(beng): replace this hack with global keyboard event handlers.
if (event->type() == ui::ET_KEY_PRESSED) {
if (MaybeFullScreen(host_.get(), event) || MaybeRotate(this, event))
return true;
}
#endif
if (focused_window_) {
KeyEvent translated_event(*event);
return ProcessKeyEvent(focused_window_, &translated_event);
......@@ -470,6 +415,12 @@ void Desktop::SetTransform(const ui::Transform& transform) {
OnHostResized(host_->GetSize());
}
#if !defined(NDEBUG)
void Desktop::ToggleFullScreen() {
host_->ToggleFullScreen();
}
#endif
void Desktop::HandleMouseMoved(const MouseEvent& event, Window* target) {
if (target == mouse_moved_handler_)
return;
......
......@@ -142,6 +142,11 @@ class AURA_EXPORT Desktop : public ui::CompositorDelegate,
// Overridden from Window:
virtual void SetTransform(const ui::Transform& transform) OVERRIDE;
#if !defined(NDEBUG)
// Toggles the host's full screen state.
void ToggleFullScreen();
#endif
private:
// Called whenever the mouse moves, tracks the current |mouse_moved_handler_|,
// sending exited and entered events as its value changes.
......
......@@ -84,6 +84,10 @@
'shelf_layout_controller.h',
'shell.cc',
'shell.h',
'shell_accelerator_controller.cc',
'shell_accelerator_controller.h',
'shell_accelerator_filter.cc',
'shell_accelerator_filter.h',
'shell_delegate.h',
'shell_factory.h',
'shell_window_ids.h',
......
......@@ -22,6 +22,8 @@
#include "ui/aura_shell/modal_container_layout_manager.h"
#include "ui/aura_shell/shadow_controller.h"
#include "ui/aura_shell/shelf_layout_controller.h"
#include "ui/aura_shell/shell_accelerator_controller.h"
#include "ui/aura_shell/shell_accelerator_filter.h"
#include "ui/aura_shell/shell_delegate.h"
#include "ui/aura_shell/shell_factory.h"
#include "ui/aura_shell/shell_window_ids.h"
......@@ -100,6 +102,7 @@ Shell* Shell::instance_ = NULL;
Shell::Shell(ShellDelegate* delegate)
: ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
accelerator_controller_(new ShellAcceleratorController),
delegate_(delegate) {
aura::Desktop::GetInstance()->SetEventFilter(
new internal::DesktopEventFilter);
......@@ -108,6 +111,8 @@ Shell::Shell(ShellDelegate* delegate)
}
Shell::~Shell() {
RemoveDesktopEventFilter(accelerator_filter_.get());
// Drag drop controller needs a valid shell instance. We destroy it first.
drag_drop_controller_.reset();
......@@ -191,6 +196,11 @@ void Shell::Init() {
// Force a layout.
desktop_layout->OnWindowResized();
// Initialize ShellAcceleratorFilter
accelerator_filter_.reset(new internal::ShellAcceleratorFilter);
AddDesktopEventFilter(accelerator_filter_.get());
// Initialize drag drop controller.
drag_drop_controller_.reset(new internal::DragDropController);
aura::Desktop::GetInstance()->SetProperty(aura::kDesktopDragDropClientKey,
static_cast<aura::DragDropClient*>(drag_drop_controller_.get()));
......
......@@ -27,6 +27,7 @@ class Rect;
namespace aura_shell {
class Launcher;
class ShellAcceleratorController;
class ShellDelegate;
namespace internal {
......@@ -34,6 +35,7 @@ class AppList;
class DragDropController;
class ShadowController;
class ShelfLayoutController;
class ShellAcceleratorFilter;
class WorkspaceController;
}
......@@ -66,6 +68,10 @@ class AURA_SHELL_EXPORT Shell {
// Toggles app list.
void ToggleAppList();
ShellAcceleratorController* accelerator_controller() {
return accelerator_controller_.get();
}
ShellDelegate* delegate() { return delegate_.get(); }
Launcher* launcher() { return launcher_.get(); }
......@@ -91,6 +97,8 @@ class AURA_SHELL_EXPORT Shell {
base::WeakPtrFactory<Shell> method_factory_;
scoped_ptr<ShellAcceleratorController> accelerator_controller_;
scoped_ptr<ShellDelegate> delegate_;
scoped_ptr<Launcher> launcher_;
......@@ -102,6 +110,9 @@ class AURA_SHELL_EXPORT Shell {
scoped_ptr<internal::ShelfLayoutController> shelf_layout_controller_;
scoped_ptr<internal::ShadowController> shadow_controller_;
// An event filter that pre-handles global accelerators.
scoped_ptr<internal::ShellAcceleratorFilter> accelerator_filter_;
DISALLOW_COPY_AND_ASSIGN(Shell);
};
......
// Copyright (c) 2011 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 "ui/aura_shell/shell_accelerator_controller.h"
#include "ui/aura/desktop.h"
#include "ui/aura/event.h"
#include "ui/aura_shell/shell.h"
#include "ui/base/accelerator_manager.h"
#include "ui/base/models/accelerator.h"
#include "ui/gfx/compositor/layer_animation_sequence.h"
#include "ui/gfx/compositor/layer_animator.h"
#include "ui/gfx/compositor/screen_rotation.h"
namespace {
// Acceleraters handled by ShellAcceleratorController.
struct AcceleratorData {
ui::KeyboardCode keycode;
bool shift;
bool ctrl;
bool alt;
} kAcceleratorData[] = {
{ ui::VKEY_F11, false, false, false },
{ ui::VKEY_HOME, false, true, false },
};
// Registers the accelerators with ShellAcceleratorController.
void RegisterAccelerators(aura_shell::ShellAcceleratorController* controller) {
for (size_t i = 0; i < arraysize(kAcceleratorData); ++i) {
controller->Register(ui::Accelerator(kAcceleratorData[i].keycode,
kAcceleratorData[i].shift,
kAcceleratorData[i].ctrl,
kAcceleratorData[i].alt),
controller);
}
}
#if !defined(NDEBUG)
// Rotates the screen.
void RotateScreen() {
static int i = 0;
int delta = 0;
switch (i) {
case 0: delta = 90; break;
case 1: delta = 90; break;
case 2: delta = 90; break;
case 3: delta = 90; break;
case 4: delta = -90; break;
case 5: delta = -90; break;
case 6: delta = -90; break;
case 7: delta = -90; break;
case 8: delta = -90; break;
case 9: delta = 180; break;
case 10: delta = 180; break;
case 11: delta = 90; break;
case 12: delta = 180; break;
case 13: delta = 180; break;
}
i = (i + 1) % 14;
aura::Desktop::GetInstance()->layer()->GetAnimator()->set_preemption_strategy(
ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
scoped_ptr<ui::LayerAnimationSequence> screen_rotation(
new ui::LayerAnimationSequence(new ui::ScreenRotation(delta)));
screen_rotation->AddObserver(aura::Desktop::GetInstance());
aura::Desktop::GetInstance()->layer()->GetAnimator()->ScheduleAnimation(
screen_rotation.release());
}
#endif
} // namespace
namespace aura_shell {
////////////////////////////////////////////////////////////////////////////////
// ShellAcceleratorController, public:
ShellAcceleratorController::ShellAcceleratorController()
: accelerator_manager_(new ui::AcceleratorManager) {
RegisterAccelerators(this);
}
ShellAcceleratorController::~ShellAcceleratorController() {
}
void ShellAcceleratorController::Register(
const ui::Accelerator& accelerator,
ui::AcceleratorTarget* target) {
accelerator_manager_->Register(accelerator, target);
}
void ShellAcceleratorController::Unregister(
const ui::Accelerator& accelerator,
ui::AcceleratorTarget* target) {
accelerator_manager_->Unregister(accelerator, target);
}
void ShellAcceleratorController::UnregisterAll(
ui::AcceleratorTarget* target) {
accelerator_manager_->UnregisterAll(target);
}
bool ShellAcceleratorController::Process(const ui::Accelerator& accelerator) {
return accelerator_manager_->Process(accelerator);
}
////////////////////////////////////////////////////////////////////////////////
// ShellAcceleratorController, ui::AcceleratorTarget implementation:
bool ShellAcceleratorController::AcceleratorPressed(
const ui::Accelerator& accelerator) {
#if !defined(NDEBUG)
if (accelerator.key_code() == ui::VKEY_F11) {
aura::Desktop::GetInstance()->ToggleFullScreen();
return true;
} else if (accelerator.key_code() == ui::VKEY_HOME &&
accelerator.IsCtrlDown()) {
RotateScreen();
return true;
}
#endif
return false;
}
} // namespace aura_shell
// Copyright (c) 2011 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 UI_AURA_SHELL_SHELL_ACCELERATOR_CONTROLLER_H_
#define UI_AURA_SHELL_SHELL_ACCELERATOR_CONTROLLER_H_
#pragma once
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "ui/aura_shell/aura_shell_export.h"
#include "ui/base/models/accelerator.h"
namespace ui {
class AcceleratorManager;
} // namespace ui
namespace aura_shell {
// ShellAcceleratorController provides functions for registering or
// unregistering global keyboard accelerators, which are handled earlier than
// any windows. It also implements several handlers as an accelerator target.
class AURA_SHELL_EXPORT ShellAcceleratorController
: public ui::AcceleratorTarget {
public:
ShellAcceleratorController();
virtual ~ShellAcceleratorController();
// Register a global keyboard accelerator for the specified target. If
// multiple targets are registered for an accelerator, a target registered
// later has higher priority.
void Register(const ui::Accelerator& accelerator,
ui::AcceleratorTarget* target);
// Unregister the specified keyboard accelerator for the specified target.
void Unregister(const ui::Accelerator& accelerator,
ui::AcceleratorTarget* target);
// Unregister all keyboard accelerators for the specified target.
void UnregisterAll(ui::AcceleratorTarget* target);
// Activate the target associated with the specified accelerator.
// First, AcceleratorPressed handler of the most recently registered target
// is called, and if that handler processes the event (i.e. returns true),
// this method immediately returns. If not, we do the same thing on the next
// target, and so on.
// Returns true if an accelerator was activated.
bool Process(const ui::Accelerator& accelerator);
// Overridden from ui::AcceleratorTarget:
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
private:
scoped_ptr<ui::AcceleratorManager> accelerator_manager_;
DISALLOW_COPY_AND_ASSIGN(ShellAcceleratorController);
};
} // namespace aura_shell
#endif // UI_AURA_SHELL_SHELL_ACCELERATOR_CONTROLLER_H_
// Copyright (c) 2011 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 "ui/aura_shell/shell_accelerator_filter.h"
#include "ui/aura/desktop.h"
#include "ui/aura/event.h"
#include "ui/aura_shell/shell.h"
#include "ui/aura_shell/shell_accelerator_controller.h"
#include "ui/base/accelerator_manager.h"
#include "ui/base/models/accelerator.h"
namespace {
const int kModifierFlagMask = (ui::EF_SHIFT_DOWN |
ui::EF_CONTROL_DOWN |
ui::EF_ALT_DOWN);
} // namespace
namespace aura_shell {
namespace internal {
////////////////////////////////////////////////////////////////////////////////
// ShellAcceleratorFilter, public:
ShellAcceleratorFilter::ShellAcceleratorFilter()
: EventFilter(aura::Desktop::GetInstance()) {
}
ShellAcceleratorFilter::~ShellAcceleratorFilter() {
}
////////////////////////////////////////////////////////////////////////////////
// ShellAcceleratorFilter, EventFilter implementation:
bool ShellAcceleratorFilter::PreHandleKeyEvent(aura::Window* target,
aura::KeyEvent* event) {
if (event->type() == ui::ET_KEY_PRESSED &&
Shell::GetInstance()->accelerator_controller()->Process(
ui::Accelerator(event->key_code(),
event->flags() & kModifierFlagMask))) {
return true;
}
return false;
}
bool ShellAcceleratorFilter::PreHandleMouseEvent(aura::Window* target,
aura::MouseEvent* event) {
return false;
}
ui::TouchStatus ShellAcceleratorFilter::PreHandleTouchEvent(
aura::Window* target,
aura::TouchEvent* event) {
return ui::TOUCH_STATUS_UNKNOWN;
}
} // namespace internal
} // namespace aura_shell
// Copyright (c) 2011 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 UI_AURA_SHELL_SHELL_ACCELERATOR_FILTER_H_
#define UI_AURA_SHELL_SHELL_ACCELERATOR_FILTER_H_
#pragma once
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "ui/aura/event_filter.h"
#include "ui/aura_shell/aura_shell_export.h"
namespace aura_shell {
namespace internal {
// ShellAcceleratorFilter filters key events for ShellAcceleratorControler
// handling global keyboard accelerators.
class AURA_SHELL_EXPORT ShellAcceleratorFilter : public aura::EventFilter {
public:
ShellAcceleratorFilter();
virtual ~ShellAcceleratorFilter();
// Overridden from aura::EventFilter:
virtual bool PreHandleKeyEvent(aura::Window* target,
aura::KeyEvent* event) OVERRIDE;
virtual bool PreHandleMouseEvent(aura::Window* target,
aura::MouseEvent* event) OVERRIDE;
virtual ui::TouchStatus PreHandleTouchEvent(aura::Window* target,
aura::TouchEvent* event) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(ShellAcceleratorFilter);
};
} // namespace internal
} // namespace aura_shell
#endif // UI_AURA_SHELL_SHELL_ACCELERATOR_FILTER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment