summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-25 19:28:31 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-25 19:28:31 +0000
commit1dfdc0b6586c4a4d2d0afc68222beb92c6dacfe8 (patch)
treeeb441c34709035408af02276536f94ca43f7a611
parentd1b2d9f5d437061a733ff4523a547fae7cd7464a (diff)
downloadchromium_src-1dfdc0b6586c4a4d2d0afc68222beb92c6dacfe8.zip
chromium_src-1dfdc0b6586c4a4d2d0afc68222beb92c6dacfe8.tar.gz
chromium_src-1dfdc0b6586c4a4d2d0afc68222beb92c6dacfe8.tar.bz2
Initial version of keyboard
Lots still to do: . never hides. . some buttons show nothing (backspace, enter...). BUG=384433 TEST=none R=ben@chromium.org Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=279769 Review URL: https://codereview.chromium.org/330883007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@279781 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--mojo/examples/browser/browser.cc67
-rw-r--r--mojo/examples/keyboard/DEPS10
-rw-r--r--mojo/examples/keyboard/keyboard.cc129
-rw-r--r--mojo/examples/keyboard/keyboard.mojom19
-rw-r--r--mojo/examples/keyboard/keyboard_delegate.h26
-rw-r--r--mojo/examples/keyboard/keyboard_view.cc251
-rw-r--r--mojo/examples/keyboard/keyboard_view.h102
-rw-r--r--mojo/examples/keyboard/keys.cc186
-rw-r--r--mojo/examples/keyboard/keys.h62
-rw-r--r--mojo/examples/window_manager/window_manager.cc136
-rw-r--r--mojo/examples/window_manager/window_manager.mojom11
-rw-r--r--mojo/mojo.gyp1
-rw-r--r--mojo/mojo_examples.gypi64
-rw-r--r--mojo/mojo_services.gypi1
-rw-r--r--mojo/services/public/cpp/input_events/input_events_type_converters.h6
-rw-r--r--mojo/services/public/cpp/input_events/lib/input_events_type_converters.cc6
-rw-r--r--mojo/views/native_widget_view_manager.cc3
-rw-r--r--mojo/views/native_widget_view_manager.h5
18 files changed, 1070 insertions, 15 deletions
diff --git a/mojo/examples/browser/browser.cc b/mojo/examples/browser/browser.cc
index 7c39da8..fed88b5 100644
--- a/mojo/examples/browser/browser.cc
+++ b/mojo/examples/browser/browser.cc
@@ -5,7 +5,9 @@
#include "base/basictypes.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "mojo/examples/window_manager/window_manager.mojom.h"
#include "mojo/public/cpp/application/application.h"
+#include "mojo/services/public/cpp/geometry/geometry_type_converters.h"
#include "mojo/services/public/cpp/view_manager/node.h"
#include "mojo/services/public/cpp/view_manager/view.h"
#include "mojo/services/public/cpp/view_manager/view_manager.h"
@@ -18,9 +20,11 @@
#include "ui/events/event.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/textfield/textfield_controller.h"
+#include "ui/views/focus/focus_manager.h"
#include "ui/views/layout/layout_manager.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
+#include "ui/views/widget/widget_observer.h"
#include "url/gurl.h"
namespace mojo {
@@ -47,6 +51,65 @@ class BrowserLayoutManager : public views::LayoutManager {
DISALLOW_COPY_AND_ASSIGN(BrowserLayoutManager);
};
+// KeyboardManager handles notifying the windowmanager when views are focused.
+// To use create one and KeyboardManager will take care of all other details.
+//
+// TODO(sky): it would be nice if this were put in NativeWidgetViewManager, but
+// that requires NativeWidgetViewManager to take an IWindowManager. That may be
+// desirable anyway...
+class KeyboardManager : public views::FocusChangeListener,
+ public views::WidgetObserver {
+ public:
+ KeyboardManager(views::Widget* widget,
+ IWindowManager* window_manager,
+ view_manager::Node* node)
+ : widget_(widget),
+ window_manager_(window_manager),
+ node_(node),
+ last_view_id_(0) {
+ widget_->AddObserver(this);
+ widget_->GetFocusManager()->AddFocusChangeListener(this);
+ }
+
+ private:
+ virtual ~KeyboardManager() {
+ widget_->GetFocusManager()->RemoveFocusChangeListener(this);
+ widget_->RemoveObserver(this);
+ }
+
+ // views::FocusChangeListener:
+ virtual void OnWillChangeFocus(views::View* focused_before,
+ views::View* focused_now) OVERRIDE {
+ }
+ virtual void OnDidChangeFocus(views::View* focused_before,
+ views::View* focused_now) OVERRIDE {
+ if (focused_now &&
+ focused_now->GetClassName() == views::Textfield::kViewClassName) {
+ const gfx::Rect bounds_in_widget =
+ focused_now->ConvertRectToWidget(
+ gfx::Rect(focused_now->bounds().size()));
+ last_view_id_ = node_->active_view()->id();
+ window_manager_->ShowKeyboard(last_view_id_,
+ Rect::From(bounds_in_widget));
+ } else {
+ window_manager_->HideKeyboard(last_view_id_);
+ last_view_id_ = 0;
+ }
+ }
+
+ // views::WidgetObserver:
+ virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE {
+ delete this;
+ }
+
+ views::Widget* widget_;
+ IWindowManager* window_manager_;
+ view_manager::Node* node_;
+ view_manager::Id last_view_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyboardManager);
+};
+
// This is the basics of creating a views widget with a textfield.
// TODO: cleanup!
class Browser : public Application,
@@ -65,6 +128,7 @@ class Browser : public Application,
views_init_.reset(new ViewsInit);
view_manager::ViewManager::Create(this, this);
ConnectTo("mojo:mojo_window_manager", &navigator_host_);
+ ConnectTo("mojo:mojo_window_manager", &window_manager_);
}
void CreateWidget(view_manager::Node* node) {
@@ -83,6 +147,8 @@ class Browser : public Application,
params.delegate = widget_delegate;
params.bounds = gfx::Rect(node->bounds().width(), node->bounds().height());
widget_->Init(params);
+ // KeyboardManager handles deleting itself when the widget is destroyed.
+ new KeyboardManager(widget_, window_manager_.get(), node);
widget_->Show();
textfield->RequestFocus();
}
@@ -132,6 +198,7 @@ class Browser : public Application,
view_manager::Node* root_;
views::Widget* widget_;
navigation::NavigatorHostPtr navigator_host_;
+ IWindowManagerPtr window_manager_;
DISALLOW_COPY_AND_ASSIGN(Browser);
};
diff --git a/mojo/examples/keyboard/DEPS b/mojo/examples/keyboard/DEPS
new file mode 100644
index 0000000..b65676e
--- /dev/null
+++ b/mojo/examples/keyboard/DEPS
@@ -0,0 +1,10 @@
+include_rules = [
+ "+cc",
+ "+skia/ext",
+ "+ui/aura",
+ "+ui/base/hit_test.h",
+ "+ui/compositor",
+ "+ui/events",
+ "+ui/gfx",
+ "+ui/views",
+]
diff --git a/mojo/examples/keyboard/keyboard.cc b/mojo/examples/keyboard/keyboard.cc
new file mode 100644
index 0000000..ae6d8c9
--- /dev/null
+++ b/mojo/examples/keyboard/keyboard.cc
@@ -0,0 +1,129 @@
+// Copyright 2014 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/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "mojo/examples/keyboard/keyboard.mojom.h"
+#include "mojo/examples/keyboard/keyboard_delegate.h"
+#include "mojo/examples/keyboard/keyboard_view.h"
+#include "mojo/public/cpp/application/application.h"
+#include "mojo/services/public/cpp/view_manager/node.h"
+#include "mojo/services/public/cpp/view_manager/view.h"
+#include "mojo/services/public/cpp/view_manager/view_manager.h"
+#include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
+#include "mojo/services/public/cpp/view_manager/view_observer.h"
+#include "mojo/services/public/interfaces/navigation/navigation.mojom.h"
+#include "mojo/views/native_widget_view_manager.h"
+#include "mojo/views/views_init.h"
+#include "ui/events/event.h"
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
+#include "url/gurl.h"
+
+using mojo::view_manager::Id;
+
+namespace mojo {
+namespace examples {
+
+class Keyboard;
+
+class KeyboardServiceImpl : public InterfaceImpl<KeyboardService> {
+ public:
+ KeyboardServiceImpl(Keyboard* keyboard);
+ virtual ~KeyboardServiceImpl() {}
+
+ // KeyboardService:
+ virtual void SetTarget(uint32_t node_id) OVERRIDE;
+
+ private:
+ Keyboard* keyboard_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyboardServiceImpl);
+};
+
+class Keyboard : public Application,
+ public view_manager::ViewManagerDelegate,
+ public KeyboardDelegate {
+ public:
+ Keyboard() : view_manager_(NULL), keyboard_service_(NULL), target_(0) {}
+
+ virtual ~Keyboard() {
+ }
+
+ void set_target(Id id) { target_ = id; }
+
+ void set_keyboard_service(KeyboardServiceImpl* keyboard) {
+ keyboard_service_ = keyboard;
+ }
+
+ private:
+ // Overridden from Application:
+ virtual void Initialize() MOJO_OVERRIDE {
+ views_init_.reset(new ViewsInit);
+ view_manager::ViewManager::Create(this, this);
+ AddService<KeyboardServiceImpl>(this);
+ }
+
+ void CreateWidget(view_manager::Node* node) {
+ views::WidgetDelegateView* widget_delegate = new views::WidgetDelegateView;
+ widget_delegate->GetContentsView()->AddChildView(new KeyboardView(this));
+ widget_delegate->GetContentsView()->SetLayoutManager(new views::FillLayout);
+
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params(
+ views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+ params.native_widget = new NativeWidgetViewManager(widget, node);
+ params.delegate = widget_delegate;
+ params.bounds = gfx::Rect(node->bounds().width(), node->bounds().height());
+ widget->Init(params);
+ widget->Show();
+ }
+
+ // view_manager::ViewManagerDelegate:
+ virtual void OnRootAdded(view_manager::ViewManager* view_manager,
+ view_manager::Node* root) OVERRIDE {
+ // TODO: deal with OnRootAdded() being invoked multiple times.
+ view_manager_ = view_manager;
+ root->SetActiveView(view_manager::View::Create(view_manager));
+ CreateWidget(root);
+ }
+
+ // KeyboardDelegate:
+ virtual void OnKeyPressed(int key_code, int event_flags) OVERRIDE {
+ if (!target_)
+ return;
+ keyboard_service_->client()->OnKeyboardEvent(target_, key_code,
+ event_flags);
+ }
+
+ scoped_ptr<ViewsInit> views_init_;
+
+ view_manager::ViewManager* view_manager_;
+
+ KeyboardServiceImpl* keyboard_service_;
+
+ Id target_;
+
+ DISALLOW_COPY_AND_ASSIGN(Keyboard);
+};
+
+KeyboardServiceImpl::KeyboardServiceImpl(Keyboard* keyboard)
+ : keyboard_(keyboard) {
+ keyboard_->set_keyboard_service(this);
+}
+
+void KeyboardServiceImpl::SetTarget(uint32_t node_id) {
+ keyboard_->set_target(node_id);
+}
+
+} // namespace examples
+
+// static
+Application* Application::Create() {
+ return new examples::Keyboard;
+}
+
+} // namespace mojo
diff --git a/mojo/examples/keyboard/keyboard.mojom b/mojo/examples/keyboard/keyboard.mojom
new file mode 100644
index 0000000..9377898
--- /dev/null
+++ b/mojo/examples/keyboard/keyboard.mojom
@@ -0,0 +1,19 @@
+// Copyright 2014 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.
+
+module mojo {
+
+[Client=KeyboardClient]
+interface KeyboardService {
+ // Sets the view keyboard events are to go to.
+ SetTarget(uint32 view_id);
+};
+
+interface KeyboardClient {
+ // Invoked when the user interacts with the keyboard. |code| is a key code
+ // |flags| is a bitmask of ui::EventFlags.
+ OnKeyboardEvent(uint32 view_id, int32 code, int32 flags);
+};
+
+}
diff --git a/mojo/examples/keyboard/keyboard_delegate.h b/mojo/examples/keyboard/keyboard_delegate.h
new file mode 100644
index 0000000..bf35fc6
--- /dev/null
+++ b/mojo/examples/keyboard/keyboard_delegate.h
@@ -0,0 +1,26 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_EXAMPLES_KEYBOARD_KEYBOARD_DELEGATE_H_
+#define MOJO_EXAMPLES_KEYBOARD_KEYBOARD_DELEGATE_H_
+
+#include "base/basictypes.h"
+
+namespace mojo {
+namespace examples {
+
+class KeyboardDelegate {
+ public:
+ KeyboardDelegate() {}
+
+ virtual void OnKeyPressed(int key_code, int event_flags) = 0;
+
+ protected:
+ virtual ~KeyboardDelegate() {}
+};
+
+} // namespace examples
+} // namespace mojo
+
+#endif // MOJO_EXAMPLES_KEYBOARD_KEYBOARD_DELEGATE_H_
diff --git a/mojo/examples/keyboard/keyboard_view.cc b/mojo/examples/keyboard/keyboard_view.cc
new file mode 100644
index 0000000..4dfeecb
--- /dev/null
+++ b/mojo/examples/keyboard/keyboard_view.cc
@@ -0,0 +1,251 @@
+// Copyright 2014 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 "mojo/examples/keyboard/keyboard_view.h"
+
+#include <algorithm>
+
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "mojo/examples/keyboard/keyboard_delegate.h"
+#include "mojo/examples/keyboard/keys.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/gfx/canvas.h"
+#include "ui/views/background.h"
+#include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/button/label_button_border.h"
+
+namespace mojo {
+namespace examples {
+
+namespace {
+
+const int kHorizontalPadding = 6;
+const int kVerticalPadding = 8;
+
+base::string16 GetDisplayString(int key_code, int flags) {
+ return base::string16(1, ui::GetCharacterFromKeyCode(
+ static_cast<ui::KeyboardCode>(key_code), flags));
+}
+
+// Returns a font that fits in the space provided. |text| is used as a basis
+// for determing the size.
+gfx::FontList CalculateFont(int width, int height, const base::string16& text) {
+ gfx::FontList font;
+ gfx::FontList last_font;
+ while (gfx::Canvas::GetStringWidth(text, font) < width &&
+ font.GetHeight() < height) {
+ last_font = font;
+ font = font.DeriveWithSizeDelta(2);
+ }
+ return last_font;
+}
+
+// Returns the total number of keys in |rows|.
+int NumKeys(const std::vector<const Row*>& rows) {
+ int result = 0;
+ for (size_t i = 0; i < rows.size(); ++i)
+ result += static_cast<int>(rows[i]->num_keys);
+ return result;
+}
+
+} // namespace
+
+KeyboardView::KeyboardView(KeyboardDelegate* delegate)
+ : delegate_(delegate),
+ max_keys_in_row_(0),
+ keyboard_layout_(KEYBOARD_LAYOUT_ALPHA) {
+ set_background(views::Background::CreateSolidBackground(SK_ColorBLACK));
+ SetRows(GetQWERTYRows());
+}
+
+KeyboardView::~KeyboardView() {
+}
+
+void KeyboardView::Layout() {
+ if (width() == 0 || height() == 0 || rows_.empty() ||
+ last_layout_size_ == bounds().size())
+ return;
+
+ last_layout_size_ = bounds().size();
+
+ const int button_width =
+ (width() - (max_keys_in_row_ - 1) * kHorizontalPadding) /
+ max_keys_in_row_;
+ const int button_height =
+ (height() - (static_cast<int>(rows_.size() - 1) * kVerticalPadding)) /
+ static_cast<int>(rows_.size());
+ for (size_t i = 0; i < rows_.size(); ++i)
+ LayoutRow(*(rows_[i]), static_cast<int>(i), button_width, button_height);
+
+ views::LabelButtonBorder border(views::Button::STYLE_TEXTBUTTON);
+ gfx::Insets insets(border.GetInsets());
+ gfx::FontList font = CalculateFont(button_width - insets.width(),
+ button_height - insets.height(),
+ base::ASCIIToUTF16("W"));
+ gfx::FontList special_font = CalculateFont(button_width - insets.width(),
+ button_height - insets.height(),
+ base::ASCIIToUTF16("?123"));
+ button_font_ = font;
+ ResetFonts(font, special_font);
+}
+
+void KeyboardView::SetLayout(KeyboardLayout keyboard_layout) {
+ if (keyboard_layout_ == keyboard_layout)
+ return;
+
+ keyboard_layout_ = keyboard_layout;
+ last_layout_size_ = gfx::Size();
+ if (keyboard_layout_ == KEYBOARD_LAYOUT_NUMERIC)
+ SetRows(GetNumericRows());
+ else
+ SetRows(GetQWERTYRows());
+ Layout();
+ SchedulePaint();
+}
+
+void KeyboardView::LayoutRow(const Row& row,
+ int row_index,
+ int button_width,
+ int button_height) {
+ int x = row.padding * (button_width + kHorizontalPadding);
+ const int y = row_index * (button_height + kVerticalPadding);
+ for (size_t i = 0; i < row.num_keys; ++i) {
+ views::View* button = GetButton(row_index, static_cast<int>(i));
+ int actual_width = button_width;
+ if (row.keys[i].size > 1) {
+ actual_width = (button_width + kHorizontalPadding) *
+ row.keys[i].size - kHorizontalPadding;
+ }
+ button->SetBounds(x, y, actual_width, button_height);
+ x += actual_width + kHorizontalPadding;
+ }
+}
+
+void KeyboardView::SetRows(const std::vector<const Row*>& rows) {
+ const int num_keys = NumKeys(rows);
+ while (child_count() > num_keys)
+ delete child_at(child_count() - 1);
+ for (int i = child_count(); i < num_keys; ++i)
+ AddChildView(CreateButton());
+
+ last_layout_size_ = gfx::Size();
+
+ rows_ = rows;
+
+ max_keys_in_row_ = 0;
+ for (size_t i = 0; i < rows_.size(); ++i) {
+ max_keys_in_row_ = std::max(max_keys_in_row_,
+ static_cast<int>(rows_[i]->num_keys));
+ ConfigureButtonsInRow(static_cast<int>(i), *rows_[i]);
+ }
+}
+
+void KeyboardView::ConfigureButtonsInRow(int row_index, const Row& row) {
+ for (size_t i = 0; i < row.num_keys; ++i) {
+ views::LabelButton* button = GetButton(row_index, static_cast<int>(i));
+ const Key& key(row.keys[i]);
+ switch (key.display_code) {
+ case SPECIAL_KEY_SHIFT:
+ // TODO: need image.
+ button->SetText(base::string16());
+ break;
+ case SPECIAL_KEY_NUMERIC:
+ button->SetText(base::ASCIIToUTF16("?123"));
+ break;
+ case SPECIAL_KEY_ALPHA:
+ button->SetText(base::ASCIIToUTF16("ABC"));
+ break;
+ default:
+ button->SetText(GetDisplayString(key.display_code,
+ key.event_flags | event_flags()));
+ break;
+ }
+ button->SetState(views::Button::STATE_NORMAL);
+ }
+}
+
+views::View* KeyboardView::CreateButton() {
+ views::LabelButton* button = new views::LabelButton(this, base::string16());
+ button->SetTextColor(views::Button::STATE_NORMAL, SK_ColorWHITE);
+ button->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+ button->set_background(views::Background::CreateSolidBackground(78, 78, 78));
+ button->SetFontList(button_font_);
+ // button->SetHaloColor(SK_ColorBLACK);
+ // Turn off animations as we reuse buttons in different layouts. If we didn't
+ // do this and you click a button to change the layout then the button you
+ // clicked on would animate the transition even though it may now represent a
+ // different key.
+ button->SetAnimationDuration(0);
+ return button;
+}
+
+views::LabelButton* KeyboardView::GetButton(int row, int column) {
+ int offset = column;
+ for (int i = 0; i < row; ++i)
+ offset += static_cast<int>(rows_[i]->num_keys);
+ return static_cast<views::LabelButton*>(child_at(offset));
+}
+
+const Key& KeyboardView::GetKeyForButton(views::Button* button) const {
+ int index = GetIndexOf(button);
+ DCHECK_NE(-1, index);
+ int row = 0;
+ while (index >= static_cast<int>(rows_[row]->num_keys)) {
+ index -= static_cast<int>(rows_[row]->num_keys);
+ row++;
+ }
+ return rows_[row]->keys[index];
+}
+
+void KeyboardView::ResetFonts(const gfx::FontList& button_font,
+ const gfx::FontList& special_font) {
+ for (size_t i = 0; i < rows_.size(); ++i) {
+ for (size_t j = 0; j < rows_[i]->num_keys; ++j) {
+ views::LabelButton* button = GetButton(static_cast<int>(i),
+ static_cast<int>(j));
+ const Key& key(GetKeyForButton(button));
+ switch (key.display_code) {
+ case SPECIAL_KEY_ALPHA:
+ case SPECIAL_KEY_NUMERIC:
+ button->SetFontList(special_font);
+ break;
+ default:
+ button->SetFontList(button_font);
+ break;
+ }
+ }
+ }
+}
+
+void KeyboardView::ButtonPressed(views::Button* sender,
+ const ui::Event& event) {
+ const Key& key(GetKeyForButton(sender));
+ switch (key.display_code) {
+ case SPECIAL_KEY_SHIFT:
+ SetLayout((keyboard_layout_ == KEYBOARD_LAYOUT_SHIFT) ?
+ KEYBOARD_LAYOUT_ALPHA : KEYBOARD_LAYOUT_SHIFT);
+ return;
+ case SPECIAL_KEY_ALPHA:
+ SetLayout(KEYBOARD_LAYOUT_ALPHA);
+ return;
+ case SPECIAL_KEY_NUMERIC:
+ SetLayout(KEYBOARD_LAYOUT_NUMERIC);
+ return;
+ default:
+ break;
+ }
+
+ // Windows isn't happy if we pass in the flags used to get the display string.
+#if defined(OS_WIN)
+ int key_event_flags = 0;
+#else
+ int key_event_flags = key.event_flags;
+#endif
+ delegate_->OnKeyPressed(key.keyboard_code(), key_event_flags | event_flags());
+}
+
+} // namespace examples
+} // namespace mojo
diff --git a/mojo/examples/keyboard/keyboard_view.h b/mojo/examples/keyboard/keyboard_view.h
new file mode 100644
index 0000000..36c6b42
--- /dev/null
+++ b/mojo/examples/keyboard/keyboard_view.h
@@ -0,0 +1,102 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_EXAMPLES_KEYBOARD_KEYBOARD_VIEW_H_
+#define MOJO_EXAMPLES_KEYBOARD_KEYBOARD_VIEW_H_
+
+#include <vector>
+
+#include "ui/gfx/font_list.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/view.h"
+
+namespace views {
+class LabelButton;
+}
+
+namespace mojo {
+namespace examples {
+
+class KeyboardDelegate;
+struct Key;
+struct Row;
+
+// Shows a keyboard the user can interact with. The delegate is notified any
+// time the user presses a button.
+class KeyboardView : public views::View, public views::ButtonListener {
+ public:
+ explicit KeyboardView(KeyboardDelegate* delegate);
+ virtual ~KeyboardView();
+
+ // views::View:
+ virtual void Layout() OVERRIDE;
+
+ private:
+ // The type of keys that are shown.
+ enum KeyboardLayout {
+ KEYBOARD_LAYOUT_ALPHA,
+
+ // Uppercase characters.
+ KEYBOARD_LAYOUT_SHIFT,
+
+ // Numeric characters.
+ KEYBOARD_LAYOUT_NUMERIC,
+ };
+
+ int event_flags() const {
+ return (keyboard_layout_ == KEYBOARD_LAYOUT_SHIFT) ?
+ ui::EF_SHIFT_DOWN : ui::EF_NONE;
+ }
+
+ void SetLayout(KeyboardLayout layout);
+
+ // Lays out the buttons for the specified row.
+ void LayoutRow(const Row& row,
+ int row_index,
+ int button_width,
+ int button_height);
+
+ // Sets the rows to show.
+ void SetRows(const std::vector<const Row*>& rows);
+
+ // Configures the button in a row.
+ void ConfigureButtonsInRow(int row_index, const Row& row);
+
+ // Creates a new button.
+ views::View* CreateButton();
+
+ // Returns the button corresponding to a key at the specified row/column.
+ views::LabelButton* GetButton(int row, int column);
+
+ const Key& GetKeyForButton(views::Button* button) const;
+
+ // Reset the fonts of all the buttons. |special_font| is used for the buttons
+ // that toggle the layout.
+ void ResetFonts(const gfx::FontList& button_font,
+ const gfx::FontList& special_font);
+
+ // views::ButtonListener:
+ virtual void ButtonPressed(views::Button* sender,
+ const ui::Event& event) OVERRIDE;
+
+ KeyboardDelegate* delegate_;
+
+ // Maximium number of keys in a row. Determined from |rows_|.
+ int max_keys_in_row_;
+
+ KeyboardLayout keyboard_layout_;
+
+ std::vector<const Row*> rows_;
+
+ gfx::Size last_layout_size_;
+
+ gfx::FontList button_font_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyboardView);
+};
+
+} // namespace examples
+} // namespace mojo
+
+#endif // MOJO_EXAMPLES_KEYBOARD_KEYBOARD_VIEW_H_
diff --git a/mojo/examples/keyboard/keys.cc b/mojo/examples/keyboard/keys.cc
new file mode 100644
index 0000000..adf9094
--- /dev/null
+++ b/mojo/examples/keyboard/keys.cc
@@ -0,0 +1,186 @@
+// Copyright 2014 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 "mojo/examples/keyboard/keys.h"
+
+#include "base/macros.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+namespace mojo {
+namespace examples {
+namespace {
+
+const Key kQWERTYKeysRow1[] =
+{
+ { ui::VKEY_Q, 1, 0, 'q' },
+ { ui::VKEY_W, 1, 0, 'w' },
+ { ui::VKEY_E, 1, 0, 'e' },
+ { ui::VKEY_R, 1, 0, 'r' },
+ { ui::VKEY_T, 1, 0, 't' },
+ { ui::VKEY_Y, 1, 0, 'y' },
+ { ui::VKEY_U, 1, 0, 'u' },
+ { ui::VKEY_I, 1, 0, 'i' },
+ { ui::VKEY_O, 1, 0, 'o' },
+ { ui::VKEY_P, 1, 0, 'p' },
+};
+
+const Key kQWERTYKeysRow2[] =
+{
+ { ui::VKEY_A, 1, 0, 'a' },
+ { ui::VKEY_S, 1, 0, 's' },
+ { ui::VKEY_D, 1, 0, 'd' },
+ { ui::VKEY_F, 1, 0, 'f' },
+ { ui::VKEY_G, 1, 0, 'g' },
+ { ui::VKEY_H, 1, 0, 'h' },
+ { ui::VKEY_J, 1, 0, 'j' },
+ { ui::VKEY_K, 1, 0, 'k' },
+ { ui::VKEY_L, 1, 0, 'l' },
+};
+
+const Key kQWERTYKeysRow3[] =
+{
+ { SPECIAL_KEY_SHIFT, 1.5, 0, 0 },
+ { ui::VKEY_Z, 1, 0, 'z' },
+ { ui::VKEY_X, 1, 0, 'x' },
+ { ui::VKEY_C, 1, 0, 'c' },
+ { ui::VKEY_V, 1, 0, 'v' },
+ { ui::VKEY_B, 1, 0, 'b' },
+ { ui::VKEY_N, 1, 0, 'n' },
+ { ui::VKEY_M, 1, 0, 'm' },
+ { ui::VKEY_BACK, 1.5, 0, 0 },
+};
+
+const Key kQWERTYKeysRow4[] =
+{
+ { SPECIAL_KEY_NUMERIC, 1.5, 0, 0 },
+ { ui::VKEY_DIVIDE, 1, 0, '/' },
+ { ui::VKEY_SPACE, 5, 0, ' ' },
+ { ui::VKEY_DECIMAL, 1, 0, '.' },
+ { ui::VKEY_RETURN, 1.5, 0, 0 },
+};
+
+const Row kQWERTYRow1 = {
+ 0,
+ kQWERTYKeysRow1,
+ arraysize(kQWERTYKeysRow1),
+};
+
+const Row kQWERTYRow2 = {
+ .5,
+ kQWERTYKeysRow2,
+ arraysize(kQWERTYKeysRow2),
+};
+
+const Row kQWERTYRow3 = {
+ 0,
+ kQWERTYKeysRow3,
+ arraysize(kQWERTYKeysRow3),
+};
+
+const Row kQWERTYRow4 = {
+ 0,
+ kQWERTYKeysRow4,
+ arraysize(kQWERTYKeysRow4),
+};
+
+const Key kNumericKeysRow1[] =
+{
+ { ui::VKEY_1, 1, 0, 0 },
+ { ui::VKEY_2, 1, 0, 0 },
+ { ui::VKEY_3, 1, 0, 0 },
+ { ui::VKEY_4, 1, 0, 0 },
+ { ui::VKEY_5, 1, 0, 0 },
+ { ui::VKEY_6, 1, 0, 0 },
+ { ui::VKEY_7, 1, 0, 0 },
+ { ui::VKEY_8, 1, 0, 0 },
+ { ui::VKEY_9, 1, 0, 0 },
+ { ui::VKEY_0, 1, 0, 0 },
+};
+
+const Key kNumericKeysRow2[] =
+{
+ // @#$%&-+()
+ { ui::VKEY_2, 1, ui::EF_SHIFT_DOWN, '@' },
+ { ui::VKEY_3, 1, ui::EF_SHIFT_DOWN, '#' },
+ { ui::VKEY_4, 1, ui::EF_SHIFT_DOWN, '$' },
+ { ui::VKEY_5, 1, ui::EF_SHIFT_DOWN, '%' },
+ { ui::VKEY_7, 1, ui::EF_SHIFT_DOWN, '&' },
+ { ui::VKEY_SUBTRACT, 1, 0, '-' },
+ { ui::VKEY_ADD, 1, 0, '+' },
+ { ui::VKEY_9, 1, ui::EF_SHIFT_DOWN, '(' },
+ { ui::VKEY_0, 1, ui::EF_SHIFT_DOWN, ')' },
+};
+
+const Key kNumericKeysRow3[] =
+{
+ // *"':;!? backspace
+ { ui::VKEY_MULTIPLY, 1, 0, '*' },
+ { ui::VKEY_OEM_7, 1, ui::EF_SHIFT_DOWN, '"' },
+ { ui::VKEY_OEM_7, 1, 0, '\'' },
+ { ui::VKEY_OEM_1, 1, ui::EF_SHIFT_DOWN, ':' },
+ { ui::VKEY_OEM_1, 1, 0, ';' },
+ { ui::VKEY_1, 1, ui::EF_SHIFT_DOWN, '!' },
+ { ui::VKEY_OEM_2, 1, ui::EF_SHIFT_DOWN, '?' },
+ { ui::VKEY_BACK, 1.5, 0, 0 },
+};
+
+const Key kNumericKeysRow4[] =
+{
+ // ABC _ / space (3) ,.enter
+ { SPECIAL_KEY_ALPHA, 1.5, 0, 0 },
+ { ui::VKEY_OEM_MINUS, 1, ui::EF_SHIFT_DOWN, '_' },
+ { ui::VKEY_OEM_2, 1, 0, '/' },
+ { ui::VKEY_SPACE, 3, 0, ' ' },
+ { ui::VKEY_OEM_COMMA, 1, 0, ',' },
+ { ui::VKEY_OEM_PERIOD, 1, 0, '.' },
+ { ui::VKEY_RETURN, 1.5, 0, 0 },
+};
+
+const Row kNumericRow1 = {
+ 0,
+ kNumericKeysRow1,
+ arraysize(kNumericKeysRow1),
+};
+
+const Row kNumericRow2 = {
+ .5,
+ kNumericKeysRow2,
+ arraysize(kNumericKeysRow2),
+};
+
+const Row kNumericRow3 = {
+ 1.5,
+ kNumericKeysRow3,
+ arraysize(kNumericKeysRow3),
+};
+
+const Row kNumericRow4 = {
+ 0,
+ kNumericKeysRow4,
+ arraysize(kNumericKeysRow4),
+};
+
+} // namespace
+
+std::vector<const Row*> GetQWERTYRows() {
+ std::vector<const Row*> rows;
+ rows.push_back(&kQWERTYRow1);
+ rows.push_back(&kQWERTYRow2);
+ rows.push_back(&kQWERTYRow3);
+ rows.push_back(&kQWERTYRow4);
+ return rows;
+}
+
+std::vector<const Row*> GetNumericRows() {
+ std::vector<const Row*> rows;
+ rows.push_back(&kNumericRow1);
+ rows.push_back(&kNumericRow2);
+ rows.push_back(&kNumericRow3);
+ rows.push_back(&kNumericRow4);
+ return rows;
+}
+
+} // namespace examples
+} // namespace mojo
diff --git a/mojo/examples/keyboard/keys.h b/mojo/examples/keyboard/keys.h
new file mode 100644
index 0000000..c09f856
--- /dev/null
+++ b/mojo/examples/keyboard/keys.h
@@ -0,0 +1,62 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_EXAMPLES_KEYBOARD_KEYS_H_
+#define MOJO_EXAMPLES_KEYBOARD_KEYS_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+
+namespace mojo {
+namespace examples {
+
+enum SpecialKey {
+ SPECIAL_KEY_SHIFT = -1,
+ SPECIAL_KEY_NUMERIC = -2,
+ SPECIAL_KEY_ALPHA = -3,
+};
+
+struct Key {
+ int keyboard_code() const {
+ // Handling of keycodes differs between in windows and others.
+#if defined(OS_WIN)
+ return generated_code ? generated_code : display_code;
+#else
+ return display_code;
+#endif
+ }
+
+ // Code used to get the value to display in the UI. This is either a
+ // KeyboardCode or a SpecialKey.
+ int display_code;
+
+ // How much space (as a percentage) the key is to take up.
+ float size;
+
+ // Any ui::EventFlags that are required to produce the key.
+ int event_flags;
+
+ // If non-zero KeyboardCode to generate. If 0 use the |display_code|.
+ int generated_code;
+};
+
+struct Row {
+ float padding;
+ const Key* keys;
+ size_t num_keys;
+};
+
+// Returns the rows for a qwerty style keyboard. The returned values are owned
+// by this object and should not be deleted.
+std::vector<const Row*> GetQWERTYRows();
+
+// Returns the rows for a numeric keyboard. The returned values are owned
+// by this object and should not be deleted.
+std::vector<const Row*> GetNumericRows();
+
+} // namespace examples
+} // namespace mojo
+
+#endif // MOJO_EXAMPLES_KEYBOARD_KEYS_H_
diff --git a/mojo/examples/window_manager/window_manager.cc b/mojo/examples/window_manager/window_manager.cc
index 201af4c..28178ba 100644
--- a/mojo/examples/window_manager/window_manager.cc
+++ b/mojo/examples/window_manager/window_manager.cc
@@ -5,8 +5,11 @@
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/strings/stringprintf.h"
+#include "mojo/examples/keyboard/keyboard.mojom.h"
#include "mojo/examples/window_manager/window_manager.mojom.h"
#include "mojo/public/cpp/application/application.h"
+#include "mojo/services/public/cpp/geometry/geometry_type_converters.h"
+#include "mojo/services/public/cpp/input_events/input_events_type_converters.h"
#include "mojo/services/public/cpp/view_manager/node.h"
#include "mojo/services/public/cpp/view_manager/view.h"
#include "mojo/services/public/cpp/view_manager/view_event_dispatcher.h"
@@ -16,6 +19,7 @@
#include "mojo/services/public/interfaces/input_events/input_events.mojom.h"
#include "mojo/services/public/interfaces/launcher/launcher.mojom.h"
#include "mojo/services/public/interfaces/navigation/navigation.mojom.h"
+#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#if defined CreateWindow
@@ -57,6 +61,8 @@ class WindowManagerConnection : public InterfaceImpl<IWindowManager> {
private:
// Overridden from IWindowManager:
virtual void CloseWindow(Id node_id) OVERRIDE;
+ virtual void ShowKeyboard(Id view_id, RectPtr bounds) OVERRIDE;
+ virtual void HideKeyboard(Id view_id) OVERRIDE;
WindowManager* window_manager_;
@@ -70,21 +76,88 @@ class NavigatorHost : public InterfaceImpl<navigation::NavigatorHost> {
}
virtual ~NavigatorHost() {
}
+
private:
virtual void RequestNavigate(
uint32 source_node_id,
navigation::Target target,
navigation::NavigationDetailsPtr nav_details) OVERRIDE;
WindowManager* window_manager_;
+
DISALLOW_COPY_AND_ASSIGN(NavigatorHost);
};
+class KeyboardManager : public KeyboardClient {
+ public:
+ KeyboardManager() : view_manager_(NULL), node_(NULL) {
+ }
+ virtual ~KeyboardManager() {
+ }
+
+ Node* node() { return node_; }
+
+ void Init(Application* application,
+ ViewManager* view_manager,
+ Node* parent,
+ const gfx::Rect& bounds) {
+ view_manager_ = view_manager;
+ node_ = Node::Create(view_manager);
+ parent->AddChild(node_);
+ node_->SetBounds(bounds);
+ node_->Embed("mojo:mojo_keyboard");
+ application->ConnectTo("mojo:mojo_keyboard", &keyboard_service_);
+ keyboard_service_.set_client(this);
+ }
+
+ void Show(Id view_id, const gfx::Rect& bounds) {
+ keyboard_service_->SetTarget(view_id);
+ }
+
+ void Hide(Id view_id) {
+ keyboard_service_->SetTarget(0);
+ }
+
+ private:
+ // KeyboardClient:
+ virtual void OnKeyboardEvent(Id view_id,
+ int32_t code,
+ int32_t flags) OVERRIDE {
+ View* view = view_manager_->GetViewById(view_id);
+ if (!view)
+ return;
+#if defined(OS_WIN)
+ const bool is_char = code != ui::VKEY_BACK && code != ui::VKEY_RETURN;
+#else
+ const bool is_char = false;
+#endif
+ view_manager_->DispatchEvent(
+ view,
+ Event::From(ui::KeyEvent(ui::ET_KEY_PRESSED,
+ static_cast<ui::KeyboardCode>(code),
+ flags, is_char)));
+ view_manager_->DispatchEvent(
+ view,
+ Event::From(ui::KeyEvent(ui::ET_KEY_RELEASED,
+ static_cast<ui::KeyboardCode>(code),
+ flags, false)));
+ }
+
+ KeyboardServicePtr keyboard_service_;
+ ViewManager* view_manager_;
+
+ // Node the keyboard is attached to.
+ Node* node_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyboardManager);
+};
+
class WindowManager : public Application,
public ViewObserver,
public ViewManagerDelegate,
public ViewEventDispatcher {
public:
- WindowManager() : launcher_ui_(NULL), view_manager_(NULL) {}
+ WindowManager() : launcher_ui_(NULL), view_manager_(NULL) {
+ }
virtual ~WindowManager() {}
void CloseWindow(Id node_id) {
@@ -97,6 +170,25 @@ class WindowManager : public Application,
node->Destroy();
}
+ void ShowKeyboard(Id view_id, const gfx::Rect& bounds) {
+ // TODO: this needs to validate |view_id|. That is, it shouldn't assume
+ // |view_id| is valid and it also needs to make sure the client that sent
+ // this really owns |view_id|.
+ if (!keyboard_manager_) {
+ keyboard_manager_.reset(new KeyboardManager);
+ keyboard_manager_->Init(this, view_manager_,
+ view_manager_->GetRoots().back(),
+ gfx::Rect(0, 400, 400, 200));
+ }
+ keyboard_manager_->Show(view_id, bounds);
+ }
+
+ void HideKeyboard(Id view_id) {
+ // See comment in ShowKeyboard() about validating args.
+ if (keyboard_manager_)
+ keyboard_manager_->Hide(view_id);
+ }
+
void RequestNavigate(
uint32 source_node_id,
navigation::Target target,
@@ -129,7 +221,7 @@ class WindowManager : public Application,
if (app_url.empty())
return;
- Node* node = view_manager_->GetNodeById(parent_node_id_);
+ Node* node = view_manager_->GetNodeById(content_node_id_);
navigation::NavigationDetailsPtr nav_details(
navigation::NavigationDetails::New());
size_t index = node->children().size() - 1;
@@ -149,7 +241,7 @@ class WindowManager : public Application,
Node* node = Node::Create(view_manager);
view_manager->GetRoots().front()->AddChild(node);
node->SetBounds(gfx::Rect(800, 600));
- parent_node_id_ = node->id();
+ content_node_id_ = node->id();
View* view = View::Create(view_manager);
node->SetActiveView(view);
@@ -162,8 +254,10 @@ class WindowManager : public Application,
// Overridden from ViewEventDispatcher:
virtual void DispatchEvent(View* target, EventPtr event) OVERRIDE {
// TODO(beng): More sophisticated focus handling than this is required!
- if (event->action == ui::ET_MOUSE_PRESSED)
+ if (event->action == ui::ET_MOUSE_PRESSED &&
+ !IsDescendantOfKeyboard(target)) {
target->node()->SetFocus();
+ }
view_manager_->DispatchEvent(target, event.Pass());
}
@@ -189,18 +283,18 @@ class WindowManager : public Application,
void CreateLauncherUI() {
navigation::NavigationDetailsPtr nav_details;
navigation::ResponseDetailsPtr response;
- Node* node = view_manager_->GetNodeById(parent_node_id_);
+ Node* node = view_manager_->GetNodeById(content_node_id_);
gfx::Rect bounds = node->bounds();
bounds.Inset(kBorderInset, kBorderInset);
bounds.set_height(kTextfieldHeight);
- launcher_ui_ = CreateChild("mojo:mojo_browser", bounds,
+ launcher_ui_ = CreateChild(content_node_id_, "mojo:mojo_browser", bounds,
nav_details.Pass(), response.Pass());
}
void CreateWindow(const std::string& handler_url,
navigation::NavigationDetailsPtr nav_details,
navigation::ResponseDetailsPtr response) {
- Node* node = view_manager_->GetNodeById(parent_node_id_);
+ Node* node = view_manager_->GetNodeById(content_node_id_);
gfx::Rect bounds(kBorderInset, 2 * kBorderInset + kTextfieldHeight,
node->bounds().width() - 2 * kBorderInset,
node->bounds().height() -
@@ -210,15 +304,16 @@ class WindowManager : public Application,
position.Offset(35, 35);
bounds.set_origin(position);
}
- windows_.push_back(CreateChild(handler_url, bounds, nav_details.Pass(),
- response.Pass()));
+ windows_.push_back(CreateChild(content_node_id_, handler_url, bounds,
+ nav_details.Pass(), response.Pass()));
}
- Node* CreateChild(const std::string& url,
+ Node* CreateChild(Id parent_id,
+ const std::string& url,
const gfx::Rect& bounds,
navigation::NavigationDetailsPtr nav_details,
navigation::ResponseDetailsPtr response) {
- Node* node = view_manager_->GetNodeById(parent_node_id_);
+ Node* node = view_manager_->GetNodeById(parent_id);
Node* embedded = Node::Create(view_manager_);
node->AddChild(embedded);
embedded->SetBounds(bounds);
@@ -238,11 +333,20 @@ class WindowManager : public Application,
}
}
+ bool IsDescendantOfKeyboard(View* target) {
+ return !keyboard_manager_.get() ||
+ !keyboard_manager_->node()->Contains(target->node());
+ }
+
launcher::LauncherPtr launcher_;
Node* launcher_ui_;
std::vector<Node*> windows_;
ViewManager* view_manager_;
- Id parent_node_id_;
+
+ // Id of the node most content is added to. The keyboard is NOT added here.
+ Id content_node_id_;
+
+ scoped_ptr<KeyboardManager> keyboard_manager_;
DISALLOW_COPY_AND_ASSIGN(WindowManager);
};
@@ -251,6 +355,14 @@ void WindowManagerConnection::CloseWindow(Id node_id) {
window_manager_->CloseWindow(node_id);
}
+void WindowManagerConnection::ShowKeyboard(Id view_id, RectPtr bounds) {
+ window_manager_->ShowKeyboard(view_id, bounds.To<gfx::Rect>());
+}
+
+void WindowManagerConnection::HideKeyboard(Id node_id) {
+ window_manager_->HideKeyboard(node_id);
+}
+
void NavigatorHost::RequestNavigate(
uint32 source_node_id,
navigation::Target target,
diff --git a/mojo/examples/window_manager/window_manager.mojom b/mojo/examples/window_manager/window_manager.mojom
index 213c5e5..29f0d89 100644
--- a/mojo/examples/window_manager/window_manager.mojom
+++ b/mojo/examples/window_manager/window_manager.mojom
@@ -2,10 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import "mojo/services/public/interfaces/geometry/geometry.mojom"
+
module mojo {
interface IWindowManager {
CloseWindow(uint32 node_id);
+
+ // Shows the keyboard for the specified view. |bounds| is the bounds of the
+ // view that is showing focus. |bounds| is relative to the bounds of the node.
+ // Events from the keyboard are routed to the view with id |view_id|.
+ ShowKeyboard(uint32 view_id, mojo.Rect bounds);
+
+ // Hides the keyboard. This is ignored if |view_id| is not the view that was
+ // last passed to ShowKeyboard().
+ HideKeyboard(uint32 view_id);
};
}
diff --git a/mojo/mojo.gyp b/mojo/mojo.gyp
index 14221e6..5621bea 100644
--- a/mojo/mojo.gyp
+++ b/mojo/mojo.gyp
@@ -75,6 +75,7 @@
'mojo_browser',
'mojo_demo_launcher',
'mojo_embedded_app',
+ 'mojo_keyboard',
'mojo_media_viewer',
'mojo_nesting_app',
'mojo_window_manager',
diff --git a/mojo/mojo_examples.gypi b/mojo/mojo_examples.gypi
index 6447842..a72f964 100644
--- a/mojo/mojo_examples.gypi
+++ b/mojo/mojo_examples.gypi
@@ -319,6 +319,7 @@
'mojo_views_support',
'mojo_view_manager_bindings',
'mojo_view_manager_lib',
+ 'mojo_window_manager_bindings',
],
'sources': [
'examples/browser/browser.cc',
@@ -356,10 +357,51 @@
],
},
{
- 'target_name': 'mojo_window_manager_bindings',
+ 'target_name': 'mojo_keyboard',
+ 'type': 'shared_library',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../cc/cc.gyp:cc',
+ '../third_party/icu/icu.gyp:icui18n',
+ '../third_party/icu/icu.gyp:icuuc',
+ '../ui/aura/aura.gyp:aura',
+ '../ui/base/ui_base.gyp:ui_base',
+ '../ui/compositor/compositor.gyp:compositor',
+ '../ui/gfx/gfx.gyp:gfx',
+ '../ui/gfx/gfx.gyp:gfx_geometry',
+ '../ui/resources/ui_resources.gyp:ui_resources',
+ '../ui/resources/ui_resources.gyp:ui_test_pak',
+ '../ui/views/views.gyp:views',
+ '../url/url.gyp:url_lib',
+ 'mojo_application',
+ 'mojo_aura_support',
+ 'mojo_common_lib',
+ 'mojo_environment_chromium',
+ 'mojo_geometry_bindings',
+ 'mojo_geometry_lib',
+ 'mojo_input_events_lib',
+ 'mojo_keyboard_bindings',
+ 'mojo_navigation_bindings',
+ 'mojo_system_impl',
+ 'mojo_views_support',
+ 'mojo_view_manager_bindings',
+ 'mojo_view_manager_lib',
+ ],
+ 'sources': [
+ 'examples/keyboard/keyboard_delegate.h',
+ 'examples/keyboard/keyboard_view.cc',
+ 'examples/keyboard/keyboard_view.h',
+ 'examples/keyboard/keyboard.cc',
+ 'examples/keyboard/keys.cc',
+ 'examples/keyboard/keys.h',
+ 'public/cpp/application/lib/mojo_main_chromium.cc',
+ ],
+ },
+ {
+ 'target_name': 'mojo_keyboard_bindings',
'type': 'static_library',
'sources': [
- 'examples/window_manager/window_manager.mojom',
+ 'examples/keyboard/keyboard.mojom',
],
'includes': [ 'public/tools/bindings/mojom_bindings_generator.gypi' ],
'export_dependent_settings': [
@@ -370,6 +412,21 @@
],
},
{
+ 'target_name': 'mojo_window_manager_bindings',
+ 'type': 'static_library',
+ 'sources': [
+ 'examples/window_manager/window_manager.mojom',
+ ],
+ 'dependencies': [
+ 'mojo_cpp_bindings',
+ 'mojo_geometry_bindings',
+ ],
+ 'includes': [ 'public/tools/bindings/mojom_bindings_generator.gypi' ],
+ 'export_dependent_settings': [
+ 'mojo_cpp_bindings',
+ ],
+ },
+ {
'target_name': 'mojo_window_manager',
'type': 'shared_library',
'dependencies': [
@@ -380,7 +437,10 @@
'mojo_cpp_bindings',
'mojo_environment_chromium',
'mojo_geometry_bindings',
+ 'mojo_geometry_lib',
'mojo_gles2',
+ 'mojo_input_events_lib',
+ 'mojo_keyboard_bindings',
'mojo_launcher_bindings',
'mojo_navigation_bindings',
'mojo_view_manager_lib',
diff --git a/mojo/mojo_services.gypi b/mojo/mojo_services.gypi
index 632b446..b4848597d 100644
--- a/mojo/mojo_services.gypi
+++ b/mojo/mojo_services.gypi
@@ -304,6 +304,7 @@
'dependencies': [
'../base/base.gyp:base',
'../skia/skia.gyp:skia',
+ '../ui/events/events.gyp:events',
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
'mojo_application',
diff --git a/mojo/services/public/cpp/input_events/input_events_type_converters.h b/mojo/services/public/cpp/input_events/input_events_type_converters.h
index 7882f62..00a03ac 100644
--- a/mojo/services/public/cpp/input_events/input_events_type_converters.h
+++ b/mojo/services/public/cpp/input_events/input_events_type_converters.h
@@ -19,6 +19,12 @@ class MOJO_INPUT_EVENTS_EXPORT TypeConverter<EventPtr, ui::Event> {
};
template<>
+class MOJO_INPUT_EVENTS_EXPORT TypeConverter<EventPtr, ui::KeyEvent> {
+ public:
+ static EventPtr ConvertFrom(const ui::KeyEvent& input);
+};
+
+template<>
class MOJO_INPUT_EVENTS_EXPORT TypeConverter<EventPtr,
scoped_ptr<ui::Event> > {
public:
diff --git a/mojo/services/public/cpp/input_events/lib/input_events_type_converters.cc b/mojo/services/public/cpp/input_events/lib/input_events_type_converters.cc
index 230c4a4..402a065 100644
--- a/mojo/services/public/cpp/input_events/lib/input_events_type_converters.cc
+++ b/mojo/services/public/cpp/input_events/lib/input_events_type_converters.cc
@@ -42,6 +42,12 @@ EventPtr TypeConverter<EventPtr, ui::Event>::ConvertFrom(
}
// static
+EventPtr TypeConverter<EventPtr, ui::KeyEvent>::ConvertFrom(
+ const ui::KeyEvent& input) {
+ return Event::From(static_cast<const ui::Event&>(input));
+}
+
+// static
scoped_ptr<ui::Event>
TypeConverter<EventPtr, scoped_ptr<ui::Event> >::ConvertTo(
const EventPtr& input) {
diff --git a/mojo/views/native_widget_view_manager.cc b/mojo/views/native_widget_view_manager.cc
index 49dfeb5..a903e2b 100644
--- a/mojo/views/native_widget_view_manager.cc
+++ b/mojo/views/native_widget_view_manager.cc
@@ -16,6 +16,7 @@
#include "ui/base/ime/input_method_factory.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/wm/core/base_focus_rules.h"
+#include "ui/wm/core/capture_controller.h"
#include "ui/wm/core/focus_controller.h"
namespace mojo {
@@ -119,6 +120,8 @@ void NativeWidgetViewManager::InitNativeWidget(
views::Widget::InitParams params(in_params);
params.parent = window_tree_host_->window();
NativeWidgetAura::InitNativeWidget(params);
+ capture_client_.reset(
+ new wm::ScopedCaptureClient(window_tree_host_->window()));
}
void NativeWidgetViewManager::CompositorContentsChanged(
diff --git a/mojo/views/native_widget_view_manager.h b/mojo/views/native_widget_view_manager.h
index 5981200..c8fa2c9 100644
--- a/mojo/views/native_widget_view_manager.h
+++ b/mojo/views/native_widget_view_manager.h
@@ -18,6 +18,7 @@ class InputMethodDelegate;
namespace wm {
class FocusController;
+class ScopedCaptureClient;
}
namespace mojo {
@@ -34,7 +35,7 @@ class NativeWidgetViewManager : public views::NativeWidgetAura,
virtual ~NativeWidgetViewManager();
private:
- // Overridden from internal::NativeWidgetPrivate:
+ // Overridden from internal::NativeWidgetAura:
virtual void InitNativeWidget(
const views::Widget::InitParams& in_params) OVERRIDE;
@@ -53,6 +54,8 @@ class NativeWidgetViewManager : public views::NativeWidgetAura,
view_manager::Node* node_;
+ scoped_ptr<wm::ScopedCaptureClient> capture_client_;
+
DISALLOW_COPY_AND_ASSIGN(NativeWidgetViewManager);
};