mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
319 lines
6.6 KiB
C++
319 lines
6.6 KiB
C++
// Copyright 2013 The Flutter 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 "flutter/shell/platform/fuchsia/flutter/keyboard.h"
|
|
|
|
#include <fuchsia/input/cpp/fidl.h>
|
|
#include <fuchsia/ui/input/cpp/fidl.h>
|
|
#include <fuchsia/ui/input3/cpp/fidl.h>
|
|
|
|
#include <iostream>
|
|
|
|
namespace flutter_runner {
|
|
|
|
using fuchsia::input::Key;
|
|
using fuchsia::ui::input::kModifierCapsLock;
|
|
using fuchsia::ui::input::kModifierLeftAlt;
|
|
using fuchsia::ui::input::kModifierLeftControl;
|
|
using fuchsia::ui::input::kModifierLeftShift;
|
|
using fuchsia::ui::input::kModifierNone;
|
|
using fuchsia::ui::input::kModifierRightAlt;
|
|
using fuchsia::ui::input::kModifierRightControl;
|
|
using fuchsia::ui::input::kModifierRightShift;
|
|
using fuchsia::ui::input3::KeyEvent;
|
|
using fuchsia::ui::input3::KeyEventType;
|
|
|
|
namespace {
|
|
|
|
// A simple keymap from a QWERTY keyboard to code points. A value 0 means no
|
|
// code point has been assigned for the respective keypress. Column 0 is the
|
|
// code point without a level modifier active, and Column 1 is the code point
|
|
// with a level modifier (e.g. Shift key) active.
|
|
static const uint32_t QWERTY_TO_CODE_POINTS[][2] = {
|
|
// 0x00
|
|
{},
|
|
{},
|
|
{},
|
|
{},
|
|
// 0x04,
|
|
{'a', 'A'},
|
|
{'b', 'B'},
|
|
{'c', 'C'},
|
|
{'d', 'D'},
|
|
// 0x08
|
|
{'e', 'E'},
|
|
{'f', 'F'},
|
|
{'g', 'G'},
|
|
{'h', 'H'},
|
|
// 0x0c
|
|
{'i', 'I'},
|
|
{'j', 'J'},
|
|
{'k', 'K'},
|
|
{'l', 'L'},
|
|
// 0x10
|
|
{'m', 'M'},
|
|
{'n', 'N'},
|
|
{'o', 'O'},
|
|
{'p', 'P'},
|
|
// 0x14
|
|
{'q', 'Q'},
|
|
{'r', 'R'},
|
|
{'s', 'S'},
|
|
{'t', 'T'},
|
|
// 0x18
|
|
{'u', 'U'},
|
|
{'v', 'V'},
|
|
{'w', 'W'},
|
|
{'x', 'X'},
|
|
// 0x1c
|
|
{'y', 'Y'},
|
|
{'z', 'Z'},
|
|
{'1', '!'},
|
|
{'2', '@'},
|
|
// 0x20
|
|
{'3', '#'},
|
|
{'4', '$'},
|
|
{'5', '%'},
|
|
{'6', '^'},
|
|
// 0x24
|
|
{'7', '&'},
|
|
{'8', '*'},
|
|
{'9', '('},
|
|
{'0', ')'},
|
|
// 0x28
|
|
{},
|
|
{},
|
|
{},
|
|
{},
|
|
// 0x2c
|
|
{' ', ' '},
|
|
{'-', '_'},
|
|
{'=', '+'},
|
|
{'[', '{'},
|
|
// 0x30
|
|
{']', '}'},
|
|
{'\\', '|'},
|
|
{},
|
|
{';', ':'},
|
|
// 0x34
|
|
{'\'', '"'},
|
|
{'`', '~'},
|
|
{',', '<'},
|
|
{'.', '>'},
|
|
// 0x38
|
|
{'/', '?'},
|
|
{},
|
|
{},
|
|
{},
|
|
// 0x3c
|
|
{},
|
|
{},
|
|
{},
|
|
{},
|
|
// 0x40
|
|
{},
|
|
{},
|
|
{},
|
|
{},
|
|
// 0x44
|
|
{},
|
|
{},
|
|
{},
|
|
{},
|
|
// 0x48
|
|
{},
|
|
{},
|
|
{},
|
|
{},
|
|
// 0x4c
|
|
{},
|
|
{},
|
|
{},
|
|
{},
|
|
// 0x50
|
|
{},
|
|
{},
|
|
{},
|
|
{},
|
|
// 0x54
|
|
{'/', 0},
|
|
{'*', 0},
|
|
{'-', 0},
|
|
{'+', 0},
|
|
// 0x58
|
|
{},
|
|
{'1', 0},
|
|
{'2', 0},
|
|
{'3', 0},
|
|
// 0x5c
|
|
{'4', 0},
|
|
{'5', 0},
|
|
{'6', 0},
|
|
{'7', 0},
|
|
// 0x60
|
|
{'8', 0},
|
|
{'9', 0},
|
|
{'0', 0},
|
|
{'.', 0},
|
|
};
|
|
|
|
} // namespace
|
|
|
|
Keyboard::Keyboard()
|
|
: any_events_received_(false),
|
|
stateful_caps_lock_(false),
|
|
left_shift_(false),
|
|
right_shift_(false),
|
|
left_alt_(false),
|
|
right_alt_(false),
|
|
left_ctrl_(false),
|
|
right_ctrl_(false),
|
|
last_event_() {}
|
|
|
|
bool Keyboard::ConsumeEvent(KeyEvent event) {
|
|
if (!event.has_type()) {
|
|
return false;
|
|
}
|
|
if (!event.has_key()) {
|
|
return false;
|
|
}
|
|
// Check if the time sequence of the events is correct.
|
|
|
|
last_event_ = std::move(event);
|
|
any_events_received_ = true;
|
|
const Key& key = last_event_.key();
|
|
const KeyEventType& event_type = last_event_.type();
|
|
switch (event_type) {
|
|
// For modifier keys, a SYNC is the same as a press.
|
|
case KeyEventType::SYNC:
|
|
switch (key) {
|
|
case Key::CAPS_LOCK:
|
|
stateful_caps_lock_ = true;
|
|
break;
|
|
case Key::LEFT_ALT:
|
|
left_alt_ = true;
|
|
break;
|
|
case Key::LEFT_CTRL:
|
|
left_ctrl_ = true;
|
|
break;
|
|
case Key::LEFT_SHIFT:
|
|
left_shift_ = true;
|
|
break;
|
|
case Key::RIGHT_ALT:
|
|
right_alt_ = true;
|
|
break;
|
|
case Key::RIGHT_CTRL:
|
|
right_ctrl_ = true;
|
|
break;
|
|
case Key::RIGHT_SHIFT:
|
|
right_shift_ = true;
|
|
break;
|
|
default:
|
|
// no-op
|
|
break;
|
|
}
|
|
break;
|
|
case KeyEventType::PRESSED:
|
|
switch (key) {
|
|
case Key::CAPS_LOCK:
|
|
stateful_caps_lock_ = !stateful_caps_lock_;
|
|
break;
|
|
case Key::LEFT_ALT:
|
|
left_alt_ = true;
|
|
break;
|
|
case Key::LEFT_CTRL:
|
|
left_ctrl_ = true;
|
|
break;
|
|
case Key::LEFT_SHIFT:
|
|
left_shift_ = true;
|
|
break;
|
|
case Key::RIGHT_ALT:
|
|
right_alt_ = true;
|
|
break;
|
|
case Key::RIGHT_CTRL:
|
|
right_ctrl_ = true;
|
|
break;
|
|
case Key::RIGHT_SHIFT:
|
|
right_shift_ = true;
|
|
break;
|
|
default:
|
|
// No-op
|
|
break;
|
|
}
|
|
break;
|
|
case KeyEventType::RELEASED:
|
|
switch (key) {
|
|
case Key::CAPS_LOCK:
|
|
// No-op.
|
|
break;
|
|
case Key::LEFT_ALT:
|
|
left_alt_ = false;
|
|
break;
|
|
case Key::LEFT_CTRL:
|
|
left_ctrl_ = false;
|
|
break;
|
|
case Key::LEFT_SHIFT:
|
|
left_shift_ = false;
|
|
break;
|
|
case Key::RIGHT_ALT:
|
|
right_alt_ = false;
|
|
break;
|
|
case Key::RIGHT_CTRL:
|
|
right_ctrl_ = false;
|
|
break;
|
|
case Key::RIGHT_SHIFT:
|
|
right_shift_ = false;
|
|
break;
|
|
default:
|
|
// No-op
|
|
break;
|
|
}
|
|
break;
|
|
case KeyEventType::CANCEL:
|
|
// No-op?
|
|
break;
|
|
default:
|
|
// No-op
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Keyboard::IsShift() {
|
|
return left_shift_ | right_shift_ | stateful_caps_lock_;
|
|
}
|
|
|
|
bool Keyboard::IsKeys() {
|
|
return (static_cast<uint64_t>(last_event_.key()) & 0xFFFF0000) == 0x00070000;
|
|
}
|
|
|
|
uint32_t Keyboard::Modifiers() {
|
|
return kModifierNone + (kModifierLeftShift * left_shift_) +
|
|
(kModifierLeftAlt * left_alt_) + (kModifierLeftControl * left_ctrl_) +
|
|
(kModifierRightShift * right_shift_) +
|
|
(kModifierRightAlt * right_alt_) +
|
|
(kModifierRightControl * right_ctrl_) +
|
|
(kModifierCapsLock * stateful_caps_lock_);
|
|
}
|
|
|
|
uint32_t Keyboard::LastCodePoint() {
|
|
static const int qwerty_map_size =
|
|
sizeof(QWERTY_TO_CODE_POINTS) / sizeof(QWERTY_TO_CODE_POINTS[0]);
|
|
if (!IsKeys()) {
|
|
return 0;
|
|
}
|
|
const auto usage = LastHIDUsage();
|
|
if (usage < qwerty_map_size) {
|
|
return QWERTY_TO_CODE_POINTS[usage][IsShift() & 1];
|
|
}
|
|
// Any other keys don't have a code point.
|
|
return 0;
|
|
}
|
|
|
|
uint32_t Keyboard::LastHIDUsage() {
|
|
return static_cast<uint64_t>(last_event_.key()) & 0xFFFF;
|
|
}
|
|
|
|
} // namespace flutter_runner
|