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 { |