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 "ash/display/cursor_window_controller.h" | |
6 | |
7 #include "ash/shell.h" | |
8 #include "ui/aura/env.h" | |
9 #include "ui/aura/root_window.h" | |
10 #include "ui/aura/window_delegate.h" | |
11 #include "ui/base/cursor/cursors_aura.h" | |
12 #include "ui/base/hit_test.h" | |
13 #include "ui/base/resource/resource_bundle.h" | |
14 #include "ui/compositor/dip_util.h" | |
15 #include "ui/gfx/canvas.h" | |
16 #include "ui/gfx/display.h" | |
17 #include "ui/gfx/image/image_skia.h" | |
18 #include "ui/gfx/image/image_skia_operations.h" | |
19 | |
20 namespace ash { | |
21 namespace internal { | |
22 | |
23 class CursorWindowDelegate : public aura::WindowDelegate { | |
24 public: | |
25 CursorWindowDelegate(bool for_mirroring) : for_mirroring_(for_mirroring) {} | |
26 virtual ~CursorWindowDelegate() {} | |
27 | |
28 // aura::WindowDelegate overrides: | |
29 virtual gfx::Size GetMinimumSize() const OVERRIDE { | |
30 return size_; | |
31 } | |
32 virtual gfx::Size GetMaximumSize() const OVERRIDE { | |
33 return size_; | |
34 } | |
35 virtual void OnBoundsChanged(const gfx::Rect& old_bounds, | |
36 const gfx::Rect& new_bounds) OVERRIDE { | |
37 } | |
38 virtual gfx::NativeCursor GetCursor(const gfx::Point& point) OVERRIDE { | |
39 return gfx::kNullCursor; | |
40 } | |
41 virtual int GetNonClientComponent( | |
42 const gfx::Point& point) const OVERRIDE { | |
43 return HTNOWHERE; | |
44 } | |
45 virtual bool ShouldDescendIntoChildForEventHandling( | |
46 aura::Window* child, | |
47 const gfx::Point& location) OVERRIDE { | |
48 return false; | |
49 } | |
50 virtual bool CanFocus() OVERRIDE { | |
51 return false; | |
52 } | |
53 virtual void OnCaptureLost() OVERRIDE { | |
54 } | |
55 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { | |
56 canvas->DrawImageInt(cursor_image_, 0, 0); | |
57 } | |
58 virtual void OnDeviceScaleFactorChanged( | |
59 float device_scale_factor) OVERRIDE { | |
60 } | |
61 virtual void OnWindowDestroying() OVERRIDE {} | |
62 virtual void OnWindowDestroyed() OVERRIDE {} | |
63 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE { | |
64 } | |
65 virtual bool HasHitTestMask() const OVERRIDE { | |
66 return false; | |
67 } | |
68 virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {} | |
69 virtual void DidRecreateLayer(ui::Layer* old_layer, | |
70 ui::Layer* new_layer) OVERRIDE {} | |
71 | |
72 // Set the cursor image for the |display|'s scale factor. | |
73 void SetCursorImage(const gfx::ImageSkia& image, | |
74 const gfx::Display& display) { | |
75 float scale_factor = display.device_scale_factor(); | |
76 const gfx::ImageSkiaRep& image_rep = image.GetRepresentation(scale_factor); | |
77 if (for_mirroring_) { | |
78 // Note that mirror window's scale factor is always 1.0f, therefore we | |
79 // need to take 2x's image and paint as if it's 1x image. | |
80 size_ = image_rep.pixel_size(); | |
81 cursor_image_ = gfx::ImageSkia::CreateFrom1xBitmap(image_rep.sk_bitmap()); | |
82 } else { | |
83 size_ = image.size(); | |
84 cursor_image_ = gfx::ImageSkia( | |
85 gfx::ImageSkiaRep(image_rep.sk_bitmap(), scale_factor)); | |
86 } | |
87 } | |
88 | |
89 const gfx::Size size() const { return size_; } | |
90 | |
91 private: | |
92 bool for_mirroring_; | |
93 gfx::ImageSkia cursor_image_; | |
94 gfx::Size size_; | |
95 | |
96 DISALLOW_COPY_AND_ASSIGN(CursorWindowDelegate); | |
97 }; | |
98 | |
99 CursorWindowController::CursorWindowController(bool for_mirroring) | |
100 : for_mirroring_(for_mirroring), | |
101 current_cursor_type_(ui::kCursorNone), | |
102 current_cursor_set_(ui::CURSOR_SET_NORMAL), | |
103 requested_cursor_set_(ui::CURSOR_SET_NORMAL), | |
104 current_cursor_rotation_(gfx::Display::ROTATE_0), | |
105 cursor_window_(NULL), | |
106 cursor_window_delegate_(new CursorWindowDelegate(for_mirroring)) { | |
107 } | |
108 | |
109 CursorWindowController::~CursorWindowController() { | |
110 CloseCursorWindow(); | |
111 } | |
112 | |
113 void CursorWindowController::InitCursorWindow(aura::Window* container) { | |
114 DCHECK(container); | |
115 | |
116 cursor_window_ = new aura::Window(cursor_window_delegate_.get()); | |
117 cursor_window_->SetTransparent(true); | |
118 cursor_window_->Init(aura::WINDOW_LAYER_TEXTURED); | |
119 cursor_window_->set_ignore_events(true); | |
120 container->AddChild(cursor_window_); | |
121 cursor_window_->Show(); | |
122 } | |
123 | |
124 void CursorWindowController::CloseCursorWindow() { | |
125 cursor_window_ = NULL; | |
126 } | |
127 | |
128 void CursorWindowController::UpdateCursorLocation() { | |
129 if (!cursor_window_) | |
130 return; | |
131 | |
132 gfx::Point point = aura::Env::GetInstance()->last_mouse_location(); | |
133 if (for_mirroring_) { | |
134 // TODO(oshima): Rotate cursor image (including hotpoint). | |
oshima
2014/02/03 20:35:53
can you remove this comment?
hshi1
2014/02/03 21:43:33
Done.
| |
135 Shell::GetPrimaryRootWindow()->GetDispatcher()->host()->ConvertPointToHost( | |
136 &point); | |
137 } | |
138 point.Offset(-hot_point_.x(), -hot_point_.y()); | |
139 gfx::Rect bounds = cursor_window_->bounds(); | |
140 bounds.set_origin(point); | |
141 cursor_window_->SetBounds(bounds); | |
142 } | |
143 | |
144 void CursorWindowController::SetCursor(gfx::NativeCursor cursor) { | |
145 const gfx::Display& display = Shell::GetScreen()->GetPrimaryDisplay(); | |
146 if (current_cursor_type_ == cursor.native_type() && | |
147 current_cursor_set_ == requested_cursor_set_ && | |
148 current_cursor_rotation_ == display.rotation()) | |
149 return; | |
150 current_cursor_type_ = cursor.native_type(); | |
151 current_cursor_set_ = requested_cursor_set_; | |
152 current_cursor_rotation_ = display.rotation(); | |
153 int resource_id; | |
154 bool success = ui::GetCursorDataFor( | |
155 current_cursor_set_, // Not support custom cursor set. | |
156 current_cursor_type_, | |
157 display.device_scale_factor(), | |
158 &resource_id, | |
159 &hot_point_); | |
160 if (!success) | |
161 return; | |
162 const gfx::ImageSkia* image = | |
163 ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id); | |
164 gfx::ImageSkia rotated = *image; | |
165 if (for_mirroring_) { | |
166 switch (current_cursor_rotation_) { | |
167 case gfx::Display::ROTATE_0: | |
168 break; | |
169 case gfx::Display::ROTATE_90: | |
170 rotated = gfx::ImageSkiaOperations::CreateRotatedImage( | |
171 *image, SkBitmapOperations::ROTATION_90_CW); | |
172 hot_point_.SetPoint( | |
173 rotated.width() - hot_point_.y(), | |
174 hot_point_.x()); | |
175 break; | |
176 case gfx::Display::ROTATE_180: | |
177 rotated = gfx::ImageSkiaOperations::CreateRotatedImage( | |
178 *image, SkBitmapOperations::ROTATION_180_CW); | |
179 hot_point_.SetPoint( | |
180 rotated.height() - hot_point_.x(), | |
181 rotated.width() - hot_point_.y()); | |
182 break; | |
183 case gfx::Display::ROTATE_270: | |
184 rotated = gfx::ImageSkiaOperations::CreateRotatedImage( | |
185 *image, SkBitmapOperations::ROTATION_270_CW); | |
186 hot_point_.SetPoint( | |
187 hot_point_.y(), | |
188 rotated.height() - hot_point_.x()); | |
189 break; | |
190 } | |
191 } else { | |
192 hot_point_ = ui::ConvertPointToDIP(Shell::GetPrimaryRootWindow()->layer(), | |
193 hot_point_); | |
194 } | |
195 if (cursor_window_) { | |
196 cursor_window_->SetBounds(gfx::Rect(cursor_window_delegate_->size())); | |
197 cursor_window_->SchedulePaintInRect( | |
198 gfx::Rect(cursor_window_->bounds().size())); | |
199 cursor_window_delegate_->SetCursorImage(rotated, display); | |
200 } | |
201 } | |
202 | |
203 void CursorWindowController::SetCursorSet(ui::CursorSetType cursor_set) { | |
204 requested_cursor_set_ = cursor_set; | |
205 SetCursor(gfx::NativeCursor(current_cursor_type_)); | |
206 } | |
207 | |
208 void CursorWindowController::SetCursorVisibility(bool visible) { | |
209 if (!cursor_window_) | |
210 return; | |
211 if (visible) | |
212 cursor_window_->Show(); | |
213 else | |
214 cursor_window_->Hide(); | |
215 } | |
216 | |
217 } // namespace internal | |
218 } // namespace ash | |
OLD | NEW |