12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/wm/ash_native_cursor_manager.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/display/cursor_window_controller.h"
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ash/display/display_controller.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shell.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/env.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
1323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/aura/window_tree_host.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/cursor/cursor.h"
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/base/cursor/image_cursors.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/base/layout.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace ash {
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace  {
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SetCursorOnAllRootWindows(gfx::NativeCursor cursor) {
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window::Windows root_windows =
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      Shell::GetInstance()->GetAllRootWindows();
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (aura::Window::Windows::iterator iter = root_windows.begin();
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != root_windows.end(); ++iter)
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    (*iter)->GetHost()->SetCursor(cursor);
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_CHROMEOS)
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Shell::GetInstance()->display_controller()->
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      cursor_window_controller()->SetCursor(cursor);
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotifyCursorVisibilityChange(bool visible) {
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window::Windows root_windows =
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      Shell::GetInstance()->GetAllRootWindows();
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (aura::Window::Windows::iterator iter = root_windows.begin();
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != root_windows.end(); ++iter)
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    (*iter)->GetHost()->OnCursorVisibilityChanged(visible);
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_CHROMEOS)
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Shell::GetInstance()->display_controller()->cursor_window_controller()->
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SetVisibility(visible);
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NotifyMouseEventsEnableStateChange(bool enabled) {
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  aura::Window::Windows root_windows =
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      Shell::GetInstance()->GetAllRootWindows();
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (aura::Window::Windows::iterator iter = root_windows.begin();
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != root_windows.end(); ++iter)
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    (*iter)->GetHost()->dispatcher()->OnMouseEventsEnableStateChanged(enabled);
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Mirror window never process events.
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AshNativeCursorManager::AshNativeCursorManager()
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : native_cursor_enabled_(true),
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      image_cursors_(new ui::ImageCursors) {
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AshNativeCursorManager::~AshNativeCursorManager() {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AshNativeCursorManager::SetNativeCursorEnabled(bool enabled) {
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  native_cursor_enabled_ = enabled;
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ::wm::CursorManager* cursor_manager =
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Shell::GetInstance()->cursor_manager();
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetCursor(cursor_manager->GetCursor(), cursor_manager);
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AshNativeCursorManager::SetDisplay(
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Display& display,
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ::wm::NativeCursorManagerDelegate* delegate) {
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(display.is_valid());
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Use the platform's device scale factor instead of the display's, which
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // might have been adjusted for the UI scale.
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const float original_scale = Shell::GetInstance()->display_manager()->
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      GetDisplayInfo(display.id()).device_scale_factor();
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // And use the nearest resource scale factor.
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const float cursor_scale = ui::GetScaleForScaleFactor(
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ui::GetSupportedScaleFactor(original_scale));
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#else
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(oshima): crbug.com/143619
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const float cursor_scale = original_scale;
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (image_cursors_->SetDisplay(display, cursor_scale))
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetCursor(delegate->GetCursor(), delegate);
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS)
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Shell::GetInstance()->display_controller()->cursor_window_controller()->
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SetDisplay(display);
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AshNativeCursorManager::SetCursor(
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::NativeCursor cursor,
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ::wm::NativeCursorManagerDelegate* delegate) {
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (native_cursor_enabled_) {
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    image_cursors_->SetPlatformCursor(&cursor);
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    gfx::NativeCursor invisible_cursor(ui::kCursorNone);
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    image_cursors_->SetPlatformCursor(&invisible_cursor);
1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (cursor == ui::kCursorCustom) {
1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      cursor = invisible_cursor;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      cursor.SetPlatformCursor(invisible_cursor.platform());
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  cursor.set_device_scale_factor(image_cursors_->GetScale());
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  delegate->CommitCursor(cursor);
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (delegate->IsCursorVisible())
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    SetCursorOnAllRootWindows(cursor);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void AshNativeCursorManager::SetCursorSet(
120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ui::CursorSetType cursor_set,
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ::wm::NativeCursorManagerDelegate* delegate) {
122424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  image_cursors_->SetCursorSet(cursor_set);
123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  delegate->CommitCursorSet(cursor_set);
124424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
125424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Sets the cursor to reflect the scale change immediately.
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (delegate->IsCursorVisible())
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetCursor(delegate->GetCursor(), delegate);
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_CHROMEOS)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Shell::GetInstance()->display_controller()->cursor_window_controller()->
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      SetCursorSet(cursor_set);
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
133424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AshNativeCursorManager::SetVisibility(
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool visible,
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ::wm::NativeCursorManagerDelegate* delegate) {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate->CommitVisibility(visible);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (visible) {
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SetCursor(delegate->GetCursor(), delegate);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::NativeCursor invisible_cursor(ui::kCursorNone);
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    image_cursors_->SetPlatformCursor(&invisible_cursor);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SetCursorOnAllRootWindows(invisible_cursor);
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotifyCursorVisibilityChange(visible);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AshNativeCursorManager::SetMouseEventsEnabled(
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool enabled,
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ::wm::NativeCursorManagerDelegate* delegate) {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate->CommitMouseEventsEnabled(enabled);
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (enabled) {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    aura::Env::GetInstance()->set_last_mouse_location(
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        disabled_cursor_location_);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    disabled_cursor_location_ = aura::Env::GetInstance()->last_mouse_location();
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetVisibility(delegate->IsCursorVisible(), delegate);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotifyMouseEventsEnableStateChange(enabled);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace ash
168