| Index: components/keyboard_lock/platform_key_hook_x11.cc
|
| diff --git a/components/keyboard_lock/platform_key_hook_x11.cc b/components/keyboard_lock/platform_key_hook_x11.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0c832569ca0985412f7e32b6f6384a105189aca2
|
| --- /dev/null
|
| +++ b/components/keyboard_lock/platform_key_hook_x11.cc
|
| @@ -0,0 +1,107 @@
|
| +// Copyright 2017 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 "components/keyboard_lock/platform_key_hook.h"
|
| +
|
| +#include <X11/Xlib.h>
|
| +#undef Status
|
| +
|
| +#include <unordered_set>
|
| +#include <vector>
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/macros.h"
|
| +#include "chrome/browser/ui/browser.h"
|
| +#include "chrome/browser/ui/browser_window.h"
|
| +#include "components/keyboard_lock/platform_key_event_filter.h"
|
| +#include "ui/aura/window.h"
|
| +#include "ui/aura/window_tree_host.h"
|
| +#include "ui/base/x/x11_window_event_manager.h"
|
| +#include "ui/events/platform/x11/x11_event_source.h"
|
| +#include "ui/gfx/x/x11_error_tracker.h"
|
| +#include "ui/gfx/x/x11_types.h"
|
| +
|
| +namespace keyboard_lock {
|
| +
|
| +namespace {
|
| +
|
| +const unsigned int kSingleStates[] = { ShiftMask,
|
| + LockMask,
|
| + ControlMask,
|
| + Mod1Mask,
|
| + Mod2Mask,
|
| + Mod3Mask,
|
| + Mod4Mask,
|
| + Mod5Mask };
|
| +
|
| +std::vector<int> all_states;
|
| +
|
| +void InitializeStates() {
|
| + if (!all_states.empty()) {
|
| + return;
|
| + }
|
| +
|
| + std::unordered_set<int> states {
|
| + kSingleStates, kSingleStates + arraysize(kSingleStates) };
|
| + for (size_t i = 0; i < arraysize(kSingleStates); i++) {
|
| + std::vector<int> new_states;
|
| + for (auto state : states) {
|
| + for (size_t j = 0; j < arraysize(kSingleStates); j++) {
|
| + new_states.push_back(state | kSingleStates[j]);
|
| + }
|
| + }
|
| + states.insert(new_states.begin(), new_states.end());
|
| + }
|
| +
|
| + all_states = std::vector<int> { states.begin(), states.end() };
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +PlatformKeyHook::PlatformKeyHook(Browser* owner, KeyEventFilter* filter)
|
| + : owner_(owner),
|
| + filter_(filter) {
|
| + DCHECK(owner_);
|
| + ui::X11EventSource::GetInstance()->set_platform_key_event_filter(&filter_);
|
| +}
|
| +
|
| +PlatformKeyHook::~PlatformKeyHook() = default;
|
| +
|
| +bool PlatformKeyHook::RegisterKey(const std::vector<ui::KeyboardCode>& codes) {
|
| + InitializeStates();
|
| + gfx::X11ErrorTracker x11_error_tracker;
|
| + Display* display = gfx::GetXDisplay();
|
| + if (owner_->window() == nullptr ||
|
| + owner_->window()->GetNativeWindow() == nullptr ||
|
| + owner_->window()->GetNativeWindow()->GetHost() == nullptr) {
|
| + LOG(ERROR) << "No native window found.";
|
| + // This should not happen in production, JavaScript cannot be executed
|
| + // before CreateBrowserWindow().
|
| + return false;
|
| + }
|
| + const Window root =
|
| + owner_->window()->GetNativeWindow()->GetHost()->GetAcceleratedWidget();
|
| + for (ui::KeyboardCode code : codes) {
|
| + for (auto state : all_states) {
|
| + XGrabKey(display, code, state, root, False, GrabModeAsync, GrabModeAsync);
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool PlatformKeyHook::UnregisterKey(
|
| + const std::vector<ui::KeyboardCode>& codes) {
|
| + InitializeStates();
|
| + gfx::X11ErrorTracker x11_error_tracker;
|
| + Display* display = gfx::GetXDisplay();
|
| + const Window root = DefaultRootWindow(display);
|
| + for (ui::KeyboardCode code : codes) {
|
| + for (auto state : all_states) {
|
| + XUngrabKey(display, code, state, root);
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +} // namespace keyboard_lock
|
|
|