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.
5 #include "athena/env/public/athena_env.h"
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/chromeos/user_activity_power_manager_notifier.h"
22 #include "ui/display/chromeos/display_configurator.h"
23 #include "ui/display/types/display_mode.h"
24 #include "ui/display/types/display_snapshot.h"
25 #include "ui/events/devices/device_data_manager.h"
26 #include "ui/events/devices/input_device_event_observer.h"
27 #include "ui/events/devices/touchscreen_device.h"
28 #include "ui/gfx/screen.h"
29 #include "ui/wm/core/compound_event_filter.h"
30 #include "ui/wm/core/cursor_manager.h"
31 #include "ui/wm/core/input_method_event_filter.h"
32 #include "ui/wm/core/native_cursor_manager.h"
33 #include "ui/wm/core/native_cursor_manager_delegate.h"
34 #include "ui/wm/core/user_activity_detector.h"
40 AthenaEnv
* instance
= nullptr;
42 // Screen object used during shutdown.
43 gfx::Screen
* screen_for_shutdown
= nullptr;
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();
51 gfx::SizeF display_size
= display
.current_mode()->size();
53 gfx::SizeF touchscreen_size
= framebuffer_size
;
54 #elif defined(USE_OZONE)
55 gfx::SizeF touchscreen_size
= touchscreen
.size
;
58 if (display_size
.IsEmpty() || touchscreen_size
.IsEmpty())
59 return gfx::Transform();
61 gfx::Transform transform
;
62 transform
.Scale(display_size
.width() / touchscreen_size
.width(),
63 display_size
.height() / touchscreen_size
.height());
68 double GetTouchRadiusScale(const ui::DisplaySnapshot
& display
,
69 const ui::TouchscreenDevice
& touchscreen
,
70 const gfx::SizeF
& framebuffer_size
) {
71 if (!display
.current_mode())
74 gfx::SizeF display_size
= display
.current_mode()->size();
76 gfx::SizeF touchscreen_size
= framebuffer_size
;
77 #elif defined(USE_OZONE)
78 gfx::SizeF touchscreen_size
= touchscreen
.size
;
81 if (display_size
.IsEmpty() || touchscreen_size
.IsEmpty())
84 return std::sqrt(display_size
.GetArea() / touchscreen_size
.GetArea());
87 // TODO(flackr:oshima): Remove this once athena switches to share
88 // ash::DisplayManager.
89 class ScreenForShutdown
: public gfx::Screen
{
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
,
100 explicit ScreenForShutdown(const gfx::Display
& primary_display
)
101 : primary_display_(primary_display
) {}
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
{
109 int GetNumDisplays() const override
{ return 1; }
110 std::vector
<gfx::Display
> GetAllDisplays() const override
{
111 std::vector
<gfx::Display
> displays(1, primary_display_
);
114 gfx::Display
GetDisplayNearestWindow(gfx::NativeView view
) const override
{
115 return primary_display_
;
117 gfx::Display
GetDisplayNearestPoint(const gfx::Point
& point
) const override
{
118 return primary_display_
;
120 gfx::Display
GetDisplayMatching(const gfx::Rect
& match_rect
) const override
{
121 return primary_display_
;
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";
127 void RemoveObserver(gfx::DisplayObserver
* observer
) override
{}
129 const gfx::Display primary_display_
;
131 DISALLOW_COPY_AND_ASSIGN(ScreenForShutdown
);
134 // A class that bridges the gap between CursorManager and Aura. It borrows
135 // heavily from AshNativeCursorManager.
136 class AthenaNativeCursorManager
: public wm::NativeCursorManager
{
138 explicit AthenaNativeCursorManager(aura::WindowTreeHost
* host
)
139 : host_(host
), image_cursors_(new ui::ImageCursors
) {}
140 ~AthenaNativeCursorManager() override
{}
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
);
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
);
155 if (delegate
->IsCursorVisible())
159 void SetVisibility(bool visible
,
160 wm::NativeCursorManagerDelegate
* delegate
) override
{
161 delegate
->CommitVisibility(visible
);
164 SetCursor(delegate
->GetCursor(), delegate
);
166 gfx::NativeCursor
invisible_cursor(ui::kCursorNone
);
167 image_cursors_
->SetPlatformCursor(&invisible_cursor
);
168 ApplyCursor(invisible_cursor
);
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
);
180 void SetMouseEventsEnabled(
182 wm::NativeCursorManagerDelegate
* delegate
) override
{
183 delegate
->CommitMouseEventsEnabled(enabled
);
184 SetVisibility(delegate
->IsCursorVisible(), delegate
);
188 // Sets |cursor| as the active cursor within Aura.
189 void ApplyCursor(gfx::NativeCursor cursor
) { host_
->SetCursor(cursor
); }
191 aura::WindowTreeHost
* host_
; // Not owned.
193 scoped_ptr
<ui::ImageCursors
> image_cursors_
;
195 DISALLOW_COPY_AND_ASSIGN(AthenaNativeCursorManager
);
198 class AthenaEnvImpl
: public AthenaEnv
,
199 public aura::WindowTreeHostObserver
,
200 public ui::DisplayConfigurator::Observer
,
201 public ui::InputDeviceEventObserver
{
203 AthenaEnvImpl() : display_configurator_(new ui::DisplayConfigurator
) {
204 display_configurator_
->Init(false);
205 display_configurator_
->ForceInitialConfigure(0);
206 display_configurator_
->AddObserver(this);
208 ui::DeviceDataManager::GetInstance()->AddObserver(this);
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);
216 screen_size
.SetSize(1280, 720);
218 screen_
.reset(aura::TestScreen::Create(screen_size
));
220 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE
, screen_
.get());
221 host_
.reset(screen_
->CreateHostForPrimaryDisplay());
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
);
229 root_window_event_filter_
.reset(new wm::CompoundEventFilter
);
230 host_
->window()->AddPreTargetHandler(root_window_event_filter_
.get());
232 root_window_event_filter_
->AddHandler(input_method_filter_
.get());
234 capture_client_
.reset(
235 new aura::client::DefaultCaptureClient(host_
->window()));
237 // Ensure new windows fill the display.
238 root_window
->SetLayoutManager(new FillLayoutManager(root_window
));
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());
248 user_activity_detector_
.reset(new wm::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()));
254 host_
->AddObserver(this);
261 ~AthenaEnvImpl() override
{
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());
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();
278 input_method_filter_
.reset();
281 ScreenForShutdown::Create(screen_
.get());
283 aura::Env::DeleteInstance();
285 ui::DeviceDataManager::GetInstance()->RemoveObserver(this);
287 display_configurator_
->RemoveObserver(this);
288 display_configurator_
.reset();
293 explicit Finder(const base::Closure
& c
) : closure(c
) {}
294 bool operator()(const base::Closure
& other
) {
295 return closure
.Equals(other
);
297 base::Closure closure
;
301 aura::WindowTreeHost
* GetHost() override
{ return host_
.get(); }
303 void SetDisplayWorkAreaInsets(const gfx::Insets
& insets
) override
{
304 screen_
->SetWorkAreaInsets(insets
);
307 void AddTerminatingCallback(const base::Closure
& closure
) override
{
308 if (closure
.is_null())
310 DCHECK(terminating_callbacks_
.end() ==
311 std::find_if(terminating_callbacks_
.begin(),
312 terminating_callbacks_
.end(),
314 terminating_callbacks_
.push_back(closure
);
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(),
322 if (iter
!= terminating_callbacks_
.end())
323 terminating_callbacks_
.erase(iter
);
326 void OnTerminating() override
{
327 for (std::vector
<base::Closure
>::iterator iter
=
328 terminating_callbacks_
.begin();
329 iter
!= terminating_callbacks_
.end();
335 // ui::DisplayConfigurator::Observer:
336 void OnDisplayModeChanged(
337 const std::vector
<ui::DisplayConfigurator::DisplayState
>& displays
)
339 MapTouchscreenToDisplay();
341 gfx::Size size
= GetPrimaryDisplaySize();
343 host_
->UpdateRootWindowSize(size
);
346 // ui::InputDeviceEventObserver:
347 void OnTouchscreenDeviceConfigurationChanged() override
{
348 MapTouchscreenToDisplay();
351 void OnKeyboardDeviceConfigurationChanged() override
{}
353 // aura::WindowTreeHostObserver:
354 void OnHostCloseRequested(const aura::WindowTreeHost
* host
) override
{
355 base::MessageLoopForUI::current()->PostTask(
356 FROM_HERE
, base::MessageLoop::QuitClosure());
359 gfx::Size
GetPrimaryDisplaySize() const {
360 const std::vector
<ui::DisplayConfigurator::DisplayState
>& displays
=
361 display_configurator_
->cached_displays();
362 if (displays
.empty())
364 const ui::DisplayMode
* mode
= displays
[0].display
->current_mode();
365 return mode
? mode
->size() : gfx::Size();
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();
373 if (displays
.empty() || touchscreens
.empty())
376 gfx::SizeF framebuffer_size
= display_configurator_
->framebuffer_size();
377 device_manager
->ClearTouchTransformerRecord();
378 device_manager
->UpdateTouchInfoForDisplay(
379 displays
[0].display
->display_id(),
381 GetTouchTransform(*displays
[0].display
,
384 device_manager
->UpdateTouchRadiusScale(
386 GetTouchRadiusScale(*displays
[0].display
,
391 scoped_ptr
<aura::TestScreen
> screen_
;
392 scoped_ptr
<aura::WindowTreeHost
> host_
;
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
<wm::UserActivityDetector
> user_activity_detector_
;
399 scoped_ptr
<ui::DisplayConfigurator
> display_configurator_
;
400 scoped_ptr
<ui::UserActivityPowerManagerNotifier
> user_activity_notifier_
;
402 std::vector
<base::Closure
> terminating_callbacks_
;
404 DISALLOW_COPY_AND_ASSIGN(AthenaEnvImpl
);
410 void AthenaEnv::Create() {
415 AthenaEnv
* AthenaEnv::Get() {
423 void AthenaEnv::Shutdown() {
428 } // namespace athena