123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- // 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/accelerators/key_hold_detector.h"
- #include <tuple>
- #include <utility>
- #include "ash/shell.h"
- #include "base/bind.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "ui/aura/window_tracker.h"
- #include "ui/aura/window_tree_host.h"
- #include "ui/events/event_dispatcher.h"
- #include "ui/events/event_sink.h"
- namespace ash {
- namespace {
- void DispatchPressedEvent(const ui::KeyEvent& key_event,
- std::unique_ptr<aura::WindowTracker> tracker) {
- // The target window may be gone.
- if (tracker->windows().empty())
- return;
- ui::KeyEvent event(key_event);
- aura::Window* target = *(tracker->windows().begin());
- std::ignore = target->GetHost()->GetEventSink()->OnEventFromSource(&event);
- }
- void PostPressedEvent(ui::KeyEvent* event) {
- // Modify RELEASED event to PRESSED event.
- const ui::KeyEvent pressed_event(
- ui::ET_KEY_PRESSED, event->key_code(), event->code(),
- event->flags() | ui::EF_SHIFT_DOWN | ui::EF_IS_SYNTHESIZED);
- std::unique_ptr<aura::WindowTracker> tracker(new aura::WindowTracker);
- tracker->Add(static_cast<aura::Window*>(event->target()));
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&DispatchPressedEvent, pressed_event, std::move(tracker)));
- }
- } // namespace
- KeyHoldDetector::KeyHoldDetector(std::unique_ptr<Delegate> delegate)
- : state_(INITIAL), delegate_(std::move(delegate)) {}
- KeyHoldDetector::~KeyHoldDetector() = default;
- void KeyHoldDetector::OnKeyEvent(ui::KeyEvent* event) {
- if (!delegate_->ShouldProcessEvent(event))
- return;
- if (delegate_->IsStartEvent(event)) {
- 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;
- if (delegate_->ShouldStopEventPropagation()) {
- // 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;
- [[fallthrough]];
- case HOLD:
- delegate_->OnKeyHold(event);
- if (delegate_->ShouldStopEventPropagation())
- event->StopPropagation();
- break;
- }
- } else if (event->type() == ui::ET_KEY_RELEASED) {
- switch (state_) {
- case INITIAL:
- break;
- case PRESSED: {
- if (delegate_->ShouldStopEventPropagation()) {
- PostPressedEvent(event);
- event->StopPropagation();
- }
- break;
- }
- case HOLD: {
- delegate_->OnKeyUnhold(event);
- if (delegate_->ShouldStopEventPropagation())
- event->StopPropagation();
- break;
- }
- }
- state_ = INITIAL;
- }
- }
- } // namespace ash
|