summaryrefslogtreecommitdiff
path: root/chromium/ui/keyboard
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@digia.com>2014-03-18 13:16:26 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-03-20 15:55:39 +0100
commit3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch)
tree92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/ui/keyboard
parente90d7c4b152c56919d963987e2503f9909a666d2 (diff)
downloadqtwebengine-chromium-3f0f86b0caed75241fa71c95a5d73bc0164348c5.tar.gz
Update to new stable branch 1750
This also includes an updated ninja and chromium dependencies needed on Windows. Change-Id: Icd597d80ed3fa4425933c9f1334c3c2e31291c42 Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu> Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
Diffstat (limited to 'chromium/ui/keyboard')
-rw-r--r--chromium/ui/keyboard/DEPS5
-rw-r--r--chromium/ui/keyboard/OWNERS2
-rw-r--r--chromium/ui/keyboard/keyboard.gyp12
-rw-r--r--chromium/ui/keyboard/keyboard_controller.cc120
-rw-r--r--chromium/ui/keyboard/keyboard_controller.h43
-rw-r--r--chromium/ui/keyboard/keyboard_controller_proxy.cc63
-rw-r--r--chromium/ui/keyboard/keyboard_controller_proxy.h24
-rw-r--r--chromium/ui/keyboard/keyboard_controller_unittest.cc147
-rw-r--r--chromium/ui/keyboard/keyboard_resources.grd22
-rw-r--r--chromium/ui/keyboard/keyboard_switches.cc3
-rw-r--r--chromium/ui/keyboard/keyboard_switches.h7
-rw-r--r--chromium/ui/keyboard/keyboard_test_suite.cc33
-rw-r--r--chromium/ui/keyboard/keyboard_ui_controller.cc40
-rw-r--r--chromium/ui/keyboard/keyboard_ui_handler.cc23
-rw-r--r--chromium/ui/keyboard/keyboard_util.cc118
-rw-r--r--chromium/ui/keyboard/keyboard_util.h44
-rw-r--r--chromium/ui/keyboard/resources/api_adapter.js16
-rw-r--r--chromium/ui/keyboard/resources/constants.js13
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-altkey-container.html30
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-altkey-set.html50
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-altkey.html73
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-key-base.html114
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-key-codes.html271
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-key-import.html10
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-key-sequence.html95
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-key.html186
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-keyboard.html690
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-keyset.html25
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-modifier-key.html142
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-options-menu.html111
-rw-r--r--chromium/ui/keyboard/resources/elements/kb-shift-key.html120
-rw-r--r--chromium/ui/keyboard/resources/images/back.svg27
-rw-r--r--chromium/ui/keyboard/resources/images/brightness-down.svg34
-rw-r--r--chromium/ui/keyboard/resources/images/brightness-up.svg34
-rw-r--r--chromium/ui/keyboard/resources/images/change-window.svg33
-rw-r--r--chromium/ui/keyboard/resources/images/down.svg27
-rw-r--r--chromium/ui/keyboard/resources/images/forward.svg27
-rw-r--r--chromium/ui/keyboard/resources/images/fullscreen.svg37
-rw-r--r--chromium/ui/keyboard/resources/images/left.svg27
-rw-r--r--chromium/ui/keyboard/resources/images/mute.svg33
-rw-r--r--chromium/ui/keyboard/resources/images/reload.svg34
-rw-r--r--chromium/ui/keyboard/resources/images/right.svg27
-rw-r--r--chromium/ui/keyboard/resources/images/search.svg14
-rw-r--r--chromium/ui/keyboard/resources/images/shutdown.svg38
-rw-r--r--chromium/ui/keyboard/resources/images/up.svg27
-rw-r--r--chromium/ui/keyboard/resources/images/volume-down.svg46
-rw-r--r--chromium/ui/keyboard/resources/images/volume-up.svg52
-rw-r--r--chromium/ui/keyboard/resources/index.html4
-rw-r--r--chromium/ui/keyboard/resources/layouts/dvorak.html112
-rw-r--r--chromium/ui/keyboard/resources/layouts/function-key-row.html25
-rw-r--r--chromium/ui/keyboard/resources/layouts/qwerty.html106
-rw-r--r--chromium/ui/keyboard/resources/layouts/spacebar-row.html2
-rw-r--r--chromium/ui/keyboard/resources/layouts/system-qwerty.html111
-rw-r--r--chromium/ui/keyboard/resources/layouts/webui_qwerty.html4
-rw-r--r--chromium/ui/keyboard/resources/main.css124
-rw-r--r--chromium/ui/keyboard/resources/main.js10
-rw-r--r--chromium/ui/keyboard/resources/polymer.min.js5
-rw-r--r--chromium/ui/keyboard/resources/polymer_loader.js11
-rw-r--r--chromium/ui/keyboard/resources/webui/api_adapter.js9
-rw-r--r--chromium/ui/keyboard/resources/webui/main.css5
-rw-r--r--chromium/ui/keyboard/resources/webui_index.html2
61 files changed, 2877 insertions, 822 deletions
diff --git a/chromium/ui/keyboard/DEPS b/chromium/ui/keyboard/DEPS
index bfcf8303e19..69c820c1776 100644
--- a/chromium/ui/keyboard/DEPS
+++ b/chromium/ui/keyboard/DEPS
@@ -2,4 +2,9 @@ include_rules = [
"+content/public",
"+grit/keyboard_resources.h",
"+grit/keyboard_resources_map.h",
+ "+ui/aura",
+ "+ui/base",
+ "+ui/compositor",
+ "+ui/gfx",
+ "+ui/test",
]
diff --git a/chromium/ui/keyboard/OWNERS b/chromium/ui/keyboard/OWNERS
index 93ca4b21c53..6f3bdd61ef2 100644
--- a/chromium/ui/keyboard/OWNERS
+++ b/chromium/ui/keyboard/OWNERS
@@ -1,2 +1,4 @@
bryeung@chromium.org
sadrul@chromium.org
+bshe@chromium.org
+kevers@chromium.org
diff --git a/chromium/ui/keyboard/keyboard.gyp b/chromium/ui/keyboard/keyboard.gyp
index 7ec43f36edb..4ea3b09808b 100644
--- a/chromium/ui/keyboard/keyboard.gyp
+++ b/chromium/ui/keyboard/keyboard.gyp
@@ -44,6 +44,8 @@
'../../url/url.gyp:url_lib',
'../aura/aura.gyp:aura',
'../compositor/compositor.gyp:compositor',
+ '../events/events.gyp:events',
+ '../gfx/gfx.gyp:gfx',
'../ui.gyp:ui',
'keyboard_resources',
],
@@ -80,16 +82,17 @@
'../../content/content.gyp:content',
'../../skia/skia.gyp:skia',
'../../testing/gtest.gyp:gtest',
+ '../../url/url.gyp:url_lib',
'../aura/aura.gyp:aura',
'../aura/aura.gyp:aura_test_support',
'../compositor/compositor.gyp:compositor',
- '../ui.gyp:run_ui_unittests',
+ '../gfx/gfx.gyp:gfx',
'../ui.gyp:ui',
+ '../ui_unittests.gyp:run_ui_unittests',
'keyboard',
],
'sources': [
'keyboard_controller_unittest.cc',
- 'keyboard_test_suite.cc',
],
'conditions': [
['OS=="linux" and linux_use_tcmalloc==1', {
@@ -100,6 +103,11 @@
'ldflags': ['-rdynamic'],
},
}],
+ ['OS=="win" and win_use_allocator_shim==1', {
+ 'dependencies': [
+ '<(DEPTH)/base/allocator/allocator.gyp:allocator',
+ ],
+ }],
],
},
],
diff --git a/chromium/ui/keyboard/keyboard_controller.cc b/chromium/ui/keyboard/keyboard_controller.cc
index 83e7f321c5c..ca8e54fcc4a 100644
--- a/chromium/ui/keyboard/keyboard_controller.cc
+++ b/chromium/ui/keyboard/keyboard_controller.cc
@@ -5,6 +5,7 @@
#include "ui/keyboard/keyboard_controller.h"
#include "base/bind.h"
+#include "base/command_line.h"
#include "ui/aura/layout_manager.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
@@ -18,13 +19,16 @@
#include "ui/gfx/skia_util.h"
#include "ui/keyboard/keyboard_controller_observer.h"
#include "ui/keyboard/keyboard_controller_proxy.h"
+#include "ui/keyboard/keyboard_switches.h"
+#include "ui/keyboard/keyboard_util.h"
namespace {
const int kHideKeyboardDelayMs = 100;
gfx::Rect KeyboardBoundsFromWindowBounds(const gfx::Rect& window_bounds) {
- const float kKeyboardHeightRatio = 0.3f;
+ const float kKeyboardHeightRatio =
+ keyboard::IsKeyboardUsabilityExperimentEnabled() ? 1.0f : 0.3f;
return gfx::Rect(
window_bounds.x(),
window_bounds.y() + window_bounds.height() * (1 - kKeyboardHeightRatio),
@@ -38,7 +42,8 @@ gfx::Rect KeyboardBoundsFromWindowBounds(const gfx::Rect& window_bounds) {
// The delegate deletes itself when the window is destroyed.
class KeyboardWindowDelegate : public aura::WindowDelegate {
public:
- KeyboardWindowDelegate() {}
+ explicit KeyboardWindowDelegate(keyboard::KeyboardControllerProxy* proxy)
+ : proxy_(proxy) {}
virtual ~KeyboardWindowDelegate() {}
private:
@@ -69,13 +74,16 @@ class KeyboardWindowDelegate : public aura::WindowDelegate {
virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {}
virtual bool HasHitTestMask() const OVERRIDE { return true; }
virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {
- gfx::Rect keyboard_bounds = KeyboardBoundsFromWindowBounds(bounds_);
+ gfx::Rect keyboard_bounds = proxy_ ? proxy_->GetKeyboardWindow()->bounds() :
+ KeyboardBoundsFromWindowBounds(bounds_);
mask->addRect(RectToSkRect(keyboard_bounds));
}
virtual void DidRecreateLayer(ui::Layer* old_layer,
ui::Layer* new_layer) OVERRIDE {}
gfx::Rect bounds_;
+ keyboard::KeyboardControllerProxy* proxy_;
+
DISALLOW_COPY_AND_ASSIGN(KeyboardWindowDelegate);
};
@@ -88,21 +96,19 @@ namespace keyboard {
// owner window.
class KeyboardLayoutManager : public aura::LayoutManager {
public:
- KeyboardLayoutManager(aura::Window* container)
- : container_(container), keyboard_(NULL) {
- CHECK(container_);
+ explicit KeyboardLayoutManager(KeyboardController* controller)
+ : controller_(controller), keyboard_(NULL) {
}
// Overridden from aura::LayoutManager
virtual void OnWindowResized() OVERRIDE {
- if (!keyboard_)
- return;
- SetChildBoundsDirect(keyboard_,
- KeyboardBoundsFromWindowBounds(container_->bounds()));
+ if (keyboard_ && !controller_->proxy()->resizing_from_contents())
+ ResizeKeyboardToDefault(keyboard_);
}
virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
DCHECK(!keyboard_);
keyboard_ = child;
+ ResizeKeyboardToDefault(keyboard_);
}
virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
@@ -110,11 +116,24 @@ class KeyboardLayoutManager : public aura::LayoutManager {
bool visible) OVERRIDE {}
virtual void SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) OVERRIDE {
- // Drop these: the size should only be set in OnWindowResized.
+ // SetChildBounds can be invoked by resizing from the container or by
+ // resizing from the contents (through window.resizeTo call in JS).
+ // The flag resizing_from_contents() is used to determine the keyboard is
+ // resizing from which.
+ if (controller_->proxy()->resizing_from_contents()) {
+ controller_->NotifyKeyboardBoundsChanging(requested_bounds);
+ SetChildBoundsDirect(child, requested_bounds);
+ }
}
private:
- aura::Window* container_;
+ void ResizeKeyboardToDefault(aura::Window* child) {
+ gfx::Rect keyboard_bounds = KeyboardBoundsFromWindowBounds(
+ controller_->GetContainerWindow()->bounds());
+ SetChildBoundsDirect(child, keyboard_bounds);
+ }
+
+ KeyboardController* controller_;
aura::Window* keyboard_;
DISALLOW_COPY_AND_ASSIGN(KeyboardLayoutManager);
@@ -122,9 +141,9 @@ class KeyboardLayoutManager : public aura::LayoutManager {
KeyboardController::KeyboardController(KeyboardControllerProxy* proxy)
: proxy_(proxy),
- container_(NULL),
input_method_(NULL),
keyboard_visible_(false),
+ lock_keyboard_(false),
weak_factory_(this) {
CHECK(proxy);
input_method_ = proxy_->GetInputMethod();
@@ -132,31 +151,50 @@ KeyboardController::KeyboardController(KeyboardControllerProxy* proxy)
}
KeyboardController::~KeyboardController() {
- if (container_)
+ if (container_) {
container_->RemoveObserver(this);
+ // Remove the keyboard window from the children because the keyboard window
+ // is owned by proxy and it should be destroyed by proxy.
+ if (container_->Contains(proxy_->GetKeyboardWindow()))
+ container_->RemoveChild(proxy_->GetKeyboardWindow());
+ }
if (input_method_)
input_method_->RemoveObserver(this);
}
aura::Window* KeyboardController::GetContainerWindow() {
- if (!container_) {
- container_ = new aura::Window(new KeyboardWindowDelegate());
+ if (!container_.get()) {
+ container_.reset(new aura::Window(
+ new KeyboardWindowDelegate(proxy_.get())));
container_->SetName("KeyboardContainer");
+ container_->set_owned_by_parent(false);
container_->Init(ui::LAYER_NOT_DRAWN);
container_->AddObserver(this);
- container_->SetLayoutManager(new KeyboardLayoutManager(container_));
+ container_->SetLayoutManager(new KeyboardLayoutManager(this));
+ }
+ return container_.get();
+}
+
+void KeyboardController::NotifyKeyboardBoundsChanging(
+ const gfx::Rect& new_bounds) {
+ if (proxy_->GetKeyboardWindow()->IsVisible()) {
+ FOR_EACH_OBSERVER(KeyboardControllerObserver,
+ observer_list_,
+ OnKeyboardBoundsChanging(new_bounds));
}
- return container_;
}
-void KeyboardController::HideKeyboard() {
+void KeyboardController::HideKeyboard(HideReason reason) {
keyboard_visible_ = false;
- FOR_EACH_OBSERVER(KeyboardControllerObserver,
- observer_list_,
- OnKeyboardBoundsChanging(gfx::Rect()));
+ keyboard::LogKeyboardControlEvent(
+ reason == HIDE_REASON_AUTOMATIC ?
+ keyboard::KEYBOARD_CONTROL_HIDE_AUTO :
+ keyboard::KEYBOARD_CONTROL_HIDE_USER);
+
+ NotifyKeyboardBoundsChanging(gfx::Rect());
- proxy_->HideKeyboardContainer(container_);
+ proxy_->HideKeyboardContainer(container_.get());
}
void KeyboardController::AddObserver(KeyboardControllerObserver* observer) {
@@ -169,50 +207,56 @@ void KeyboardController::RemoveObserver(KeyboardControllerObserver* observer) {
void KeyboardController::OnWindowHierarchyChanged(
const HierarchyChangeParams& params) {
- if (params.new_parent && params.target == container_)
+ if (params.new_parent && params.target == container_.get())
OnTextInputStateChanged(proxy_->GetInputMethod()->GetTextInputClient());
}
-void KeyboardController::OnWindowDestroying(aura::Window* window) {
- DCHECK_EQ(container_, window);
- container_ = NULL;
+void KeyboardController::SetOverrideContentUrl(const GURL& url) {
+ proxy_->SetOverrideContentUrl(url);
}
void KeyboardController::OnTextInputStateChanged(
const ui::TextInputClient* client) {
- if (!container_)
+ if (!container_.get())
return;
bool was_showing = keyboard_visible_;
bool should_show = was_showing;
ui::TextInputType type =
client ? client->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE;
- if (type == ui::TEXT_INPUT_TYPE_NONE) {
+ if (type == ui::TEXT_INPUT_TYPE_NONE &&
+ !IsKeyboardUsabilityExperimentEnabled() &&
+ !lock_keyboard_) {
should_show = false;
} else {
if (container_->children().empty()) {
+ keyboard::MarkKeyboardLoadStarted();
aura::Window* keyboard = proxy_->GetKeyboardWindow();
keyboard->Show();
container_->AddChild(keyboard);
- container_->layout_manager()->OnWindowResized();
}
- proxy_->SetUpdateInputType(type);
- container_->parent()->StackChildAtTop(container_);
+ if (type != ui::TEXT_INPUT_TYPE_NONE)
+ proxy_->SetUpdateInputType(type);
+ container_->parent()->StackChildAtTop(container_.get());
should_show = true;
}
if (was_showing != should_show) {
if (should_show) {
keyboard_visible_ = true;
+
+ // If the controller is in the process of hiding the keyboard, do not log
+ // the stat here since the keyboard will not actually be shown.
+ if (!WillHideKeyboard())
+ keyboard::LogKeyboardControlEvent(keyboard::KEYBOARD_CONTROL_SHOW);
+
weak_factory_.InvalidateWeakPtrs();
if (container_->IsVisible())
return;
- FOR_EACH_OBSERVER(
- KeyboardControllerObserver,
- observer_list_,
- OnKeyboardBoundsChanging(container_->children()[0]->bounds()));
- proxy_->ShowKeyboardContainer(container_);
+ NotifyKeyboardBoundsChanging(container_->children()[0]->bounds());
+
+ proxy_->ShowKeyboardContainer(container_.get());
} else {
// Set the visibility state here so that any queries for visibility
// before the timer fires returns the correct future value.
@@ -220,7 +264,7 @@ void KeyboardController::OnTextInputStateChanged(
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&KeyboardController::HideKeyboard,
- weak_factory_.GetWeakPtr()),
+ weak_factory_.GetWeakPtr(), HIDE_REASON_AUTOMATIC),
base::TimeDelta::FromMilliseconds(kHideKeyboardDelayMs));
}
}
diff --git a/chromium/ui/keyboard/keyboard_controller.h b/chromium/ui/keyboard/keyboard_controller.h
index 31f48d3da43..e5cfbe5d847 100644
--- a/chromium/ui/keyboard/keyboard_controller.h
+++ b/chromium/ui/keyboard/keyboard_controller.h
@@ -6,11 +6,13 @@
#define UI_KEYBOARD_KEYBOARD_CONTROLLER_H_
#include "base/basictypes.h"
+#include "base/event_types.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "ui/aura/window_observer.h"
#include "ui/base/ime/input_method_observer.h"
#include "ui/keyboard/keyboard_export.h"
+#include "url/gurl.h"
namespace aura {
class Window;
@@ -34,23 +36,43 @@ class KeyboardLayoutManager;
class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
public aura::WindowObserver {
public:
+ // Different ways to hide the keyboard.
+ enum HideReason {
+ // System initiated.
+ HIDE_REASON_AUTOMATIC,
+ // User initiated.
+ HIDE_REASON_MANUAL,
+ };
+
// Takes ownership of |proxy|.
explicit KeyboardController(KeyboardControllerProxy* proxy);
virtual ~KeyboardController();
- // Returns the container for the keyboard, which is then owned by the caller.
- // It is the responsibility of the caller to Show() the returned window.
+ // Returns the container for the keyboard, which is owned by
+ // KeyboardController.
aura::Window* GetContainerWindow();
+ // Sets the override content url. This is used by for input view for extension
+ // IMEs.
+ void SetOverrideContentUrl(const GURL& url);
+
// Hides virtual keyboard and notifies observer bounds change.
// This function should be called with a delay to avoid layout flicker
- // when the focus of input field quickly change.
- void HideKeyboard();
+ // when the focus of input field quickly change. |automatic| is true when the
+ // call is made by the system rather than initiated by the user.
+ void HideKeyboard(HideReason reason);
+
+ // Notifies the keyboard observer for keyboard bounds changed.
+ void NotifyKeyboardBoundsChanging(const gfx::Rect& new_bounds);
// Management of the observer list.
virtual void AddObserver(KeyboardControllerObserver* observer);
virtual void RemoveObserver(KeyboardControllerObserver* observer);
+ KeyboardControllerProxy* proxy() { return proxy_.get(); }
+
+ void set_lock_keyboard(bool lock) { lock_keyboard_ = lock; }
+
private:
// For access to Observer methods for simulation.
friend class KeyboardControllerTest;
@@ -58,9 +80,14 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
// aura::WindowObserver overrides
virtual void OnWindowHierarchyChanged(
const HierarchyChangeParams& params) OVERRIDE;
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
// InputMethodObserver overrides
+ virtual void OnTextInputTypeChanged(
+ const ui::TextInputClient* client) OVERRIDE {}
+ virtual void OnFocus() OVERRIDE {}
+ virtual void OnBlur() OVERRIDE {}
+ virtual void OnCaretBoundsChanged(
+ const ui::TextInputClient* client) OVERRIDE {}
virtual void OnTextInputStateChanged(
const ui::TextInputClient* client) OVERRIDE;
virtual void OnInputMethodDestroyed(
@@ -70,13 +97,15 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
bool WillHideKeyboard() const;
scoped_ptr<KeyboardControllerProxy> proxy_;
- aura::Window* container_;
+ scoped_ptr<aura::Window> container_;
ui::InputMethod* input_method_;
bool keyboard_visible_;
- base::WeakPtrFactory<KeyboardController> weak_factory_;
+ bool lock_keyboard_;
ObserverList<KeyboardControllerObserver> observer_list_;
+ base::WeakPtrFactory<KeyboardController> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(KeyboardController);
};
diff --git a/chromium/ui/keyboard/keyboard_controller_proxy.cc b/chromium/ui/keyboard/keyboard_controller_proxy.cc
index 1cfb99d92b1..fb6f04d9ede 100644
--- a/chromium/ui/keyboard/keyboard_controller_proxy.cc
+++ b/chromium/ui/keyboard/keyboard_controller_proxy.cc
@@ -13,6 +13,7 @@
#include "content/public/browser/web_contents_view.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/bindings_policy.h"
+#include "ui/aura/layout_manager.h"
#include "ui/aura/window.h"
#include "ui/keyboard/keyboard_constants.h"
@@ -71,6 +72,23 @@ class KeyboardContentsDelegate : public content::WebContentsDelegate,
return source;
}
+ virtual bool IsPopupOrPanel(
+ const content::WebContents* source) const OVERRIDE {
+ return true;
+ }
+
+ virtual void MoveContents(content::WebContents* source,
+ const gfx::Rect& pos) OVERRIDE {
+ aura::Window* keyboard = proxy_->GetKeyboardWindow();
+ gfx::Rect bounds = keyboard->bounds();
+ int new_height = pos.height();
+ bounds.set_y(bounds.y() + bounds.height() - new_height);
+ bounds.set_height(new_height);
+ proxy_->set_resizing_from_contents(true);
+ keyboard->SetBounds(bounds);
+ proxy_->set_resizing_from_contents(false);
+ }
+
// Overridden from content::WebContentsDelegate:
virtual void RequestMediaAccessPermission(content::WebContents* web_contents,
const content::MediaStreamRequest& request,
@@ -93,39 +111,64 @@ class KeyboardContentsDelegate : public content::WebContentsDelegate,
namespace keyboard {
-KeyboardControllerProxy::KeyboardControllerProxy() {
+KeyboardControllerProxy::KeyboardControllerProxy()
+ : default_url_(kKeyboardWebUIURL), resizing_from_contents_(false) {
}
KeyboardControllerProxy::~KeyboardControllerProxy() {
}
+const GURL& KeyboardControllerProxy::GetValidUrl() {
+ return override_url_.is_valid() ? override_url_ : default_url_;
+}
+
+void KeyboardControllerProxy::SetOverrideContentUrl(const GURL& url) {
+ if (override_url_ == url)
+ return;
+
+ override_url_ = url;
+ // Restores the keyboard window size to default.
+ aura::Window* container = GetKeyboardWindow()->parent();
+ CHECK(container);
+ container->layout_manager()->OnWindowResized();
+
+ ReloadContents();
+}
+
+void KeyboardControllerProxy::ReloadContents() {
+ if (keyboard_contents_) {
+ content::OpenURLParams params(
+ GetValidUrl(),
+ content::Referrer(),
+ SINGLETON_TAB,
+ content::PAGE_TRANSITION_AUTO_TOPLEVEL,
+ false);
+ keyboard_contents_->OpenURL(params);
+ }
+}
+
aura::Window* KeyboardControllerProxy::GetKeyboardWindow() {
if (!keyboard_contents_) {
content::BrowserContext* context = GetBrowserContext();
- GURL url(kKeyboardWebUIURL);
keyboard_contents_.reset(content::WebContents::Create(
content::WebContents::CreateParams(context,
- content::SiteInstance::CreateForURL(context, url))));
+ content::SiteInstance::CreateForURL(context, GetValidUrl()))));
keyboard_contents_->SetDelegate(new KeyboardContentsDelegate(this));
SetupWebContents(keyboard_contents_.get());
-
- content::OpenURLParams params(url,
- content::Referrer(),
- SINGLETON_TAB,
- content::PAGE_TRANSITION_AUTO_TOPLEVEL,
- false);
- keyboard_contents_->OpenURL(params);
+ ReloadContents();
}
return keyboard_contents_->GetView()->GetNativeView();
}
void KeyboardControllerProxy::ShowKeyboardContainer(aura::Window* container) {
+ GetKeyboardWindow()->Show();
container->Show();
}
void KeyboardControllerProxy::HideKeyboardContainer(aura::Window* container) {
container->Hide();
+ GetKeyboardWindow()->Hide();
}
void KeyboardControllerProxy::SetUpdateInputType(ui::TextInputType type) {
diff --git a/chromium/ui/keyboard/keyboard_controller_proxy.h b/chromium/ui/keyboard/keyboard_controller_proxy.h
index 53585977998..c028b74ddcb 100644
--- a/chromium/ui/keyboard/keyboard_controller_proxy.h
+++ b/chromium/ui/keyboard/keyboard_controller_proxy.h
@@ -38,6 +38,18 @@ class KEYBOARD_EXPORT KeyboardControllerProxy {
// with the proxy.
virtual aura::Window* GetKeyboardWindow();
+ // Sets the override content url.
+ void SetOverrideContentUrl(const GURL& url);
+
+ // Whether the keyboard window is resizing from its web contents.
+ bool resizing_from_contents() const { return resizing_from_contents_; }
+
+ // Sets the flag of whether the keyboard window is resizing from
+ // its web contents.
+ void set_resizing_from_contents(bool resizing) {
+ resizing_from_contents_ = resizing;
+ }
+
// Gets the InputMethod that will provide notifications about changes in the
// text input context.
virtual ui::InputMethod* GetInputMethod() = 0;
@@ -74,8 +86,20 @@ class KEYBOARD_EXPORT KeyboardControllerProxy {
virtual void SetupWebContents(content::WebContents* contents);
private:
+ // Reloads the web contents to the valid url from GetValidUrl().
+ void ReloadContents();
+
+ // Gets the valid url from default url or override url.
+ const GURL& GetValidUrl();
+
+ const GURL default_url_;
+ GURL override_url_;
+
scoped_ptr<content::WebContents> keyboard_contents_;
+ // Whether the current keyboard window is resizing from its web content.
+ bool resizing_from_contents_;
+
DISALLOW_COPY_AND_ASSIGN(KeyboardControllerProxy);
};
diff --git a/chromium/ui/keyboard/keyboard_controller_unittest.cc b/chromium/ui/keyboard/keyboard_controller_unittest.cc
index 1d461166ff6..d79c9ba3d82 100644
--- a/chromium/ui/keyboard/keyboard_controller_unittest.cc
+++ b/chromium/ui/keyboard/keyboard_controller_unittest.cc
@@ -3,10 +3,12 @@
// found in the LICENSE file.
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/focus_client.h"
+#include "ui/aura/layout_manager.h"
#include "ui/aura/root_window.h"
#include "ui/aura/test/aura_test_helper.h"
#include "ui/aura/test/event_generator.h"
@@ -19,6 +21,7 @@
#include "ui/gfx/rect.h"
#include "ui/keyboard/keyboard_controller.h"
#include "ui/keyboard/keyboard_controller_proxy.h"
+#include "ui/keyboard/keyboard_switches.h"
namespace keyboard {
namespace {
@@ -27,7 +30,7 @@ namespace {
// used to match the focus manger behaviour in ash and views.
class TestFocusController : public ui::EventHandler {
public:
- explicit TestFocusController(aura::RootWindow* root)
+ explicit TestFocusController(aura::Window* root)
: root_(root) {
root_->AddPreTargetHandler(this);
}
@@ -128,24 +131,27 @@ class TestTextInputClient : public ui::TextInputClient {
return ui::TEXT_INPUT_MODE_DEFAULT;
}
virtual bool CanComposeInline() const OVERRIDE { return false; }
- virtual gfx::Rect GetCaretBounds() OVERRIDE { return gfx::Rect(); }
+ virtual gfx::Rect GetCaretBounds() const OVERRIDE { return gfx::Rect(); }
- virtual bool GetCompositionCharacterBounds(uint32 index,
- gfx::Rect* rect) OVERRIDE {
+ virtual bool GetCompositionCharacterBounds(
+ uint32 index,
+ gfx::Rect* rect) const OVERRIDE {
return false;
}
- virtual bool HasCompositionText() OVERRIDE { return false; }
- virtual bool GetTextRange(gfx::Range* range) OVERRIDE { return false; }
- virtual bool GetCompositionTextRange(gfx::Range* range) OVERRIDE {
+ virtual bool HasCompositionText() const OVERRIDE { return false; }
+ virtual bool GetTextRange(gfx::Range* range) const OVERRIDE { return false; }
+ virtual bool GetCompositionTextRange(gfx::Range* range) const OVERRIDE {
+ return false;
+ }
+ virtual bool GetSelectionRange(gfx::Range* range) const OVERRIDE {
return false;
}
- virtual bool GetSelectionRange(gfx::Range* range) OVERRIDE { return false; }
virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE {
return false;
}
virtual bool DeleteRange(const gfx::Range& range) OVERRIDE { return false; }
virtual bool GetTextFromRange(const gfx::Range& range,
- base::string16* text) OVERRIDE {
+ base::string16* text) const OVERRIDE {
return false;
}
virtual void OnInputMethodChanged() OVERRIDE {}
@@ -153,6 +159,9 @@ class TestTextInputClient : public ui::TextInputClient {
base::i18n::TextDirection direction) OVERRIDE { return false; }
virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE {}
virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE {}
+ virtual void OnCandidateWindowShown() OVERRIDE {}
+ virtual void OnCandidateWindowUpdated() OVERRIDE {}
+ virtual void OnCandidateWindowHidden() OVERRIDE {}
ui::TextInputType type_;
@@ -201,7 +210,7 @@ class KeyboardControllerTest : public testing::Test {
aura_test_helper_->TearDown();
}
- aura::RootWindow* root_window() { return aura_test_helper_->root_window(); }
+ aura::Window* root_window() { return aura_test_helper_->root_window(); }
KeyboardControllerProxy* proxy() { return proxy_; }
KeyboardController* controller() { return controller_.get(); }
@@ -227,7 +236,7 @@ class KeyboardControllerTest : public testing::Test {
};
TEST_F(KeyboardControllerTest, KeyboardSize) {
- scoped_ptr<aura::Window> container(controller()->GetContainerWindow());
+ aura::Window* container(controller()->GetContainerWindow());
gfx::Rect bounds(0, 0, 100, 100);
container->SetBounds(bounds);
@@ -252,11 +261,10 @@ TEST_F(KeyboardControllerTest, ClickDoesNotFocusKeyboard) {
window->Show();
window->Focus();
- scoped_ptr<aura::Window> keyboard_container(
- controller()->GetContainerWindow());
+ aura::Window* keyboard_container(controller()->GetContainerWindow());
keyboard_container->SetBounds(root_bounds);
- root_window()->AddChild(keyboard_container.get());
+ root_window()->AddChild(keyboard_container);
keyboard_container->Show();
ShowKeyboard();
@@ -297,12 +305,11 @@ TEST_F(KeyboardControllerTest, VisibilityChangeWithTextInputTypeChange) {
TestTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE);
input_method->SetFocusedTextInputClient(&input_client_0);
- scoped_ptr<aura::Window> keyboard_container(
- controller()->GetContainerWindow());
+ aura::Window* keyboard_container(controller()->GetContainerWindow());
scoped_ptr<KeyboardContainerObserver> keyboard_container_observer(
- new KeyboardContainerObserver(keyboard_container.get()));
+ new KeyboardContainerObserver(keyboard_container));
keyboard_container->SetBounds(root_bounds);
- root_window()->AddChild(keyboard_container.get());
+ root_window()->AddChild(keyboard_container);
EXPECT_TRUE(keyboard_container->IsVisible());
@@ -328,4 +335,108 @@ TEST_F(KeyboardControllerTest, VisibilityChangeWithTextInputTypeChange) {
EXPECT_TRUE(keyboard_container->IsVisible());
}
+TEST_F(KeyboardControllerTest, AlwaysVisibleWhenLocked) {
+ const gfx::Rect& root_bounds = root_window()->bounds();
+
+ ui::InputMethod* input_method = proxy()->GetInputMethod();
+ TestTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT);
+ TestTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT);
+ TestTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE);
+ TestTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE);
+ input_method->SetFocusedTextInputClient(&input_client_0);
+
+ aura::Window* keyboard_container(controller()->GetContainerWindow());
+ scoped_ptr<KeyboardContainerObserver> keyboard_container_observer(
+ new KeyboardContainerObserver(keyboard_container));
+ keyboard_container->SetBounds(root_bounds);
+ root_window()->AddChild(keyboard_container);
+
+ EXPECT_TRUE(keyboard_container->IsVisible());
+
+ // Lock keyboard.
+ controller()->set_lock_keyboard(true);
+
+ input_method->SetFocusedTextInputClient(&no_input_client_0);
+ // Keyboard should not try to hide itself as it is locked.
+ EXPECT_TRUE(keyboard_container->IsVisible());
+ EXPECT_FALSE(WillHideKeyboard());
+
+ input_method->SetFocusedTextInputClient(&input_client_1);
+ EXPECT_TRUE(keyboard_container->IsVisible());
+
+ // Unlock keyboard.
+ controller()->set_lock_keyboard(false);
+
+ // Keyboard should hide when focus on no input client.
+ input_method->SetFocusedTextInputClient(&no_input_client_1);
+ EXPECT_TRUE(WillHideKeyboard());
+
+ // Wait for hide keyboard to finish.
+ base::MessageLoop::current()->Run();
+ EXPECT_FALSE(keyboard_container->IsVisible());
+}
+
+TEST_F(KeyboardControllerTest, KeyboardResizingFromContents) {
+ aura::Window* keyboard_container = controller()->GetContainerWindow();
+ aura::Window* keyboard_window = proxy()->GetKeyboardWindow();
+ keyboard_container->SetBounds(gfx::Rect(800, 600));
+ keyboard_container->AddChild(keyboard_window);
+
+ // Default keyboard size.
+ EXPECT_EQ(180, keyboard_window->bounds().height());
+
+ // Resizes from contents when flag is unset.
+ keyboard_window->SetBounds(gfx::Rect(100, 80));
+ EXPECT_EQ(180, keyboard_window->bounds().height());
+
+ // Resizes from contents when flag is set.
+ proxy()->set_resizing_from_contents(true);
+ keyboard_window->SetBounds(gfx::Rect(100, 80));
+ EXPECT_EQ(80, keyboard_window->bounds().height());
+
+ // Resizes from container when flag is set.
+ keyboard_container->SetBounds(gfx::Rect(400, 300));
+ EXPECT_EQ(80, keyboard_window->bounds().height());
+
+ // Resizes from container when flag is unset.
+ proxy()->set_resizing_from_contents(false);
+ keyboard_container->SetBounds(gfx::Rect(800, 600));
+ EXPECT_EQ(180, keyboard_window->bounds().height());
+}
+
+class KeyboardControllerUsabilityTest : public KeyboardControllerTest {
+ public:
+ KeyboardControllerUsabilityTest() {}
+ virtual ~KeyboardControllerUsabilityTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kKeyboardUsabilityExperiment);
+ KeyboardControllerTest::SetUp();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(KeyboardControllerUsabilityTest);
+};
+
+TEST_F(KeyboardControllerUsabilityTest, KeyboardAlwaysVisibleInUsabilityTest) {
+ const gfx::Rect& root_bounds = root_window()->bounds();
+
+ ui::InputMethod* input_method = proxy()->GetInputMethod();
+ TestTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT);
+ TestTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE);
+ input_method->SetFocusedTextInputClient(&input_client);
+
+ aura::Window* keyboard_container(controller()->GetContainerWindow());
+ keyboard_container->SetBounds(root_bounds);
+ root_window()->AddChild(keyboard_container);
+
+ EXPECT_TRUE(keyboard_container->IsVisible());
+
+ input_method->SetFocusedTextInputClient(&no_input_client);
+ // Keyboard should not hide itself after lost focus.
+ EXPECT_TRUE(keyboard_container->IsVisible());
+ EXPECT_FALSE(WillHideKeyboard());
+}
+
} // namespace keyboard
diff --git a/chromium/ui/keyboard/keyboard_resources.grd b/chromium/ui/keyboard/keyboard_resources.grd
index 8e3da16b8ab..1fbf9684ffd 100644
--- a/chromium/ui/keyboard/keyboard_resources.grd
+++ b/chromium/ui/keyboard/keyboard_resources.grd
@@ -28,11 +28,30 @@
<include name="IDR_KEYBOARD_ELEMENTS_KEY_SEQUENCE" file="resources/elements/kb-key-sequence.html" type="BINDATA" />
<include name="IDR_KEYBOARD_ELEMENTS_KEYBOARD" file="resources/elements/kb-keyboard.html" type="BINDATA" />
<include name="IDR_KEYBOARD_ELEMENTS_KEYSET" file="resources/elements/kb-keyset.html" type="BINDATA" />
+ <include name="IDR_KEYBOARD_ELEMENTS_MODIFIER_KEY" file="resources/elements/kb-modifier-key.html" type="BINDATA" />
+ <include name="IDR_KEYBOARD_ELEMENTS_OPTIONS_MENU" file="resources/elements/kb-options-menu.html" type="BINDATA" />
<include name="IDR_KEYBOARD_ELEMENTS_ROW" file="resources/elements/kb-row.html" type="BINDATA" />
<include name="IDR_KEYBOARD_ELEMENTS_SHIFT_KEY" file="resources/elements/kb-shift-key.html" type="BINDATA" />
+ <include name="IDR_KEYBOARD_FUNCTION_KEY_ROW" file="resources/layouts/function-key-row.html" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_BACK" file="resources/images/back.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_BRIGHTNESS_DOWN" file="resources/images/brightness-down.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_BRIGHTNESS_UP" file="resources/images/brightness-up.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_CHANGE_WINDOW" file="resources/images/change-window.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_DOWN" file="resources/images/down.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_FORWARD" file="resources/images/forward.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_FULLSCREEN" file="resources/images/fullscreen.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_KEYBOARD" file="resources/images/keyboard.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_LEFT" file="resources/images/left.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_MICROPHONE" file="resources/images/microphone.svg" type="BINDATA" />
<include name="IDR_KEYBOARD_IMAGES_MICROPHONE_GREEN" file="resources/images/microphone-green.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_MUTE" file="resources/images/mute.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_RELOAD" file="resources/images/reload.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_RIGHT" file="resources/images/right.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_SEARCH" file="resources/images/search.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_SHUTDOWN" file="resources/images/shutdown.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_UP" file="resources/images/up.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_VOLUME_DOWN" file="resources/images/volume-down.svg" type="BINDATA" />
+ <include name="IDR_KEYBOARD_IMAGES_VOLUME_UP" file="resources/images/volume-up.svg" type="BINDATA" />
<!-- Don't flatten html file here. Otherwise, webui keyboard will not load the correct css file. -->
<include name="IDR_KEYBOARD_INDEX" file="resources/index.html" allowexternalscript="true" type="BINDATA" />
<include name="IDR_KEYBOARD_LAYOUTS_DVORAK" file="resources/layouts/dvorak.html" type="BINDATA" />
@@ -40,10 +59,11 @@
<include name="IDR_KEYBOARD_LAYOUTS_NUMERIC" file="resources/layouts/numeric.html" type="BINDATA" />
<include name="IDR_KEYBOARD_LAYOUTS_QWERTY" file="resources/layouts/qwerty.html" type="BINDATA" />
<include name="IDR_KEYBOARD_LAYOUTS_SYMBOL_ALTKEYS" file="resources/layouts/symbol-altkeys.js" type="BINDATA" />
+ <include name="IDR_KEYBOARD_LAYOUTS_SYSTEM_QWERTY" file="resources/layouts/system-qwerty.html" type="BINDATA" />
<include name="IDR_KEYBOARD_MAIN_JS" file="resources/main.js" type="BINDATA" />
<include name="IDR_KEYBOARD_MANIFEST" file="resources/manifest.json" type="BINDATA" />
<include name="IDR_KEYBOARD_MAIN_CSS" file="resources/main.css" type="BINDATA" />
- <include name="IDR_KEYBOARD_POLYMER" file="resources/polymer.min.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_KEYBOARD_POLYMER_LOADER" file="resources/polymer_loader.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_KEYBOARD_SPACEBAR_ROW" file="resources/layouts/spacebar-row.html" type="BINDATA" />
<include name="IDR_KEYBOARD_VOICE_INPUT_JS" file="resources/voice_input.js" type="BINDATA" />
<include name="IDR_KEYBOARD_WEBUI_INDEX" file="resources/webui_index.html" allowexternalscript="true" type="BINDATA" />
diff --git a/chromium/ui/keyboard/keyboard_switches.cc b/chromium/ui/keyboard/keyboard_switches.cc
index d1ea4e2cbba..aeecf37b070 100644
--- a/chromium/ui/keyboard/keyboard_switches.cc
+++ b/chromium/ui/keyboard/keyboard_switches.cc
@@ -7,7 +7,10 @@
namespace keyboard {
namespace switches {
+const char kEnableSwipeSelection[] = "enable-swipe-selection";
+
const char kEnableVirtualKeyboard[] = "enable-virtual-keyboard";
+const char kKeyboardUsabilityExperiment[] = "keyboard-usability-experiment";
} // namespace switches
} // namespace keyboard
diff --git a/chromium/ui/keyboard/keyboard_switches.h b/chromium/ui/keyboard/keyboard_switches.h
index a7d053314b6..04d4e737024 100644
--- a/chromium/ui/keyboard/keyboard_switches.h
+++ b/chromium/ui/keyboard/keyboard_switches.h
@@ -10,9 +10,16 @@
namespace keyboard {
namespace switches {
+// Enables the swipe selection feature on the virtual keyboard.
+KEYBOARD_EXPORT extern const char kEnableSwipeSelection[];
+
// Enables the virtual keyboard.
KEYBOARD_EXPORT extern const char kEnableVirtualKeyboard[];
+// Enables the keyboard usability experiment. This is an experimental mode for
+// testing the usability of various experimental keyboard layouts.
+KEYBOARD_EXPORT extern const char kKeyboardUsabilityExperiment[];
+
} // namespace switches
} // namespace keyboard
diff --git a/chromium/ui/keyboard/keyboard_test_suite.cc b/chromium/ui/keyboard/keyboard_test_suite.cc
deleted file mode 100644
index dc4ec5b5e98..00000000000
--- a/chromium/ui/keyboard/keyboard_test_suite.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2013 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 "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "ui/test/test_suite.h"
-
-class KeyboardTestSuite : public ui::test::UITestSuite {
- public:
- KeyboardTestSuite(int argc, char** argv)
- : ui::test::UITestSuite(argc, argv) {
- }
-
- protected:
- virtual void Initialize() OVERRIDE;
- virtual void Shutdown() OVERRIDE;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(KeyboardTestSuite);
-};
-
-void KeyboardTestSuite::Initialize() {
- ui::test::UITestSuite::Initialize();
-}
-
-void KeyboardTestSuite::Shutdown() {
- ui::test::UITestSuite::Shutdown();
-}
-
-int main(int argc, char** argv) {
- return KeyboardTestSuite(argc, argv).Run();
-}
diff --git a/chromium/ui/keyboard/keyboard_ui_controller.cc b/chromium/ui/keyboard/keyboard_ui_controller.cc
index 8bc009202d0..1c37cdf35a4 100644
--- a/chromium/ui/keyboard/keyboard_ui_controller.cc
+++ b/chromium/ui/keyboard/keyboard_ui_controller.cc
@@ -36,18 +36,56 @@ content::WebUIDataSource* CreateKeyboardUIDataSource() {
IDR_KEYBOARD_ELEMENTS_KEYBOARD);
source->AddResourcePath("elements/kb-keyset.html",
IDR_KEYBOARD_ELEMENTS_KEYSET);
+ source->AddResourcePath("elements/kb-modifier-key.html",
+ IDR_KEYBOARD_ELEMENTS_MODIFIER_KEY);
+ source->AddResourcePath("elements/kb-options-menu.html",
+ IDR_KEYBOARD_ELEMENTS_OPTIONS_MENU);
source->AddResourcePath("elements/kb-row.html", IDR_KEYBOARD_ELEMENTS_ROW);
source->AddResourcePath("elements/kb-shift-key.html",
IDR_KEYBOARD_ELEMENTS_SHIFT_KEY);
+ source->AddResourcePath("images/back.svg",
+ IDR_KEYBOARD_IMAGES_BACK);
+ source->AddResourcePath("images/brightness-down.svg",
+ IDR_KEYBOARD_IMAGES_BRIGHTNESS_DOWN);
+ source->AddResourcePath("images/brightness-up.svg",
+ IDR_KEYBOARD_IMAGES_BRIGHTNESS_UP);
+ source->AddResourcePath("images/change-window.svg",
+ IDR_KEYBOARD_IMAGES_CHANGE_WINDOW);
+ source->AddResourcePath("images/down.svg",
+ IDR_KEYBOARD_IMAGES_DOWN);
+ source->AddResourcePath("images/forward.svg",
+ IDR_KEYBOARD_IMAGES_FORWARD);
+ source->AddResourcePath("images/fullscreen.svg",
+ IDR_KEYBOARD_IMAGES_FULLSCREEN);
+ source->AddResourcePath("images/left.svg",
+ IDR_KEYBOARD_IMAGES_LEFT);
source->AddResourcePath("images/microphone.svg",
IDR_KEYBOARD_IMAGES_MICROPHONE);
source->AddResourcePath("images/microphone-green.svg",
IDR_KEYBOARD_IMAGES_MICROPHONE_GREEN);
+ source->AddResourcePath("images/mute.svg",
+ IDR_KEYBOARD_IMAGES_MUTE);
+ source->AddResourcePath("images/reload.svg",
+ IDR_KEYBOARD_IMAGES_RELOAD);
+ source->AddResourcePath("images/right.svg",
+ IDR_KEYBOARD_IMAGES_RIGHT);
+ source->AddResourcePath("images/search.svg",
+ IDR_KEYBOARD_IMAGES_SEARCH);
+ source->AddResourcePath("images/shutdown.svg",
+ IDR_KEYBOARD_IMAGES_SHUTDOWN);
+ source->AddResourcePath("images/up.svg",
+ IDR_KEYBOARD_IMAGES_UP);
+ source->AddResourcePath("images/volume-down.svg",
+ IDR_KEYBOARD_IMAGES_VOLUME_DOWN);
+ source->AddResourcePath("images/volume-up.svg",
+ IDR_KEYBOARD_IMAGES_VOLUME_UP);
source->AddResourcePath("layouts/latin-accents.js",
IDR_KEYBOARD_LAYOUTS_LATIN_ACCENTS);
source->AddResourcePath("layouts/numeric.html", IDR_KEYBOARD_LAYOUTS_NUMERIC);
+ source->AddResourcePath("layouts/system-qwerty.html",
+ IDR_KEYBOARD_LAYOUTS_SYSTEM_QWERTY);
source->AddResourcePath("main.js", IDR_KEYBOARD_MAIN_JS);
- source->AddResourcePath("polymer.min.js", IDR_KEYBOARD_POLYMER);
+ source->AddResourcePath("polymer_loader.js", IDR_KEYBOARD_POLYMER_LOADER);
source->AddResourcePath("voice_input.js", IDR_KEYBOARD_VOICE_INPUT_JS);
// These files are specific to the WebUI version
diff --git a/chromium/ui/keyboard/keyboard_ui_handler.cc b/chromium/ui/keyboard/keyboard_ui_handler.cc
index 26909c2d49e..780e0be4aaf 100644
--- a/chromium/ui/keyboard/keyboard_ui_handler.cc
+++ b/chromium/ui/keyboard/keyboard_ui_handler.cc
@@ -54,7 +54,7 @@ void KeyboardUIHandler::HandleInsertTextMessage(const base::ListValue* args) {
return;
}
- aura::RootWindow* root_window =
+ aura::Window* root_window =
web_ui()->GetWebContents()->GetView()->GetNativeView()->GetRootWindow();
if (!root_window) {
LOG(ERROR) << "insertText failed: no root window";
@@ -75,7 +75,7 @@ void KeyboardUIHandler::HandleGetInputContextMessage(
base::DictionaryValue results;
results.SetInteger("requestId", request_id);
- aura::RootWindow* root_window =
+ aura::Window* root_window =
web_ui()->GetWebContents()->GetView()->GetNativeView()->GetRootWindow();
if (!root_window) {
LOG(ERROR) << "getInputContext failed: no root window";
@@ -102,29 +102,32 @@ void KeyboardUIHandler::HandleSendKeyEventMessage(
std::string type;
int char_value;
int key_code;
- bool shift_modifier;
+ std::string key_name;
+ int modifiers;
if (!args->GetDictionary(0, &params) ||
!params->GetString("type", &type) ||
!params->GetInteger("charValue", &char_value) ||
!params->GetInteger("keyCode", &key_code) ||
- !params->GetBoolean("shiftKey", &shift_modifier)) {
+ !params->GetString("keyName", &key_name) ||
+ !params->GetInteger("modifiers", &modifiers)) {
LOG(ERROR) << "SendKeyEvent failed: bad argument";
return;
}
- aura::RootWindow* root_window =
- web_ui()->GetWebContents()->GetView()->GetNativeView()->GetRootWindow();
- if (!root_window) {
- LOG(ERROR) << "sendKeyEvent failed: no root window";
+ aura::WindowEventDispatcher* dispatcher =
+ web_ui()->GetWebContents()->GetView()->GetNativeView()->GetDispatcher();
+ if (!dispatcher) {
+ LOG(ERROR) << "sendKeyEvent failed: no dispatcher";
return;
}
if (!keyboard::SendKeyEvent(type,
char_value,
key_code,
- shift_modifier,
- root_window)) {
+ key_name,
+ modifiers,
+ dispatcher)) {
LOG(ERROR) << "sendKeyEvent failed";
}
}
diff --git a/chromium/ui/keyboard/keyboard_util.cc b/chromium/ui/keyboard/keyboard_util.cc
index 8389e55f03b..bdb049df32c 100644
--- a/chromium/ui/keyboard/keyboard_util.cc
+++ b/chromium/ui/keyboard/keyboard_util.cc
@@ -7,7 +7,9 @@
#include <string>
#include "base/command_line.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/metrics/histogram.h"
#include "base/strings/string16.h"
#include "grit/keyboard_resources.h"
#include "grit/keyboard_resources_map.h"
@@ -22,23 +24,33 @@ namespace {
const char kKeyDown[] ="keydown";
const char kKeyUp[] = "keyup";
-void SendProcessKeyEvent(ui::EventType type, aura::RootWindow* root_window) {
+void SendProcessKeyEvent(ui::EventType type,
+ aura::WindowEventDispatcher* dispatcher) {
ui::TranslatedKeyEvent event(type == ui::ET_KEY_PRESSED,
ui::VKEY_PROCESSKEY,
ui::EF_NONE);
- root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&event);
+ dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&event);
}
+base::LazyInstance<base::Time> g_keyboard_load_time_start =
+ LAZY_INSTANCE_INITIALIZER;
+
} // namespace
namespace keyboard {
bool IsKeyboardEnabled() {
return CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableVirtualKeyboard);
+ switches::kEnableVirtualKeyboard) ||
+ IsKeyboardUsabilityExperimentEnabled();
}
-bool InsertText(const base::string16& text, aura::RootWindow* root_window) {
+bool IsKeyboardUsabilityExperimentEnabled() {
+ return CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kKeyboardUsabilityExperiment);
+}
+
+bool InsertText(const base::string16& text, aura::Window* root_window) {
if (!root_window)
return false;
@@ -62,8 +74,8 @@ bool InsertText(const base::string16& text, aura::RootWindow* root_window) {
// ui::TextInputClient from that (see above in InsertText()).
bool MoveCursor(int swipe_direction,
int modifier_flags,
- aura::RootWindow* root_window) {
- if (!root_window)
+ aura::WindowEventDispatcher* dispatcher) {
+ if (!dispatcher)
return false;
ui::KeyboardCode codex = ui::VKEY_UNKNOWN;
ui::KeyboardCode codey = ui::VKEY_UNKNOWN;
@@ -80,17 +92,17 @@ bool MoveCursor(int swipe_direction,
// First deal with the x movement.
if (codex != ui::VKEY_UNKNOWN) {
ui::KeyEvent press_event(ui::ET_KEY_PRESSED, codex, modifier_flags, 0);
- root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&press_event);
+ dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&press_event);
ui::KeyEvent release_event(ui::ET_KEY_RELEASED, codex, modifier_flags, 0);
- root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&release_event);
+ dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&release_event);
}
// Then deal with the y movement.
if (codey != ui::VKEY_UNKNOWN) {
ui::KeyEvent press_event(ui::ET_KEY_PRESSED, codey, modifier_flags, 0);
- root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&press_event);
+ dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&press_event);
ui::KeyEvent release_event(ui::ET_KEY_RELEASED, codey, modifier_flags, 0);
- root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&release_event);
+ dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&release_event);
}
return true;
}
@@ -98,8 +110,9 @@ bool MoveCursor(int swipe_direction,
bool SendKeyEvent(const std::string type,
int key_value,
int key_code,
- bool shift_modifier,
- aura::RootWindow* root_window) {
+ std::string key_name,
+ int modifiers,
+ aura::WindowEventDispatcher* dispatcher) {
ui::EventType event_type = ui::ET_UNKNOWN;
if (type == kKeyDown)
event_type = ui::ET_KEY_PRESSED;
@@ -108,34 +121,65 @@ bool SendKeyEvent(const std::string type,
if (event_type == ui::ET_UNKNOWN)
return false;
- int flags = ui::EF_NONE;
- if (shift_modifier)
- flags = ui::EF_SHIFT_DOWN;
-
ui::KeyboardCode code = static_cast<ui::KeyboardCode>(key_code);
if (code == ui::VKEY_UNKNOWN) {
// Handling of special printable characters (e.g. accented characters) for
// which there is no key code.
if (event_type == ui::ET_KEY_RELEASED) {
- ui::InputMethod* input_method = root_window->GetProperty(
+ ui::InputMethod* input_method = dispatcher->window()->GetProperty(
aura::client::kRootWindowInputMethodKey);
if (!input_method)
return false;
ui::TextInputClient* tic = input_method->GetTextInputClient();
- SendProcessKeyEvent(ui::ET_KEY_PRESSED, root_window);
+ SendProcessKeyEvent(ui::ET_KEY_PRESSED, dispatcher);
tic->InsertChar(static_cast<uint16>(key_value), ui::EF_NONE);
- SendProcessKeyEvent(ui::ET_KEY_RELEASED, root_window);
+ SendProcessKeyEvent(ui::ET_KEY_RELEASED, dispatcher);
}
} else {
- ui::KeyEvent event(event_type, code, flags, false);
- root_window->AsRootWindowHostDelegate()->OnHostKeyEvent(&event);
+ if (event_type == ui::ET_KEY_RELEASED) {
+ // The number of key press events seen since the last backspace.
+ static int keys_seen = 0;
+ if (code == ui::VKEY_BACK) {
+ // Log the rough lengths of characters typed between backspaces. This
+ // metric will be used to determine the error rate for the keyboard.
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "VirtualKeyboard.KeystrokesBetweenBackspaces",
+ keys_seen, 1, 1000, 50);
+ keys_seen = 0;
+ } else {
+ ++keys_seen;
+ }
+ }
+
+ ui::KeyEvent event(event_type, code, key_name, modifiers, false);
+ dispatcher->AsRootWindowHostDelegate()->OnHostKeyEvent(&event);
}
return true;
}
+const void MarkKeyboardLoadStarted() {
+ if (!g_keyboard_load_time_start.Get().ToInternalValue())
+ g_keyboard_load_time_start.Get() = base::Time::Now();
+}
+
+const void MarkKeyboardLoadFinished() {
+ // It should not be possible to finish loading the keyboard without starting
+ // to load it first.
+ DCHECK(g_keyboard_load_time_start.Get().ToInternalValue());
+
+ static bool logged = false;
+ if (!logged) {
+ // Log the delta only once.
+ UMA_HISTOGRAM_TIMES(
+ "VirtualKeyboard.FirstLoadTime",
+ base::Time::Now() - g_keyboard_load_time_start.Get());
+ logged = true;
+ }
+}
+
const GritResourceMap* GetKeyboardExtensionResources(size_t* size) {
// This looks a lot like the contents of a resource map; however it is
// necessary to have a custom path for the extension path, so the resource
@@ -158,12 +202,34 @@ const GritResourceMap* GetKeyboardExtensionResources(size_t* size) {
IDR_KEYBOARD_ELEMENTS_KEY_SEQUENCE},
{"keyboard/elements/kb-keyboard.html", IDR_KEYBOARD_ELEMENTS_KEYBOARD},
{"keyboard/elements/kb-keyset.html", IDR_KEYBOARD_ELEMENTS_KEYSET},
+ {"keyboard/elements/kb-modifier-key.html",
+ IDR_KEYBOARD_ELEMENTS_MODIFIER_KEY},
+ {"keyboard/elements/kb-options-menu.html",
+ IDR_KEYBOARD_ELEMENTS_OPTIONS_MENU},
{"keyboard/elements/kb-row.html", IDR_KEYBOARD_ELEMENTS_ROW},
{"keyboard/elements/kb-shift-key.html", IDR_KEYBOARD_ELEMENTS_SHIFT_KEY},
+ {"keyboard/layouts/function-key-row.html", IDR_KEYBOARD_FUNCTION_KEY_ROW},
+ {"keyboard/images/back.svg", IDR_KEYBOARD_IMAGES_BACK},
+ {"keyboard/images/brightness-down.svg",
+ IDR_KEYBOARD_IMAGES_BRIGHTNESS_DOWN},
+ {"keyboard/images/brightness-up.svg", IDR_KEYBOARD_IMAGES_BRIGHTNESS_UP},
+ {"keyboard/images/change-window.svg", IDR_KEYBOARD_IMAGES_CHANGE_WINDOW},
+ {"keyboard/images/down.svg", IDR_KEYBOARD_IMAGES_DOWN},
+ {"keyboard/images/forward.svg", IDR_KEYBOARD_IMAGES_FORWARD},
+ {"keyboard/images/fullscreen.svg", IDR_KEYBOARD_IMAGES_FULLSCREEN},
{"keyboard/images/keyboard.svg", IDR_KEYBOARD_IMAGES_KEYBOARD},
+ {"keyboard/images/left.svg", IDR_KEYBOARD_IMAGES_LEFT},
{"keyboard/images/microphone.svg", IDR_KEYBOARD_IMAGES_MICROPHONE},
{"keyboard/images/microphone-green.svg",
IDR_KEYBOARD_IMAGES_MICROPHONE_GREEN},
+ {"keyboard/images/mute.svg", IDR_KEYBOARD_IMAGES_MUTE},
+ {"keyboard/images/reload.svg", IDR_KEYBOARD_IMAGES_RELOAD},
+ {"keyboard/images/right.svg", IDR_KEYBOARD_IMAGES_RIGHT},
+ {"keyboard/images/search.svg", IDR_KEYBOARD_IMAGES_SEARCH},
+ {"keyboard/images/shutdown.svg", IDR_KEYBOARD_IMAGES_SHUTDOWN},
+ {"keyboard/images/up.svg", IDR_KEYBOARD_IMAGES_UP},
+ {"keyboard/images/volume-down.svg", IDR_KEYBOARD_IMAGES_VOLUME_DOWN},
+ {"keyboard/images/volume-up.svg", IDR_KEYBOARD_IMAGES_VOLUME_UP},
{"keyboard/index.html", IDR_KEYBOARD_INDEX},
{"keyboard/layouts/dvorak.html", IDR_KEYBOARD_LAYOUTS_DVORAK},
{"keyboard/layouts/latin-accents.js", IDR_KEYBOARD_LAYOUTS_LATIN_ACCENTS},
@@ -171,11 +237,12 @@ const GritResourceMap* GetKeyboardExtensionResources(size_t* size) {
{"keyboard/layouts/qwerty.html", IDR_KEYBOARD_LAYOUTS_QWERTY},
{"keyboard/layouts/symbol-altkeys.js",
IDR_KEYBOARD_LAYOUTS_SYMBOL_ALTKEYS},
+ {"keyboard/layouts/system-qwerty.html", IDR_KEYBOARD_LAYOUTS_SYSTEM_QWERTY},
{"keyboard/layouts/spacebar-row.html", IDR_KEYBOARD_SPACEBAR_ROW},
{"keyboard/main.js", IDR_KEYBOARD_MAIN_JS},
{"keyboard/manifest.json", IDR_KEYBOARD_MANIFEST},
{"keyboard/main.css", IDR_KEYBOARD_MAIN_CSS},
- {"keyboard/polymer.min.js", IDR_KEYBOARD_POLYMER},
+ {"keyboard/polymer_loader.js", IDR_KEYBOARD_POLYMER_LOADER},
{"keyboard/voice_input.js", IDR_KEYBOARD_VOICE_INPUT_JS},
};
static const size_t kKeyboardResourcesSize = arraysize(kKeyboardResources);
@@ -183,4 +250,11 @@ const GritResourceMap* GetKeyboardExtensionResources(size_t* size) {
return kKeyboardResources;
}
+void LogKeyboardControlEvent(KeyboardControlEvent event) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "VirtualKeyboard.KeyboardControlEvent",
+ event,
+ keyboard::KEYBOARD_CONTROL_MAX);
+}
+
} // namespace keyboard
diff --git a/chromium/ui/keyboard/keyboard_util.h b/chromium/ui/keyboard/keyboard_util.h
index bb0edfb7bd7..232127320b0 100644
--- a/chromium/ui/keyboard/keyboard_util.h
+++ b/chromium/ui/keyboard/keyboard_util.h
@@ -8,11 +8,10 @@
#include <string>
#include "base/strings/string16.h"
+// TODO(beng): replace with forward decl once RootWindow is renamed.
+#include "ui/aura/window.h"
#include "ui/keyboard/keyboard_export.h"
-namespace aura {
-class RootWindow;
-}
struct GritResourceMap;
namespace keyboard {
@@ -25,38 +24,63 @@ enum CursorMoveDirection {
kCursorMoveDown = 0x08
};
+// An enumeration of different keyboard control events that should be logged.
+enum KeyboardControlEvent {
+ KEYBOARD_CONTROL_SHOW = 0,
+ KEYBOARD_CONTROL_HIDE_AUTO,
+ KEYBOARD_CONTROL_HIDE_USER,
+ KEYBOARD_CONTROL_MAX,
+};
+
// Returns true if the virtual keyboard is enabled.
KEYBOARD_EXPORT bool IsKeyboardEnabled();
+// Returns true if the keyboard usability test is enabled.
+KEYBOARD_EXPORT bool IsKeyboardUsabilityExperimentEnabled();
+
// Insert |text| into the active TextInputClient associated with |root_window|,
// if there is one. Returns true if |text| was successfully inserted. Note
// that this may convert |text| into ui::KeyEvents for injection in some
// special circumstances (i.e. VKEY_RETURN, VKEY_BACK).
KEYBOARD_EXPORT bool InsertText(const base::string16& text,
- aura::RootWindow* root_window);
+ aura::Window* root_window);
// Move cursor when swipe on the virtualkeyboard. Returns true if cursor was
// successfully moved according to |swipe_direction|.
KEYBOARD_EXPORT bool MoveCursor(int swipe_direction,
int modifier_flags,
- aura::RootWindow* root_window);
+ aura::WindowEventDispatcher* dispatcher);
// Sends a fabricated key event, where |type| is the event type, |key_value|
// is the unicode value of the character, |key_code| is the legacy key code
-// value, and |shift_modifier| indicates if the shift key is being virtually
-// pressed. The event is dispatched to the active TextInputClient associated
-// with |root_window|. The type may be "keydown" or "keyup".
+// value, |key_name| is the name of the key as defined in the DOM3 key event
+// specification, and |modifier| indicates if any modifier keys are being
+// virtually pressed. The event is dispatched to the active TextInputClient
+// associated with |root_window|. The type may be "keydown" or "keyup".
KEYBOARD_EXPORT bool SendKeyEvent(std::string type,
int key_value,
int key_code,
- bool shift_modifier,
- aura::RootWindow* root_window);
+ std::string key_name,
+ int modifiers,
+ aura::WindowEventDispatcher* dispatcher);
+
+// Marks that the keyboard load has started. This is used to measure the time it
+// takes to fully load the keyboard. This should be called before
+// MarkKeyboardLoadFinished.
+KEYBOARD_EXPORT const void MarkKeyboardLoadStarted();
+
+// Marks that the keyboard load has ended. This finishes measuring that the
+// keyboard is loaded.
+KEYBOARD_EXPORT const void MarkKeyboardLoadFinished();
// Get the list of keyboard resources. |size| is populated with the number of
// resources in the returned array.
KEYBOARD_EXPORT const GritResourceMap* GetKeyboardExtensionResources(
size_t* size);
+// Logs the keyboard control event as a UMA stat.
+void LogKeyboardControlEvent(KeyboardControlEvent event);
+
} // namespace keyboard
#endif // UI_KEYBOARD_KEYBOARD_UTIL_H_
diff --git a/chromium/ui/keyboard/resources/api_adapter.js b/chromium/ui/keyboard/resources/api_adapter.js
index 049c3666242..934a7600463 100644
--- a/chromium/ui/keyboard/resources/api_adapter.js
+++ b/chromium/ui/keyboard/resources/api_adapter.js
@@ -2,6 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+/**
+ * Queries the document for an element with a matching id.
+ * @param {string} id is a case-sensitive string representing the unique ID of
+ * the element being sought.
+ * @return {?Element} The element with that id.
+ */
+var $ = function(id) {
+ return document.getElementById(id);
+}
+
function logIfError() {
if (chrome.runtime.lastError) {
console.log(chrome.runtime.lastError);
@@ -24,8 +34,12 @@ function hideKeyboard() {
chrome.virtualKeyboardPrivate.hideKeyboard(logIfError);
}
+function keyboardLoaded() {
+ chrome.virtualKeyboardPrivate.keyboardLoaded(logIfError);
+}
+
chrome.virtualKeyboardPrivate.onTextInputBoxFocused.addListener(
function (inputContext) {
- // TODO(bshe): Making keyboard aware of inputContext.
+ $('keyboard').inputTypeValue = inputContext.type;
}
);
diff --git a/chromium/ui/keyboard/resources/constants.js b/chromium/ui/keyboard/resources/constants.js
index b7028c28fb0..e80507ee7c7 100644
--- a/chromium/ui/keyboard/resources/constants.js
+++ b/chromium/ui/keyboard/resources/constants.js
@@ -22,3 +22,16 @@ var FONT_SIZE_RATIO = 3;
// in kb-keyset. Remove this variable once figure out how to calculate the
// number from keysets.
var ROW_LENGTH = 4;
+
+/**
+ * The enumeration of swipe directions.
+ * @const
+ * @type {Enum}
+ */
+var SWIPE_DIRECTION = {
+ RIGHT: 0x1,
+ LEFT: 0x2,
+ UP: 0x4,
+ DOWN: 0x8
+};
+
diff --git a/chromium/ui/keyboard/resources/elements/kb-altkey-container.html b/chromium/ui/keyboard/resources/elements/kb-altkey-container.html
index 88666524bae..552c70fedb0 100644
--- a/chromium/ui/keyboard/resources/elements/kb-altkey-container.html
+++ b/chromium/ui/keyboard/resources/elements/kb-altkey-container.html
@@ -4,19 +4,18 @@
-- found in the LICENSE file.
-->
-<polymer-element name="kb-altkey-container" attributes="keyset" on-pointerup="up">
+<polymer-element name="kb-altkey-container" attributes="keyset"
+ on-pointerup="{{up}}">
<template>
<style>
- @host {
- * {
- background-color: rgba(0, 0, 0, 0.6);
- bottom: 0;
- left: 0;
- -webkit-box-flex: 1;
- position: absolute;
- right: 0;
- top: 0;
- }
+ :host {
+ -webkit-box-flex: 1;
+ background-color: rgba(0, 0, 0, 0.6);
+ bottom: 0;
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
}
</style>
<content select="#{{keyset}}"></content>
@@ -37,7 +36,14 @@
this.hidden = true;
this.resetActiveElement();
this.keyset = null;
- }
+ },
+
+ hiddenChanged: function() {
+ this.fire('stateChange', {
+ state: 'candidatePopupVisibility',
+ value: !!this.hidden
+ });
+ },
});
</script>
</polymer-element>
diff --git a/chromium/ui/keyboard/resources/elements/kb-altkey-set.html b/chromium/ui/keyboard/resources/elements/kb-altkey-set.html
index 65b7b0ba45c..85ca1b06afc 100644
--- a/chromium/ui/keyboard/resources/elements/kb-altkey-set.html
+++ b/chromium/ui/keyboard/resources/elements/kb-altkey-set.html
@@ -7,50 +7,12 @@
<polymer-element name="kb-altkey-set" attributes="offset char">
<template>
<style>
- /* TODO(stevet): Migrate this to main.css using custom pseudo
- * selectors.
- */
- @host {
- * {
- background-color: #3b3b3e;
- border-radius: 2px;
- display: -webkit-box;
- text-align: center;
- position: absolute;
- }
- }
-
- content::-webkit-distributed(.active) {
- background-color: #848490 !important;
- /* This artificial border is used to prevent the key contents from
- * "bouncing" due to the inactive state having a different border size.
- */
- border-radius: 2px;
- border-top: 1px solid #848490;
- /* Do not use box shadow until performance improves
- * http://code.google.com/p/chromium/issues/detail?id=99045
- box-shadow: 0px 0px 15px #fff;
- */
- }
-
- content::-webkit-distributed(kb-altkey) {
- -webkit-flex: 1 auto;
- background-color: #3b3b3e;
- border-left: 1px solid rgba(0, 0, 0, 0.15);
- border-top: 2px solid #4b4b4e;
- color: #ffffff;
- font-family: 'Open Sans', sans-serif;
- font-weight: 100;
- }
-
- content::-webkit-distributed(kb-altkey:first-child) {
- border-top-left-radius: 2px;
- border-bottom-left-radius: 2px;
- }
-
- content::-webkit-distributed(kb-altkey:last-child) {
- border-top-right-radius: 2px;
- border-bottom-right-radius: 2px;
+ :host {
+ background-color: #3b3b3e;
+ border-radius: 2px;
+ display: -webkit-box;
+ text-align: center;
+ position: absolute;
}
</style>
<content select="*"></content>
diff --git a/chromium/ui/keyboard/resources/elements/kb-altkey.html b/chromium/ui/keyboard/resources/elements/kb-altkey.html
index 42324cdf6a0..276ca5c1191 100644
--- a/chromium/ui/keyboard/resources/elements/kb-altkey.html
+++ b/chromium/ui/keyboard/resources/elements/kb-altkey.html
@@ -4,22 +4,51 @@
-- found in the LICENSE file.
-->
-<polymer-element name="kb-altkey" attributes="char" on-pointerover="over"
- on-pointerout="out" on-pointerup="up">
+<polymer-element name="kb-altkey" attributes="char" on-pointerover="{{over}}"
+ on-pointerout="{{out}}" on-pointerup="{{up}}">
<template>
<style>
- @host {
- * {
- -webkit-box-flex: 1;
- display: -webkit-box;
- position: relative;
- background-position: center center;
- background-repeat: no-repeat;
- background-size: contain;
- }
+ :host {
+ -webkit-box-flex: 1;
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: contain;
+ border-left: 1px solid rgba(0, 0, 0, 0.15);
+ border-top: 2px solid #4b4b4e;
+ display: -webkit-box;
+ position: relative;
+ }
+
+ :host.active {
+ background-color: #848490;
+ border-top: 1px solid #848490;
+ }
+
+ :host:first-child {
+ border-top-left-radius: 2px;
+ border-bottom-left-radius: 2px;
+ }
+
+ :host:last-child {
+ border-top-right-radius: 2px;
+ border-bottom-right-radius: 2px;
+ }
+
+ ::part(key) {
+ bottom: 0;
+ color: #ffffff;
+ font-family: 'Open Sans', 'Noto Sans UI', sans-serif;
+ font-weight: 100;
+ height: 1.2em;
+ left: 0;
+ margin: auto;
+ position: absolute;
+ right: 0;
+ top: 0;
+ text-align: center;
}
</style>
- <div pseudo="x-key">
+ <div part="key">
<content></content>
</div>
</template>
@@ -29,7 +58,7 @@
* inside a node, the event should be filter out.
* @param {Node} node The accent key node which receives event.
* @param {event} event A pointer move event.
- * @return {boolean} True if event is externla to node.
+ * @return {boolean} True if event is external to node.
*/
function isRelevantEvent(node, event) {
return !(node.compareDocumentPosition(event.relatedTarget)
@@ -43,16 +72,32 @@
this.fire('key-down', {});
}
},
+
out: function(event) {
if (isRelevantEvent(this, event)) {
this.classList.remove('active');
}
},
+
up: function(event) {
var detail = {
- char: this.char || this.textContent
+ char: this.charValue
};
this.fire('key-up', detail);
+ },
+
+ // TODO(bshe): kb-altkey should extend from kb-key-base.
+ autoRelease: function() {
+ },
+
+ /**
+ * Character value associated with the key. Typically, the value is a
+ * single character, but may be multi-character in cases like a ".com"
+ * button.
+ * @return {string}
+ */
+ get charValue() {
+ return this.char || this.textContent;
}
});
</script>
diff --git a/chromium/ui/keyboard/resources/elements/kb-key-base.html b/chromium/ui/keyboard/resources/elements/kb-key-base.html
index 89a174809d3..21d25149c3b 100644
--- a/chromium/ui/keyboard/resources/elements/kb-key-base.html
+++ b/chromium/ui/keyboard/resources/elements/kb-key-base.html
@@ -5,8 +5,8 @@
-->
<polymer-element name="kb-key-base"
- on-pointerdown="down" on-pointerup="up" on-pointerout="out"
- attributes="accents char invert repeat hintText toKeyset toLayout">
+ on-pointerdown="{{down}}" on-pointerup="{{up}}" on-pointerout="{{out}}"
+ attributes="char invert repeat hintText toKeyset toLayout">
<script>
/**
* The long-press delay in milliseconds before long-press handler is
@@ -69,6 +69,7 @@
repeat: false,
invert: false,
longPressTimer: null,
+ pointerId: undefined,
/**
* The keyset transition rules. It defines which keyset to transit to on
@@ -108,51 +109,120 @@
});
}
},
+
down: function(event) {
- var detail = this.populateDetails();
- if (this.keysetRules && this.keysetRules.down != undefined) {
- detail.toKeyset = this.keysetRules.down[TO_KEYSET - OFFSET];
- detail.nextKeyset = this.keysetRules.down[NEXT_KEYSET - OFFSET];
- }
+ this.pointerId = event.pointerId;
+ var detail = this.populateDetails('down');
this.fire('key-down', detail);
this.longPressTimer = this.generateLongPressTimer();
},
out: function(event) {
+ this.classList.remove('active');
clearTimeout(this.longPressTimer);
},
up: function(event) {
+ this.generateKeyup();
+ },
+
+ /**
+ * Releases the pressed key programmatically and fires key-up event. This
+ * should be called if a second key is pressed while the first key is not
+ * released yet.
+ */
+ autoRelease: function() {
+ this.generateKeyup();
+ },
+
+ /**
+ * Drops the pressed key.
+ */
+ dropKey: function() {
+ this.classList.remove('active');
clearTimeout(this.longPressTimer);
- var detail = this.populateDetails();
- if (this.keysetRules && this.keysetRules.up != undefined) {
- detail.toKeyset = this.keysetRules.up[TO_KEYSET - OFFSET];
- detail.nextKeyset = this.keysetRules.up[NEXT_KEYSET - OFFSET];
- }
+ this.pointerId = undefined;
+ },
+
+ /**
+ * Populates details for this key, and then fires a key-up event.
+ */
+ generateKeyup: function() {
+ if (this.pointerId === undefined)
+ return;
+
+ // Invalidates the pointerId so the subsequent pointerup event is a
+ // noop.
+ this.pointerId = undefined;
+ clearTimeout(this.longPressTimer);
+ var detail = this.populateDetails('up');
this.fire('key-up', detail);
},
/**
* Character value associated with the key. Typically, the value is a
- * single charcater, but may be multi-character in cases like a ".com"
+ * single character, but may be multi-character in cases like a ".com"
* button.
- * @type {string}
+ * @return {string}
*/
get charValue() {
- return this.char || this.textContent;
+ return this.invert ? this.hintText : (this.char || this.textContent);
},
- populateDetails: function() {
- return {
- char: this.charValue,
- toLayout: this.toLayout,
- repeat: this.repeat
- };
+ /**
+ * Hint text value associated with the key. Typically, the value is a
+ * single character.
+ * @return {string}
+ */
+ get hintTextValue() {
+ return this.invert ? (this.char || this.textContent) : this.hintText;
+ },
+
+ /**
+ * Handles a swipe flick that originated from this key.
+ * @param {detail} The details of the swipe.
+ */
+ onFlick: function(detail) {
+ if (!(detail.direction & SWIPE_DIRECTION.UP) || !this.hintTextValue)
+ return;
+ var typeDetails = {char: this.hintTextValue};
+ this.fire('type-key', typeDetails);
+ },
+
+ /**
+ * Returns a subset of the key attributes.
+ * @param {string} caller The id of the function which called
+ * populateDetails.
+ */
+ populateDetails: function(caller) {
+ var detail = {
+ char: this.charValue,
+ toLayout: this.toLayout,
+ repeat: this.repeat
+ };
+
+ switch (caller) {
+ case ('up'):
+ if (this.keysetRules && this.keysetRules.up != undefined) {
+ detail.toKeyset = this.keysetRules.up[TO_KEYSET - OFFSET];
+ detail.nextKeyset = this.keysetRules.up[NEXT_KEYSET - OFFSET];
+ }
+ break;
+ case ('down'):
+ if (this.keysetRules && this.keysetRules.down != undefined) {
+ detail.toKeyset = this.keysetRules.down[TO_KEYSET - OFFSET];
+ detail.nextKeyset = this.keysetRules.down[NEXT_KEYSET - OFFSET];
+ }
+ break;
+ default:
+ break;
+ }
+ return detail;
},
generateLongPressTimer: function() {
return this.asyncMethod(function() {
var detail = {
char: this.charValue,
- hintText: this.hintText
+ hintText: this.hintTextValue
};
if (this.keysetRules && this.keysetRules.long != undefined) {
detail.toKeyset = this.keysetRules.long[TO_KEYSET - OFFSET];
diff --git a/chromium/ui/keyboard/resources/elements/kb-key-codes.html b/chromium/ui/keyboard/resources/elements/kb-key-codes.html
index b8353ecd938..d99a00fcf73 100644
--- a/chromium/ui/keyboard/resources/elements/kb-key-codes.html
+++ b/chromium/ui/keyboard/resources/elements/kb-key-codes.html
@@ -7,6 +7,17 @@
<polymer-element name="kb-key-codes">
<script>
(function() {
+
+ // Flag values for ctrl, alt and shift as defined by EventFlags
+ // in "event_constants.h".
+ // @enum {number}
+ var Modifier = {
+ NONE: 0,
+ ALT: 8,
+ CONTROL: 4,
+ SHIFT: 2
+ }
+
// Each virtual key event is assigned a unique ID.
var nextRequestID = 0;
@@ -18,106 +29,133 @@
// keyCode attribute for kb-key or kb-keysequence elements to refer to
// indices in this table in order to emulate a physical keyboard with an
// alternate layout. Not all keys on a virtual keyboard are required to
- // have keyCodes.
+ // have keyCodes. The shiftModifier specifies whether to always include or
+ // exclude the shift modifer when sending key events for this key. If it's
+ // undefined, it will defer to state of the keyboard.
+ // TODO(rsadam): Correctly propagate shutdown keycode. This is currently
+ // ignored due to chromoting (crbug/146609)
var keyCodes = {
- '\b': {keyCode: 0x08, shiftModifier: false},
- '\t': {keyCode: 0x09, shiftModifier: false},
- '\n': {keyCode: 0x0D, shiftModifier: false},
- ' ': {keyCode: 0x20, shiftModifier: false},
- '0': {keyCode: 0x30, shiftModifier: false},
- ')': {keyCode: 0x30, shiftModifier: true},
- '1': {keyCode: 0x31, shiftModifier: false},
- '!': {keyCode: 0x31, shiftModifier: true},
- '2': {keyCode: 0x32, shiftModifier: false},
- '@': {keyCode: 0x32, shiftModifier: true},
- '3': {keyCode: 0x33, shiftModifier: false},
- '#': {keyCode: 0x33, shiftModifier: true},
- '4': {keyCode: 0x34, shiftModifier: false},
- '$': {keyCode: 0x34, shiftModifier: true},
- '5': {keyCode: 0x35, shiftModifier: false},
- '%': {keyCode: 0x35, shiftModifier: true},
- '6': {keyCode: 0x36, shiftModifier: false},
- '^': {keyCode: 0x36, shiftModifier: true},
- '7': {keyCode: 0x37, shiftModifier: false},
- '&': {keyCode: 0x37, shiftModifier: true},
- '8': {keyCode: 0x38, shiftModifier: false},
- '*': {keyCode: 0x38, shiftModifier: true},
- '9': {keyCode: 0x39, shiftModifier: false},
- '(': {keyCode: 0x39, shiftModifier: true},
- 'a': {keyCode: 0x41, shiftModifier: false},
- 'A': {keyCode: 0x41, shiftModifier: true},
- 'b': {keyCode: 0x42, shiftModifier: false},
- 'B': {keyCode: 0x42, shiftModifier: true},
- 'c': {keyCode: 0x43, shiftModifier: false},
- 'C': {keyCode: 0x43, shiftModifier: true},
- 'd': {keyCode: 0x44, shiftModifier: false},
- 'D': {keyCode: 0x44, shiftModifier: true},
- 'e': {keyCode: 0x45, shiftModifier: false},
- 'E': {keyCode: 0x45, shiftModifier: true},
- 'f': {keyCode: 0x46, shiftModifier: false},
- 'F': {keyCode: 0x46, shiftModifier: true},
- 'g': {keyCode: 0x47, shiftModifier: false},
- 'G': {keyCode: 0x47, shiftModifier: true},
- 'h': {keyCode: 0x48, shiftModifier: false},
- 'H': {keyCode: 0x48, shiftModifier: true},
- 'i': {keyCode: 0x49, shiftModifier: false},
- 'I': {keyCode: 0x49, shiftModifier: true},
- 'j': {keyCode: 0x4A, shiftModifier: false},
- 'J': {keyCode: 0x4A, shiftModifier: true},
- 'k': {keyCode: 0x4B, shiftModifier: false},
- 'K': {keyCode: 0x4B, shiftModifier: true},
- 'l': {keyCode: 0x4C, shiftModifier: false},
- 'L': {keyCode: 0x4C, shiftModifier: true},
- 'm': {keyCode: 0x4D, shiftModifier: false},
- 'M': {keyCode: 0x4D, shiftModifier: true},
- 'n': {keyCode: 0x4E, shiftModifier: false},
- 'N': {keyCode: 0x4E, shiftModifier: true},
- 'o': {keyCode: 0x4F, shiftModifier: false},
- 'O': {keyCode: 0x4F, shiftModifier: true},
- 'p': {keyCode: 0x50, shiftModifier: false},
- 'P': {keyCode: 0x50, shiftModifier: true},
- 'q': {keyCode: 0x51, shiftModifier: false},
- 'Q': {keyCode: 0x51, shiftModifier: true},
- 'r': {keyCode: 0x52, shiftModifier: false},
- 'R': {keyCode: 0x52, shiftModifier: true},
- 's': {keyCode: 0x53, shiftModifier: false},
- 'S': {keyCode: 0x53, shiftModifier: true},
- 't': {keyCode: 0x54, shiftModifier: false},
- 'T': {keyCode: 0x54, shiftModifier: true},
- 'u': {keyCode: 0x55, shiftModifier: false},
- 'U': {keyCode: 0x55, shiftModifier: true},
- 'v': {keyCode: 0x56, shiftModifier: false},
- 'V': {keyCode: 0x56, shiftModifier: true},
- 'w': {keyCode: 0x57, shiftModifier: false},
- 'W': {keyCode: 0x57, shiftModifier: true},
- 'x': {keyCode: 0x58, shiftModifier: false},
- 'X': {keyCode: 0x58, shiftModifier: true},
- 'y': {keyCode: 0x59, shiftModifier: false},
- 'Y': {keyCode: 0x59, shiftModifier: true},
- 'z': {keyCode: 0x5A, shiftModifier: false},
- 'Z': {keyCode: 0x5A, shiftModifier: true},
- ';': {keyCode: 0xBA, shiftModifier: false},
- ':': {keyCode: 0xBA, shiftModifier: true},
- '=': {keyCode: 0xBB, shiftModifier: false},
- '+': {keyCode: 0xBB, shiftModifier: true},
- ',': {keyCode: 0xBC, shiftModifier: false},
- '<': {keyCode: 0xBC, shiftModifier: true},
- '-': {keyCode: 0xBD, shiftModifier: false},
- '_': {keyCode: 0xBD, shiftModifier: true},
- '.': {keyCode: 0xBE, shiftModifier: false},
- '>': {keyCode: 0xBE, shiftModifier: true},
- '/': {keyCode: 0xBF, shiftModifier: false},
- '?': {keyCode: 0xBF, shiftModifier: true},
- '`': {keyCode: 0xC0, shiftModifier: false},
- '~': {keyCode: 0xC0, shiftModifier: true},
- '[': {keyCode: 0xDB, shiftModifier: false},
- '{': {keyCode: 0xDB, shiftModifier: true},
- '\\': {keyCode: 0xDC, shiftModifier: false},
- '|': {keyCode: 0xDC, shiftModifier: true},
- ']': {keyCode: 0xDD, shiftModifier: false},
- '}': {keyCode: 0xDD, shiftModifier: true},
- '\'': {keyCode: 0xDE, shiftModifier: false},
- '"': {keyCode: 0xDE, shiftModifier: true},
+ '\b': {keyCode: 0x08, keyName: 'Backspace', shiftModifier: false},
+ '\t': {keyCode: 0x09, keyName: 'Tab', shiftModifier: false},
+ '\n': {keyCode: 0x0D, keyName: 'Enter', shiftModifier: false},
+ 'Esc': {keyCode: 0x1B, keyName: 'Escape', shiftModifier: false},
+ ' ': {keyCode: 0x20, keyName: 'Space', shiftModifier: false},
+ 'Arrow-Left': {keyCode: 0x25, keyName: 'ArrowLeft',
+ shiftModifier: undefined},
+ 'Arrow-Up': {keyCode: 0x26, keyName: 'ArrowUp', shiftModifier: undefined},
+ 'Arrow-Right': {keyCode: 0x27, keyName: 'ArrowRight',
+ shiftModifier: undefined},
+ 'Arrow-Down': {keyCode: 0x28, keyName: 'ArrowDown',
+ shiftModifier: undefined},
+ '0': {keyCode: 0x30, keyName: 'Digit0', shiftModifier: false},
+ ')': {keyCode: 0x30, keyName: 'Digit0', shiftModifier: true},
+ '1': {keyCode: 0x31, keyName: 'Digit1', shiftModifier: false},
+ '!': {keyCode: 0x31, keyName: 'Digit1', shiftModifier: true},
+ '2': {keyCode: 0x32, keyName: 'Digit2', shiftModifier: false},
+ '@': {keyCode: 0x32, keyName: 'Digit2', shiftModifier: true},
+ '3': {keyCode: 0x33, keyName: 'Digit3', shiftModifier: false},
+ '#': {keyCode: 0x33, keyName: 'Digit3', shiftModifier: true},
+ '4': {keyCode: 0x34, keyName: 'Digit4', shiftModifier: false},
+ '$': {keyCode: 0x34, keyName: 'Digit4', shiftModifier: true},
+ '5': {keyCode: 0x35, keyName: 'Digit5', shiftModifier: false},
+ '%': {keyCode: 0x35, keyName: 'Digit5', shiftModifier: true},
+ '6': {keyCode: 0x36, keyName: 'Digit6', shiftModifier: false},
+ '^': {keyCode: 0x36, keyName: 'Digit6', shiftModifier: true},
+ '7': {keyCode: 0x37, keyName: 'Digit7', shiftModifier: false},
+ '&': {keyCode: 0x37, keyName: 'Digit7', shiftModifier: true},
+ '8': {keyCode: 0x38, keyName: 'Digit8', shiftModifier: false},
+ '*': {keyCode: 0x38, keyName: 'Digit8', shiftModifier: true},
+ '9': {keyCode: 0x39, keyName: 'Digit9', shiftModifier: false},
+ '(': {keyCode: 0x39, keyName: 'Digit9', shiftModifier: true},
+ 'a': {keyCode: 0x41, keyName: 'KeyA', shiftModifier: false},
+ 'A': {keyCode: 0x41, keyName: 'KeyA', shiftModifier: true},
+ 'b': {keyCode: 0x42, keyName: 'KeyB', shiftModifier: false},
+ 'B': {keyCode: 0x42, keyName: 'KeyB', shiftModifier: true},
+ 'c': {keyCode: 0x43, keyName: 'KeyC', shiftModifier: false},
+ 'C': {keyCode: 0x43, keyName: 'KeyC', shiftModifier: true},
+ 'd': {keyCode: 0x44, keyName: 'KeyD', shiftModifier: false},
+ 'D': {keyCode: 0x44, keyName: 'KeyD', shiftModifier: true},
+ 'e': {keyCode: 0x45, keyName: 'KeyE', shiftModifier: false},
+ 'E': {keyCode: 0x45, keyName: 'KeyE', shiftModifier: true},
+ 'f': {keyCode: 0x46, keyName: 'KeyF', shiftModifier: false},
+ 'F': {keyCode: 0x46, keyName: 'KeyF', shiftModifier: true},
+ 'g': {keyCode: 0x47, keyName: 'KeyG', shiftModifier: false},
+ 'G': {keyCode: 0x47, keyName: 'KeyG', shiftModifier: true},
+ 'h': {keyCode: 0x48, keyName: 'KeyH', shiftModifier: false},
+ 'H': {keyCode: 0x48, keyName: 'KeyH', shiftModifier: true},
+ 'i': {keyCode: 0x49, keyName: 'KeyI', shiftModifier: false},
+ 'I': {keyCode: 0x49, keyName: 'KeyI', shiftModifier: true},
+ 'j': {keyCode: 0x4A, keyName: 'KeyJ', shiftModifier: false},
+ 'J': {keyCode: 0x4A, keyName: 'KeyJ', shiftModifier: true},
+ 'k': {keyCode: 0x4B, keyName: 'KeyK', shiftModifier: false},
+ 'K': {keyCode: 0x4B, keyName: 'KeyK', shiftModifier: true},
+ 'l': {keyCode: 0x4C, keyName: 'KeyL', shiftModifier: false},
+ 'L': {keyCode: 0x4C, keyName: 'KeyL', shiftModifier: true},
+ 'm': {keyCode: 0x4D, keyName: 'KeyM', shiftModifier: false},
+ 'M': {keyCode: 0x4D, keyName: 'KeyM', shiftModifier: true},
+ 'n': {keyCode: 0x4E, keyName: 'KeyN', shiftModifier: false},
+ 'N': {keyCode: 0x4E, keyName: 'KeyN', shiftModifier: true},
+ 'o': {keyCode: 0x4F, keyName: 'KeyO', shiftModifier: false},
+ 'O': {keyCode: 0x4F, keyName: 'KeyO', shiftModifier: true},
+ 'p': {keyCode: 0x50, keyName: 'KeyP', shiftModifier: false},
+ 'P': {keyCode: 0x50, keyName: 'KeyP', shiftModifier: true},
+ 'q': {keyCode: 0x51, keyName: 'KeyQ', shiftModifier: false},
+ 'Q': {keyCode: 0x51, keyName: 'KeyQ', shiftModifier: true},
+ 'r': {keyCode: 0x52, keyName: 'KeyR', shiftModifier: false},
+ 'R': {keyCode: 0x52, keyName: 'KeyR', shiftModifier: true},
+ 's': {keyCode: 0x53, keyName: 'KeyS', shiftModifier: false},
+ 'S': {keyCode: 0x53, keyName: 'KeyS', shiftModifier: true},
+ 't': {keyCode: 0x54, keyName: 'KeyT', shiftModifier: false},
+ 'T': {keyCode: 0x54, keyName: 'KeyT', shiftModifier: true},
+ 'u': {keyCode: 0x55, keyName: 'KeyU', shiftModifier: false},
+ 'U': {keyCode: 0x55, keyName: 'KeyU', shiftModifier: true},
+ 'v': {keyCode: 0x56, keyName: 'KeyV', shiftModifier: false},
+ 'V': {keyCode: 0x56, keyName: 'KeyV', shiftModifier: true},
+ 'w': {keyCode: 0x57, keyName: 'KeyW', shiftModifier: false},
+ 'W': {keyCode: 0x57, keyName: 'KeyW', shiftModifier: true},
+ 'x': {keyCode: 0x58, keyName: 'KeyX', shiftModifier: false},
+ 'X': {keyCode: 0x58, keyName: 'KeyX', shiftModifier: true},
+ 'y': {keyCode: 0x59, keyName: 'KeyY', shiftModifier: false},
+ 'Y': {keyCode: 0x59, keyName: 'KeyY', shiftModifier: true},
+ 'z': {keyCode: 0x5A, keyName: 'KeyZ', shiftModifier: false},
+ 'Z': {keyCode: 0x5A, keyName: 'KeyZ', shiftModifier: true},
+ 'Fullscreen': {keyCode: 0x7A, shiftModifier: false},
+ 'Shutdown': {keyCode: 0x98, shiftModifier: false},
+ 'Back': {keyCode: 0xA6, shiftModifier: false},
+ 'Forward': {keyCode: 0xA7, shiftModifier: false},
+ 'Reload': {keyCode: 0xA8, shiftModifier: false},
+ 'Search': {keyCode: 0xAA, shiftModifier: false},
+ 'Mute': {keyCode: 0xAD, keyName: 'VolumeMute', shiftModifier: false},
+ 'Volume-Down': {keyCode: 0xAE, keyName: 'VolumeDown',
+ shiftModifier: false},
+ 'Volume-Up': {keyCode: 0xAF, keyName: 'VolumeUp', shiftModifier: false},
+ 'Change-Window': {keyCode: 0xB6, shiftModifier: false},
+ ';': {keyCode: 0xBA, keyName: 'Semicolon', shiftModifier: false},
+ ':': {keyCode: 0xBA, keyName: 'Semicolon',shiftModifier: true},
+ '=': {keyCode: 0xBB, keyName: 'Equal', shiftModifier: false},
+ '+': {keyCode: 0xBB, keyName: 'Equal', shiftModifier: true},
+ ',': {keyCode: 0xBC, keyName: 'Comma', shiftModifier: false},
+ '<': {keyCode: 0xBC, keyName: 'Comma', shiftModifier: true},
+ '-': {keyCode: 0xBD, keyName: 'Minus', shiftModifier: false},
+ '_': {keyCode: 0xBD, keyName: 'Minus', shiftModifier: true},
+ '.': {keyCode: 0xBE, keyName: 'Period', shiftModifier: false},
+ '>': {keyCode: 0xBE, keyName: 'Period', shiftModifier: true},
+ '/': {keyCode: 0xBF, keyName: 'Slash', shiftModifier: false},
+ '?': {keyCode: 0xBF, keyName: 'Slash', shiftModifier: true},
+ '`': {keyCode: 0xC0, keyName: 'Backquote', shiftModifier: false},
+ '~': {keyCode: 0xC0, keyName: 'Backquote', shiftModifier: true},
+ 'Brightness-Down': {keyCode: 0xD8, keyName: 'BrightnessDown',
+ shiftModifier: false},
+ 'Brightness-Up': {keyCode: 0xD9, keyName: 'BrightnessUp',
+ shiftModifier: false},
+ '[': {keyCode: 0xDB, keyName: 'BracketLeft', shiftModifier: false},
+ '{': {keyCode: 0xDB, keyName: 'BracketLeft', shiftModifier: true},
+ '\\': {keyCode: 0xDC, keyName: 'Backslash', shiftModifier: false},
+ '|': {keyCode: 0xDC, keyName: 'Backslash', shiftModifier: true},
+ ']': {keyCode: 0xDD, keyName: 'BracketRight', shiftModifier: false},
+ '}': {keyCode: 0xDD, keyName: 'BracketRight', shiftModifier: true},
+ '\'': {keyCode: 0xDE, keyName: 'Quote', shiftModifier: false},
+ '"': {keyCode: 0xDE, keyName: 'Quote', shiftModifier: true},
};
Polymer('kb-key-codes', {
@@ -131,11 +169,16 @@
if (entry) {
return {
keyCode: entry.keyCode,
+ keyName: entry.keyName || 'Unidentified',
shiftModifier: entry.shiftModifier
};
}
+ if (id.length != 1)
+ return;
+ // Special case of accented characters.
return {
keyCode: 0,
+ keyName: 'Unidentified',
shiftModifier: false
};
},
@@ -151,27 +194,37 @@
*/
createVirtualKeyEvent: function(detail, type) {
var char = detail.char;
- if (!char || char.length != 1) {
- console.error('Invalid key. Expected single character.');
- return;
- }
var keyCode = detail.keyCode;
+ var keyName = detail.keyName;
+ // The shift modifier is handled specially. Some charactares like '+'
+ // {keyCode: 0xBB, shiftModifier: true}, are available on non-upper
+ // keysets, and so we rely on caching the correct shiftModifier. If
+ // the cached value of the shiftModifier is undefined, we defer to
+ // the shiftModifier in the detail.
var shiftModifier = detail.shiftModifier;
- if (keyCode == undefined) {
+ if (keyCode == undefined || keyName == undefined) {
var state = this.GetKeyCodeAndModifiers(char);
if (state) {
- keyCode = state.keyCode;
- shiftModifier = state.shiftModifier;
+ keyCode = keyCode || state.keyCode;
+ keyName = keyName || state.keyName;
+ shiftModifier = (state.shiftModifier == undefined) ?
+ shiftModifier : state.shiftModifier;
} else {
- keyCode = 0;
- shiftModifier = false;
+ // Keycode not defined.
+ return;
}
}
+ var modifiers = Modifier.NONE;
+ modifiers = shiftModifier ? modifiers | Modifier.SHIFT : modifiers;
+ modifiers = detail.controlModifier ?
+ modifiers | Modifier.CONTROL : modifiers;
+ modifiers = detail.altModifier ? modifiers | Modifier.ALT : modifiers;
return {
type: type,
charValue: char.charCodeAt(0),
keyCode: keyCode,
- shiftKey: shiftModifier
+ keyName: keyName,
+ modifiers: modifiers
};
},
});
diff --git a/chromium/ui/keyboard/resources/elements/kb-key-import.html b/chromium/ui/keyboard/resources/elements/kb-key-import.html
index 2b12b675416..1174eb45eed 100644
--- a/chromium/ui/keyboard/resources/elements/kb-key-import.html
+++ b/chromium/ui/keyboard/resources/elements/kb-key-import.html
@@ -7,10 +7,8 @@
<polymer-element name="kb-key-import" attributes="importId">
<template>
<style>
- @host {
- * {
- display: none;
- }
+ :host {
+ display: none;
}
</style>
</template>
@@ -27,7 +25,9 @@
* the content to import.
*/
importDoc: function(content) {
- return content.querySelector('#' + this.importId).content;
+ var id = this.getAttribute('importId');
+ var fragment = content.querySelector('#' + id);
+ return fragment && fragment.content ? fragment.content : fragment;
}
});
</script>
diff --git a/chromium/ui/keyboard/resources/elements/kb-key-sequence.html b/chromium/ui/keyboard/resources/elements/kb-key-sequence.html
index ad01003b2a1..b0bbc233496 100644
--- a/chromium/ui/keyboard/resources/elements/kb-key-sequence.html
+++ b/chromium/ui/keyboard/resources/elements/kb-key-sequence.html
@@ -4,55 +4,70 @@
-- found in the LICENSE file.
-->
-<polymer-element name="kb-key-sequence" attributes="keys hintTexts keyCodes">
+<polymer-element name="kb-key-sequence"
+ attributes="keys hintTexts keyCodes invert">
<template>
<style>
- @host {
- * {
- display: none;
- }
+ :host {
+ display: none;
}
</style>
- <kb-key-codes id="keyCodeMetadata"></kb-key-codes>
</template>
<script>
- Polymer('kb-key-sequence', {
- /**
- * Generates the DOM structure to replace (expand) this kb-key-sequence.
- */
- generateDom: function() {
- var result;
- if (this.keys) {
- var newKeys = this.keys;
- var newHintTexts = this.hintTexts;
- if (newHintTexts && newKeys.length != newHintTexts.length) {
- console.error('keys and hintTexts do not match');
- return;
- }
- var keyCodes = this.keyCodes || newKeys;
- if (keyCodes && newKeys.length != keyCodes.length) {
- console.error('keys and keyCodes do not match');
- return;
- }
+ (function() {
+
+ var metadata = null;
+
+ function getKeyCodeAndModifiers(keyCodeIndex) {
+ if (!metadata)
+ metadata = document.createElement('kb-key-codes');
+ return metadata.GetKeyCodeAndModifiers(keyCodeIndex);
+ }
+
+ Polymer('kb-key-sequence', {
+ /**
+ * Generates the DOM structure to replace (expand) this kb-key-sequence.
+ */
+ generateDom: function() {
var replacement = document.createDocumentFragment();
- for (var i = 0; i < newKeys.length; i++) {
- var key = document.createElement('kb-key');
- key.innerText = newKeys[i];
- key.accents = newKeys[i];
- if (newHintTexts)
- key.hintText = newHintTexts[i];
- var state = this.$.keyCodeMetadata.GetKeyCodeAndModifiers(
- keyCodes[i]);
- if (state) {
- key.keyCode = state.keyCode;
- key.shiftModifier = state.shiftModifier;
+ var newKeys = this.getAttribute('keys');
+ var newHintTexts = this.getAttribute('hintTexts');
+ var keyCodes = this.getAttribute('hintCodes') || newKeys;
+ var invert = this.getAttribute('invert');
+ if (newKeys) {
+ if (newHintTexts && newKeys.length != newHintTexts.length) {
+ console.error('keys and hintTexts do not match');
+ return;
+ }
+ if (keyCodes && newKeys.length != keyCodes.length) {
+ console.error('keys and keyCodes do not match');
+ return;
+ }
+
+ for (var i = 0; i < newKeys.length; i++) {
+ var key = document.createElement('kb-key');
+ key.innerText = newKeys[i];
+ key.accents = newKeys[i];
+ if (newHintTexts)
+ key.hintText = newHintTexts[i];
+ var keyCodeIndex = keyCodes[i];
+ if (invert) {
+ key.invert = true;
+ key.char = newKeys[i];
+ keyCodeIndex = key.hintText;
+ }
+ var state = getKeyCodeAndModifiers(keyCodeIndex);
+ if (state) {
+ key.keyCode = state.keyCode;
+ key.keyName = state.keyName;
+ key.shiftModifier = state.shiftModifier;
+ }
+ replacement.appendChild(key);
}
- replacement.appendChild(key);
}
- result = replacement;
+ return replacement;
}
- return result;
- }
- });
+ });
+ })();
</script>
</polymer-element>
diff --git a/chromium/ui/keyboard/resources/elements/kb-key.html b/chromium/ui/keyboard/resources/elements/kb-key.html
index d9bf0776750..447c491af88 100644
--- a/chromium/ui/keyboard/resources/elements/kb-key.html
+++ b/chromium/ui/keyboard/resources/elements/kb-key.html
@@ -5,23 +5,82 @@
-->
<polymer-element name="kb-key" extends="kb-key-base"
- attributes="keyCode shiftModifier weight">
+ attributes="image imageSize keyCode keyName shiftModifier weight">
<template>
<style>
- @host {
- * {
- -webkit-box-flex: {{weight}};
- }
+ :host {
+ /* TODO(kevers): A regression in the Polymer library broke
+ * handling of {{}} in CSS rules. Switch back to
+ * "-webkit-box-flex: {{weight}}" once the regression is fixed
+ * (https://github.com/Polymer/polymer/issues/270). */
+ -webkit-box-flex: 100;
+ background-color: #3b3b3e;
+ /* TODO(rsadam): remove when {{}} regression is fixed */
+ background-image: none;
+ background-position: center center;
+ background-repeat: no-repeat;
+ /* TODO(rsadam): remove when {{}} regression is fixed */
+ background-size: 50%;
+ border-top: 2px solid #4b4b4e;
+ border-radius: 2px;
+ color: #ffffff;
+ display: -webkit-box;
+ font-family: 'Open Sans', 'Noto Sans UI', sans-serif;
+ font-weight: 300;
+ margin-left: 0.25em;
+ position: relative;
+ }
+
+ ::part(key) {
+ bottom: 0;
+ height: 1.2em;
+ left: 0;
+ margin: auto;
+ padding-left: 0.7em;
+ padding-right: 0.7em;
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+
+ ::part(hint) {
+ color: #7c7c7c;
+ font-size: 70%;
+ position: absolute;
+ right: 7%;
+ top: 5%;
+ }
+
+ :host[invert] ::part(key) {
+ color: #7c7c7c;
+ }
+
+ :host[invert] ::part(hint) {
+ color: #ffffff;
}
</style>
- <div id="key" pseudo="x-key" inverted?={{invert}}>
+ <div id="key" part="key">
<content></content>
</div>
- <div pseudo="x-hinttext" inverted?={{invert}}>{{hintText}}</div>
+ <div part="hint">{{hintText}}</div>
</template>
<script>
Polymer('kb-key', {
/**
+ * The background image to display on this key. Does not display an
+ * image if this is the empty string.
+ * @type {string}
+ */
+ image: "",
+
+ /**
+ * The background image size to use if an image is specified. The size
+ * is provided as a string, for example, "50%".
+ * @type {string}
+ */
+ imageSize: "",
+
+ /**
* Key codes have been deprecated in DOM3 key events, but are required
* for legacy web content. The key codes depend on the position of the
* key on the keyboard and is independent of which modifier keys (shift,
@@ -29,6 +88,15 @@
* @type {number|undefined}
*/
keyCode: undefined,
+
+ /**
+ * Name of the key as defined in the DOM3 specification for key events.
+ * Like the keyCode, the keyName is independent of the state of the
+ * modifier keys.
+ * @type {string|undefined}
+ */
+ keyName: undefined,
+
/**
* Whether the shift key is pressed when producing the key value.
* @type {boolean}
@@ -39,44 +107,116 @@
* Keys with a high weighting are wider than normal keys.
* @type {number}
*/
- weight: 1,
+ weight: 100,
+
+ /**
+ * Called when the image attribute changes. This is used to set the
+ * background image of the key.
+ * TODO(rsadam): Remove when polymer {{}} syntax regression is fixed.
+ */
+ imageChanged: function() {
+ if (!this.image)
+ this.style.backgroundImage = "none";
+ else
+ this.style.backgroundImage = "url(images/" + this.image + ".svg)";
+ },
+
+ /**
+ * Called when the image attribute changes. This is used to set the
+ * background image of the key.
+ * TODO(rsadam): Remove when polymer {{}} syntax regression is fixed.
+ */
+ imageSizeChanged: function() {
+ this.style.backgroundSize = this.imageSize;
+ },
/**
* Returns a subset of the key attributes.
+ * @param {string} caller The id of the function that called
+ * populateDetails.
* @return {Object} Mapping of attributes for the key element.
*/
- populateDetails: function() {
- var details = this.super();
+ populateDetails: function(caller) {
+ var details = this.super([caller]);
details.keyCode = this.keyCode;
+ details.keyName = this.keyName;
details.shiftModifier = this.shiftModifier;
return details;
},
+
+ /**
+ * Adjusts the CSS rules for rendering the key to reflect the new
+ * weight. The preferred way is to use {{weight}} directly in the CSS
+ * rules; however, this is currently broken in the Polymer library.
+ * TODO(kevers): Cleanup once handling of {{}} in CSS rules is fixed.
+ */
+ weightChanged: function() {
+ if (this.weight > 0)
+ this.style['webkitBoxFlex'] = this.weight;
+ },
});
</script>
</polymer-element>
<!-- Special keys -->
-
-<!--
- -- TODO(kevers): Rip this out if and when we are done implementing the proper
- -- layout switcher.
- -->
-<polymer-element name="kb-layout-selector" class="layout-selector dark" char="Invalid"
- extends="kb-key">
+<polymer-element name="kb-abc-key" class="symbol dark" char="Invalid"
+ extends="kb-key" weight="125">
<script>
- Polymer('kb-layout-selector', {
- toLayout: 'qwerty'
+ Polymer('kb-abc-key', {
+ populateDetails: function(caller) {
+ var detail = this.super([caller]);
+ switch (caller) {
+ case ('down'):
+ detail.relegateToShift = true;
+ break;
+ default:
+ break;
+ }
+ return detail;
+ }
});
</script>
</polymer-element>
-<polymer-element name="kb-hide-keyboard-key" class="hide-keyboard dark" char="Invalid"
- extends="kb-key">
+<polymer-element name="kb-hide-keyboard-key" class="hide-keyboard dark"
+ char="Invalid" extends="kb-key">
<script>
Polymer('kb-hide-keyboard-key', {
- down: function(event) {},
+ /**
+ * Timer for a long press event which triggers the display of a keyboard
+ * options menu.
+ * @type {?Function}
+ */
+ longPressTimer: undefined,
+
+ down: function(event) {
+ var self = this;
+ this.longPressTimer = this.asyncMethod(function() {
+ if (self.longPressTimer) {
+ clearTimeout(self.longPressTimer);
+ self.longPressTimer = undefined;
+ var details = {
+ left: this.offsetLeft,
+ top: this.offsetTop,
+ width: this.clientWidth,
+ };
+ this.fire('show-options', details);
+ }
+ }, null, LONGPRESS_DELAY_MSEC);
+ },
+
+ /** @override */
+ ready: function() {
+ this.super();
+ this.image = "keyboard";
+ },
+
up: function(event) {
- hideKeyboard();
+ if (this.longPressTimer) {
+ clearTimeout(this.longPressTimer);
+ hideKeyboard();
+ this.longPressTimer = undefined;
+ }
}
});
</script>
diff --git a/chromium/ui/keyboard/resources/elements/kb-keyboard.html b/chromium/ui/keyboard/resources/elements/kb-keyboard.html
index ea09e372f78..d47ca6d9ebe 100644
--- a/chromium/ui/keyboard/resources/elements/kb-keyboard.html
+++ b/chromium/ui/keyboard/resources/elements/kb-keyboard.html
@@ -4,11 +4,14 @@
-- found in the LICENSE file.
-->
-<polymer-element name="kb-keyboard" on-key-over="keyOver" on-key-up="keyUp"
- on-key-down="keyDown" on-key-longpress="keyLongpress" on-pointerup="up"
- on-pointerdown="down" on-enable-sel="enableSel"
- on-enable-dbl="enableDbl"
- attributes="keyset layout rows inputType inputTypeToLayoutMap">
+<polymer-element name="kb-keyboard" on-key-over="{{keyOver}}"
+ on-key-up="{{keyUp}}" on-key-down="{{keyDown}}"
+ on-key-longpress="{{keyLongpress}}" on-pointerup="{{up}}"
+ on-pointerdown="{{down}}" on-pointerout="{{out}}"
+ on-enable-sel="{{enableSel}}" on-enable-dbl="{{enableDbl}}"
+ on-key-out="{{keyOut}}" on-show-options="{{showOptions}}"
+ on-set-layout="{{setLayout}}" on-type-key="{{type}}"
+ attributes="keyset layout inputType inputTypeToLayoutMap">
<template>
<style>
@host {
@@ -23,7 +26,8 @@
-- allowing the shift and spacebar keys to be common across multiple
-- keyboard layouts.
-->
- <content select="#{{layout}}-{{keyset}}"></content>
+ <content id="content" select="#{{layout}}-{{keyset}}"></content>
+ <kb-keyboard-overlay id="overlay" hidden></kb-keyboard-overlay>
<kb-key-codes id="keyCodeMetadata"></kb-key-codes>
</template>
<script>
@@ -114,17 +118,16 @@
* @const
* @type {number}
*/
- var MIN_SWIPE_DIST = 30;
+ var MIN_SWIPE_DIST_X = 50;
+ var MIN_SWIPE_DIST_Y = 20;
/**
- * The flags constants when shift is on. It is according to the EventFlags
- * in event_constants.h in chromium c++ code.
+ * The maximum swipe distance that will trigger hintText of a key
+ * to be typed.
* @const
* @type {number}
- * TODO(zyaozhujun): Might add more flags here according to the defination
- * in EventFlags.
*/
- var SHIFT = 2;
+ var MAX_SWIPE_FLICK_DIST = 60;
/**
* The boolean to decide if it is swipe in process or finished.
@@ -132,29 +135,38 @@
*/
var swipeInProgress = false;
- /**
- * The enumeration of swipe directions.
- * @const
- * @type {Enum}
- */
- var SWIPE_DIRECTION = {
- RIGHT: 0x1,
- LEFT: 0x2,
- UP: 0x4,
- DOWN: 0x8
+ // Flag values for ctrl, alt and shift as defined by EventFlags
+ // in "event_constants.h".
+ // @enum {number}
+ var Modifier = {
+ NONE: 0,
+ ALT: 8,
+ CONTROL: 4,
+ SHIFT: 2
};
/**
* A structure to track the current swipe status.
*/
- var swipeStatus = {
+ var swipeTracker = {
+ /**
+ * The latest PointerMove event in the swipe.
+ * @type {Object}
+ */
+ currentEvent: undefined,
+
+ /**
+ * Whether or not a swipe changes direction.
+ * @type {false}
+ */
+ isComplex: false,
/**
* The count of horizontal and vertical movement.
* @type {number}
*/
- offset_x : 0,
- offset_y : 0,
+ offset_x : 0,
+ offset_y : 0,
/**
* Last touch coordinate.
@@ -164,6 +176,12 @@
pre_y : 0,
/**
+ * The PointerMove event which triggered the swipe.
+ * @type {Object}
+ */
+ startEvent: undefined,
+
+ /**
* The flag of current modifier key.
* @type {number}
*/
@@ -176,6 +194,56 @@
swipeDirection : 0,
/**
+ * The number of times we've swiped within a single swipe.
+ * @type {number}
+ */
+ swipeIndex: 0,
+
+ /**
+ * Returns the combined direction of the x and y offsets.
+ * @return {number} The latest direction.
+ */
+ getOffsetDirection: function() {
+ // TODO (rsadam): Use angles to figure out the direction.
+ var direction = 0;
+ // Checks for horizontal swipe.
+ if (Math.abs(this.offset_x) > MIN_SWIPE_DIST_X) {
+ if (this.offset_x > 0) {
+ direction |= SWIPE_DIRECTION.RIGHT;
+ } else {
+ direction |= SWIPE_DIRECTION.LEFT;
+ }
+ }
+ // Checks for vertical swipe.
+ if (Math.abs(this.offset_y) > MIN_SWIPE_DIST_Y) {
+ if (this.offset_y < 0) {
+ direction |= SWIPE_DIRECTION.UP;
+ } else {
+ direction |= SWIPE_DIRECTION.DOWN;
+ }
+ }
+ return direction;
+ },
+
+ /**
+ * Populates the swipe update details.
+ * @param {boolean} endSwipe Whether this is the final event for this
+ * swipe.
+ * @return {Object} The current state of the swipeTracker.
+ */
+ populateDetails: function(endSwipe) {
+ var detail = {};
+ detail.direction = this.swipeDirection;
+ detail.index = this.swipeIndex;
+ detail.status = this.swipeStatus;
+ detail.endSwipe = endSwipe;
+ detail.startEvent = this.startEvent;
+ detail.currentEvent = this.currentEvent;
+ detail.isComplex = this.isComplex;
+ return detail;
+ },
+
+ /**
* Reset all the values when swipe finished.
*/
resetAll: function() {
@@ -183,19 +251,60 @@
this.offset_y = 0;
this.pre_x = 0;
this.pre_y = 0;
- this.swipeFlags = 0;
- this.swipeDirection = 0;
- }
+ this.swipeFlags = 0;
+ this.swipeDirection = 0;
+ this.swipeIndex = 0;
+ this.startEvent = undefined;
+ this.currentEvent = undefined;
+ this.isComplex = false;
+ },
+
+ /**
+ * Updates the swipe path with the current event.
+ * @param {Object} event The PointerEvent that triggered this update.
+ * @return {boolean} Whether or not to notify swipe observers.
+ */
+ update: function(event) {
+ if(!event.isPrimary)
+ return false;
+ // Update priors.
+ this.offset_x += event.screenX - this.pre_x;
+ this.offset_y += event.screenY - this.pre_y;
+ this.pre_x = event.screenX;
+ this.pre_y = event.screenY;
+
+ // Check if movement crosses minimum thresholds in each direction.
+ var direction = this.getOffsetDirection();
+ if (direction == 0)
+ return false;
+ // If swipeIndex is zero the current event is triggering the swipe.
+ if (this.swipeIndex == 0) {
+ this.startEvent = event;
+ } else if (direction != this.swipeDirection) {
+ // Toggle the isComplex flag.
+ this.isComplex = true;
+ }
+ // Update the swipe tracker.
+ this.swipeDirection = direction;
+ this.offset_x = 0;
+ this.offset_y = 0;
+ this.currentEvent = event;
+ this.swipeIndex++;
+ return true;
+ },
+
};
Polymer('kb-keyboard', {
- lastPressedKey: null,
- voiceInput_: null,
+ alt: null,
+ control: null,
dblDetail_: null,
dblTimer_: null,
- swipeHandler: null,
- shift: null,
inputType: null,
+ lastPressedKey: null,
+ shift: null,
+ swipeHandler: null,
+ voiceInput_: null,
/**
* The default input type to keyboard layout map. The key must be one of
@@ -204,12 +313,65 @@
*/
inputTypeToLayoutMap: {
number: "numeric",
- text: "qwerty"
+ text: "qwerty",
+ password: "qwerty"
+ },
+
+ /**
+ * Changes the current keyset.
+ * @param {Object} detail The detail of the event that called this
+ * function.
+ */
+ changeKeyset: function(detail) {
+ if (detail.relegateToShift && this.shift) {
+ this.keyset = this.shift.textKeyset;
+ this.activeKeyset.nextKeyset = undefined;
+ return true;
+ }
+ var toKeyset = detail.toKeyset;
+ if (toKeyset) {
+ this.keyset = toKeyset;
+ this.activeKeyset.nextKeyset = detail.nextKeyset;
+ return true;
+ }
+ return false;
},
ready: function() {
this.voiceInput_ = new VoiceInput(this);
- this.swipeHandler = this.onSwipeUpdate.bind(this);
+ this.swipeHandler = this.move.bind(this);
+ },
+
+ /**
+ * Registers a callback for state change events. Lazy initializes a
+ * mutation observer used to detect when the keyset selection is changed.
+ * @param{!Function} callback Callback function to register.
+ */
+ addKeysetChangedObserver: function(callback) {
+ if (!this.keysetChangedObserver) {
+ var target = this.$.content;
+ var self = this;
+ var observer = new MutationObserver(function(mutations) {
+ mutations.forEach(function(m) {
+ if (m.type == 'attributes' && m.attributeName == 'select') {
+ var value = m.target.getAttribute('select');
+ self.fire('stateChange', {
+ state: 'keysetChanged',
+ value: value
+ });
+ }
+ });
+ });
+
+ observer.observe(target, {
+ attributes: true,
+ childList: true,
+ subtree: true
+ });
+ this.keysetChangedObserver = observer;
+
+ }
+ this.addEventListener('stateChange', callback);
},
/**
@@ -247,45 +409,59 @@
},
/**
- * This function is bound to swipeHandler. And swipeHandler handle
- * the pointermove event after pointerdown event happened.
- * @para {PointerEvent} event.
+ * Handles a swipe update.
+ * param {Object} detail The swipe update details.
*/
- onSwipeUpdate: function(event) {
- swipeStatus.offset_x += event.screenX - swipeStatus.pre_x;
- swipeStatus.offset_y += event.screenY - swipeStatus.pre_y;
- if (Math.abs(swipeStatus.offset_x) > MIN_SWIPE_DIST ||
- Math.abs(swipeStatus.offset_y) > MIN_SWIPE_DIST) {
- swipeInProgress = true;
- this.lastPressedKey.classList.remove('active');
- }
- if (swipeStatus.offset_x > MIN_SWIPE_DIST) {
- swipeStatus.swipeDirection |= SWIPE_DIRECTION.RIGHT;
- swipeStatus.offset_x = 0;
+ onSwipeUpdate: function(detail) {
+ var direction = detail.direction;
+ if (!direction)
+ console.error("Swipe direction cannot be: " + direction);
+ // Triggers swipe editting if it's a purely horizontal swipe.
+ if (!(direction & (SWIPE_DIRECTION.UP | SWIPE_DIRECTION.DOWN))) {
+ // Nothing to do if the swipe has ended.
+ if (detail.endSwipe)
+ return;
+ var modifiers = 0;
+ // TODO (rsadam): This doesn't take into account index shifts caused
+ // by vertical swipes.
+ if (detail.index % 2 != 0) {
+ modifiers |= Modifier.SHIFT;
+ modifiers |= Modifier.CONTROL;
+ }
+ MoveCursor(direction, modifiers);
+ return;
}
- else if (swipeStatus.offset_x < -MIN_SWIPE_DIST) {
- swipeStatus.swipeDirection |= SWIPE_DIRECTION.LEFT;
- swipeStatus.offset_x = 0;
- }
- // Swipe vertically only when the swipe reaches the gradient of 45
- // degree. This can also be larger.
- if (Math.abs(event.screenY - swipeStatus.pre_y) >
- Math.abs(event.screenX - swipeStatus.pre_x)) {
- if (swipeStatus.offset_y > MIN_SWIPE_DIST) {
- swipeStatus.swipeDirection |= SWIPE_DIRECTION.DOWN;
- swipeStatus.offset_y = 0;
- }
- else if (swipeStatus.offset_y < -MIN_SWIPE_DIST) {
- swipeStatus.swipeDirection |= SWIPE_DIRECTION.UP;
- swipeStatus.offset_y = 0;
- }
+ // Triggers swipe hintText if it's a purely vertical swipe.
+ if (!(direction & (SWIPE_DIRECTION.LEFT | SWIPE_DIRECTION.RIGHT))) {
+ // Check if event is relevant to us.
+ if ((!detail.endSwipe) || (detail.isComplex))
+ return;
+ // Too long a swipe.
+ var distance = Math.abs(detail.startEvent.screenY -
+ detail.currentEvent.screenY);
+ if (distance > MAX_SWIPE_FLICK_DIST)
+ return;
+ var triggerKey = detail.startEvent.target;
+ if (triggerKey && triggerKey.onFlick)
+ triggerKey.onFlick(detail);
}
- if (swipeStatus.swipeDirection) {
- MoveCursor(swipeStatus.swipeDirection, swipeStatus.swipeFlags);
- swipeStatus.swipeDirection = 0;
+ },
+
+ /**
+ * This function is bound to swipeHandler. Updates the current swipe
+ * status so that PointerEvents can be converted to Swipe events.
+ * @param {PointerEvent} event.
+ */
+ move: function(event) {
+ if (!swipeTracker.update(event))
+ return;
+ // Conversion was successful, swipe is now in progress.
+ swipeInProgress = true;
+ if (this.lastPressedKey) {
+ this.lastPressedKey.classList.remove('active');
+ this.lastPressedKey = null;
}
- swipeStatus.pre_x = event.screenX;
- swipeStatus.pre_y = event.screenY;
+ this.onSwipeUpdate(swipeTracker.populateDetails(false));
},
/**
@@ -298,8 +474,10 @@
if (this.skipEvent(detail))
return;
- if (this.lastPressedKey)
+ if (this.lastPressedKey) {
this.lastPressedKey.classList.remove('active');
+ this.lastPressedKey.autoRelease();
+ }
this.lastPressedKey = event.target;
this.lastPressedKey.classList.add('active');
repeatKey.cancel();
@@ -307,30 +485,30 @@
var char = detail.char;
switch(char) {
case 'Shift':
- // Removes caps-lock if caps-locked.
- if(this.classList.contains('caps-locked')) {
- this.classList.remove('caps-locked');
- }
+ this.classList.remove('caps-locked');
+ break;
+ case 'Alt':
+ case 'Ctrl':
+ var modifier = char.toLowerCase() + "-active";
+ // Removes modifier if already active.
+ if (this.classList.contains(modifier))
+ this.classList.remove(modifier);
break;
default:
- // Non-control key pressed, notify control keys.
- // Control keys are shift, control and alt.
- if(this.shift)
+ // Notify shift key.
+ if (this.shift)
this.shift.onNonControlKeyDown();
+ if (this.ctrl)
+ this.ctrl.onNonControlKeyDown();
+ if (this.alt)
+ this.alt.onNonControlKeyDown();
break;
}
-
- // A transition key was pressed, immediately move to new keyset.
- var toKeyset = detail.toKeyset;
- if (toKeyset) {
- this.keyset = toKeyset;
- this.querySelector('#' + this.layout + '-' + this.keyset).nextKeyset =
- detail.nextKeyset;
+ if(this.changeKeyset(detail))
return;
- }
-
if (detail.repeat) {
this.keyTyped(detail);
+ this.onNonControlKeyTyped();
repeatKey.key = this.lastPressedKey;
var self = this;
repeatKey.timer = setTimeout(function() {
@@ -343,6 +521,16 @@
},
/**
+ * Handles key-out event that is sent by kb-shift-key.
+ * @param {CustomEvent} event The key-out event dispatched by
+ * kb-shift-key.
+ * @param {Object} detail The detail of pressed kb-shift-key.
+ */
+ keyOut: function(event, detail) {
+ this.changeKeyset(detail);
+ },
+
+ /**
* Enable/start double click/tap event recognition.
* @param {CustomEvent} event The enable-dbl event dispatched by
* kb-shift-key.
@@ -366,7 +554,8 @@
* kb-shift-key.
*/
enableSel: function(event) {
- swipeStatus.swipeFlags = SHIFT;
+ // TODO(rsadam): Disabled for now. May come back if we revert swipe
+ // selection to not do word selection.
},
/**
@@ -377,9 +566,11 @@
* kb-keyboard.
*/
down: function(event) {
- swipeStatus.pre_x = event.screenX;
- swipeStatus.pre_y = event.screenY;
- this.addEventListener("pointermove", this.swipeHandler, false);
+ if (event.isPrimary) {
+ swipeTracker.pre_x = event.screenX;
+ swipeTracker.pre_y = event.screenY;
+ this.addEventListener("pointermove", this.swipeHandler, false);
+ }
},
/**
@@ -388,16 +579,21 @@
* kb-keyboard.
*/
up: function(event) {
+ // When touch typing, it is very possible that finger moves slightly out
+ // of the key area before releases. The key should not be dropped in
+ // this case.
+ if (this.lastPressedKey &&
+ this.lastPressedKey.pointerId == event.pointerId) {
+ this.lastPressedKey.autoRelease();
+ }
+
if (this.dblDetail_) {
this.dblDetail_.clickCount++;
if (this.dblDetail_.clickCount == 2) {
this.dblDetail_.callback();
- this.keyset = this.dblDetail_.toKeyset;
- var keysetId = '#' + this.layout + '-' + this.keyset;
- var keyset = this.querySelector(keysetId);
- keyset.nextKeyset = this.dblTimer_.nextKeyset;
+ this.changeKeyset(this.dblDetail_);
clearTimeout(this.dblTimer_);
-
+
this.classList.add('caps-locked');
this.dblDetail_ = null;
@@ -406,17 +602,47 @@
// TODO(zyaozhujun): There are some edge cases to deal with later.
// (for instance, what if a second finger trigger a down and up
- // event sequence while swiping).
+ // event sequence while swiping).
// When pointer up from the screen, a swipe selection session finished,
// all the data should be reset to prepare for the next session.
- if (swipeInProgress) {
+ if (event.isPrimary && swipeInProgress) {
swipeInProgress = false;
- swipeStatus.resetAll();
+ this.onSwipeUpdate(swipeTracker.populateDetails(true))
+ swipeTracker.resetAll();
}
this.removeEventListener('pointermove', this.swipeHandler, false);
},
/**
+ * Handles PointerOut event. This is used for when a swipe gesture goes
+ * outside of the keyboard window.
+ * @param {Object} event The pointerout event that bubbled to the
+ * kb-keyboard.
+ */
+ out: function(event) {
+ // Ignore if triggered from one of the keys.
+ if (this.compareDocumentPosition(event.relatedTarget) &
+ Node.DOCUMENT_POSITION_CONTAINED_BY)
+ return;
+ if (swipeInProgress)
+ this.onSwipeUpdate(swipeTracker.populateDetails(true))
+ // Touched outside of the keyboard area, so disables swipe.
+ swipeInProgress = false;
+ swipeTracker.resetAll();
+ this.removeEventListener('pointermove', this.swipeHandler, false);
+ },
+
+ /**
+ * Handles a TypeKey event. This is used for when we programmatically
+ * want to type a specific key.
+ * @param {CustomEvent} event The TypeKey event that bubbled to the
+ * kb-keyboard.
+ */
+ type: function(event) {
+ this.keyTyped(event.detail);
+ },
+
+ /**
* Handles key-up event that is sent by kb-key-base.
* @param {CustomEvent} event The key-up event dispatched by kb-key-base.
* @param {Object} detail The detail of pressed kb-key.
@@ -426,67 +652,85 @@
return;
if (swipeInProgress)
return;
- this.lastPressedKey.classList.remove('active');
- if (this.lastPressedKey.char != event.target.char)
+ if (detail.activeModifier) {
+ var modifier = detail.activeModifier.toLowerCase() + "-active";
+ this.classList.add(modifier);
+ }
+ // Adds the current keyboard modifiers to the detail.
+ if (this.ctrl)
+ detail.controlModifier = this.ctrl.isActive();
+ if (this.alt)
+ detail.altModifier = this.alt.isActive();
+ if (this.lastPressedKey)
+ this.lastPressedKey.classList.remove('active');
+ // Keyset transition key. This is needed to transition from upper
+ // to lower case when we are not in caps mode, as well as when
+ // we're ending chording.
+ this.changeKeyset(detail);
+
+ if (this.lastPressedKey &&
+ this.lastPressedKey.charValue != event.target.charValue) {
return;
+ }
if (repeatKey.key == event.target) {
repeatKey.cancel();
+ this.lastPressedKey = null;
return;
}
- var toKeysetId = detail.toKeyset;
- // Keyset transition key. This is needed to transition from upper
- // to lower case when we are not in caps mode.
- if (toKeysetId) {
- this.keyset = toKeysetId;
- this.querySelector('#' + this.layout + '-' + this.keyset).nextKeyset =
- detail.nextKeyset;
- }
var toLayoutId = detail.toLayout;
// Layout transition key.
if (toLayoutId)
this.layout = toLayoutId;
var char = detail.char;
- if (enterUpperOnSpace) {
- enterUpperOnSpace = false;
- if (char == ' ') {
- // If shift key defined in layout.
- if(this.shift) {
- var shiftDetail = this.shift.onSpaceAfterPunctuation();
- var toKeyset = shiftDetail.toKeyset;
- // Check if transition defined.
- if(toKeyset) {
- this.keyset = toKeyset;
- this.querySelector('#' + this.layout + '-' +
- this.keyset).nextKeyset = shiftDetail.nextKeyset;
- }
- } else {
- console.error('Capitalization on space after punctuation \
- enabled, but cannot find target keyset.');
- }
- }
- }
+ this.lastPressedKey = null;
+ // Characters that should not be typed.
switch(char) {
case 'Invalid':
- swipeStatus.swipeFlags = 0;
- return;
case 'Shift':
- swipeStatus.swipeFlags = 0;
+ case 'Ctrl':
+ case 'Alt':
+ enterUpperOnSpace = false;
+ swipeTracker.swipeFlags = 0;
return;
case 'Microphone':
this.voiceInput_.onDown();
return;
+ default:
+ break;
+ }
+ // Tries to type the character. Resorts to insertText if that fails.
+ if(!this.keyTyped(detail))
+ insertText(char);
+ // Post-typing logic.
+ switch(char) {
+ case ' ':
+ if(enterUpperOnSpace) {
+ enterUpperOnSpace = false;
+ if (this.shift) {
+ var shiftDetail = this.shift.onSpaceAfterPunctuation();
+ // Check if transition defined.
+ this.changeKeyset(shiftDetail);
+ } else {
+ console.error('Capitalization on space after punctuation \
+ enabled, but cannot find target keyset.');
+ }
+ // Immediately return to maintain shift-state. Space is a
+ // non-control key and would otherwise trigger a reset of the
+ // shift key, causing a transition to lower case.
+ // TODO(rsadam): Add unit test after Polymer uprev complete.
+ return;
+ }
+ break;
case '.':
case '?':
case '!':
- enterUpperOnSpace = true;
+ enterUpperOnSpace = this.shouldUpperOnSpace();
break;
default:
break;
}
- if (char.length == 1)
- this.keyTyped(detail);
- else
- insertText(char);
+ // Reset control keys.
+ this.onNonControlKeyTyped();
},
/*
@@ -498,31 +742,76 @@
keyLongpress: function(event, detail) {
// If the gesture is long press, remove the pointermove listener.
this.removeEventListener('pointermove', this.swipeHandler, false);
- var toKeyset = detail.toKeyset;
// Keyset transtion key.
- if (toKeyset) {
- this.keyset = toKeyset;
- this.querySelector('#' + this.layout + '-' + this.keyset).nextKeyset =
- detail.nextKeyset;
-
+ if (this.changeKeyset(detail)) {
// Locks the keyset before removing active to prevent flicker.
this.classList.add('caps-locked');
// Makes last pressed key inactive if transit to a new keyset on long
// press.
- this.lastPressedKey.classList.remove('active');
+ if (this.lastPressedKey)
+ this.lastPressedKey.classList.remove('active');
}
},
/**
+ * Whether we should transit to upper case when seeing a space after
+ * punctuation.
+ * @return {boolean}
+ */
+ shouldUpperOnSpace: function() {
+ // TODO(rsadam): Add other input types in which we should not
+ // transition to upper after a space.
+ return this.inputTypeValue != 'password';
+ },
+
+ /**
+ * Show menu for selecting a keyboard layout.
+ * @param {!Event} event The triggering event.
+ * @param {{left: number, top: number, width: number}} details Location of
+ * the button that triggered the popup.
+ */
+ showOptions: function(event, details) {
+ var overlay = this.$.overlay;
+ if (!overlay) {
+ console.error('Missing overlay.');
+ return;
+ }
+ var menu = overlay.$.options;
+ if (!menu) {
+ console.error('Missing options menu.');
+ }
+
+ menu.hidden = false;
+ overlay.hidden = false;
+ var left = details.left + details.width - menu.clientWidth;
+ var top = details.top - menu.clientHeight;
+ menu.style.left = left + 'px';
+ menu.style.top = top + 'px';
+ },
+
+ /**
+ * Handler for the 'set-layout' event.
+ * @param {!Event} event The triggering event.
+ * @param {{layout: string}} details Details of the event, which contains
+ * the name of the layout to activate.
+ */
+ setLayout: function(event, details) {
+ this.layout = details.layout;
+ },
+
+ /**
* Handles a change in the keyboard layout. Auto-selects the default
* keyset for the new layout.
*/
layoutChanged: function() {
if (!this.selectDefaultKeyset()) {
+ this.fire('stateChange', {state: 'loadingKeyset'});
+
// Keyset selection fails if the keysets have not been loaded yet.
var keysets = document.querySelector('#' + this.layout);
- if (keysets) {
- keyboard.appendChild(flattenKeysets(keysets.content));
+ if (keysets && keysets.content) {
+ var content = flattenKeysets(keysets.content);
+ this.appendChild(content);
this.selectDefaultKeyset();
} else {
// Add link for the keysets if missing from the document. Force
@@ -545,21 +834,94 @@
}
}
}
- this.classList.remove('caps-locked');
- this.shift = this.querySelector('kb-shift-key');
- if(this.shift)
- this.shift.reset();
+ },
+
+ /**
+ * Notifies the modifier keys that a non-control key was typed. This
+ * lets them reset sticky behaviour. A non-control key is defined as
+ * any key that is not Control, Alt, or Shift.
+ */
+ onNonControlKeyTyped: function() {
+ if (this.shift)
+ this.shift.onNonControlKeyTyped();
+ if (this.ctrl)
+ this.ctrl.onNonControlKeyTyped();
+ if (this.alt)
+ this.alt.onNonControlKeyTyped();
+ this.classList.remove('ctrl-active');
+ this.classList.remove('alt-active');
+ },
+
+ /**
+ * Id for the active keyset.
+ * @type {string}
+ */
+ get activeKeysetId() {
+ return this.layout + '-' + this.keyset;
+ },
+
+ /**
+ * The active keyset DOM object.
+ * @type {kb-keyset}
+ */
+ get activeKeyset() {
+ return this.querySelector('#' + this.activeKeysetId);
+ },
+
+ /**
+ * The current input type.
+ * @type {string}
+ */
+ get inputTypeValue() {
+ return this.inputType;
+ },
+
+ /**
+ * Changes the input type if it's different from the current
+ * type, else resets the keyset to the default keyset.
+ * @type {string}
+ */
+ set inputTypeValue(value) {
+ if (value == this.inputType)
+ this.selectDefaultKeyset();
+ else
+ this.inputType = value;
+ },
+
+ /**
+ * The keyboard is ready for input once the target keyset appears
+ * in the distributed nodes for the keyboard.
+ * @return {boolean} Indicates if the keyboard is ready for input.
+ */
+ isReady: function() {
+ var keyset = this.activeKeyset;
+ if (!keyset)
+ return false;
+ var content = this.$.content.getDistributedNodes()[0];
+ return content == keyset;
},
/**
* Generates fabricated key events to simulate typing on a
* physical keyboard.
* @param {Object} detail Attributes of the key being typed.
+ * @return {boolean} Whether the key type succeeded.
*/
keyTyped: function(detail) {
var builder = this.$.keyCodeMetadata;
- sendKeyEvent(builder.createVirtualKeyEvent(detail, "keydown"));
- sendKeyEvent(builder.createVirtualKeyEvent(detail, "keyup"));
+ if (this.shift)
+ detail.shiftModifier = this.shift.isActive();
+ if (this.ctrl)
+ detail.controlModifier = this.ctrl.isActive();
+ if (this.alt)
+ detail.altModifier = this.alt.isActive();
+ var downEvent = builder.createVirtualKeyEvent(detail, "keydown");
+ if (downEvent) {
+ sendKeyEvent(downEvent);
+ sendKeyEvent(builder.createVirtualKeyEvent(detail, "keyup"));
+ return true;
+ }
+ return false;
},
/**
@@ -576,8 +938,34 @@
var matches = keysets[i].id.match(regex);
if (matches && matches.length == REGEX_MATCH_COUNT) {
keysetsLoaded = true;
- if (keysets[i].isDefault) {
+ // Without both tests for a default keyset, it is possible to get
+ // into a state where multiple layouts are displayed. A
+ // reproducable test case is do the following set of keyset
+ // transitions: qwerty -> system -> dvorak -> qwerty.
+ // TODO(kevers): Investigate why this is the case.
+ if (keysets[i].isDefault ||
+ keysets[i].getAttribute('isDefault') == 'true') {
this.keyset = matches[REGEX_KEYSET_INDEX];
+ this.classList.remove('caps-locked');
+ this.classList.remove('alt-active');
+ this.classList.remove('ctrl-active');
+ // Caches shift key.
+ this.shift = this.querySelector('kb-shift-key');
+ if (this.shift)
+ this.shift.reset();
+ // Caches control key.
+ this.ctrl = this.querySelector('kb-modifier-key[char=Ctrl]');
+ if (this.ctrl)
+ this.ctrl.reset();
+ // Caches alt key.
+ this.alt = this.querySelector('kb-modifier-key[char=Alt]');
+ if (this.alt)
+ this.alt.reset();
+ this.fire('stateChange', {
+ state: 'keysetLoaded',
+ value: this.keyset,
+ });
+ keyboardLoaded();
return true;
}
}
diff --git a/chromium/ui/keyboard/resources/elements/kb-keyset.html b/chromium/ui/keyboard/resources/elements/kb-keyset.html
index 92dd8b7f687..1089385e26e 100644
--- a/chromium/ui/keyboard/resources/elements/kb-keyset.html
+++ b/chromium/ui/keyboard/resources/elements/kb-keyset.html
@@ -4,17 +4,14 @@
-- found in the LICENSE file.
-->
-<polymer-element name="kb-keyset" attributes="nextKeyset isDefault
- capsLocksTo capsLockable" on-key-up="keyUp"
- on-key-longpress="keyLongpress">
+<polymer-element name="kb-keyset" attributes="nextKeyset isDefault"
+ on-key-up="{{keyUp}}" on-key-longpress="{{keyLongpress}}">
<template>
<style>
- @host {
- * {
- -webkit-box-orient: vertical;
- -webkit-box-flex: 1;
- display: -webkit-box;
- }
+ :host {
+ -webkit-box-flex: 1;
+ -webkit-box-orient: vertical;
+ display: -webkit-box;
}
</style>
<content select="kb-row"></content>
@@ -28,6 +25,14 @@
nextKeyset: undefined,
// TODO(bshe): support select keyset on down, long and dbl events.
keyUp: function(event, detail) {
+ switch (detail.char) {
+ case 'Shift':
+ case 'Alt':
+ case 'Ctrl':
+ return;
+ default:
+ break;
+ }
if (!detail.toKeyset)
detail.toKeyset = this.nextKeyset;
},
@@ -61,7 +66,7 @@
}
altkeyContainer.keyset = id;
- event.target.classList.remove('active');
+ event.target.dropKey();
activeAltKeySet.style.width = event.target.clientWidth *
activeAltKeySet.childElementCount + 'px';
activeAltKeySet.style.height = event.target.clientHeight + 'px';
diff --git a/chromium/ui/keyboard/resources/elements/kb-modifier-key.html b/chromium/ui/keyboard/resources/elements/kb-modifier-key.html
new file mode 100644
index 00000000000..adba4765562
--- /dev/null
+++ b/chromium/ui/keyboard/resources/elements/kb-modifier-key.html
@@ -0,0 +1,142 @@
+<!--
+ -- Copyright 2013 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.
+ -->
+
+<polymer-element name="kb-modifier-key" class="unlocked dark" extends="kb-key"
+ on-pointerout="{{out}}">
+ <script>
+ (function () {
+
+ /**
+ * The possible states of the key.
+ * @const
+ * @type {Enum}
+ */
+ var KEY_STATES = {
+ PRESSED: "pressed", // Key-down.
+ UNLOCKED: "unlocked", // Default state.
+ TAPPED: "tapped", // Key-down followed by key-up.
+ CHORDING: "chording", // Chording mode.
+ };
+
+ /**
+ * A map of the state of all modifier keys.
+ * @type {Object}
+ */
+ var states = {};
+
+ Polymer('kb-modifier-key', {
+ up: function(event) {
+ if (this.state == KEY_STATES.PRESSED)
+ this.state = KEY_STATES.TAPPED;
+ else
+ this.state = KEY_STATES.UNLOCKED;
+ this.super([event]);
+ },
+
+ down: function(event) {
+ // First transition state so that populateDetails generates
+ // correct data.
+ switch (this.state) {
+ case KEY_STATES.UNLOCKED:
+ this.state = KEY_STATES.PRESSED;
+ break;
+ case KEY_STATES.TAPPED:
+ this.state = KEY_STATES.UNLOCKED;
+ break;
+ case KEY_STATES.PRESSED:
+ case KEY_STATES.CHORDING:
+ // We pressed another key at the same time,
+ // so ignore second press.
+ return;
+ default:
+ console.error("Undefined key state: " + state);
+ break;
+ }
+ this.super([event]);
+ },
+
+ /**
+ * Returns whether the modifier for this key is active.
+ * @return {boolean}
+ */
+ isActive: function() {
+ return this.state != KEY_STATES.UNLOCKED;
+ },
+
+ /**
+ * Notifies key that a non-control keyed down.
+ * A control key is defined as one of shift, control or alt.
+ */
+ onNonControlKeyDown: function() {
+ switch(this.state) {
+ case (KEY_STATES.PRESSED):
+ this.state = KEY_STATES.CHORDING;
+ break;
+ }
+ },
+
+ /**
+ * Notifies key that a non-control keyed was typed.
+ * A control key is defined as one of shift, control or alt.
+ */
+ onNonControlKeyTyped: function() {
+ switch(this.state) {
+ case (KEY_STATES.TAPPED):
+ this.state = KEY_STATES.UNLOCKED;
+ break;
+ }
+ },
+
+ /**
+ * Called on a pointer-out event. Ends chording.
+ * @param {event} event The pointer-out event.
+ */
+ out: function(event) {
+ // TODO(rsadam): Add chording event so that we don't reset
+ // when shift-chording.
+ if (this.state == KEY_STATES.CHORDING) {
+ this.state = KEY_STATES.UNLOCKED;
+ }
+ },
+
+ /*
+ * Overrides the autoRelease function to enable chording.
+ */
+ autoRelease: function() {
+ },
+
+ populateDetails: function(caller) {
+ var detail = this.super([caller]);
+ if (this.state != KEY_STATES.UNLOCKED)
+ detail.activeModifier = this.charValue;
+ return detail;
+ },
+
+ /**
+ * Resets the modifier key state.
+ */
+ reset: function() {
+ this.state = KEY_STATES.UNLOCKED;
+ },
+
+ get state() {
+ var key = this.charValue;
+ if (!key)
+ console.error("missing key for kb-modifier-key state: " + this);
+ // All keys default to the unlock state.
+ if (!(key in states))
+ states[key] = KEY_STATES.UNLOCKED;
+ return states[key];
+ },
+
+ set state(value) {
+ var key = this.charValue;
+ states[key] = value;
+ }
+ });
+ })();
+ </script>
+</polymer-element>
diff --git a/chromium/ui/keyboard/resources/elements/kb-options-menu.html b/chromium/ui/keyboard/resources/elements/kb-options-menu.html
new file mode 100644
index 00000000000..f33bd3c82bb
--- /dev/null
+++ b/chromium/ui/keyboard/resources/elements/kb-options-menu.html
@@ -0,0 +1,111 @@
+<!--
+ -- Copyright 2013 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.
+ -->
+
+<polymer-element name="kb-options-menu-item" attributes="layout label active"
+ on-pointerup="up" on-pointerover="over" on-pointerout="out">
+ <template>
+ <style>
+ @host {
+ * {
+ -webkit-padding-end: 5px;
+ -webkit-padding-start: 5px;
+ color: #fff;
+ display: -webkit-box;
+ font-family: 'Open Sans', 'Noto Sans UI', sans-serif;
+ font-weight: 300;
+ height: 28px;
+ }
+ *.active {
+ background-color: #848490;
+ }
+ </style>
+ <span>{{label}}</span>
+ </template>
+ <script>
+ Polymer('kb-options-menu-item', {
+ /**
+ * Layout to select on a key press.
+ */
+ layout: null,
+
+ up: function(event) {
+ if (this.layout == 'none')
+ hideKeyboard();
+ else
+ this.fire('set-layout', {layout: this.layout});
+ this.hidden = true;
+ },
+
+ over: function(event) {
+ this.classList.add('active');
+ },
+
+ out: function(event) {
+ this.classList.remove('active');
+ },
+ });
+ </script>
+</polymer>
+
+<polymer-element name="kb-options-menu">
+ <template>
+ <style>
+ @host {
+ * {
+ -webkit-box-orient: vertical;
+ background-color: #3b3b3e;
+ border-radius: 2px;
+ display: -webkit-box;
+ left: 0;
+ position: absolute;
+ top: 0;
+ z-index: 1;
+ }
+ }
+ </style>
+ <!-- TODO(kevers): This is a temporary placeholder to enable testing
+ -- of layout switching. Deprecate once a decision is reached on
+ -- a more permanent solution for layout selection. -->
+ <kb-options-menu-item layout="system-qwerty" label="System QWERTY">
+ </kb-options-menu-item>
+ <kb-options-menu-item layout="qwerty" label="QWERTY">
+ </kb-options-menu-item>
+ <kb-options-menu-item layout="dvorak" label="Dvorak">
+ </kb-options-menu-item>
+ <kb-options-menu-item layout="none" label="Hide keyboard">
+ </kb-options-menu-item>
+ </template>
+ <script>
+ Polymer('kb-options-menu', {});
+ </script>
+</polymer>
+
+<polymer-element name="kb-keyboard-overlay" attributes="keyset"
+ on-pointerup="up">
+ <template>
+ <style>
+ @host {
+ * {
+ background-color: rgba(0, 0, 0, 0.6);
+ bottom: 0;
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+ }
+ </style>
+ <!-- Insert popups here. -->
+ <kb-options-menu id="options" hidden></kb-options-menu>
+ </template>
+ <script>
+ Polymer('kb-keyboard-overlay', {
+ up: function() {
+ this.hidden = true;
+ }
+ });
+ </script>
+</polymer-element>
diff --git a/chromium/ui/keyboard/resources/elements/kb-shift-key.html b/chromium/ui/keyboard/resources/elements/kb-shift-key.html
index 686a59c5125..4778b622134 100644
--- a/chromium/ui/keyboard/resources/elements/kb-shift-key.html
+++ b/chromium/ui/keyboard/resources/elements/kb-shift-key.html
@@ -6,7 +6,7 @@
<polymer-element name="kb-shift-key"
attributes="lowerCaseKeysetId upperCaseKeysetId"
- class="shift dark" char="Shift" extends="kb-key">
+ class="shift dark" char="Shift" on-pointerout="{{out}}" extends="kb-key">
<script>
(function () {
@@ -21,10 +21,18 @@
PRESSED: "pressed", // Key-down on shift key.
LOCKED: "locked", // Key is capslocked.
UNLOCKED: "unlocked", // Default state.
- TAPPED: "tapped" // Key-down followed by key-up.
+ TAPPED: "tapped", // Key-down followed by key-up.
+ CHORDING: "chording" // Key-down followed by other keys.
};
/**
+ * The pointerdown event on shiftkey that may eventually trigger chording
+ * state. pointerId and eventTarget are the two fields that is used now.
+ * @type {PointerEvent}
+ */
+ var enterChordingEvent = undefined;
+
+ /**
* Uses a closure to define one long press timer among all shift keys
* regardless of the layout they are in.
* @type {function}
@@ -40,18 +48,51 @@
Polymer('kb-shift-key', {
/**
* Defines how capslock effects keyset transition. We always transition
- * from the lowerCaseKeysetId to the upperCaseKeysetId if capslock is on.
+ * from the lowerCaseKeysetId to the upperCaseKeysetId if capslock is
+ * on.
* @type {string}
*/
lowerCaseKeysetId: 'lower',
upperCaseKeysetId: 'upper',
up: function(event) {
- if (state == KEY_STATES.PRESSED) {
- state = KEY_STATES.TAPPED;
- // TODO(rsadam@): Add chording logic here.
+ if (state == KEY_STATES.CHORDING &&
+ event.pointerId != enterChordingEvent.pointerId) {
+ // Disables all other pointer events on shift keys when chording.
+ return;
+ }
+ switch (state) {
+ case KEY_STATES.PRESSED:
+ state = KEY_STATES.TAPPED;
+ break;
+ case KEY_STATES.CHORDING:
+ // Leaves chording only if the pointer that triggered it is
+ // released.
+ state = KEY_STATES.UNLOCKED;
+ break;
+ default:
+ break;
+ }
+ // When releasing the shift key, it is not the same shift key that was
+ // pressed. Updates the pointerId of the releasing shift key to make
+ // sure key-up event fires correctly in kb-key-base.
+ this.pointerId = enterChordingEvent.pointerId;
+ this.super([event]);
+ },
+
+ out: function(event) {
+ // Sliding off the shift key while chording is treated as a key-up.
+ // Note that we switch to a new keyset on shift keydown, and a finger
+ // movement on the new shift key will trigger this function being
+ // called on the old shift key. We should not end chording in that
+ // case.
+ if (state == KEY_STATES.CHORDING &&
+ event.pointerId == enterChordingEvent.pointerId &&
+ event.target != enterChordingEvent.target) {
+ state = KEY_STATES.UNLOCKED;
+ var detail = this.populateDetails('out');
+ this.fire("key-out", detail);
}
- this.super();
},
down: function(event) {
@@ -66,15 +107,17 @@
state = KEY_STATES.UNLOCKED;
break;
case KEY_STATES.PRESSED:
+ case KEY_STATES.CHORDING:
// We pressed another shift key at the same time,
// so ignore second press.
- break;
+ return;
default:
console.error("Undefined shift key state: " + state);
break;
}
+ enterChordingEvent = event;
// Trigger parent behaviour.
- this.super();
+ this.super([event]);
this.fire('enable-sel');
// Populate double click transition details.
var detail = {};
@@ -101,6 +144,11 @@
}, null, LONGPRESS_DELAY_MSEC);
},
+ // @return Whether the shift modifier is currently active.
+ isActive: function() {
+ return state != KEY_STATES.UNLOCKED;
+ },
+
/**
* Callback function for when a double click is triggered.
*/
@@ -113,19 +161,25 @@
* A control key is defined as one of shift, control or alt.
*/
onNonControlKeyDown: function() {
- // TODO(rsadam@): add logic for chording here.
- switch (state) {
- case (KEY_STATES.TAPPED):
- state = KEY_STATES.UNLOCKED;
- break;
- case (KEY_STATES.PRESSED):
- // Enter chording mode. First disable longpress timer.
- clearTimeout(this.shiftLongPressTimer);
- break;
- default:
- break;
- }
- },
+ switch (state) {
+ case (KEY_STATES.PRESSED):
+ state = KEY_STATES.CHORDING;
+ // Disable longpress timer.
+ clearTimeout(shiftLongPressTimer);
+ break;
+ default:
+ break;
+ }
+ },
+
+ /**
+ * Notifies key that a non-control keyed was typed.
+ * A control key is defined as one of shift, control or alt.
+ */
+ onNonControlKeyTyped: function() {
+ if (state == KEY_STATES.TAPPED)
+ state = KEY_STATES.UNLOCKED;
+ },
/**
* Callback function for when a space is pressed after punctuation.
@@ -139,8 +193,8 @@
return detail;
},
- populateDetails: function() {
- var detail = this.super();
+ populateDetails: function(caller) {
+ var detail = this.super([caller]);
switch(state) {
case(KEY_STATES.LOCKED):
detail.toKeyset = this.upperCaseKeysetId;
@@ -155,6 +209,11 @@
detail.toKeyset = this.upperCaseKeysetId;
detail.nextKeyset = this.lowerCaseKeysetId;
break;
+ case(KEY_STATES.CHORDING):
+ detail.toKeyset = this.lowerCaseKeysetId;
+ break;
+ default:
+ break;
}
return detail;
},
@@ -179,8 +238,17 @@
get state() {
return state;
- }
+ },
+
+ get textKeyset() {
+ switch (state) {
+ case KEY_STATES.UNLOCKED:
+ return this.lowerCaseKeysetId;
+ default:
+ return this.upperCaseKeysetId;
+ }
+ },
});
})();
</script>
-</polymer-element> \ No newline at end of file
+</polymer-element>
diff --git a/chromium/ui/keyboard/resources/images/back.svg b/chromium/ui/keyboard/resources/images/back.svg
new file mode 100644
index 00000000000..33d519a7f55
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/back.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6" /><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><g
+ transform="translate(22.2734,11.2998)"
+ id="g12"><path
+ d="m 0,0 -6.845,0 2.8,2.8 -1.132,1.132 -4.697,-4.699 4.688,-4.764 1.14,1.122 L -6.81,-1.6 0,-1.6 0,0 z"
+ inkscape:connector-curvature="0"
+ id="path14"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/brightness-down.svg b/chromium/ui/keyboard/resources/images/brightness-down.svg
new file mode 100644
index 00000000000..5f5c5dc5753
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/brightness-down.svg
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6"><clipPath
+ id="clipPath16"><path
+ d="M 0,21 35,21 35,0 0,0 0,21 z"
+ inkscape:connector-curvature="0"
+ id="path18" /></clipPath></defs><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><g
+ id="g12"><g
+ clip-path="url(#clipPath16)"
+ id="g14"><g
+ transform="translate(17.5,8.5654)"
+ id="g20"><path
+ d="m 0,0 c -1.068,0 -1.934,0.868 -1.934,1.935 0,1.066 0.866,1.933 1.934,1.933 1.067,0 1.932,-0.867 1.932,-1.933 C 1.932,0.868 1.067,0 0,0 m 2.766,3.081 0,1.618 -1.62,0 L 0,5.846 -1.145,4.699 l -1.62,0 0,-1.618 -1.145,-1.146 1.145,-1.147 0,-1.619 1.62,0 1.145,-1.146 1.146,1.146 1.62,0 0,1.62 1.144,1.146 -1.144,1.146 z"
+ inkscape:connector-curvature="0"
+ id="path22"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/brightness-up.svg b/chromium/ui/keyboard/resources/images/brightness-up.svg
new file mode 100644
index 00000000000..cdd92d3db9f
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/brightness-up.svg
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6"><clipPath
+ id="clipPath16"><path
+ d="M 0,21 35,21 35,0 0,0 0,21 z"
+ inkscape:connector-curvature="0"
+ id="path18" /></clipPath></defs><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><g
+ id="g12"><g
+ clip-path="url(#clipPath16)"
+ id="g14"><g
+ transform="translate(17.5,7.4746)"
+ id="g20"><path
+ d="m 0,0 c -1.667,0 -3.024,1.358 -3.024,3.025 0,1.668 1.357,3.024 3.024,3.024 1.667,0 3.023,-1.356 3.023,-3.024 C 3.023,1.358 1.667,0 0,0 m 3.788,4.595 0,2.217 -2.22,0 L 0,8.383 -1.568,6.812 l -2.219,0 0,-2.217 -1.568,-1.57 1.568,-1.569 0,-2.219 2.219,0 1.568,-1.569 1.568,1.569 2.22,0 0,2.219 1.568,1.569 -1.568,1.57 z"
+ inkscape:connector-curvature="0"
+ id="path22"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/change-window.svg b/chromium/ui/keyboard/resources/images/change-window.svg
new file mode 100644
index 00000000000..d6b88fe7032
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/change-window.svg
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6" /><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><path
+ d="m 11.035,13.444 7.73,0 0,-5.889 -7.73,0 0,5.889 z m -1.3,-7.188 10.33,0 0,8.488 -10.33,0 0,-8.488 z"
+ inkscape:connector-curvature="0"
+ id="path12"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
+ d="m 21.365,6.255 1.3,0 0,8.49 -1.3,0 0,-8.49 z"
+ inkscape:connector-curvature="0"
+ id="path14"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
+ d="m 23.965,6.255 1.3,0 0,8.49 -1.3,0 0,-8.49 z"
+ inkscape:connector-curvature="0"
+ id="path16"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/down.svg b/chromium/ui/keyboard/resources/images/down.svg
new file mode 100644
index 00000000000..45f6466e6e1
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/down.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6" /><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><g
+ transform="translate(13.9023,12.2852)"
+ id="g12"><path
+ d="M 0,0 3.57,-3.57 7.199,0"
+ inkscape:connector-curvature="0"
+ id="path14"
+ style="fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/forward.svg b/chromium/ui/keyboard/resources/images/forward.svg
new file mode 100644
index 00000000000..10e011e7d87
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/forward.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6" /><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><g
+ transform="translate(17.8662,15.2314)"
+ id="g12"><path
+ d="m 0,0 -1.122,-1.141 2.836,-2.791 -6.884,0 0,-1.599 6.848,0 -2.801,-2.801 1.132,-1.131 4.764,4.765 L 0,0 z"
+ inkscape:connector-curvature="0"
+ id="path14"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/fullscreen.svg b/chromium/ui/keyboard/resources/images/fullscreen.svg
new file mode 100644
index 00000000000..1688ebdb2c0
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/fullscreen.svg
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6" /><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><path
+ d="m 21.866,7.056 -8.73,0 0,6.889 8.73,0 0,-6.889 z m -10.031,-1.3 11.33,0 0,9.488 -11.33,0 0,-9.488 z"
+ inkscape:connector-curvature="0"
+ id="path12"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /><g
+ transform="translate(20.8311,10.3906)"
+ id="g14"><path
+ d="M 0,0 -2.344,-2.344 0,-2.344 0,0 z"
+ inkscape:connector-curvature="0"
+ id="path16"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+ transform="translate(14.1631,12.9219)"
+ id="g18"><path
+ d="M 0,0 0,-2.344 2.344,0 0,0 z"
+ inkscape:connector-curvature="0"
+ id="path20"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/left.svg b/chromium/ui/keyboard/resources/images/left.svg
new file mode 100644
index 00000000000..0d31feb576e
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/left.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6" /><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><g
+ transform="translate(17.9902,14.0996)"
+ id="g12"><path
+ d="M 0,0 -3.57,-3.57 0,-7.199"
+ inkscape:connector-curvature="0"
+ id="path14"
+ style="fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/mute.svg b/chromium/ui/keyboard/resources/images/mute.svg
new file mode 100644
index 00000000000..2c0dafa0d36
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/mute.svg
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6" /><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><g
+ transform="translate(18.5635,13.6641)"
+ id="g12"><path
+ d="m 0,0 0,2.205 -3.193,-3.197 -1.598,0 0,-3.191 0.608,0 L 0,0 z"
+ inkscape:connector-curvature="0"
+ id="path14"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+ transform="translate(18.5635,10.9497)"
+ id="g16"><path
+ d="m 0,0 2.331,2.331 -0.714,0.714 -6.112,-6.113 0.714,-0.713 1.45,1.45 L 0,-4.663 0,0 z"
+ inkscape:connector-curvature="0"
+ id="path18"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/reload.svg b/chromium/ui/keyboard/resources/images/reload.svg
new file mode 100644
index 00000000000..d8749e7de83
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/reload.svg
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6"><clipPath
+ id="clipPath16"><path
+ d="M 0,21 35,21 35,0 0,0 0,21 z"
+ inkscape:connector-curvature="0"
+ id="path18" /></clipPath></defs><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><g
+ id="g12"><g
+ clip-path="url(#clipPath16)"
+ id="g14"><g
+ transform="translate(22.5938,10.7666)"
+ id="g20"><path
+ d="M 0,0 0,4.266 -1.659,2.607 C -2.556,3.619 -3.84,4.238 -5.214,4.263 -6.502,4.291 -7.753,3.804 -8.692,2.899 c -0.94,-0.905 -1.47,-2.122 -1.495,-3.426 -0.048,-2.691 2.101,-4.921 4.791,-4.971 0.03,-10e-4 0.059,-10e-4 0.088,-10e-4 1.7,0 3.295,0.899 4.182,2.362 l -1.197,0.725 c -0.646,-1.063 -1.815,-1.681 -3.047,-1.687 -1.919,0.036 -3.451,1.627 -3.416,3.546 0.016,0.93 0.395,1.799 1.065,2.444 0.67,0.645 1.509,0.987 2.481,0.973 1.009,-0.019 1.949,-0.487 2.59,-1.248 L -4.267,0 0,0 z"
+ inkscape:connector-curvature="0"
+ id="path22"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/right.svg b/chromium/ui/keyboard/resources/images/right.svg
new file mode 100644
index 00000000000..09f2e28c72f
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/right.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6" /><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><g
+ transform="translate(15.2148,6.9004)"
+ id="g12"><path
+ d="M 0,0 3.57,3.57 0,7.199"
+ inkscape:connector-curvature="0"
+ id="path14"
+ style="fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/search.svg b/chromium/ui/keyboard/resources/images/search.svg
new file mode 100644
index 00000000000..0a2fa51f5cc
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/search.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
+ width="97.000000pt" height="58.000000pt" viewBox="0 0 97.000000 58.000000"
+ preserveAspectRatio="xMidYMid meet">
+<g transform="translate(0.000000,58.000000) scale(0.100000,-0.100000)"
+fill="#ffffff" stroke="none">
+<path d="M385 395 c-34 -33 -35 -102 -2 -133 27 -26 78 -38 102 -25 13 8 26 0
+60 -36 42 -44 45 -45 62 -28 17 17 16 20 -28 61 -38 37 -44 47 -37 66 11 30
+-7 86 -35 105 -34 24 -94 19 -122 -10z m110 -35 c35 -39 -6 -99 -59 -86 -16 4
+-31 17 -37 33 -22 58 54 100 96 53z"/>
+</g>
+</svg>
diff --git a/chromium/ui/keyboard/resources/images/shutdown.svg b/chromium/ui/keyboard/resources/images/shutdown.svg
new file mode 100644
index 00000000000..70c75cc24dd
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/shutdown.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6"><clipPath
+ id="clipPath18"><path
+ d="M 0,21 35,21 35,0 0,0 0,21 z"
+ inkscape:connector-curvature="0"
+ id="path20" /></clipPath></defs><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><path
+ d="m 18.095,10.755 -1.26,0 0,6.159 1.26,0 0,-6.159 z"
+ inkscape:connector-curvature="0"
+ id="path12"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /><g
+ id="g14"><g
+ clip-path="url(#clipPath18)"
+ id="g16"><g
+ transform="translate(17.4648,5.8057)"
+ id="g22"><path
+ d="m 0,0 c -2.695,0 -4.889,2.193 -4.889,4.888 0,1.416 0.629,2.765 1.727,3.703 L -2.684,9 -1.864,8.042 -2.344,7.633 C -3.16,6.935 -3.629,5.935 -3.629,4.888 c 0,-2 1.628,-3.628 3.629,-3.628 2,0 3.628,1.628 3.628,3.628 0,1.037 -0.46,2.03 -1.263,2.727 L 1.89,8.028 2.716,8.979 3.191,8.567 C 4.27,7.631 4.888,6.29 4.888,4.888 4.888,2.193 2.695,0 0,0"
+ inkscape:connector-curvature="0"
+ id="path24"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/up.svg b/chromium/ui/keyboard/resources/images/up.svg
new file mode 100644
index 00000000000..3b55bd7a08a
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/up.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6" /><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><g
+ transform="translate(19.791,8.7148)"
+ id="g12"><path
+ d="M 0,0 -3.57,3.57 -7.199,0"
+ inkscape:connector-curvature="0"
+ id="path14"
+ style="fill:none;stroke:#ffffff;stroke-width:1.60000002;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/volume-down.svg b/chromium/ui/keyboard/resources/images/volume-down.svg
new file mode 100644
index 00000000000..17802493bb5
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/volume-down.svg
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6"><clipPath
+ id="clipPath16"><path
+ d="M 0,21 35,21 35,0 0,0 0,21 z"
+ inkscape:connector-curvature="0"
+ id="path18" /></clipPath></defs><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><g
+ id="g12"><g
+ clip-path="url(#clipPath16)"
+ id="g14"><g
+ transform="translate(15.0176,11.0693)"
+ id="g20"><path
+ d="m 0,0 c 0,0.002 4.796,-4.8 4.796,-4.8 l 0,9.6 L 0,0 z"
+ inkscape:connector-curvature="0"
+ id="path22"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+ transform="translate(20.9336,13.5557)"
+ id="g24"><path
+ d="M 0,0 0,-1.169 C 0.512,-1.387 0.872,-1.896 0.872,-2.486 0.872,-3.077 0.512,-3.585 0,-3.804 l 0,-1.169 c 1.14,0.257 1.992,1.27 1.992,2.487 C 1.992,-1.27 1.14,-0.256 0,0"
+ inkscape:connector-curvature="0"
+ id="path26"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+ transform="translate(15.0225,12.6724)"
+ id="g28"><path
+ d="m 0,0 0,-3.191 1.598,0 3.193,-3.195 0,9.583 L 1.598,0 0,0 z"
+ inkscape:connector-curvature="0"
+ id="path30"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/images/volume-up.svg b/chromium/ui/keyboard/resources/images/volume-up.svg
new file mode 100644
index 00000000000..d2890268496
--- /dev/null
+++ b/chromium/ui/keyboard/resources/images/volume-up.svg
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="43.75"
+ height="26.25"
+ id="svg2"
+ xml:space="preserve"><metadata
+ id="metadata8"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs6"><clipPath
+ id="clipPath16"><path
+ d="M 0,21 35,21 35,0 0,0 0,21 z"
+ inkscape:connector-curvature="0"
+ id="path18" /></clipPath></defs><g
+ transform="matrix(1.25,0,0,-1.25,0,26.25)"
+ id="g10"><g
+ id="g12"><g
+ clip-path="url(#clipPath16)"
+ id="g14"><g
+ transform="translate(13.3418,11.0693)"
+ id="g20"><path
+ d="m 0,0 c 0,0.002 4.797,-4.8 4.797,-4.8 l 0,9.6 L 0,0 z"
+ inkscape:connector-curvature="0"
+ id="path22"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+ transform="translate(21.251,11.0693)"
+ id="g24"><path
+ d="m 0,0 c 0,1.216 -0.854,2.23 -1.992,2.486 l 0,-1.169 C -1.48,1.099 -1.12,0.591 -1.12,0 c 0,-0.591 -0.36,-1.099 -0.872,-1.317 l 0,-1.169 C -0.854,-2.23 0,-1.216 0,0"
+ inkscape:connector-curvature="0"
+ id="path26"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+ transform="translate(19.2588,15.8086)"
+ id="g28"><path
+ d="M 0,0 0,-1.12 C 1.76,-1.393 3.115,-2.904 3.115,-4.739 3.115,-6.575 1.76,-8.086 0,-8.359 l 0,-1.12 c 2.381,0.281 4.235,2.283 4.235,4.74 C 4.235,-2.282 2.381,-0.281 0,0"
+ inkscape:connector-curvature="0"
+ id="path30"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+ transform="translate(13.3564,12.6724)"
+ id="g32"><path
+ d="m 0,0 0,-3.191 1.598,0 3.193,-3.195 0,9.583 L 1.598,0 0,0 z"
+ inkscape:connector-curvature="0"
+ id="path34"
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g></svg> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/index.html b/chromium/ui/keyboard/resources/index.html
index c18e8e89285..16733ba6b7d 100644
--- a/chromium/ui/keyboard/resources/index.html
+++ b/chromium/ui/keyboard/resources/index.html
@@ -10,7 +10,7 @@
<meta charset="UTF-8">
<link rel="stylesheet" href="main.css">
<script src="constants.js"></script>
- <script src="polymer.min.js"></script>
+ <script src="polymer_loader.js"></script>
<script src="api_adapter.js"></script>
<script src="voice_input.js"></script>
<script src="main.js"></script>
@@ -28,10 +28,12 @@
<link rel="import" href="elements/kb-key.html">
<link rel="import" href="elements/kb-keyboard.html">
<link rel="import" href="elements/kb-keyset.html">
+ <link rel="import" href="elements/kb-modifier-key.html">
<link rel="import" href="elements/kb-row.html">
<link rel="import" href="elements/kb-shift-key.html">
<link rel="import" href="elements/kb-key-sequence.html">
<link rel="import" href="elements/kb-key-import.html">
+ <link rel="import" href="elements/kb-options-menu.html">
<!-- New layouts are dynamically loaded on demand. The link elements are
-- inserted here.
-->
diff --git a/chromium/ui/keyboard/resources/layouts/dvorak.html b/chromium/ui/keyboard/resources/layouts/dvorak.html
index 1bd2300aefd..d3d9ee440d1 100644
--- a/chromium/ui/keyboard/resources/layouts/dvorak.html
+++ b/chromium/ui/keyboard/resources/layouts/dvorak.html
@@ -9,25 +9,31 @@
<template>
<kb-keyset id="dvorak-upper">
<kb-row>
- <kb-key class="tab dark" char="&#x0009;" align="left">tab</kb-key>
- <kb-key-sequence keys="&quot;,.PYFGCRL" hintTexts="1234567890"></kb-key-sequence>
- <kb-key class="backspace dark" char="&#x0008;" repeat align="right">backspace</kb-key>
+ <kb-key class="dark" char="&#x0009;" align="left"
+ weight="120">tab</kb-key>
+ <kb-key-sequence keys="&quot;,.PYFGCRL" hintTexts="1234567890">
+ </kb-key-sequence>
+ <kb-key class="dark" char="&#x0008;" repeat align="right"
+ weight="140">backspace</kb-key>
</kb-row>
<kb-row>
- <kb-key class="microphone dark" char="Microphone"></kb-key>
+ <kb-key class="microphone dark" char="Microphone" weight="110"></kb-key>
<kb-key-sequence keys="AOEUIDHTNS"></kb-key-sequence>
- <kb-key class='return dark' char="&#x000A;" align="right">enter</kb-key>
+ <kb-key class="dark" char="&#x000A;" align="right"
+ weight="150">enter</kb-key>
</kb-row>
<kb-row>
- <kb-shift-key weight="1.8" align="left">shift</kb-shift-key>
+ <kb-shift-key weight="130" align="left">shift</kb-shift-key>
<kb-key-sequence keys=";QJKXBMWVZ"></kb-key-sequence>
- <kb-shift-key weight="1.8" align="right">shift</kb-shift-key>
+ <kb-shift-key weight="130" align="right">shift</kb-shift-key>
</kb-row>
<kb-row>
- <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="left">#123</kb-key>
+ <kb-key class="dark" toKeyset="down:symbol" char="Invalid"
+ align="left" weight="130">#123</kb-key>
<kb-key-import importId="spacebar-row"></kb-key-import>
- <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="right">#123</kb-key>
- <kb-layout-selector></kb-layout-selector>
+ <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid"
+ align="right" weight="130">#123</kb-key>
+ <kb-hide-keyboard-key></kb-hide-keyboard-key>
</kb-row>
<kb-altkey-container hidden>
</kb-altkey-container>
@@ -35,25 +41,31 @@
<kb-keyset id="dvorak-lower" isDefault=true>
<kb-row>
- <kb-key class="tab dark" char="&#x0009;" align="left">tab</kb-key>
- <kb-key-sequence keys="&quot;,.pyfgcrl" hintTexts="1234567890"></kb-key-sequence>
- <kb-key class="backspace dark" char="&#x0008;" repeat align="right">backspace</kb-key>
+ <kb-key class="dark" char="&#x0009;" align="left"
+ weight="120">tab</kb-key>
+ <kb-key-sequence keys="&quot;,.pyfgcrl" hintTexts="1234567890">
+ </kb-key-sequence>
+ <kb-key class="dark" char="&#x0008;" repeat align="right"
+ weight="140">backspace</kb-key>
</kb-row>
<kb-row>
- <kb-key class="microphone dark" char="Microphone"></kb-key>
+ <kb-key class="microphone dark" char="Microphone" weight="110"></kb-key>
<kb-key-sequence keys="aoeuidhtns"></kb-key-sequence>
- <kb-key class='return dark' char="&#x000A;" align="right">enter</kb-key>
+ <kb-key class="dark" char="&#x000A;" align="right"
+ weight="150">enter</kb-key>
</kb-row>
<kb-row>
- <kb-shift-key weight="1.8" align="left">shift</kb-shift-key>
+ <kb-shift-key weight="130" align="left">shift</kb-shift-key>
<kb-key-sequence keys=";qjkxbmwvz"></kb-key-sequence>
- <kb-shift-key weight="1.8" align="right">shift</kb-shift-key>
+ <kb-shift-key weight="130" align="right">shift</kb-shift-key>
</kb-row>
<kb-row>
- <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="left">#123</kb-key>
+ <kb-key class="dark" toKeyset="down:symbol" char="Invalid"
+ align="left" weight="130">#123</kb-key>
<kb-key-import importId="spacebar-row"></kb-key-import>
- <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="right">#123</kb-key>
- <kb-layout-selector></kb-layout-selector>
+ <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid"
+ align="right" weight="130">#123</kb-key>
+ <kb-hide-keyboard-key></kb-hide-keyboard-key>
</kb-row>
<kb-altkey-container hidden>
</kb-altkey-container>
@@ -61,25 +73,30 @@
<kb-keyset id="dvorak-symbol">
<kb-row>
- <kb-key class="tab dark" char="&#x0009;" align="left">tab</kb-key>
+ <kb-key class="dark" char="&#x0009;" align="left"
+ weight="120">tab</kb-key>
<kb-key-sequence keys="1234567890"></kb-key-sequence>
- <kb-key class="backspace dark" char="&#x0008;" repeat align="right">backspace</kb-key>
+ <kb-key class="dark" char="&#x0008;" repeat align="right"
+ weight="140">backspace</kb-key>
</kb-row>
<kb-row>
- <kb-key class="microphone dark" char="Microphone"></kb-key>
+ <kb-key class="microphone dark" char="Microphone" weight="110"></kb-key>
<kb-key-sequence keys="@#$%&amp;*-=()"></kb-key-sequence>
- <kb-key class='return dark' char="&#x000A;" align="right">enter</kb-key>
+ <kb-key class="dark" char="&#x000A;" align="right"
+ weight="150">enter</kb-key>
</kb-row>
<kb-row>
- <kb-key class="left-more dark" toKeyset="down:more" char="Invalid" align="left">more</kb-key>
+ <kb-key class="dark" toKeyset="down:more" char="Invalid"
+ align="left" weight="280">more</kb-key>
<kb-key-sequence keys="!&quot;':;/?"></kb-key-sequence>
- <kb-key class="right-more dark" toKeyset="down:more" char="Invalid" align="right">more</kb-key>
+ <kb-key class="dark" toKeyset="down:more" char="Invalid"
+ align="right" weight="280">more</kb-key>
</kb-row>
<kb-row>
- <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="left">abc</kb-key>
+ <kb-abc-key align="left" weight="130">abc</kb-abc-key>
<kb-key-import importId="spacebar-row"></kb-key-import>
- <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="right">abc</kb-key>
- <kb-layout-selector></kb-layout-selector>
+ <kb-abc-key align="right" weight="130">abc</kb-abc-key>
+ <kb-hide-keyboard-key></kb-hide-keyboard-key>
</kb-row>
<kb-altkey-container hidden>
</kb-altkey-container>
@@ -87,31 +104,36 @@
<kb-keyset id="dvorak-more">
<kb-row>
- <kb-key class="tab dark" char="&#x0009;" align="left">tab</kb-key>
+ <kb-key class="dark" char="&#x0009;" align="left"
+ weight="120">tab</kb-key>
<kb-key>~</kb-key><kb-key>`</kb-key><kb-key>|</kb-key><kb-key>^</kb-key>
<kb-key>+</kb-key><kb-key>=</kb-key><kb-key>{</kb-key><kb-key>}</kb-key>
<kb-key>&#x003C;</kb-key><kb-key>&#x003E;</kb-key>
- <kb-key class="backspace dark" char="&#x0008;" repeat align="right">backspace</kb-key>
+ <kb-key class="dark" char="&#x0008;" repeat align="right"
+ weight="140">backspace</kb-key>
</kb-row>
<kb-row>
- <kb-key class="microphone dark" char="Microphone"></kb-key>
- <kb-key>&#x00A3</kb-key><kb-key>&#x00A2</kb-key><kb-key>&#x20AC</kb-key><kb-key>&#x2122</kb-key>
- <kb-key>&#x00A9</kb-key><kb-key>&#x00AE</kb-key><kb-key>\</kb-key><kb-key>[</kb-key>
- <kb-key>]</kb-key>
- <kb-key class='return dark' char="&#x000A;" align="right">enter</kb-key>
+ <kb-key class="microphone dark" char="Microphone" weight="150"></kb-key>
+ <kb-key>&#x00A3</kb-key><kb-key>&#x00A2</kb-key><kb-key>&#x20AC</kb-key>
+ <kb-key>&#x2122</kb-key><kb-key>&#x00A9</kb-key><kb-key>&#x00AE</kb-key>
+ <kb-key>\</kb-key><kb-key>[</kb-key><kb-key>]</kb-key>
+ <kb-key class="dark" char="&#x000A;" align="right"
+ weight="210">enter</kb-key>
</kb-row>
<kb-row>
- <kb-key class="left-more dark" toKeyset="down:symbol" char="Invalid" align="left">#123</kb-key>
- <kb-key>&#x00D7</kb-key><kb-key>&#x00F7</kb-key><kb-key>_</kb-key><kb-key>&#x00A7</kb-key>
- <kb-key>&#x00B6</kb-key><kb-key>&#x00A1</kb-key><kb-key>&#x00BF</kb-key><kb-key>&#x2022</kb-key>
- <kb-key>&#x0394</kb-key>
- <kb-key class="right-more dark" toKeyset="down:symbol" char="Invalid" align="right">#123</kb-key>
+ <kb-key class="dark" toKeyset="down:symbol" char="Invalid"
+ align="left" weight="180">#123</kb-key>
+ <kb-key>&#x00D7</kb-key><kb-key>&#x00F7</kb-key><kb-key>_</kb-key>
+ <kb-key>&#x00A7</kb-key><kb-key>&#x00B6</kb-key><kb-key>&#x00A1</kb-key>
+ <kb-key>&#x00BF</kb-key><kb-key>&#x2022</kb-key><kb-key>&#x0394</kb-key>
+ <kb-key class="dark" toKeyset="down:symbol" char="Invalid"
+ align="left" weight="180">#123</kb-key>
</kb-row>
<kb-row>
- <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="left">abc</kb-key>
+ <kb-abc-key align="left" weight="130">abc</kb-abc-key>
<kb-key-import importId="spacebar-row"></kb-key-import>
- <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="right">abc</kb-key>
- <kb-layout-selector></kb-layout-selector>
+ <kb-abc-key align="right" weight="130">abc</kb-abc-key>
+ <kb-hide-keyboard-key></kb-hide-keyboard-key>
</kb-row>
</kb-keyset>
-</template>
+</template> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/layouts/function-key-row.html b/chromium/ui/keyboard/resources/layouts/function-key-row.html
new file mode 100644
index 00000000000..ef70914c6db
--- /dev/null
+++ b/chromium/ui/keyboard/resources/layouts/function-key-row.html
@@ -0,0 +1,25 @@
+<!--
+ -- Copyright 2013 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.
+ -->
+
+<template>
+ <kb-key class="esc dark" char="Esc">esc</kb-key>
+ <kb-key class="back dark" char="Back" image="back"></kb-key>
+ <kb-key class="forward dark" char="Forward" image="forward"></kb-key>
+ <kb-key class="reload dark" char="Reload" image="reload"></kb-key>
+ <kb-key class="fullscreen dark" char="Fullscreen"
+ image="fullscreen"></kb-key>
+ <kb-key class="change-window dark" char="Change-Window"
+ image="change-window"></kb-key>
+ <kb-key class="brightness-down dark" repeat char="Brightness-Down"
+ image="brightness-down"></kb-key>
+ <kb-key class="brightness-up dark" repeat char="Brightness-Up"
+ image="brightness-up"></kb-key>
+ <kb-key class="mute dark" char="Mute" image="mute"></kb-key>
+ <kb-key class="volume-down dark" repeat char="Volume-Down"
+ image="volume-down"></kb-key>
+ <kb-key class="volume-up dark" repeat char="Volume-Up"
+ image="volume-up"></kb-key>
+</template>
diff --git a/chromium/ui/keyboard/resources/layouts/qwerty.html b/chromium/ui/keyboard/resources/layouts/qwerty.html
index 361eaf0e726..b8f83f1c0c1 100644
--- a/chromium/ui/keyboard/resources/layouts/qwerty.html
+++ b/chromium/ui/keyboard/resources/layouts/qwerty.html
@@ -9,26 +9,32 @@
<template>
<kb-keyset id="qwerty-upper">
<kb-row>
- <kb-key class="tab dark" char="&#x0009;" align="left">tab</kb-key>
- <kb-key-sequence keys="QWERTYUIOP" hintTexts="1234567890"></kb-key-sequence>
- <kb-key class="backspace dark" char="&#x0008;" repeat align="right">backspace</kb-key>
+ <kb-key class="dark" char="&#x0009;" align="left"
+ weight="120">tab</kb-key>
+ <kb-key-sequence keys="QWERTYUIOP" hintTexts="1234567890">
+ </kb-key-sequence>
+ <kb-key class="dark" char="&#x0008;" repeat align="right"
+ weight="140">backspace</kb-key>
</kb-row>
<kb-row>
- <kb-key class="microphone dark" char="Microphone"></kb-key>
+ <kb-key class="microphone dark" char="Microphone" weight="150"></kb-key>
<kb-key-sequence keys="ASDFGHJKL"></kb-key-sequence>
- <kb-key class='return dark' char="&#x000A;" align="right">enter</kb-key>
+ <kb-key class="dark" char="&#x000A;" align="right"
+ weight="210">enter</kb-key>
</kb-row>
<kb-row>
- <kb-shift-key weight="1.8" align="left">shift</kb-shift-key>
+ <kb-shift-key weight="180" align="left">shift</kb-shift-key>
<kb-key-sequence keys="ZXCVBNM"></kb-key-sequence>
- <kb-key invert hintText="!" char="!">,</kb-key>
- <kb-key invert hintText="?" char="?">.</kb-key>
- <kb-shift-key weight="1.8" align="right">shift</kb-shift-key>
+ <kb-key invert hintText="!" char=",">,</kb-key>
+ <kb-key invert hintText="?" char=".">.</kb-key>
+ <kb-shift-key weight="180" align="right">shift</kb-shift-key>
</kb-row>
<kb-row>
- <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="left">#123</kb-key>
+ <kb-key class="dark" toKeyset="down:symbol" char="Invalid"
+ align="left" weight="130">#123</kb-key>
<kb-key-import importId="spacebar-row"></kb-key-import>
- <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="right">#123</kb-key>
+ <kb-key class="dark" toKeyset="down:symbol" char="Invalid"
+ align="right" weight="130">#123</kb-key>
<kb-hide-keyboard-key></kb-hide-keyboard-key>
</kb-row>
<kb-altkey-container hidden>
@@ -37,25 +43,31 @@
<kb-keyset id="qwerty-lower" isDefault=true>
<kb-row>
- <kb-key class="tab dark" char="&#x0009;" align="left">tab</kb-key>
- <kb-key-sequence keys="qwertyuiop" hintTexts="1234567890"></kb-key-sequence>
- <kb-key class="backspace dark" char="&#x0008;" repeat align="right">backspace</kb-key>
+ <kb-key class="dark" char="&#x0009;" align="left"
+ weight="120">tab</kb-key>
+ <kb-key-sequence keys="qwertyuiop" hintTexts="1234567890">
+ </kb-key-sequence>
+ <kb-key class="dark" char="&#x0008;" repeat align="right"
+ weight="140">backspace</kb-key>
</kb-row>
<kb-row>
- <kb-key class="microphone dark" char="Microphone"></kb-key>
+ <kb-key class="microphone dark" char="Microphone" weight="150"></kb-key>
<kb-key-sequence keys="asdfghjkl"></kb-key-sequence>
- <kb-key class='return dark' char="&#x000A;" align="right">enter</kb-key>
+ <kb-key class="dark" char="&#x000A;" align="right"
+ weight="210">enter</kb-key>
</kb-row>
<kb-row>
- <kb-shift-key weight="1.8" align="left">shift</kb-shift-key>
+ <kb-shift-key weight="180" align="left">shift</kb-shift-key>
<kb-key-sequence keys="zxcvbnm"></kb-key-sequence>
<kb-key hintText="!">,</kb-key><kb-key hintText="?">.</kb-key>
- <kb-shift-key weight="1.8" align="right">shift</kb-shift-key>
+ <kb-shift-key weight="180" align="right">shift</kb-shift-key>
</kb-row>
<kb-row>
- <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="left">#123</kb-key>
+ <kb-key class="dark" toKeyset="down:symbol" char="Invalid"
+ align="left" weight="130">#123</kb-key>
<kb-key-import importId="spacebar-row"></kb-key-import>
- <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid" align="right">#123</kb-key>
+ <kb-key class="dark" toKeyset="down:symbol" char="Invalid"
+ align="right" weight="130">#123</kb-key>
<kb-hide-keyboard-key></kb-hide-keyboard-key>
</kb-row>
<kb-altkey-container hidden>
@@ -64,32 +76,37 @@
<kb-keyset id="qwerty-symbol">
<kb-row>
- <kb-key class="tab dark" char="&#x0009;" align="left">tab</kb-key>
+ <kb-key class="dark" char="&#x0009;" align="left"
+ weight="120">tab</kb-key>
<kb-key>1</kb-key><kb-key>2</kb-key>
<kb-key>3</kb-key><kb-key>4</kb-key>
<kb-key>5</kb-key><kb-key>6</kb-key><kb-key>7</kb-key>
<kb-key>8</kb-key><kb-key>9</kb-key><kb-key>0</kb-key>
- <kb-key class="backspace dark" char="&#x0008;" repeat align="right">backspace</kb-key>
+ <kb-key class="dark" char="&#x0008;" repeat align="right"
+ weight="140">backspace</kb-key>
</kb-row>
<kb-row>
- <kb-key class="microphone dark" char="Microphone"></kb-key>
+ <kb-key class="microphone dark" char="Microphone" weight="150"></kb-key>
<kb-key>@</kb-key><kb-key>#</kb-key><kb-key>$</kb-key>
<kb-key>%</kb-key><kb-key>&</kb-key>
<kb-key>*</kb-key><kb-key>/</kb-key>
<kb-key>(</kb-key><kb-key>)</kb-key>
- <kb-key class='return dark' char="&#x000A;" align="right">enter</kb-key>
+ <kb-key class="dark" char="&#x000A;" align="right"
+ weight="210">enter</kb-key>
</kb-row>
<kb-row>
- <kb-key class="left-more dark" toKeyset="down:more" char="Invalid" align="left">more</kb-key>
+ <kb-key class="dark" toKeyset="down:more" char="Invalid" align="left"
+ weight="180">more</kb-key>
<kb-key>:</kb-key><kb-key>;</kb-key><kb-key>-</kb-key><kb-key>'</kb-key>
<kb-key>"</kb-key><kb-key>!</kb-key>
<kb-key>?</kb-key><kb-key>,</kb-key><kb-key>.</kb-key>
- <kb-key class="right-more dark" toKeyset="down:more" char="Invalid" align="right">more</kb-key>
+ <kb-key class="dark" toKeyset="down:more" char="Invalid" align="right"
+ weight="180">more</kb-key>
</kb-row>
<kb-row>
- <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="left">abc</kb-key>
+ <kb-abc-key align="left" weight="130">abc</kb-abc-key>
<kb-key-import importId="spacebar-row"></kb-key-import>
- <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="right">abc</kb-key>
+ <kb-abc-key align="right" weight="130">abc</kb-abc-key>
<kb-hide-keyboard-key></kb-hide-keyboard-key>
</kb-row>
<kb-altkey-container hidden>
@@ -98,30 +115,39 @@
<kb-keyset id="qwerty-more">
<kb-row>
- <kb-key class="tab dark" char="&#x0009;" align="left">tab</kb-key>
+ <kb-key class="dark" char="&#x0009;" align="left"
+ weight="120">tab</kb-key>
<kb-key>~</kb-key><kb-key>`</kb-key><kb-key>|</kb-key><kb-key>^</kb-key>
<kb-key>+</kb-key><kb-key>=</kb-key><kb-key>{</kb-key><kb-key>}</kb-key>
<kb-key>&#x003C;</kb-key><kb-key>&#x003E;</kb-key>
- <kb-key class="backspace dark" char="&#x0008;" repeat align="right">backspace</kb-key>
+ <kb-key class="dark" char="&#x0008;" repeat align="right"
+ weight="140">backspace</kb-key>
</kb-row>
<kb-row>
- <kb-key class="microphone dark" char="Microphone"></kb-key>
- <kb-key>&#x00A3;</kb-key><kb-key>&#x00A2;</kb-key><kb-key>&#x20AC;</kb-key><kb-key>&#x2122;</kb-key>
- <kb-key>&#x00A9;</kb-key><kb-key>&#x00AE;</kb-key><kb-key>\</kb-key><kb-key>[</kb-key>
+ <kb-key class="microphone dark" char="Microphone" weight="150"></kb-key>
+ <kb-key>&#x00A3;</kb-key><kb-key>&#x00A2;</kb-key>
+ <kb-key>&#x20AC;</kb-key><kb-key>&#x2122;</kb-key>
+ <kb-key>&#x00A9;</kb-key><kb-key>&#x00AE;</kb-key>
+ <kb-key>\</kb-key><kb-key>[</kb-key>
<kb-key>]</kb-key>
- <kb-key class='return dark' char="&#x000A;" align="right">enter</kb-key>
+ <kb-key class="dark" char="&#x000A;" align="right"
+ weight="210">enter</kb-key>
</kb-row>
<kb-row>
- <kb-key class="left-more dark" toKeyset="down:symbol" char="Invalid" align="left">#123</kb-key>
- <kb-key>&#x00D7;</kb-key><kb-key>&#x00F7;</kb-key><kb-key>_</kb-key><kb-key>&#x00A7;</kb-key>
- <kb-key>&#x00B6;</kb-key><kb-key>&#x00A1;</kb-key><kb-key>&#x00BF;</kb-key><kb-key>&#x2022;</kb-key>
+ <kb-key class="dark" toKeyset="down:symbol" char="Invalid"
+ align="left" weight="180">#123</kb-key>
+ <kb-key>&#x00D7;</kb-key><kb-key>&#x00F7;</kb-key>
+ <kb-key>_</kb-key><kb-key>&#x00A7;</kb-key>
+ <kb-key>&#x00B6;</kb-key><kb-key>&#x00A1;</kb-key>
+ <kb-key>&#x00BF;</kb-key><kb-key>&#x2022;</kb-key>
<kb-key>&#x0394;</kb-key>
- <kb-key class="right-more dark" toKeyset="down:symbol" char="Invalid" align="right">#123</kb-key>
+ <kb-key class="dark" toKeyset="down:symbol" char="Invalid"
+ align="right" weight="180">#123</kb-key>
</kb-row>
<kb-row>
- <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="left">abc</kb-key>
+ <kb-abc-key align="left" weight="130">abc</kb-abc-key>
<kb-key-import importId="spacebar-row"></kb-key-import>
- <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid" align="right">abc</kb-key>
+ <kb-abc-key align="right" weight="130">abc</kb-abc-key>
<kb-hide-keyboard-key></kb-hide-keyboard-key>
</kb-row>
</kb-keyset>
diff --git a/chromium/ui/keyboard/resources/layouts/spacebar-row.html b/chromium/ui/keyboard/resources/layouts/spacebar-row.html
index db8bcca11c7..b4b0e8b4999 100644
--- a/chromium/ui/keyboard/resources/layouts/spacebar-row.html
+++ b/chromium/ui/keyboard/resources/layouts/spacebar-row.html
@@ -6,5 +6,5 @@
<template>
<kb-key class="dotcom dark" align="left">.com</kb-key>
- <kb-key char=" " class="space dark" weight="6.0"></kb-key>
+ <kb-key char=" " class="space dark" weight="800"></kb-key>
</template>
diff --git a/chromium/ui/keyboard/resources/layouts/system-qwerty.html b/chromium/ui/keyboard/resources/layouts/system-qwerty.html
new file mode 100644
index 00000000000..53bd3ae95d9
--- /dev/null
+++ b/chromium/ui/keyboard/resources/layouts/system-qwerty.html
@@ -0,0 +1,111 @@
+<!--
+ -- Copyright 2013 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.
+ -->
+
+<link id="spacebar-row" rel="import" href="spacebar-row.html">
+<link id="function-key-row" rel="import" href="function-key-row.html">
+
+<template>
+ <kb-keyset id="system-qwerty-upper">
+ <kb-row>
+ <kb-key-import importId="function-key-row"></kb-key-import>
+ </kb-row>
+ <kb-row>
+ <kb-key-sequence invert=true keys="'1234567890-="
+ hintTexts="~!@#$%^&*()_+"> </kb-key-sequence>
+ <kb-key class="dark" char="&#x0008;" repeat align="right"
+ weight="160">backspace</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="dark" char="&#x0009;" align="left"
+ weight="160">tab</kb-key>
+ <kb-key-sequence keys="QWERTYUIOP"></kb-key-sequence>
+ <kb-key-sequence invert=true keys="[]\"
+ hintTexts="{}|"></kb-key-sequence>
+ </kb-row>
+ <kb-row>
+ <kb-key class="microphone dark" char="Microphone" weight="150"></kb-key>
+ <kb-key-sequence keys="ASDFGHJKL"></kb-key-sequence>
+ <kb-key-sequence invert=true keys=";&apos;" hintTexts=':"'>
+ </kb-key-sequence>
+ <kb-key class="dark" char="&#x000A;" align="right"
+ weight="210">enter</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-shift-key weight="230" align="left">shift</kb-shift-key>
+ <kb-key-sequence keys="ZXCVBNM"></kb-key-sequence>
+ <kb-key-sequence invert=true keys=",./" hintTexts="<>?">
+ </kb-key-sequence>
+ <kb-shift-key weight="230" align="right">shift</kb-shift-key>
+ </kb-row>
+ <kb-row>
+ <kb-modifier-key class="dark" weight="150" char="Ctrl"
+ align="left">ctrl</kb-modifier-key>
+ <kb-modifier-key class="dark" weight="150" char="Alt"
+ align="left">alt</kb-modifier-key>
+ <kb-key char=" " class="space dark" weight="760"></kb-key>
+ <kb-key class="dark" repeat char="Arrow-Left" image="left"
+ weight="75"> </kb-key>
+ <kb-key class="dark" repeat char="Arrow-Up" image="up"
+ weight="75"></kb-key>
+ <kb-key class="dark" repeat char="Arrow-Down" image="down"
+ weight="75"> </kb-key>
+ <kb-key class="dark" repeat char="Arrow-Right" image="right"
+ weight="75"></kb-key>
+ <kb-hide-keyboard-key></kb-hide-keyboard-key>
+ </kb-row>
+ <kb-altkey-container hidden>
+ </kb-altkey-container>
+ </kb-keyset>
+
+ <kb-keyset id="system-qwerty-lower" isDefault=true>
+ <kb-row>
+ <kb-key-import importId="function-key-row"></kb-key-import>
+ </kb-row>
+ <kb-row>
+ <kb-key-sequence keys="'1234567890-=" hintTexts="~!@#$%^&*()_+">
+ </kb-key-sequence>
+ <kb-key class="dark" weight="160" char="&#x0008;"
+ repeat align="right">backspace</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-key class="dark" char="&#x0009;" align="left"
+ weight="160">tab</kb-key>
+ <kb-key-sequence keys="qwertyuiop"></kb-key-sequence>
+ <kb-key-sequence keys="[]\" hintTexts="{}|"></kb-key-sequence>
+ </kb-row>
+ <kb-row>
+ <kb-key class="microphone dark" char="Microphone" weight="150"></kb-key>
+ <kb-key-sequence keys="asdfghjkl"></kb-key-sequence>
+ <kb-key-sequence keys=";&apos;" hintTexts=':"'></kb-key-sequence>
+ <kb-key class="dark" char="&#x000A;" align="right"
+ weight="210">enter</kb-key>
+ </kb-row>
+ <kb-row>
+ <kb-shift-key weight="230" align="left">shift</kb-shift-key>
+ <kb-key-sequence keys="zxcvbnm"></kb-key-sequence>
+ <kb-key-sequence keys=",./" hintTexts="<>?"></kb-key-sequence>
+ <kb-shift-key weight="230" align="right">shift</kb-shift-key>
+ </kb-row>
+ <kb-row>
+ <kb-modifier-key class="symbol dark" weight="150" char="Ctrl"
+ align="left">ctrl</kb-modifier-key>
+ <kb-modifier-key class="symbol dark" weight="150" char="Alt"
+ align="left">alt</kb-modifier-key>
+ <kb-key char=" " class="space dark" weight="760"></kb-key>
+ <kb-key class="dark" repeat char="Arrow-Left" image="left"
+ weight="75"> </kb-key>
+ <kb-key class="dark" repeat char="Arrow-Up" image="up"
+ weight="75"></kb-key>
+ <kb-key class="dark" repeat char="Arrow-Down" image="down"
+ weight="75"> </kb-key>
+ <kb-key class="dark" repeat char="Arrow-Right" image="right"
+ weight="75"></kb-key>
+ <kb-hide-keyboard-key></kb-hide-keyboard-key>
+ </kb-row>
+ <kb-altkey-container hidden>
+ </kb-altkey-container>
+ </kb-keyset>
+</template> \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/layouts/webui_qwerty.html b/chromium/ui/keyboard/resources/layouts/webui_qwerty.html
index 0c5353f810f..2763307d708 100644
--- a/chromium/ui/keyboard/resources/layouts/webui_qwerty.html
+++ b/chromium/ui/keyboard/resources/layouts/webui_qwerty.html
@@ -84,7 +84,7 @@
<kb-key class="backspace padded-right-special dark" char="&#x0008;" repeat>delete</kb-key>
</kb-row>
<kb-row>
- <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid">abc</kb-key>
+ <kb-abc-key>abc</kb-abc-key>
<kb-key class="microphone dark" char="Microphone"></kb-key>
<kb-key class="dark">,</kb-key>
<kb-key class="space dark" char=" "></kb-key>
@@ -111,7 +111,7 @@
<kb-key class="backspace padded-right-special dark" char="&#x0008;" repeat>delete</kb-key>
</kb-row>
<kb-row>
- <kb-key class="symbol dark" toKeyset="down:lower" char="Invalid">abc</kb-key>
+ <kb-abc-key>abc</kb-abc-key>
<kb-key class="microphone dark" char="Microphone"></kb-key>
<kb-key class="dark">,</kb-key>
<kb-key class="space dark" char=" "></kb-key>
diff --git a/chromium/ui/keyboard/resources/main.css b/chromium/ui/keyboard/resources/main.css
index b0948afd95c..e2c672adc7e 100644
--- a/chromium/ui/keyboard/resources/main.css
+++ b/chromium/ui/keyboard/resources/main.css
@@ -21,52 +21,9 @@ kb-keyboard {
width: 1280px;
}
-kb-shift-key,
-kb-hide-keyboard-key,
-kb-layout-selector,
-kb-key {
- background-color: #3b3b3e;
- background-position: center center;
- background-repeat: no-repeat;
- background-size: contain;
- border-top: 2px solid #4b4b4e;
- border-radius: 2px;
- color: #ffffff;
- display: -webkit-box;
- font-family: 'Open Sans', 'Noto Sans UI', sans-serif;
- font-weight: 300;
- margin-left: 0.25em;
- position: relative;
-}
-
-kb-shift-key::x-key,
-kb-layout-selector::x-key,
-kb-key::x-key {
- bottom: 0;
- height: 1.2em;
- left: 0;
- margin: auto;
- padding-left: 0.7em;
- padding-right: 0.7em;
- position: absolute;
- right: 0;
- top: 0;
-}
-
-kb-key::x-hinttext {
- color: #7c7c7c;
- font-size: 70%;
- position: absolute;
- right: 7%;
- top: 5%;
-}
-
-kb-key::x-key[inverted] {
- color: #7c7c7c;
-}
-
-kb-key::x-hinttext[inverted] {
- color: #ffffff;
+kb-keyboard.ctrl-active kb-modifier-key[char=Ctrl],
+kb-keyboard.alt-active kb-modifier-key[char=Alt] {
+ color: lightblue;
}
/**
@@ -80,19 +37,10 @@ kb-keyboard:not(.caps-locked)[keyset=upper] kb-shift-key {
*.dark {
background-color: #2a2a2c;
border-top: 2px solid #3a3a3c;
+ font-size: 70%;
+ margin-left: 0.35em;
}
-/* TODO(stevet): We can probably share most of this with kb-key::x-key. */
-kb-altkey::x-key {
- bottom: 0;
- height: 1.2em;
- left: 0;
- margin: auto;
- position: absolute;
- right: 0;
- top: 0;
- text-align: center;
-}
.caps-locked kb-shift-key,
.active {
@@ -105,69 +53,15 @@ kb-altkey::x-key {
}
/**
- * TODO(kevers): Use weight attribute for kb-key rather than CSS rules to
- * enable special keys to be used for multiple layouts when the weights
- * need to vary.
+ * The microphone key is handled separately from other images since the image
+ * displayed changes depending on whether it's pressed or not.
*/
-.at,
-.com,
-.comma,
-.period,
-.tab {
- -webkit-box-flex: 1.3 !important;
-}
-
-.return {
- -webkit-box-flex: 2.1 !important;
-}
-
-.microphone {
- -webkit-box-flex: 1.5 !important;
-}
-
-.symbol {
- -webkit-box-flex: 1.25 !important;
-}
-
-.backspace {
- -webkit-box-flex: 1.7 !important;
-}
-
-.left-more {
- -webkit-box-flex: 1.8 !important;
-}
-
-.right-more {
- -webkit-box-flex: 1.8 !important;
-}
-
-.bar {
- -webkit-box-flex: 0.6 !important;
-}
-
-kb-shift-key.shift,
-kb-key:-webkit-any(.backspace,
- .dotcom,
- .left-more,
- .return,
- .symbol,
- .tab) {
- font-size: 70%;
- /* Adjust margin for consistent spacing with the smaller font size. */
- margin-left: 0.35em;
-}
-
.microphone {
background-image: url('images/microphone.svg');
background-position: 4%;
- background-size: 25%;
+ background-size: 25% !important;
}
.audio .microphone {
background-image: url('images/microphone-green.svg');
-}
-
-.hide-keyboard,
-.layout-selector {
- background-image: url('images/keyboard.svg');
-}
+} \ No newline at end of file
diff --git a/chromium/ui/keyboard/resources/main.js b/chromium/ui/keyboard/resources/main.js
index 0abc0f1368c..69975f6c95b 100644
--- a/chromium/ui/keyboard/resources/main.js
+++ b/chromium/ui/keyboard/resources/main.js
@@ -19,7 +19,7 @@ function importHTML(content) {
var dom = content.querySelector('template').createInstance();
var keyImports = dom.querySelectorAll('kb-key-import');
if (keyImports.length != 0) {
- keyImports.forEach(function(element) {
+ keyImports.array().forEach(function(element) {
if (element.importDoc(content)) {
var generatedDom = importHTML(element.importDoc(content));
element.parentNode.replaceChild(generatedDom, element);
@@ -36,7 +36,7 @@ function importHTML(content) {
function expandHTML(importedContent) {
var keySequences = importedContent.querySelectorAll('kb-key-sequence');
if (keySequences.length != 0) {
- keySequences.forEach(function(element) {
+ keySequences.array().forEach(function(element) {
var generatedDom = element.generateDom();
element.parentNode.replaceChild(generatedDom, element);
});
@@ -59,3 +59,9 @@ function flattenKeysets(content) {
addEventListener('resize', onResize);
addEventListener('load', onResize);
+
+// Prevents all default actions of touch. Keyboard should use its own gesture
+// recognizer.
+addEventListener('touchstart', function(e) { e.preventDefault() });
+addEventListener('touchend', function(e) { e.preventDefault() });
+addEventListener('touchmove', function(e) { e.preventDefault() });
diff --git a/chromium/ui/keyboard/resources/polymer.min.js b/chromium/ui/keyboard/resources/polymer.min.js
deleted file mode 100644
index 915f7d97510..00000000000
--- a/chromium/ui/keyboard/resources/polymer.min.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2013 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 src="../../../third_party/polymer/polymer.min.js"></include>
diff --git a/chromium/ui/keyboard/resources/polymer_loader.js b/chromium/ui/keyboard/resources/polymer_loader.js
new file mode 100644
index 00000000000..f39ea61fae2
--- /dev/null
+++ b/chromium/ui/keyboard/resources/polymer_loader.js
@@ -0,0 +1,11 @@
+// Copyright 2013 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.
+
+// This is necessary because polymer currently doesn't handle the configuration
+// where native Custom Elements are available but native Shadow DOM is not.
+// TODO(bshe): remove this line when polymer supports the configuration.
+document.register = undefined;
+
+<include src="../../../third_party/polymer/platform.js"></include>
+<include src="../../../third_party/polymer/polymer.js"></include>
diff --git a/chromium/ui/keyboard/resources/webui/api_adapter.js b/chromium/ui/keyboard/resources/webui/api_adapter.js
index 17d84b9d7c3..206f60dd8af 100644
--- a/chromium/ui/keyboard/resources/webui/api_adapter.js
+++ b/chromium/ui/keyboard/resources/webui/api_adapter.js
@@ -14,6 +14,10 @@ function hideKeyboard() {
chrome.send('hideKeyboard');
}
+function keyboardLoaded() {
+ chrome.send('keyboardLoaded');
+}
+
(function(exports) {
/**
* An array to save callbacks of each request.
@@ -34,7 +38,10 @@ function hideKeyboard() {
* "text" are supported.
*/
function OnTextInputBoxFocused(inputContext) {
- keyboard.inputType = inputContext.type;
+ // Do not want to use the system keyboard for passwords in webui.
+ if (inputContext.type == 'password')
+ inputContext.type = 'text';
+ keyboard.inputTypeValue = inputContext.type;
}
/**
diff --git a/chromium/ui/keyboard/resources/webui/main.css b/chromium/ui/keyboard/resources/webui/main.css
index 092abd26362..e14611d3d33 100644
--- a/chromium/ui/keyboard/resources/webui/main.css
+++ b/chromium/ui/keyboard/resources/webui/main.css
@@ -19,6 +19,7 @@ kb-keyboard {
display: -webkit-box;
}
+kb-abc-key,
kb-shift-key,
kb-key {
background-color: #3b3b3e;
@@ -35,6 +36,7 @@ kb-key {
position: relative;
}
+kb-abc-key::x-key,
kb-shift-key::x-key,
kb-key::x-key {
bottom: 0;
@@ -64,6 +66,7 @@ kb-key::x-hinttext[inverted] {
color: #ffffff;
}
+kb-abc-key.dark,
kb-shift-key.dark,
kb-key.dark {
background-color: #2a2a2c;
@@ -84,11 +87,13 @@ kb-altkey::x-key {
/* Left and right-side special keys with a character letter next to them need
* additional padding.
* */
+kb-abc-key.padded-left-special,
kb-shift-key.padded-left-special,
kb-key.padded-left-special {
margin-right: 2px;
}
+kb-abc-key.padded-right-special,
kb-shift-key.padded-right-special,
kb-key.padded-right-special {
margin-left: 5px;
diff --git a/chromium/ui/keyboard/resources/webui_index.html b/chromium/ui/keyboard/resources/webui_index.html
index 47ae8ed169b..bdc81167fc3 100644
--- a/chromium/ui/keyboard/resources/webui_index.html
+++ b/chromium/ui/keyboard/resources/webui_index.html
@@ -18,7 +18,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<link rel="stylesheet" href="main.css">
<script src="constants.js"></script>
- <script src="polymer.min.js"></script>
+ <script src="polymer_loader.js"></script>
<script src="api_adapter.js"></script>
<script src="voice_input.js"></script>
<link rel="import" href="elements/kb-altkey.html">