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 |