Commit dbe71383 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.

BUG=97255
TEST=Manual


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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110637 0039d316-1c4b-4281-b951-d872f2087c98
parent 62e3e655
......@@ -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"
using std::string;
using std::vector;
......@@ -95,50 +92,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;
......@@ -274,14 +227,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);
......@@ -451,6 +396,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;
......
......@@ -136,6 +136,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.
......
......@@ -76,6 +76,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',
......
......@@ -9,6 +9,7 @@
#include "ui/aura/focus_manager.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura_shell/shell.h"
#include "ui/aura_shell/shell_accelerator_filter.h"
#include "ui/aura_shell/stacking_controller.h"
#include "ui/base/hit_test.h"
......@@ -43,13 +44,16 @@ gfx::NativeCursor CursorForWindowComponent(int window_component) {
// DesktopEventFilter, public:
DesktopEventFilter::DesktopEventFilter()
: EventFilter(aura::Desktop::GetInstance()) {
: EventFilter(aura::Desktop::GetInstance()),
shell_accelerator_filter_(new ShellAcceleratorFilter) {
AddFilter(shell_accelerator_filter_.get());
}
DesktopEventFilter::~DesktopEventFilter() {
// Additional filters are not owned by DesktopEventFilter and they
// should all be removed when running here. |filters_| has
// check_empty == true and will DCHECK failure if it is not empty.
RemoveFilter(shell_accelerator_filter_.get());
}
void DesktopEventFilter::AddFilter(aura::EventFilter* filter) {
......
......@@ -7,6 +7,7 @@
#pragma once
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "ui/aura/event_filter.h"
#include "ui/aura_shell/aura_shell_export.h"
......@@ -14,6 +15,8 @@
namespace aura_shell {
namespace internal {
class ShellAcceleratorFilter;
// DesktopEventFilter gets all desktop events first and can provide actions to
// those events. It implements desktop features such as click to activate a
// window and cursor change when moving mouse.
......@@ -56,6 +59,9 @@ class AURA_SHELL_EXPORT DesktopEventFilter : public aura::EventFilter {
// Additional event filters that pre-handles events.
ObserverList<aura::EventFilter, true> filters_;
// An event filter that pre-handles global accelerators.
scoped_ptr<ShellAcceleratorFilter> shell_accelerator_filter_;
DISALLOW_COPY_AND_ASSIGN(DesktopEventFilter);
};
......
......@@ -20,6 +20,7 @@
#include "ui/aura_shell/launcher/launcher.h"
#include "ui/aura_shell/modal_container_layout_manager.h"
#include "ui/aura_shell/shelf_layout_controller.h"
#include "ui/aura_shell/shell_accelerator_controller.h"
#include "ui/aura_shell/shell_delegate.h"
#include "ui/aura_shell/shell_factory.h"
#include "ui/aura_shell/shell_window_ids.h"
......@@ -98,6 +99,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);
......
......@@ -27,6 +27,7 @@ class Rect;
namespace aura_shell {
class Launcher;
class ShellAcceleratorController;
class ShellDelegate;
namespace internal {
......@@ -61,6 +62,9 @@ class AURA_SHELL_EXPORT Shell {
// Toggles between overview mode and normal mode.
void ToggleOverview();
ShellAcceleratorController* accelerator_controller() {
return accelerator_controller_.get();
}
ShellDelegate* delegate() { return delegate_.get(); }
Launcher* launcher() { return launcher_.get(); }
......@@ -81,6 +85,8 @@ class AURA_SHELL_EXPORT Shell {
base::WeakPtrFactory<Shell> method_factory_;
scoped_ptr<ShellAcceleratorController> accelerator_controller_;
scoped_ptr<ShellDelegate> delegate_;
scoped_ptr<Launcher> launcher_;
......
// 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