1// Copyright (c) 2012 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 "ash/wm/image_cursors.h"
6
7#include <float.h>
8
9#include "base/logging.h"
10#include "base/strings/string16.h"
11#include "ui/base/cursor/cursor.h"
12#include "ui/base/cursor/cursor_loader.h"
13#include "ui/base/cursor/cursors_aura.h"
14#include "ui/gfx/display.h"
15#include "ui/gfx/point.h"
16
17namespace ash {
18
19const int kImageCursorIds[] = {
20  ui::kCursorNull,
21  ui::kCursorPointer,
22  ui::kCursorNoDrop,
23  ui::kCursorNotAllowed,
24  ui::kCursorCopy,
25  ui::kCursorHand,
26  ui::kCursorMove,
27  ui::kCursorNorthEastResize,
28  ui::kCursorSouthWestResize,
29  ui::kCursorSouthEastResize,
30  ui::kCursorNorthWestResize,
31  ui::kCursorNorthResize,
32  ui::kCursorSouthResize,
33  ui::kCursorEastResize,
34  ui::kCursorWestResize,
35  ui::kCursorIBeam,
36  ui::kCursorAlias,
37  ui::kCursorCell,
38  ui::kCursorContextMenu,
39  ui::kCursorCross,
40  ui::kCursorHelp,
41  ui::kCursorVerticalText,
42  ui::kCursorZoomIn,
43  ui::kCursorZoomOut,
44  ui::kCursorRowResize,
45  ui::kCursorColumnResize,
46  ui::kCursorEastWestResize,
47  ui::kCursorNorthSouthResize,
48  ui::kCursorNorthEastSouthWestResize,
49  ui::kCursorNorthWestSouthEastResize,
50  ui::kCursorGrab,
51  ui::kCursorGrabbing,
52};
53
54const int kAnimatedCursorIds[] = {
55  ui::kCursorWait,
56  ui::kCursorProgress
57};
58
59ImageCursors::ImageCursors() : scale_(1.f), cursor_set_(ui::CURSOR_SET_NORMAL) {
60}
61
62ImageCursors::~ImageCursors() {
63}
64
65gfx::Display ImageCursors::GetDisplay() const {
66  if (!cursor_loader_) {
67    NOTREACHED();
68    // Returning default on release build as it's not serious enough to crash
69    // even if this ever happens.
70    return gfx::Display();
71  }
72  return cursor_loader_->display();
73}
74
75bool ImageCursors::SetDisplay(const gfx::Display& display) {
76  float device_scale_factor = display.device_scale_factor();
77  if (!cursor_loader_) {
78    cursor_loader_.reset(ui::CursorLoader::Create());
79    cursor_loader_->set_scale(scale_);
80  } else if (cursor_loader_->display().rotation() == display.rotation() &&
81             cursor_loader_->display().device_scale_factor() ==
82             device_scale_factor) {
83    return false;
84  }
85
86  cursor_loader_->set_display(display);
87  ReloadCursors();
88  return true;
89}
90
91void ImageCursors::ReloadCursors() {
92  const gfx::Display& display = cursor_loader_->display();
93  float device_scale_factor = display.device_scale_factor();
94
95  cursor_loader_->UnloadAll();
96
97  for (size_t i = 0; i < arraysize(kImageCursorIds); ++i) {
98    int resource_id = -1;
99    gfx::Point hot_point;
100    bool success = ui::GetCursorDataFor(cursor_set_,
101                                        kImageCursorIds[i],
102                                        device_scale_factor,
103                                        &resource_id,
104                                        &hot_point);
105    DCHECK(success);
106    cursor_loader_->LoadImageCursor(kImageCursorIds[i], resource_id, hot_point);
107  }
108  for (size_t i = 0; i < arraysize(kAnimatedCursorIds); ++i) {
109    int resource_id = -1;
110    gfx::Point hot_point;
111    bool success = ui::GetAnimatedCursorDataFor(cursor_set_,
112                                                kAnimatedCursorIds[i],
113                                                device_scale_factor,
114                                                &resource_id,
115                                                &hot_point);
116    DCHECK(success);
117    cursor_loader_->LoadAnimatedCursor(kAnimatedCursorIds[i],
118                                       resource_id,
119                                       hot_point,
120                                       ui::kAnimatedCursorFrameDelayMs);
121  }
122}
123
124void ImageCursors::SetScale(float scale) {
125  if (scale < FLT_EPSILON) {
126    NOTREACHED() << "Scale must be bigger than 0.";
127    scale = 1.0f;
128  }
129
130  scale_ = scale;
131
132  if (cursor_loader_.get()) {
133    cursor_loader_->set_scale(scale);
134    ReloadCursors();
135  }
136}
137
138void ImageCursors::SetCursorSet(ui::CursorSetType cursor_set) {
139  if (cursor_set_ == cursor_set)
140    return;
141
142  cursor_set_ = cursor_set;
143
144  if (cursor_loader_.get())
145    ReloadCursors();
146}
147
148void ImageCursors::SetPlatformCursor(gfx::NativeCursor* cursor) {
149  cursor_loader_->SetPlatformCursor(cursor);
150}
151
152}  // namespace ash
153