diff options
author | Andras Becsi <andras.becsi@digia.com> | 2014-03-18 13:16:26 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-03-20 15:55:39 +0100 |
commit | 3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch) | |
tree | 92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/ui/keyboard | |
parent | e90d7c4b152c56919d963987e2503f9909a666d2 (diff) | |
download | qtwebengine-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')
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, ¶ms) || !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="	" align="left">tab</kb-key> - <kb-key-sequence keys="",.PYFGCRL" hintTexts="1234567890"></kb-key-sequence> - <kb-key class="backspace dark" char="" repeat align="right">backspace</kb-key> + <kb-key class="dark" char="	" align="left" + weight="120">tab</kb-key> + <kb-key-sequence keys="",.PYFGCRL" hintTexts="1234567890"> + </kb-key-sequence> + <kb-key class="dark" char="" 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="
" align="right">enter</kb-key> + <kb-key class="dark" char="
" 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="	" align="left">tab</kb-key> - <kb-key-sequence keys="",.pyfgcrl" hintTexts="1234567890"></kb-key-sequence> - <kb-key class="backspace dark" char="" repeat align="right">backspace</kb-key> + <kb-key class="dark" char="	" align="left" + weight="120">tab</kb-key> + <kb-key-sequence keys="",.pyfgcrl" hintTexts="1234567890"> + </kb-key-sequence> + <kb-key class="dark" char="" 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="
" align="right">enter</kb-key> + <kb-key class="dark" char="
" 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="	" align="left">tab</kb-key> + <kb-key class="dark" char="	" align="left" + weight="120">tab</kb-key> <kb-key-sequence keys="1234567890"></kb-key-sequence> - <kb-key class="backspace dark" char="" repeat align="right">backspace</kb-key> + <kb-key class="dark" char="" 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="@#$%&*-=()"></kb-key-sequence> - <kb-key class='return dark' char="
" align="right">enter</kb-key> + <kb-key class="dark" char="
" 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="!"':;/?"></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="	" align="left">tab</kb-key> + <kb-key class="dark" char="	" 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><</kb-key><kb-key>></kb-key> - <kb-key class="backspace dark" char="" repeat align="right">backspace</kb-key> + <kb-key class="dark" char="" repeat align="right" + weight="140">backspace</kb-key> </kb-row> <kb-row> - <kb-key class="microphone dark" char="Microphone"></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="
" align="right">enter</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="dark" char="
" 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>×</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: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>×</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="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="	" align="left">tab</kb-key> - <kb-key-sequence keys="QWERTYUIOP" hintTexts="1234567890"></kb-key-sequence> - <kb-key class="backspace dark" char="" repeat align="right">backspace</kb-key> + <kb-key class="dark" char="	" align="left" + weight="120">tab</kb-key> + <kb-key-sequence keys="QWERTYUIOP" hintTexts="1234567890"> + </kb-key-sequence> + <kb-key class="dark" char="" 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="
" align="right">enter</kb-key> + <kb-key class="dark" char="
" 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="	" align="left">tab</kb-key> - <kb-key-sequence keys="qwertyuiop" hintTexts="1234567890"></kb-key-sequence> - <kb-key class="backspace dark" char="" repeat align="right">backspace</kb-key> + <kb-key class="dark" char="	" align="left" + weight="120">tab</kb-key> + <kb-key-sequence keys="qwertyuiop" hintTexts="1234567890"> + </kb-key-sequence> + <kb-key class="dark" char="" 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="
" align="right">enter</kb-key> + <kb-key class="dark" char="
" 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="	" align="left">tab</kb-key> + <kb-key class="dark" char="	" 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="" repeat align="right">backspace</kb-key> + <kb-key class="dark" char="" 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="
" align="right">enter</kb-key> + <kb-key class="dark" char="
" 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="	" align="left">tab</kb-key> + <kb-key class="dark" char="	" 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><</kb-key><kb-key>></kb-key> - <kb-key class="backspace dark" char="" repeat align="right">backspace</kb-key> + <kb-key class="dark" char="" repeat align="right" + weight="140">backspace</kb-key> </kb-row> <kb-row> - <kb-key class="microphone dark" char="Microphone"></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="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="
" align="right">enter</kb-key> + <kb-key class="dark" char="
" 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>×</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="dark" toKeyset="down:symbol" char="Invalid" + align="left" weight="180">#123</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: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="" repeat align="right" + weight="160">backspace</kb-key> + </kb-row> + <kb-row> + <kb-key class="dark" char="	" 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=";'" hintTexts=':"'> + </kb-key-sequence> + <kb-key class="dark" char="
" 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="" + repeat align="right">backspace</kb-key> + </kb-row> + <kb-row> + <kb-key class="dark" char="	" 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=";'" hintTexts=':"'></kb-key-sequence> + <kb-key class="dark" char="
" 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="" 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="" 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"> |