| 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 "athena/env/public/athena_env.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "athena/util/fill_layout_manager.h" | |
| 10 #include "base/sys_info.h" | |
| 11 #include "ui/aura/client/aura_constants.h" | |
| 12 #include "ui/aura/client/cursor_client.h" | |
| 13 #include "ui/aura/client/default_capture_client.h" | |
| 14 #include "ui/aura/env.h" | |
| 15 #include "ui/aura/test/test_screen.h" | |
| 16 #include "ui/aura/window_event_dispatcher.h" | |
| 17 #include "ui/aura/window_tree_host.h" | |
| 18 #include "ui/aura/window_tree_host_observer.h" | |
| 19 #include "ui/base/cursor/cursor.h" | |
| 20 #include "ui/base/cursor/image_cursors.h" | |
| 21 #include "ui/base/user_activity/user_activity_detector.h" | |
| 22 #include "ui/chromeos/user_activity_power_manager_notifier.h" | |
| 23 #include "ui/display/chromeos/display_configurator.h" | |
| 24 #include "ui/display/types/display_mode.h" | |
| 25 #include "ui/display/types/display_snapshot.h" | |
| 26 #include "ui/events/devices/device_data_manager.h" | |
| 27 #include "ui/events/devices/input_device_event_observer.h" | |
| 28 #include "ui/events/devices/touchscreen_device.h" | |
| 29 #include "ui/gfx/screen.h" | |
| 30 #include "ui/wm/core/compound_event_filter.h" | |
| 31 #include "ui/wm/core/cursor_manager.h" | |
| 32 #include "ui/wm/core/input_method_event_filter.h" | |
| 33 #include "ui/wm/core/native_cursor_manager.h" | |
| 34 #include "ui/wm/core/native_cursor_manager_delegate.h" | |
| 35 | |
| 36 namespace athena { | |
| 37 | |
| 38 namespace { | |
| 39 | |
| 40 AthenaEnv* instance = nullptr; | |
| 41 | |
| 42 // Screen object used during shutdown. | |
| 43 gfx::Screen* screen_for_shutdown = nullptr; | |
| 44 | |
| 45 gfx::Transform GetTouchTransform(const ui::DisplaySnapshot& display, | |
| 46 const ui::TouchscreenDevice& touchscreen, | |
| 47 const gfx::SizeF& framebuffer_size) { | |
| 48 if (!display.current_mode()) | |
| 49 return gfx::Transform(); | |
| 50 | |
| 51 gfx::SizeF display_size = display.current_mode()->size(); | |
| 52 #if defined(USE_X11) | |
| 53 gfx::SizeF touchscreen_size = framebuffer_size; | |
| 54 #elif defined(USE_OZONE) | |
| 55 gfx::SizeF touchscreen_size = touchscreen.size; | |
| 56 #endif | |
| 57 | |
| 58 if (display_size.IsEmpty() || touchscreen_size.IsEmpty()) | |
| 59 return gfx::Transform(); | |
| 60 | |
| 61 gfx::Transform transform; | |
| 62 transform.Scale(display_size.width() / touchscreen_size.width(), | |
| 63 display_size.height() / touchscreen_size.height()); | |
| 64 | |
| 65 return transform; | |
| 66 } | |
| 67 | |
| 68 double GetTouchRadiusScale(const ui::DisplaySnapshot& display, | |
| 69 const ui::TouchscreenDevice& touchscreen, | |
| 70 const gfx::SizeF& framebuffer_size) { | |
| 71 if (!display.current_mode()) | |
| 72 return 1; | |
| 73 | |
| 74 gfx::SizeF display_size = display.current_mode()->size(); | |
| 75 #if defined(USE_X11) | |
| 76 gfx::SizeF touchscreen_size = framebuffer_size; | |
| 77 #elif defined(USE_OZONE) | |
| 78 gfx::SizeF touchscreen_size = touchscreen.size; | |
| 79 #endif | |
| 80 | |
| 81 if (display_size.IsEmpty() || touchscreen_size.IsEmpty()) | |
| 82 return 1; | |
| 83 | |
| 84 return std::sqrt(display_size.GetArea() / touchscreen_size.GetArea()); | |
| 85 } | |
| 86 | |
| 87 // TODO(flackr:oshima): Remove this once athena switches to share | |
| 88 // ash::DisplayManager. | |
| 89 class ScreenForShutdown : public gfx::Screen { | |
| 90 public: | |
| 91 // Creates and sets the screen for shutdown. Deletes existing one if any. | |
| 92 static void Create(const gfx::Screen* screen) { | |
| 93 delete screen_for_shutdown; | |
| 94 screen_for_shutdown = new ScreenForShutdown(screen->GetPrimaryDisplay()); | |
| 95 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, | |
| 96 screen_for_shutdown); | |
| 97 } | |
| 98 | |
| 99 private: | |
| 100 explicit ScreenForShutdown(const gfx::Display& primary_display) | |
| 101 : primary_display_(primary_display) {} | |
| 102 | |
| 103 // gfx::Screen overrides: | |
| 104 gfx::Point GetCursorScreenPoint() override { return gfx::Point(); } | |
| 105 gfx::NativeWindow GetWindowUnderCursor() override { return NULL; } | |
| 106 gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override { | |
| 107 return nullptr; | |
| 108 } | |
| 109 int GetNumDisplays() const override { return 1; } | |
| 110 std::vector<gfx::Display> GetAllDisplays() const override { | |
| 111 std::vector<gfx::Display> displays(1, primary_display_); | |
| 112 return displays; | |
| 113 } | |
| 114 gfx::Display GetDisplayNearestWindow(gfx::NativeView view) const override { | |
| 115 return primary_display_; | |
| 116 } | |
| 117 gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const override { | |
| 118 return primary_display_; | |
| 119 } | |
| 120 gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const override { | |
| 121 return primary_display_; | |
| 122 } | |
| 123 gfx::Display GetPrimaryDisplay() const override { return primary_display_; } | |
| 124 void AddObserver(gfx::DisplayObserver* observer) override { | |
| 125 NOTREACHED() << "Observer should not be added during shutdown"; | |
| 126 } | |
| 127 void RemoveObserver(gfx::DisplayObserver* observer) override {} | |
| 128 | |
| 129 const gfx::Display primary_display_; | |
| 130 | |
| 131 DISALLOW_COPY_AND_ASSIGN(ScreenForShutdown); | |
| 132 }; | |
| 133 | |
| 134 // A class that bridges the gap between CursorManager and Aura. It borrows | |
| 135 // heavily from AshNativeCursorManager. | |
| 136 class AthenaNativeCursorManager : public wm::NativeCursorManager { | |
| 137 public: | |
| 138 explicit AthenaNativeCursorManager(aura::WindowTreeHost* host) | |
| 139 : host_(host), image_cursors_(new ui::ImageCursors) {} | |
| 140 ~AthenaNativeCursorManager() override {} | |
| 141 | |
| 142 // wm::NativeCursorManager overrides. | |
| 143 void SetDisplay(const gfx::Display& display, | |
| 144 wm::NativeCursorManagerDelegate* delegate) override { | |
| 145 if (image_cursors_->SetDisplay(display, display.device_scale_factor())) | |
| 146 SetCursor(delegate->GetCursor(), delegate); | |
| 147 } | |
| 148 | |
| 149 void SetCursor(gfx::NativeCursor cursor, | |
| 150 wm::NativeCursorManagerDelegate* delegate) override { | |
| 151 image_cursors_->SetPlatformCursor(&cursor); | |
| 152 cursor.set_device_scale_factor(image_cursors_->GetScale()); | |
| 153 delegate->CommitCursor(cursor); | |
| 154 | |
| 155 if (delegate->IsCursorVisible()) | |
| 156 ApplyCursor(cursor); | |
| 157 } | |
| 158 | |
| 159 void SetVisibility(bool visible, | |
| 160 wm::NativeCursorManagerDelegate* delegate) override { | |
| 161 delegate->CommitVisibility(visible); | |
| 162 | |
| 163 if (visible) { | |
| 164 SetCursor(delegate->GetCursor(), delegate); | |
| 165 } else { | |
| 166 gfx::NativeCursor invisible_cursor(ui::kCursorNone); | |
| 167 image_cursors_->SetPlatformCursor(&invisible_cursor); | |
| 168 ApplyCursor(invisible_cursor); | |
| 169 } | |
| 170 } | |
| 171 | |
| 172 void SetCursorSet(ui::CursorSetType cursor_set, | |
| 173 wm::NativeCursorManagerDelegate* delegate) override { | |
| 174 image_cursors_->SetCursorSet(cursor_set); | |
| 175 delegate->CommitCursorSet(cursor_set); | |
| 176 if (delegate->IsCursorVisible()) | |
| 177 SetCursor(delegate->GetCursor(), delegate); | |
| 178 } | |
| 179 | |
| 180 void SetMouseEventsEnabled( | |
| 181 bool enabled, | |
| 182 wm::NativeCursorManagerDelegate* delegate) override { | |
| 183 delegate->CommitMouseEventsEnabled(enabled); | |
| 184 SetVisibility(delegate->IsCursorVisible(), delegate); | |
| 185 } | |
| 186 | |
| 187 private: | |
| 188 // Sets |cursor| as the active cursor within Aura. | |
| 189 void ApplyCursor(gfx::NativeCursor cursor) { host_->SetCursor(cursor); } | |
| 190 | |
| 191 aura::WindowTreeHost* host_; // Not owned. | |
| 192 | |
| 193 scoped_ptr<ui::ImageCursors> image_cursors_; | |
| 194 | |
| 195 DISALLOW_COPY_AND_ASSIGN(AthenaNativeCursorManager); | |
| 196 }; | |
| 197 | |
| 198 class AthenaEnvImpl : public AthenaEnv, | |
| 199 public aura::WindowTreeHostObserver, | |
| 200 public ui::DisplayConfigurator::Observer, | |
| 201 public ui::InputDeviceEventObserver { | |
| 202 public: | |
| 203 AthenaEnvImpl() : display_configurator_(new ui::DisplayConfigurator) { | |
| 204 display_configurator_->Init(false); | |
| 205 display_configurator_->ForceInitialConfigure(0); | |
| 206 display_configurator_->AddObserver(this); | |
| 207 | |
| 208 ui::DeviceDataManager::GetInstance()->AddObserver(this); | |
| 209 | |
| 210 gfx::Size screen_size = GetPrimaryDisplaySize(); | |
| 211 if (screen_size.IsEmpty()) { | |
| 212 // TODO(oshima): Remove this hack. | |
| 213 if (base::SysInfo::IsRunningOnChromeOS()) | |
| 214 screen_size.SetSize(2560, 1600); | |
| 215 else | |
| 216 screen_size.SetSize(1280, 720); | |
| 217 } | |
| 218 screen_.reset(aura::TestScreen::Create(screen_size)); | |
| 219 | |
| 220 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get()); | |
| 221 host_.reset(screen_->CreateHostForPrimaryDisplay()); | |
| 222 host_->InitHost(); | |
| 223 | |
| 224 aura::Window* root_window = GetHost()->window(); | |
| 225 input_method_filter_.reset( | |
| 226 new wm::InputMethodEventFilter(host_->GetAcceleratedWidget())); | |
| 227 input_method_filter_->SetInputMethodPropertyInRootWindow(root_window); | |
| 228 | |
| 229 root_window_event_filter_.reset(new wm::CompoundEventFilter); | |
| 230 host_->window()->AddPreTargetHandler(root_window_event_filter_.get()); | |
| 231 | |
| 232 root_window_event_filter_->AddHandler(input_method_filter_.get()); | |
| 233 | |
| 234 capture_client_.reset( | |
| 235 new aura::client::DefaultCaptureClient(host_->window())); | |
| 236 | |
| 237 // Ensure new windows fill the display. | |
| 238 root_window->SetLayoutManager(new FillLayoutManager(root_window)); | |
| 239 | |
| 240 cursor_manager_.reset( | |
| 241 new wm::CursorManager(scoped_ptr<wm::NativeCursorManager>( | |
| 242 new AthenaNativeCursorManager(host_.get())))); | |
| 243 cursor_manager_->SetDisplay( | |
| 244 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay()); | |
| 245 cursor_manager_->SetCursor(ui::kCursorPointer); | |
| 246 aura::client::SetCursorClient(host_->window(), cursor_manager_.get()); | |
| 247 | |
| 248 user_activity_detector_.reset(new ui::UserActivityDetector); | |
| 249 host_->event_processor()->GetRootTarget()->AddPreTargetHandler( | |
| 250 user_activity_detector_.get()); | |
| 251 user_activity_notifier_.reset(new ui::UserActivityPowerManagerNotifier( | |
| 252 user_activity_detector_.get())); | |
| 253 | |
| 254 host_->AddObserver(this); | |
| 255 host_->Show(); | |
| 256 | |
| 257 DCHECK(!instance); | |
| 258 instance = this; | |
| 259 } | |
| 260 | |
| 261 ~AthenaEnvImpl() override { | |
| 262 instance = nullptr; | |
| 263 | |
| 264 host_->RemoveObserver(this); | |
| 265 if (input_method_filter_) | |
| 266 root_window_event_filter_->RemoveHandler(input_method_filter_.get()); | |
| 267 if (user_activity_detector_) { | |
| 268 host_->event_processor()->GetRootTarget()->RemovePreTargetHandler( | |
| 269 user_activity_detector_.get()); | |
| 270 } | |
| 271 root_window_event_filter_.reset(); | |
| 272 capture_client_.reset(); | |
| 273 input_method_filter_.reset(); | |
| 274 cursor_manager_.reset(); | |
| 275 user_activity_notifier_.reset(); | |
| 276 user_activity_detector_.reset(); | |
| 277 | |
| 278 input_method_filter_.reset(); | |
| 279 host_.reset(); | |
| 280 | |
| 281 ScreenForShutdown::Create(screen_.get()); | |
| 282 screen_.reset(); | |
| 283 aura::Env::DeleteInstance(); | |
| 284 | |
| 285 ui::DeviceDataManager::GetInstance()->RemoveObserver(this); | |
| 286 | |
| 287 display_configurator_->RemoveObserver(this); | |
| 288 display_configurator_.reset(); | |
| 289 } | |
| 290 | |
| 291 private: | |
| 292 struct Finder { | |
| 293 explicit Finder(const base::Closure& c) : closure(c) {} | |
| 294 bool operator()(const base::Closure& other) { | |
| 295 return closure.Equals(other); | |
| 296 } | |
| 297 base::Closure closure; | |
| 298 }; | |
| 299 | |
| 300 // AthenaEnv: | |
| 301 aura::WindowTreeHost* GetHost() override { return host_.get(); } | |
| 302 | |
| 303 void SetDisplayWorkAreaInsets(const gfx::Insets& insets) override { | |
| 304 screen_->SetWorkAreaInsets(insets); | |
| 305 } | |
| 306 | |
| 307 void AddTerminatingCallback(const base::Closure& closure) override { | |
| 308 if (closure.is_null()) | |
| 309 return; | |
| 310 DCHECK(terminating_callbacks_.end() == | |
| 311 std::find_if(terminating_callbacks_.begin(), | |
| 312 terminating_callbacks_.end(), | |
| 313 Finder(closure))); | |
| 314 terminating_callbacks_.push_back(closure); | |
| 315 } | |
| 316 | |
| 317 void RemoveTerminatingCallback(const base::Closure& closure) override { | |
| 318 std::vector<base::Closure>::iterator iter = | |
| 319 std::find_if(terminating_callbacks_.begin(), | |
| 320 terminating_callbacks_.end(), | |
| 321 Finder(closure)); | |
| 322 if (iter != terminating_callbacks_.end()) | |
| 323 terminating_callbacks_.erase(iter); | |
| 324 } | |
| 325 | |
| 326 void OnTerminating() override { | |
| 327 for (std::vector<base::Closure>::iterator iter = | |
| 328 terminating_callbacks_.begin(); | |
| 329 iter != terminating_callbacks_.end(); | |
| 330 ++iter) { | |
| 331 iter->Run(); | |
| 332 } | |
| 333 } | |
| 334 | |
| 335 // ui::DisplayConfigurator::Observer: | |
| 336 void OnDisplayModeChanged( | |
| 337 const std::vector<ui::DisplayConfigurator::DisplayState>& displays) | |
| 338 override { | |
| 339 MapTouchscreenToDisplay(); | |
| 340 | |
| 341 gfx::Size size = GetPrimaryDisplaySize(); | |
| 342 if (!size.IsEmpty()) | |
| 343 host_->UpdateRootWindowSize(size); | |
| 344 } | |
| 345 | |
| 346 // ui::InputDeviceEventObserver: | |
| 347 void OnTouchscreenDeviceConfigurationChanged() override { | |
| 348 MapTouchscreenToDisplay(); | |
| 349 } | |
| 350 | |
| 351 void OnKeyboardDeviceConfigurationChanged() override {} | |
| 352 | |
| 353 // aura::WindowTreeHostObserver: | |
| 354 void OnHostCloseRequested(const aura::WindowTreeHost* host) override { | |
| 355 base::MessageLoopForUI::current()->PostTask( | |
| 356 FROM_HERE, base::MessageLoop::QuitClosure()); | |
| 357 } | |
| 358 | |
| 359 gfx::Size GetPrimaryDisplaySize() const { | |
| 360 const std::vector<ui::DisplayConfigurator::DisplayState>& displays = | |
| 361 display_configurator_->cached_displays(); | |
| 362 if (displays.empty()) | |
| 363 return gfx::Size(); | |
| 364 const ui::DisplayMode* mode = displays[0].display->current_mode(); | |
| 365 return mode ? mode->size() : gfx::Size(); | |
| 366 } | |
| 367 | |
| 368 void MapTouchscreenToDisplay() const { | |
| 369 auto device_manager = ui::DeviceDataManager::GetInstance(); | |
| 370 auto displays = display_configurator_->cached_displays(); | |
| 371 auto touchscreens = device_manager->touchscreen_devices(); | |
| 372 | |
| 373 if (displays.empty() || touchscreens.empty()) | |
| 374 return; | |
| 375 | |
| 376 gfx::SizeF framebuffer_size = display_configurator_->framebuffer_size(); | |
| 377 device_manager->ClearTouchTransformerRecord(); | |
| 378 device_manager->UpdateTouchInfoForDisplay( | |
| 379 displays[0].display->display_id(), | |
| 380 touchscreens[0].id, | |
| 381 GetTouchTransform(*displays[0].display, | |
| 382 touchscreens[0], | |
| 383 framebuffer_size)); | |
| 384 device_manager->UpdateTouchRadiusScale( | |
| 385 touchscreens[0].id, | |
| 386 GetTouchRadiusScale(*displays[0].display, | |
| 387 touchscreens[0], | |
| 388 framebuffer_size)); | |
| 389 } | |
| 390 | |
| 391 scoped_ptr<aura::TestScreen> screen_; | |
| 392 scoped_ptr<aura::WindowTreeHost> host_; | |
| 393 | |
| 394 scoped_ptr<wm::InputMethodEventFilter> input_method_filter_; | |
| 395 scoped_ptr<wm::CompoundEventFilter> root_window_event_filter_; | |
| 396 scoped_ptr<aura::client::DefaultCaptureClient> capture_client_; | |
| 397 scoped_ptr<wm::CursorManager> cursor_manager_; | |
| 398 scoped_ptr<ui::UserActivityDetector> user_activity_detector_; | |
| 399 scoped_ptr<ui::DisplayConfigurator> display_configurator_; | |
| 400 scoped_ptr<ui::UserActivityPowerManagerNotifier> user_activity_notifier_; | |
| 401 | |
| 402 std::vector<base::Closure> terminating_callbacks_; | |
| 403 | |
| 404 DISALLOW_COPY_AND_ASSIGN(AthenaEnvImpl); | |
| 405 }; | |
| 406 | |
| 407 } // namespace | |
| 408 | |
| 409 // static | |
| 410 void AthenaEnv::Create() { | |
| 411 DCHECK(!instance); | |
| 412 new AthenaEnvImpl(); | |
| 413 } | |
| 414 | |
| 415 AthenaEnv* AthenaEnv::Get() { | |
| 416 DCHECK(instance); | |
| 417 return instance; | |
| 418 } | |
| 419 | |
| 420 // static | |
| 421 | |
| 422 // static | |
| 423 void AthenaEnv::Shutdown() { | |
| 424 DCHECK(instance); | |
| 425 delete instance; | |
| 426 } | |
| 427 | |
| 428 } // namespace athena | |
| OLD | NEW |