cursor_window_controller.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/display/cursor_window_controller.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/display/display_controller.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/display/mirror_window_controller.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/root_window_controller.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shell.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shell_window_ids.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/env.h"
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/aura/window_delegate.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/cursor/cursors_aura.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/hit_test.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/compositor/dip_util.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/canvas.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/display.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/image/image_skia.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/image/image_skia_operations.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace ash {
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class CursorWindowDelegate : public aura::WindowDelegate {
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CursorWindowDelegate() : is_cursor_compositing_enabled_(false) {}
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~CursorWindowDelegate() {}
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // aura::WindowDelegate overrides:
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual gfx::Size GetMinimumSize() const OVERRIDE { return size_; }
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual gfx::Size GetMaximumSize() const OVERRIDE { return size_; }
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               const gfx::Rect& new_bounds) OVERRIDE {}
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE {
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return gfx::kNullCursor;
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual int GetNonClientComponent(
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const gfx::Point& point) const OVERRIDE {
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return HTNOWHERE;
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool ShouldDescendIntoChildForEventHandling(
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      aura::Window* child,
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const gfx::Point& location) OVERRIDE {
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool CanFocus() OVERRIDE { return false; }
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnCaptureLost() OVERRIDE {}
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    canvas->DrawImageInt(cursor_image_, 0, 0);
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnDeviceScaleFactorChanged(
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      float device_scale_factor) OVERRIDE {}
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {}
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {}
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {}
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual bool HasHitTestMask() const OVERRIDE { return false; }
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Sets cursor compositing mode on/off.
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetCursorCompositingEnabled(bool enabled) {
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    is_cursor_compositing_enabled_ = enabled;
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Sets the cursor image for the |display|'s scale factor.
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetCursorImage(const gfx::ImageSkia& image,
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      const gfx::Display& display) {
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    float scale_factor = display.device_scale_factor();
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const gfx::ImageSkiaRep& image_rep = image.GetRepresentation(scale_factor);
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!is_cursor_compositing_enabled_) {
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Note that mirror window's scale factor is always 1.0f, therefore we
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // need to take 2x's image and paint as if it's 1x image.
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      size_ = image_rep.pixel_size();
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      cursor_image_ = gfx::ImageSkia::CreateFrom1xBitmap(image_rep.sk_bitmap());
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      size_ = image.size();
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      cursor_image_ = gfx::ImageSkia(
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          gfx::ImageSkiaRep(image_rep.sk_bitmap(), scale_factor));
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::Size size() const { return size_; }
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private:
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool is_cursor_compositing_enabled_;
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::ImageSkia cursor_image_;
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Size size_;
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CursorWindowDelegate);
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CursorWindowController::CursorWindowController()
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : is_cursor_compositing_enabled_(false),
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      container_(NULL),
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      cursor_type_(ui::kCursorNone),
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      cursor_set_(ui::CURSOR_SET_NORMAL),
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      cursor_rotation_(gfx::Display::ROTATE_0),
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      delegate_(new CursorWindowDelegate()) {
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CursorWindowController::~CursorWindowController() {
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetContainer(NULL);
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CursorWindowController::SetCursorCompositingEnabled(bool enabled) {
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_cursor_compositing_enabled_ != enabled) {
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    is_cursor_compositing_enabled_ = enabled;
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    delegate_->SetCursorCompositingEnabled(enabled);
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UpdateCursorImage();
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UpdateContainer();
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CursorWindowController::UpdateContainer() {
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (is_cursor_compositing_enabled_) {
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    gfx::Screen* screen = Shell::GetScreen();
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    gfx::Display display = screen->GetDisplayNearestPoint(
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        screen->GetCursorScreenPoint());
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK(display.is_valid());
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (display.is_valid())
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SetDisplay(display);
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    aura::Window* mirror_window = Shell::GetInstance()->
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        display_controller()->
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        mirror_window_controller()->
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        GetWindow();
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (mirror_window)
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      display_ = Shell::GetScreen()->GetPrimaryDisplay();
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    SetContainer(mirror_window);
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CursorWindowController::SetDisplay(const gfx::Display& display) {
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!is_cursor_compositing_enabled_)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  display_ = display;
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aura::Window* root_window = Shell::GetInstance()->display_controller()->
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetRootWindowForDisplayId(display.id());
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!root_window)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetContainer(GetRootWindowController(root_window)->GetContainer(
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kShellWindowId_MouseCursorContainer));
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBoundsInScreen(display.bounds());
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CursorWindowController::UpdateLocation() {
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!cursor_window_)
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Point point = aura::Env::GetInstance()->last_mouse_location();
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!is_cursor_compositing_enabled_) {
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Shell::GetPrimaryRootWindow()->GetHost()->ConvertPointToHost(&point);
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    point.Offset(-bounds_in_screen_.x(), -bounds_in_screen_.y());
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  point.Offset(-hot_point_.x(), -hot_point_.y());
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::Rect bounds = cursor_window_->bounds();
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bounds.set_origin(point);
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor_window_->SetBounds(bounds);
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CursorWindowController::SetCursor(gfx::NativeCursor cursor) {
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (cursor_type_ == cursor.native_type() &&
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      cursor_rotation_ == display_.rotation())
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor_type_ = cursor.native_type();
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor_rotation_ = display_.rotation();
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UpdateCursorImage();
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CursorWindowController::SetCursorSet(ui::CursorSetType cursor_set) {
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor_set_ = cursor_set;
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UpdateCursorImage();
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CursorWindowController::SetVisibility(bool visible) {
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!cursor_window_)
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (visible)
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cursor_window_->Show();
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cursor_window_->Hide();
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CursorWindowController::SetContainer(aura::Window* container) {
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (container_ == container)
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  container_ = container;
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!container) {
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cursor_window_.reset();
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Reusing the window does not work when the display is disconnected.
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Just creates a new one instead. crbug.com/384218.
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  cursor_window_.reset(new aura::Window(delegate_.get()));
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  cursor_window_->SetTransparent(true);
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  cursor_window_->Init(aura::WINDOW_LAYER_TEXTURED);
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  cursor_window_->set_ignore_events(true);
202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  cursor_window_->set_owned_by_parent(false);
203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  UpdateCursorImage();
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  container->AddChild(cursor_window_.get());
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  cursor_window_->Show();
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SetBoundsInScreen(container->bounds());
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CursorWindowController::SetBoundsInScreen(const gfx::Rect& bounds) {
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bounds_in_screen_ = bounds;
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  UpdateLocation();
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CursorWindowController::UpdateCursorImage() {
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int resource_id;
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(hshi): support custom cursor set.
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ui::GetCursorDataFor(cursor_set_,
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            cursor_type_,
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            display_.device_scale_factor(),
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            &resource_id,
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            &hot_point_)) {
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const gfx::ImageSkia* image =
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gfx::ImageSkia rotated = *image;
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!is_cursor_compositing_enabled_) {
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    switch (cursor_rotation_) {
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case gfx::Display::ROTATE_0:
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case gfx::Display::ROTATE_90:
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        rotated = gfx::ImageSkiaOperations::CreateRotatedImage(
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            *image, SkBitmapOperations::ROTATION_90_CW);
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        hot_point_.SetPoint(
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            rotated.width() - hot_point_.y(),
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            hot_point_.x());
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case gfx::Display::ROTATE_180:
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        rotated = gfx::ImageSkiaOperations::CreateRotatedImage(
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            *image, SkBitmapOperations::ROTATION_180_CW);
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        hot_point_.SetPoint(
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            rotated.height() - hot_point_.x(),
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            rotated.width() - hot_point_.y());
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case gfx::Display::ROTATE_270:
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        rotated = gfx::ImageSkiaOperations::CreateRotatedImage(
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            *image, SkBitmapOperations::ROTATION_270_CW);
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        hot_point_.SetPoint(
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            hot_point_.y(),
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            rotated.height() - hot_point_.x());
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    hot_point_ = ui::ConvertPointToDIP(Shell::GetPrimaryRootWindow()->layer(),
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       hot_point_);
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delegate_->SetCursorImage(rotated, display_);
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (cursor_window_) {
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cursor_window_->SetBounds(gfx::Rect(delegate_->size()));
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    cursor_window_->SchedulePaintInRect(
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        gfx::Rect(cursor_window_->bounds().size()));
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UpdateLocation();
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace ash
268