Commit 3d29912a authored by zork@chromium.org's avatar zork@chromium.org

Allow focus to be sent between browser window and launcher/status window

R=sky@chromium.org
BUG=104192
TEST=Use ctrl+forward/back to move between browser window and status area/launcher


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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@120738 0039d316-1c4b-4281-b951-d872f2087c98
parent 97b1b733
......@@ -69,6 +69,8 @@
'drag_drop/drag_drop_controller.h',
'drag_drop/drag_image_view.cc',
'drag_drop/drag_image_view.h',
'focus_cycler.cc',
'focus_cycler.h',
'ime/event.cc',
'ime/event.h',
'ime/input_method_event_filter.cc',
......
// Copyright (c) 2012 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 "ash/focus_cycler.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ui/views/widget/widget.h"
#include "ui/views/focus/focus_search.h"
#include "ui/aura/window.h"
#include "ui/aura/client/activation_client.h"
#include "ui/views/accessible_pane_view.h"
namespace ash {
namespace internal {
FocusCycler::FocusCycler() {
}
FocusCycler::~FocusCycler() {
}
void FocusCycler::AddWidget(views::Widget* widget) {
widgets_.push_back(widget);
widget->GetFocusManager()->RegisterAccelerator(
ui::Accelerator(ui::VKEY_F2, false, true, false), this);
widget->GetFocusManager()->RegisterAccelerator(
ui::Accelerator(ui::VKEY_F1, false, true, false), this);
}
void FocusCycler::RotateFocus(Direction direction) {
int index = 0;
int count = static_cast<int>(widgets_.size());
int browser_index = count;
for (; index < count; ++index) {
if (widgets_[index]->IsActive())
break;
}
int start_index = index;
count = count + 1;
for (;;) {
if (direction == FORWARD)
index = (index + 1) % count;
else
index = ((index - 1) + count) % count;
// Ensure that we don't loop more than once.
if (index == start_index)
break;
if (index == browser_index) {
// Activate the browser window.
const std::vector<aura::Window*>& windows =
Shell::GetInstance()->delegate()->GetCycleWindowList(
ShellDelegate::SOURCE_LAUNCHER, ShellDelegate::ORDER_MRU);
if (!windows.empty()) {
aura::client::GetActivationClient()->ActivateWindow(windows[0]);
break;
}
} else {
views::Widget* widget = widgets_[index];
views::AccessiblePaneView* view =
static_cast<views::AccessiblePaneView*>(widget->GetContentsView());
if (view->SetPaneFocusAndFocusDefault()) {
widget->Activate();
if (widget->IsActive())
break;
}
}
}
}
bool FocusCycler::AcceleratorPressed(const ui::Accelerator& accelerator) {
switch (accelerator.key_code()) {
case ui::VKEY_F1:
RotateFocus(BACKWARD);
return true;
case ui::VKEY_F2:
RotateFocus(FORWARD);
return true;
default:
return false;
}
}
bool FocusCycler::CanHandleAccelerators() const {
return true;
}
} // namespace internal
} // namespace ash
// Copyright (c) 2012 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 FOCUS_CYCLER_H_
#define FOCUS_CYCLER_H_
#pragma once
#include <vector>
#include "base/compiler_specific.h"
#include "ui/base/accelerators/accelerator.h"
namespace views {
class Widget;
} // namespace views
namespace ash {
namespace internal {
// This class handles moving focus between a set of widgets and the main browser
// window.
class FocusCycler : public ui::AcceleratorTarget {
public:
enum Direction {
FORWARD,
BACKWARD
};
FocusCycler();
virtual ~FocusCycler();
// Add a widget to the focus cycle and set up accelerators. The widget needs
// to have an AccessiblePaneView as the content view.
void AddWidget(views::Widget* widget);
// Move focus to the next widget.
void RotateFocus(Direction direction);
// ui::AcceleratorTarget overrides
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
virtual bool CanHandleAccelerators() const OVERRIDE;
private:
std::vector<views::Widget*> widgets_;
DISALLOW_COPY_AND_ASSIGN(FocusCycler);
};
} // namespace internal
} // namespace ash
#endif // FOCUS_CYCLER_H_
......@@ -11,6 +11,7 @@
#include "ash/app_list/app_list.h"
#include "ash/ash_switches.h"
#include "ash/drag_drop/drag_drop_controller.h"
#include "ash/focus_cycler.h"
#include "ash/ime/input_method_event_filter.h"
#include "ash/launcher/launcher.h"
#include "ash/shell_delegate.h"
......@@ -328,6 +329,10 @@ void Shell::Init() {
if (!command_line->HasSwitch(switches::kAuraNoShadows))
shadow_controller_.reset(new internal::ShadowController());
focus_cycler_.reset(new internal::FocusCycler());
focus_cycler_->AddWidget(status_widget_);
focus_cycler_->AddWidget(launcher_->widget());
// Force a layout.
root_window->layout_manager()->OnWindowResized();
......@@ -453,6 +458,12 @@ views::NonClientFrameView* Shell::CreateDefaultNonClientFrameView(
return NULL;
}
void Shell::RotateFocus(Direction direction) {
focus_cycler_->RotateFocus(
direction == FORWARD ? internal::FocusCycler::FORWARD :
internal::FocusCycler::BACKWARD);
}
////////////////////////////////////////////////////////////////////////////////
// Shell, private:
......
......@@ -47,6 +47,7 @@ class ActivationController;
class AcceleratorFilter;
class AppList;
class DragDropController;
class FocusCycler;
class InputMethodEventFilter;
class RootWindowLayoutManager;
class ShadowController;
......@@ -73,6 +74,11 @@ class ASH_EXPORT Shell {
MODE_OVERLAPPING,
};
enum Direction {
FORWARD,
BACKWARD
};
// A shell must be explicitly created so that it can call |Init()| with the
// delegate set. |delegate| can be NULL (if not required for initialization).
static Shell* CreateInstance(ShellDelegate* delegate);
......@@ -118,6 +124,9 @@ class ASH_EXPORT Shell {
views::NonClientFrameView* CreateDefaultNonClientFrameView(
views::Widget* widget);
// Rotate focus through containers that can recieve focus.
void RotateFocus(Direction direction);
AcceleratorController* accelerator_controller() {
return accelerator_controller_.get();
}
......@@ -193,6 +202,7 @@ class ASH_EXPORT Shell {
scoped_ptr<PowerButtonController> power_button_controller_;
scoped_ptr<VideoDetector> video_detector_;
scoped_ptr<WindowCycleController> window_cycle_controller_;
scoped_ptr<internal::FocusCycler> focus_cycler_;
// An event filter that pre-handles all key events to send them to an IME.
scoped_ptr<internal::InputMethodEventFilter> input_method_filter_;
......
......@@ -961,6 +961,7 @@ void BrowserView::RotatePaneFocus(bool forwards) {
std::vector<views::AccessiblePaneView*> accessible_panes;
GetAccessiblePanes(&accessible_panes);
int pane_count = static_cast<int>(accessible_panes.size());
int special_index = -1;
std::vector<views::View*> accessible_views(
accessible_panes.begin(), accessible_panes.end());
......@@ -987,6 +988,12 @@ void BrowserView::RotatePaneFocus(bool forwards) {
if (focused_view && index >= pane_count)
GetFocusManager()->StoreFocusedView();
#if defined(OS_CHROMEOS) && defined(USE_AURA)
// Add the special panes to the rotation.
special_index = count;
++count;
#endif
// Try to focus the next pane; if SetPaneFocusAndFocusDefault returns
// false it means the pane didn't have any focusable controls, so skip
// it and try the next one.
......@@ -996,7 +1003,13 @@ void BrowserView::RotatePaneFocus(bool forwards) {
else
index = ((index - 1) + count) % count;
if (index < pane_count) {
if (index == special_index) {
#if defined(OS_CHROMEOS) && defined(USE_AURA)
ash::Shell::GetInstance()->RotateFocus(
forwards ? ash::Shell::FORWARD : ash::Shell::BACKWARD);
break;
#endif
} else if (index < pane_count) {
if (accessible_panes[index]->SetPaneFocusAndFocusDefault())
break;
} else {
......
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