| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/macros.h" | |
| 6 #include "base/strings/string_util.h" | |
| 7 #include "base/strings/utf_string_conversions.h" | |
| 8 #include "mojo/application/application_runner_chromium.h" | |
| 9 #include "mojo/common/common_type_converters.h" | |
| 10 #include "mojo/converters/geometry/geometry_type_converters.h" | |
| 11 #include "mojo/examples/window_manager/window_manager.mojom.h" | |
| 12 #include "mojo/public/c/system/main.h" | |
| 13 #include "mojo/public/cpp/application/application_connection.h" | |
| 14 #include "mojo/public/cpp/application/application_delegate.h" | |
| 15 #include "mojo/public/cpp/application/application_impl.h" | |
| 16 #include "mojo/public/cpp/application/connect.h" | |
| 17 #include "mojo/services/public/cpp/view_manager/view.h" | |
| 18 #include "mojo/services/public/cpp/view_manager/view_manager.h" | |
| 19 #include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h" | |
| 20 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" | |
| 21 #include "mojo/services/public/interfaces/navigation/navigation.mojom.h" | |
| 22 #include "mojo/views/native_widget_view_manager.h" | |
| 23 #include "mojo/views/views_init.h" | |
| 24 #include "ui/aura/client/focus_client.h" | |
| 25 #include "ui/aura/window.h" | |
| 26 #include "ui/events/event.h" | |
| 27 #include "ui/views/background.h" | |
| 28 #include "ui/views/controls/textfield/textfield.h" | |
| 29 #include "ui/views/controls/textfield/textfield_controller.h" | |
| 30 #include "ui/views/focus/focus_manager.h" | |
| 31 #include "ui/views/layout/layout_manager.h" | |
| 32 #include "ui/views/widget/widget.h" | |
| 33 #include "ui/views/widget/widget_delegate.h" | |
| 34 #include "ui/views/widget/widget_observer.h" | |
| 35 #include "url/gurl.h" | |
| 36 | |
| 37 namespace mojo { | |
| 38 namespace examples { | |
| 39 | |
| 40 class BrowserLayoutManager : public views::LayoutManager { | |
| 41 public: | |
| 42 BrowserLayoutManager() {} | |
| 43 virtual ~BrowserLayoutManager() {} | |
| 44 | |
| 45 private: | |
| 46 // Overridden from views::LayoutManager: | |
| 47 virtual void Layout(views::View* host) override { | |
| 48 // Browser view has one child, a text input field. | |
| 49 DCHECK_EQ(1, host->child_count()); | |
| 50 views::View* text_field = host->child_at(0); | |
| 51 gfx::Size ps = text_field->GetPreferredSize(); | |
| 52 text_field->SetBoundsRect(gfx::Rect(host->width(), ps.height())); | |
| 53 } | |
| 54 virtual gfx::Size GetPreferredSize(const views::View* host) const override { | |
| 55 return gfx::Size(); | |
| 56 } | |
| 57 | |
| 58 DISALLOW_COPY_AND_ASSIGN(BrowserLayoutManager); | |
| 59 }; | |
| 60 | |
| 61 // KeyboardManager handles notifying the windowmanager when views are focused. | |
| 62 // To use create one and KeyboardManager will take care of all other details. | |
| 63 // | |
| 64 // TODO(sky): it would be nice if this were put in NativeWidgetViewManager, but | |
| 65 // that requires NativeWidgetViewManager to take an IWindowManager. That may be | |
| 66 // desirable anyway... | |
| 67 class KeyboardManager | |
| 68 : public views::FocusChangeListener, | |
| 69 public ui::EventHandler, | |
| 70 public views::WidgetObserver { | |
| 71 public: | |
| 72 KeyboardManager(views::Widget* widget, | |
| 73 IWindowManager* window_manager, | |
| 74 View* view) | |
| 75 : widget_(widget), | |
| 76 window_manager_(window_manager), | |
| 77 view_(view), | |
| 78 last_view_id_(0), | |
| 79 focused_view_(NULL) { | |
| 80 widget_->GetFocusManager()->AddFocusChangeListener(this); | |
| 81 widget_->AddObserver(this); | |
| 82 widget_->GetNativeView()->AddPostTargetHandler(this); | |
| 83 } | |
| 84 | |
| 85 private: | |
| 86 virtual ~KeyboardManager() { | |
| 87 widget_->GetFocusManager()->RemoveFocusChangeListener(this); | |
| 88 widget_->GetNativeView()->RemovePostTargetHandler(this); | |
| 89 widget_->RemoveObserver(this); | |
| 90 | |
| 91 HideKeyboard(); | |
| 92 } | |
| 93 | |
| 94 void ShowKeyboard(views::View* view) { | |
| 95 if (focused_view_ == view) | |
| 96 return; | |
| 97 | |
| 98 const gfx::Rect bounds_in_widget = | |
| 99 view->ConvertRectToWidget(gfx::Rect(view->bounds().size())); | |
| 100 last_view_id_ = view_->id(); | |
| 101 window_manager_->ShowKeyboard(last_view_id_, | |
| 102 Rect::From(bounds_in_widget)); | |
| 103 // TODO(sky): listen for view to be removed. | |
| 104 focused_view_ = view; | |
| 105 } | |
| 106 | |
| 107 void HideKeyboard() { | |
| 108 if (!focused_view_) | |
| 109 return; | |
| 110 | |
| 111 window_manager_->HideKeyboard(last_view_id_); | |
| 112 last_view_id_ = 0; | |
| 113 focused_view_ = NULL; | |
| 114 } | |
| 115 | |
| 116 // views::FocusChangeListener: | |
| 117 virtual void OnWillChangeFocus(views::View* focused_before, | |
| 118 views::View* focused_now) override { | |
| 119 } | |
| 120 virtual void OnDidChangeFocus(views::View* focused_before, | |
| 121 views::View* focused_now) override { | |
| 122 if (focused_view_ && focused_now != focused_view_) | |
| 123 HideKeyboard(); | |
| 124 } | |
| 125 | |
| 126 // ui::EventHandler: | |
| 127 virtual void OnMouseEvent(ui::MouseEvent* event) override { | |
| 128 views::View* focused_now = widget_->GetFocusManager()->GetFocusedView(); | |
| 129 if (focused_now && | |
| 130 focused_now->GetClassName() == views::Textfield::kViewClassName && | |
| 131 (event->flags() & ui::EF_FROM_TOUCH) != 0) { | |
| 132 ShowKeyboard(focused_now); | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 // views::WidgetObserver: | |
| 137 virtual void OnWidgetDestroying(views::Widget* widget) override { | |
| 138 delete this; | |
| 139 } | |
| 140 | |
| 141 views::Widget* widget_; | |
| 142 IWindowManager* window_manager_; | |
| 143 View* view_; | |
| 144 Id last_view_id_; | |
| 145 views::View* focused_view_; | |
| 146 | |
| 147 DISALLOW_COPY_AND_ASSIGN(KeyboardManager); | |
| 148 }; | |
| 149 | |
| 150 // This is the basics of creating a views widget with a textfield. | |
| 151 // TODO: cleanup! | |
| 152 class Browser : public ApplicationDelegate, | |
| 153 public ViewManagerDelegate, | |
| 154 public views::TextfieldController, | |
| 155 public ViewObserver { | |
| 156 public: | |
| 157 Browser() | |
| 158 : shell_(nullptr), view_manager_(NULL), root_(NULL), widget_(NULL) {} | |
| 159 | |
| 160 virtual ~Browser() { | |
| 161 if (root_) | |
| 162 root_->RemoveObserver(this); | |
| 163 } | |
| 164 | |
| 165 private: | |
| 166 // Overridden from ApplicationDelegate: | |
| 167 virtual void Initialize(ApplicationImpl* app) override { | |
| 168 shell_ = app->shell(); | |
| 169 view_manager_client_factory_.reset( | |
| 170 new ViewManagerClientFactory(shell_, this)); | |
| 171 views_init_.reset(new ViewsInit); | |
| 172 app->ConnectToService("mojo:window_manager", &window_manager_); | |
| 173 } | |
| 174 | |
| 175 virtual bool ConfigureIncomingConnection( | |
| 176 ApplicationConnection* connection) override { | |
| 177 connection->AddService(view_manager_client_factory_.get()); | |
| 178 return true; | |
| 179 } | |
| 180 | |
| 181 void CreateWidget(View* view) { | |
| 182 views::Textfield* textfield = new views::Textfield; | |
| 183 textfield->set_controller(this); | |
| 184 | |
| 185 views::WidgetDelegateView* widget_delegate = new views::WidgetDelegateView; | |
| 186 widget_delegate->GetContentsView()->set_background( | |
| 187 views::Background::CreateSolidBackground(SK_ColorBLUE)); | |
| 188 widget_delegate->GetContentsView()->AddChildView(textfield); | |
| 189 widget_delegate->GetContentsView()->SetLayoutManager( | |
| 190 new BrowserLayoutManager); | |
| 191 | |
| 192 widget_ = new views::Widget; | |
| 193 views::Widget::InitParams params( | |
| 194 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); | |
| 195 params.native_widget = new NativeWidgetViewManager(widget_, shell_, view); | |
| 196 params.delegate = widget_delegate; | |
| 197 params.bounds = gfx::Rect(view->bounds().width, view->bounds().height); | |
| 198 widget_->Init(params); | |
| 199 // KeyboardManager handles deleting itself when the widget is destroyed. | |
| 200 new KeyboardManager(widget_, window_manager_.get(), view); | |
| 201 widget_->Show(); | |
| 202 textfield->RequestFocus(); | |
| 203 } | |
| 204 | |
| 205 // ViewManagerDelegate: | |
| 206 virtual void OnEmbed(ViewManager* view_manager, | |
| 207 View* root, | |
| 208 ServiceProviderImpl* exported_services, | |
| 209 scoped_ptr<ServiceProvider> imported_services) override { | |
| 210 // TODO: deal with OnEmbed() being invoked multiple times. | |
| 211 ConnectToService(imported_services.get(), &navigator_host_); | |
| 212 view_manager_ = view_manager; | |
| 213 root_ = root; | |
| 214 root_->AddObserver(this); | |
| 215 root_->SetFocus(); | |
| 216 CreateWidget(root_); | |
| 217 } | |
| 218 virtual void OnViewManagerDisconnected( | |
| 219 ViewManager* view_manager) override { | |
| 220 DCHECK_EQ(view_manager_, view_manager); | |
| 221 view_manager_ = NULL; | |
| 222 base::MessageLoop::current()->Quit(); | |
| 223 } | |
| 224 | |
| 225 // views::TextfieldController: | |
| 226 virtual bool HandleKeyEvent(views::Textfield* sender, | |
| 227 const ui::KeyEvent& key_event) override { | |
| 228 if (key_event.key_code() == ui::VKEY_RETURN) { | |
| 229 GURL url(sender->text()); | |
| 230 printf("User entered this URL: %s\n", url.spec().c_str()); | |
| 231 URLRequestPtr request(URLRequest::New()); | |
| 232 request->url = String::From(url); | |
| 233 navigator_host_->RequestNavigate(TARGET_NEW_NODE, request.Pass()); | |
| 234 } | |
| 235 return false; | |
| 236 } | |
| 237 | |
| 238 // ViewObserver: | |
| 239 virtual void OnViewFocusChanged(View* gained_focus, | |
| 240 View* lost_focus) override { | |
| 241 aura::client::FocusClient* focus_client = | |
| 242 aura::client::GetFocusClient(widget_->GetNativeView()); | |
| 243 if (lost_focus == root_) | |
| 244 focus_client->FocusWindow(NULL); | |
| 245 else if (gained_focus == root_) | |
| 246 focus_client->FocusWindow(widget_->GetNativeView()); | |
| 247 } | |
| 248 virtual void OnViewDestroyed(View* view) override { | |
| 249 DCHECK_EQ(root_, view); | |
| 250 view->RemoveObserver(this); | |
| 251 root_ = NULL; | |
| 252 } | |
| 253 | |
| 254 Shell* shell_; | |
| 255 | |
| 256 scoped_ptr<ViewsInit> views_init_; | |
| 257 | |
| 258 ViewManager* view_manager_; | |
| 259 scoped_ptr<ViewManagerClientFactory> view_manager_client_factory_; | |
| 260 View* root_; | |
| 261 views::Widget* widget_; | |
| 262 NavigatorHostPtr navigator_host_; | |
| 263 IWindowManagerPtr window_manager_; | |
| 264 | |
| 265 DISALLOW_COPY_AND_ASSIGN(Browser); | |
| 266 }; | |
| 267 | |
| 268 } // namespace examples | |
| 269 } // namespace mojo | |
| 270 | |
| 271 MojoResult MojoMain(MojoHandle shell_handle) { | |
| 272 mojo::ApplicationRunnerChromium runner(new mojo::examples::Browser); | |
| 273 return runner.Run(shell_handle); | |
| 274 } | |
| OLD | NEW |