Chromium Code Reviews| Index: ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc |
| diff --git a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc |
| index a756db9131a69dfdc20747c23bf5f8514021a2f6..5f779753ea292486f951c7cd332152c39ca14c86 100644 |
| --- a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc |
| +++ b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc |
| @@ -6,7 +6,13 @@ |
| #include <xkbcommon/xkbcommon-names.h> |
| +#include "base/bind.h" |
| +#include "base/location.h" |
| #include "base/logging.h" |
| +#include "base/single_thread_task_runner.h" |
| +#include "base/task_runner.h" |
| +#include "base/thread_task_runner_handle.h" |
| +#include "base/threading/worker_pool.h" |
| #include "ui/events/event_constants.h" |
| #include "ui/events/keycodes/dom3/dom_code.h" |
| #include "ui/events/keycodes/dom3/dom_key.h" |
| @@ -18,6 +24,10 @@ namespace ui { |
| namespace { |
| +typedef base::Callback<void(const std::string&, |
| + scoped_ptr<xkb_keymap, XkbKeymapDeleter> keymap)> |
| + LoadKeymapCallback; |
| + |
| DomKey CharacterToDomKey(base::char16 character) { |
| switch (character) { |
| case 0x08: |
| @@ -616,6 +626,18 @@ const PrintableSimpleEntry kSimpleMap[] = { |
| {0x0259, VKEY_OEM_3}, // schwa |
| }; |
| +void LoadKeymap(const std::string& layout_name, |
| + scoped_ptr<xkb_rule_names> names, |
| + xkb_context* context, |
| + scoped_refptr<base::SingleThreadTaskRunner> reply_runner, |
| + const LoadKeymapCallback& reply_callback) { |
| + scoped_ptr<xkb_keymap, XkbKeymapDeleter> keymap; |
| + keymap.reset(xkb_keymap_new_from_names(context, names.get(), |
| + XKB_KEYMAP_COMPILE_NO_FLAGS)); |
| + reply_runner->PostTask(FROM_HERE, base::Bind(reply_callback, layout_name, |
| + base::Passed(&keymap))); |
| +} |
| + |
| } // anonymous namespace |
| XkbKeyCodeConverter::XkbKeyCodeConverter() { |
| @@ -626,7 +648,7 @@ XkbKeyCodeConverter::~XkbKeyCodeConverter() { |
| XkbKeyboardLayoutEngine::XkbKeyboardLayoutEngine( |
| const XkbKeyCodeConverter& converter) |
| - : key_code_converter_(converter) { |
| + : key_code_converter_(converter), weak_ptr_factory_(this) { |
| // TODO: add XKB_CONTEXT_NO_ENVIRONMENT_NAMES |
| xkb_context_.reset(xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES)); |
| xkb_context_include_path_append(xkb_context_.get(), |
| @@ -634,6 +656,9 @@ XkbKeyboardLayoutEngine::XkbKeyboardLayoutEngine( |
| } |
| XkbKeyboardLayoutEngine::~XkbKeyboardLayoutEngine() { |
| + for (const auto& entry : xkb_keymaps_) { |
| + xkb_keymap_unref(entry.keymap); |
| + } |
| } |
| bool XkbKeyboardLayoutEngine::CanSetCurrentLayout() const { |
| @@ -647,6 +672,29 @@ bool XkbKeyboardLayoutEngine::CanSetCurrentLayout() const { |
| bool XkbKeyboardLayoutEngine::SetCurrentLayoutByName( |
| const std::string& layout_name) { |
| #if defined(OS_CHROMEOS) |
| + current_layout_name_ = layout_name; |
| + for (const auto& entry : xkb_keymaps_) { |
| + if (entry.layout_name == layout_name) { |
| + SetKeymap(entry.keymap); |
| + return true; |
| + } |
| + } |
| + LoadKeymapCallback reply_callback = base::Bind( |
| + &XkbKeyboardLayoutEngine::OnKeymapLoaded, weak_ptr_factory_.GetWeakPtr()); |
| + scoped_ptr<xkb_rule_names> names = GetXkbRuleNames(layout_name); |
| + base::WorkerPool::PostTask( |
| + FROM_HERE, |
| + base::Bind(&LoadKeymap, layout_name, base::Passed(&names), |
| + base::Unretained(xkb_context_.get()), |
|
spang
2015/01/06 17:35:50
..oh dear
I didn't look at this closely enough.
|
| + base::ThreadTaskRunnerHandle::Get(), reply_callback), |
| + true); |
| + return true; |
| +#endif // defined(OS_CHROMEOS) |
| + return false; |
| +} |
| + |
| +scoped_ptr<xkb_rule_names> XkbKeyboardLayoutEngine::GetXkbRuleNames( |
| + const std::string& layout_name) { |
| size_t dash_index = layout_name.find('-'); |
| size_t parentheses_index = layout_name.find('('); |
| std::string layout_id = layout_name; |
| @@ -662,22 +710,25 @@ bool XkbKeyboardLayoutEngine::SetCurrentLayoutByName( |
| layout_id = layout_name.substr(0, dash_index); |
| layout_variant = layout_name.substr(dash_index + 1); |
| } |
| - struct xkb_rule_names names = { |
| - .rules = NULL, |
| - .model = "pc101", |
| - .layout = layout_id.c_str(), |
| - .variant = layout_variant.c_str(), |
| - .options = "" |
| - }; |
| - xkb_keymap* keymap = xkb_keymap_new_from_names(xkb_context_.get(), |
| - &names, |
| - XKB_KEYMAP_COMPILE_NO_FLAGS); |
| + return make_scoped_ptr<xkb_rule_names>( |
| + new xkb_rule_names{.rules = NULL, |
| + .model = "pc101", |
| + .layout = layout_id.c_str(), |
| + .variant = layout_variant.c_str(), |
| + .options = ""}); |
| +} |
| + |
| +void XkbKeyboardLayoutEngine::OnKeymapLoaded( |
| + const std::string& layout_name, |
| + scoped_ptr<xkb_keymap, XkbKeymapDeleter> keymap) { |
| if (keymap) { |
| - SetKeymap(keymap); |
| - return true; |
| + XkbKeymapEntry entry = {layout_name, xkb_keymap_ref(keymap.get())}; |
| + xkb_keymaps_.push_back(entry); |
| + if (layout_name == current_layout_name_) |
| + SetKeymap(keymap.get()); |
| + } else { |
| + LOG(ERROR) << "Keymap file fail to load: " << layout_name; |
| } |
| -#endif // defined(OS_CHROMEOS) |
| - return false; |
| } |
| bool XkbKeyboardLayoutEngine::UsesISOLevel5Shift() const { |