| Index: ash/magnifier/magnifier_key_scroller.cc
|
| diff --git a/ash/magnifier/magnifier_key_scroller.cc b/ash/magnifier/magnifier_key_scroller.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..745fe8a59c841a367e540a0d914d707d96d31d53
|
| --- /dev/null
|
| +++ b/ash/magnifier/magnifier_key_scroller.cc
|
| @@ -0,0 +1,146 @@
|
| +// Copyright 2014 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/magnifier/magnifier_key_scroller.h"
|
| +
|
| +#include <X11/Xlib.h>
|
| +
|
| +#undef RootWindow
|
| +#undef Status
|
| +
|
| +#include "ash/ash_switches.h"
|
| +#include "ash/magnifier/magnification_controller.h"
|
| +#include "ash/shell.h"
|
| +#include "base/command_line.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "ui/aura/root_window.h"
|
| +#include "ui/aura/window_tracker.h"
|
| +
|
| +namespace ash {
|
| +namespace {
|
| +
|
| +bool magnifier_key_scroller_enabled = false;
|
| +
|
| +void ScrollScreen(ui::KeyEvent* event) {
|
| + MagnificationController* controller =
|
| + Shell::GetInstance()->magnification_controller();
|
| + switch (event->key_code()) {
|
| + case ui::VKEY_UP:
|
| + controller->SetScrollDirection(MagnificationController::SCROLL_UP);
|
| + break;
|
| + case ui::VKEY_DOWN:
|
| + controller->SetScrollDirection(MagnificationController::SCROLL_DOWN);
|
| + break;
|
| + case ui::VKEY_LEFT:
|
| + controller->SetScrollDirection(MagnificationController::SCROLL_LEFT);
|
| + break;
|
| + case ui::VKEY_RIGHT:
|
| + controller->SetScrollDirection(MagnificationController::SCROLL_RIGHT);
|
| + break;
|
| + default:
|
| + NOTREACHED() << "Unknown keyboard_code:" << event->key_code();
|
| + }
|
| +}
|
| +
|
| +void DispatchPressedEvent(XEvent native_event,
|
| + scoped_ptr<aura::WindowTracker> tracker) {
|
| + // The target window may be gone.
|
| + if (tracker->windows().empty())
|
| + return;
|
| + aura::Window* target = *(tracker->windows().begin());
|
| + ui::KeyEvent event(&native_event, false);
|
| + event.set_flags(event.flags() | ui::EF_IS_SYNTHESIZED);
|
| + ui::EventDispatchDetails result ALLOW_UNUSED =
|
| + target->GetDispatcher()->OnEventFromSource(&event);
|
| +}
|
| +
|
| +void PostPressedEvent(ui::KeyEvent* event) {
|
| + // Modify RELEASED event to PRESSED event.
|
| + XEvent xkey = *(event->native_event());
|
| + xkey.xkey.type = KeyPress;
|
| + xkey.xkey.state |= ShiftMask;
|
| + scoped_ptr<aura::WindowTracker> tracker(new aura::WindowTracker);
|
| + tracker->Add(static_cast<aura::Window*>(event->target()));
|
| +
|
| + base::MessageLoopForUI::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&DispatchPressedEvent, xkey, base::Passed(&tracker)));
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// static
|
| +bool MagnifierKeyScroller::IsEnabled() {
|
| + return (magnifier_key_scroller_enabled ||
|
| + CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kAshEnableMagnifierKeyScroller)) &&
|
| + ash::Shell::GetInstance()->magnification_controller()->IsEnabled();
|
| +}
|
| +
|
| +// static
|
| +void MagnifierKeyScroller::SetEnabled(bool enabled) {
|
| + magnifier_key_scroller_enabled = enabled;
|
| +}
|
| +
|
| +MagnifierKeyScroller::MagnifierKeyScroller()
|
| + : state_(INITIAL) {}
|
| +
|
| +MagnifierKeyScroller::~MagnifierKeyScroller() {}
|
| +
|
| +void MagnifierKeyScroller::OnKeyEvent(
|
| + ui::KeyEvent* event) {
|
| + if (!IsEnabled())
|
| + return;
|
| +
|
| + if (event->key_code() != ui::VKEY_UP &&
|
| + event->key_code() != ui::VKEY_DOWN &&
|
| + event->key_code() != ui::VKEY_LEFT &&
|
| + event->key_code() != ui::VKEY_RIGHT) {
|
| + return;
|
| + }
|
| +
|
| + if (event->type() == ui::ET_KEY_PRESSED &&
|
| + event->flags() & ui::EF_SHIFT_DOWN) {
|
| + switch (state_) {
|
| + case INITIAL:
|
| + // Pass through posted event.
|
| + if (event->flags() & ui::EF_IS_SYNTHESIZED) {
|
| + event->set_flags(event->flags() & ~ui::EF_IS_SYNTHESIZED);
|
| + return;
|
| + }
|
| + state_ = PRESSED;
|
| + // Don't process ET_KEY_PRESSED event yet. The ET_KEY_PRESSED
|
| + // event will be generated upon ET_KEY_RELEASEED event below.
|
| + event->StopPropagation();
|
| + break;
|
| + case PRESSED:
|
| + state_ = HOLD;
|
| + // pass through
|
| + case HOLD:
|
| + ScrollScreen(event);
|
| + event->StopPropagation();
|
| + break;
|
| + }
|
| + } else if (event->type() == ui::ET_KEY_RELEASED) {
|
| + switch (state_) {
|
| + case INITIAL:
|
| + break;
|
| + case PRESSED: {
|
| + PostPressedEvent(event);
|
| + event->StopPropagation();
|
| + break;
|
| + }
|
| + case HOLD: {
|
| + MagnificationController* controller =
|
| + Shell::GetInstance()->magnification_controller();
|
| + controller->SetScrollDirection(MagnificationController::SCROLL_NONE);
|
| + event->StopPropagation();
|
| + break;
|
| + }
|
| + }
|
| + state_ = INITIAL;
|
| + }
|
| +}
|
| +
|
| +} // namespace ash
|
|
|