OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/display/root_window_transformers.h" | 5 #include "ash/display/root_window_transformers.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "ash/common/shelf/shelf_widget.h" | 9 #include "ash/common/shelf/shelf_widget.h" |
10 #include "ash/display/display_manager.h" | 10 #include "ash/display/display_manager.h" |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 float touch_radius_x_; | 104 float touch_radius_x_; |
105 float touch_radius_y_; | 105 float touch_radius_y_; |
106 float scroll_x_offset_; | 106 float scroll_x_offset_; |
107 float scroll_y_offset_; | 107 float scroll_y_offset_; |
108 float scroll_x_offset_ordinal_; | 108 float scroll_x_offset_ordinal_; |
109 float scroll_y_offset_ordinal_; | 109 float scroll_y_offset_ordinal_; |
110 | 110 |
111 DISALLOW_COPY_AND_ASSIGN(TestEventHandler); | 111 DISALLOW_COPY_AND_ASSIGN(TestEventHandler); |
112 }; | 112 }; |
113 | 113 |
114 float GetStoredUIScale(int64_t id) { | 114 class RootWindowTransformersTest : public test::AshTestBase { |
115 return Shell::GetInstance() | 115 public: |
116 ->display_manager() | 116 RootWindowTransformersTest(){}; |
117 ->GetDisplayInfo(id) | 117 ~RootWindowTransformersTest() override{}; |
118 .GetEffectiveUIScale(); | |
119 } | |
120 | 118 |
121 std::unique_ptr<RootWindowTransformer> | 119 float GetStoredUIScale(int64_t id) { |
122 CreateCurrentRootWindowTransformerForMirroring() { | 120 return display_manager()->GetDisplayInfo(id).GetEffectiveUIScale(); |
123 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); | 121 }; |
124 DCHECK(display_manager->IsInMirrorMode()); | 122 |
125 const display::ManagedDisplayInfo& mirror_display_info = | 123 std::unique_ptr<RootWindowTransformer> |
126 display_manager->GetDisplayInfo(display_manager->mirroring_display_id()); | 124 CreateCurrentRootWindowTransformerForMirroring() { |
127 const display::ManagedDisplayInfo& source_display_info = | 125 DCHECK(display_manager()->IsInMirrorMode()); |
128 display_manager->GetDisplayInfo( | 126 const display::ManagedDisplayInfo& mirror_display_info = |
129 display::Screen::GetScreen()->GetPrimaryDisplay().id()); | 127 display_manager()->GetDisplayInfo( |
130 return std::unique_ptr<RootWindowTransformer>( | 128 display_manager()->mirroring_display_id()); |
131 CreateRootWindowTransformerForMirroredDisplay(source_display_info, | 129 const display::ManagedDisplayInfo& source_display_info = |
132 mirror_display_info)); | 130 display_manager()->GetDisplayInfo( |
133 } | 131 display::Screen::GetScreen()->GetPrimaryDisplay().id()); |
| 132 return std::unique_ptr<RootWindowTransformer>( |
| 133 CreateRootWindowTransformerForMirroredDisplay(source_display_info, |
| 134 mirror_display_info)); |
| 135 }; |
| 136 |
| 137 DISALLOW_COPY_AND_ASSIGN(RootWindowTransformersTest); |
| 138 }; |
134 | 139 |
135 } // namespace | 140 } // namespace |
136 | 141 |
137 typedef test::AshTestBase RootWindowTransformersTest; | 142 // using RootWindowTransformersTest = test::AshTestBase; |
138 | 143 |
139 #if defined(OS_WIN) | 144 #if defined(OS_WIN) |
140 // TODO(scottmg): RootWindow doesn't get resized on Windows | 145 // TODO(scottmg): RootWindow doesn't get resized on Windows |
141 // Ash. http://crbug.com/247916. | 146 // Ash. http://crbug.com/247916. |
142 #define MAYBE_RotateAndMagnify DISABLED_RotateAndMagniy | 147 #define MAYBE_RotateAndMagnify DISABLED_RotateAndMagniy |
143 #define MAYBE_TouchScaleAndMagnify DISABLED_TouchScaleAndMagnify | 148 #define MAYBE_TouchScaleAndMagnify DISABLED_TouchScaleAndMagnify |
144 #define MAYBE_ConvertHostToRootCoords DISABLED_ConvertHostToRootCoords | 149 #define MAYBE_ConvertHostToRootCoords DISABLED_ConvertHostToRootCoords |
145 #else | 150 #else |
146 #define MAYBE_RotateAndMagnify RotateAndMagniy | 151 #define MAYBE_RotateAndMagnify RotateAndMagniy |
147 #define MAYBE_TouchScaleAndMagnify TouchScaleAndMagnify | 152 #define MAYBE_TouchScaleAndMagnify TouchScaleAndMagnify |
148 #define MAYBE_ConvertHostToRootCoords ConvertHostToRootCoords | 153 #define MAYBE_ConvertHostToRootCoords ConvertHostToRootCoords |
149 #endif | 154 #endif |
150 | 155 |
151 TEST_F(RootWindowTransformersTest, MAYBE_RotateAndMagnify) { | 156 TEST_F(RootWindowTransformersTest, MAYBE_RotateAndMagnify) { |
152 MagnificationController* magnifier = | 157 MagnificationController* magnifier = |
153 Shell::GetInstance()->magnification_controller(); | 158 Shell::GetInstance()->magnification_controller(); |
154 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); | |
155 | 159 |
156 TestEventHandler event_handler; | 160 TestEventHandler event_handler; |
157 Shell::GetInstance()->AddPreTargetHandler(&event_handler); | 161 Shell::GetInstance()->AddPreTargetHandler(&event_handler); |
158 | 162 |
159 UpdateDisplay("120x200,300x400*2"); | 163 UpdateDisplay("120x200,300x400*2"); |
160 display::Display display1 = display::Screen::GetScreen()->GetPrimaryDisplay(); | 164 display::Display display1 = display::Screen::GetScreen()->GetPrimaryDisplay(); |
161 int64_t display2_id = ScreenUtil::GetSecondaryDisplay().id(); | 165 int64_t display2_id = display_manager()->GetSecondaryDisplay().id(); |
162 | 166 |
163 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | 167 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
164 ui::test::EventGenerator generator1(root_windows[0]); | 168 ui::test::EventGenerator generator1(root_windows[0]); |
165 ui::test::EventGenerator generator2(root_windows[1]); | 169 ui::test::EventGenerator generator2(root_windows[1]); |
166 | 170 |
167 magnifier->SetEnabled(true); | 171 magnifier->SetEnabled(true); |
168 EXPECT_EQ(2.0f, magnifier->GetScale()); | 172 EXPECT_EQ(2.0f, magnifier->GetScale()); |
169 EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString()); | 173 EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString()); |
170 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString()); | 174 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString()); |
171 EXPECT_EQ("120,0 150x200", | 175 EXPECT_EQ("120,0 150x200", |
172 ScreenUtil::GetSecondaryDisplay().bounds().ToString()); | 176 display_manager()->GetSecondaryDisplay().bounds().ToString()); |
173 generator1.MoveMouseToInHost(40, 80); | 177 generator1.MoveMouseToInHost(40, 80); |
174 EXPECT_EQ("50,90", event_handler.GetLocationAndReset()); | 178 EXPECT_EQ("50,90", event_handler.GetLocationAndReset()); |
175 EXPECT_EQ("50,90", | 179 EXPECT_EQ("50,90", |
176 aura::Env::GetInstance()->last_mouse_location().ToString()); | 180 aura::Env::GetInstance()->last_mouse_location().ToString()); |
177 EXPECT_EQ(display::Display::ROTATE_0, | 181 EXPECT_EQ(display::Display::ROTATE_0, |
178 GetActiveDisplayRotation(display1.id())); | 182 GetActiveDisplayRotation(display1.id())); |
179 EXPECT_EQ(display::Display::ROTATE_0, GetActiveDisplayRotation(display2_id)); | 183 EXPECT_EQ(display::Display::ROTATE_0, GetActiveDisplayRotation(display2_id)); |
180 magnifier->SetEnabled(false); | 184 magnifier->SetEnabled(false); |
181 | 185 |
182 display_manager->SetDisplayRotation(display1.id(), | 186 display_manager()->SetDisplayRotation( |
183 display::Display::ROTATE_90, | 187 display1.id(), display::Display::ROTATE_90, |
184 display::Display::ROTATION_SOURCE_ACTIVE); | 188 display::Display::ROTATION_SOURCE_ACTIVE); |
185 // Move the cursor to the center of the first root window. | 189 // Move the cursor to the center of the first root window. |
186 generator1.MoveMouseToInHost(59, 100); | 190 generator1.MoveMouseToInHost(59, 100); |
187 | 191 |
188 magnifier->SetEnabled(true); | 192 magnifier->SetEnabled(true); |
189 EXPECT_EQ(2.0f, magnifier->GetScale()); | 193 EXPECT_EQ(2.0f, magnifier->GetScale()); |
190 EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString()); | 194 EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString()); |
191 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString()); | 195 EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString()); |
192 EXPECT_EQ("200,0 150x200", | 196 EXPECT_EQ("200,0 150x200", |
193 ScreenUtil::GetSecondaryDisplay().bounds().ToString()); | 197 display_manager()->GetSecondaryDisplay().bounds().ToString()); |
194 generator1.MoveMouseToInHost(39, 120); | 198 generator1.MoveMouseToInHost(39, 120); |
195 EXPECT_EQ("110,70", event_handler.GetLocationAndReset()); | 199 EXPECT_EQ("110,70", event_handler.GetLocationAndReset()); |
196 EXPECT_EQ("110,70", | 200 EXPECT_EQ("110,70", |
197 aura::Env::GetInstance()->last_mouse_location().ToString()); | 201 aura::Env::GetInstance()->last_mouse_location().ToString()); |
198 EXPECT_EQ(display::Display::ROTATE_90, | 202 EXPECT_EQ(display::Display::ROTATE_90, |
199 GetActiveDisplayRotation(display1.id())); | 203 GetActiveDisplayRotation(display1.id())); |
200 EXPECT_EQ(display::Display::ROTATE_0, GetActiveDisplayRotation(display2_id)); | 204 EXPECT_EQ(display::Display::ROTATE_0, GetActiveDisplayRotation(display2_id)); |
201 magnifier->SetEnabled(false); | 205 magnifier->SetEnabled(false); |
202 | 206 |
203 display_manager->SetLayoutForCurrentDisplays( | 207 display_manager()->SetLayoutForCurrentDisplays(test::CreateDisplayLayout( |
204 test::CreateDisplayLayout(display::DisplayPlacement::BOTTOM, 50)); | 208 display_manager(), display::DisplayPlacement::BOTTOM, 50)); |
205 EXPECT_EQ("50,120 150x200", | 209 EXPECT_EQ("50,120 150x200", |
206 ScreenUtil::GetSecondaryDisplay().bounds().ToString()); | 210 display_manager()->GetSecondaryDisplay().bounds().ToString()); |
207 | 211 |
208 display_manager->SetDisplayRotation(display2_id, display::Display::ROTATE_270, | 212 display_manager()->SetDisplayRotation( |
209 display::Display::ROTATION_SOURCE_ACTIVE); | 213 display2_id, display::Display::ROTATE_270, |
| 214 display::Display::ROTATION_SOURCE_ACTIVE); |
210 // Move the cursor to the center of the second root window. | 215 // Move the cursor to the center of the second root window. |
211 generator2.MoveMouseToInHost(151, 199); | 216 generator2.MoveMouseToInHost(151, 199); |
212 | 217 |
213 magnifier->SetEnabled(true); | 218 magnifier->SetEnabled(true); |
214 EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString()); | 219 EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString()); |
215 EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString()); | 220 EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString()); |
216 EXPECT_EQ("50,120 200x150", | 221 EXPECT_EQ("50,120 200x150", |
217 ScreenUtil::GetSecondaryDisplay().bounds().ToString()); | 222 display_manager()->GetSecondaryDisplay().bounds().ToString()); |
218 generator2.MoveMouseToInHost(172, 219); | 223 generator2.MoveMouseToInHost(172, 219); |
219 EXPECT_EQ("95,80", event_handler.GetLocationAndReset()); | 224 EXPECT_EQ("95,80", event_handler.GetLocationAndReset()); |
220 EXPECT_EQ("145,200", | 225 EXPECT_EQ("145,200", |
221 aura::Env::GetInstance()->last_mouse_location().ToString()); | 226 aura::Env::GetInstance()->last_mouse_location().ToString()); |
222 EXPECT_EQ(display::Display::ROTATE_90, | 227 EXPECT_EQ(display::Display::ROTATE_90, |
223 GetActiveDisplayRotation(display1.id())); | 228 GetActiveDisplayRotation(display1.id())); |
224 EXPECT_EQ(display::Display::ROTATE_270, | 229 EXPECT_EQ(display::Display::ROTATE_270, |
225 GetActiveDisplayRotation(display2_id)); | 230 GetActiveDisplayRotation(display2_id)); |
226 magnifier->SetEnabled(false); | 231 magnifier->SetEnabled(false); |
227 | 232 |
228 display_manager->SetDisplayRotation(display1.id(), | 233 display_manager()->SetDisplayRotation( |
229 display::Display::ROTATE_180, | 234 display1.id(), display::Display::ROTATE_180, |
230 display::Display::ROTATION_SOURCE_ACTIVE); | 235 display::Display::ROTATION_SOURCE_ACTIVE); |
231 // Move the cursor to the center of the first root window. | 236 // Move the cursor to the center of the first root window. |
232 generator1.MoveMouseToInHost(59, 99); | 237 generator1.MoveMouseToInHost(59, 99); |
233 | 238 |
234 magnifier->SetEnabled(true); | 239 magnifier->SetEnabled(true); |
235 EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString()); | 240 EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString()); |
236 EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString()); | 241 EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString()); |
237 // Dislay must share at least 100, so the x's offset becomes 20. | 242 // Dislay must share at least 100, so the x's offset becomes 20. |
238 EXPECT_EQ("20,200 200x150", | 243 EXPECT_EQ("20,200 200x150", |
239 ScreenUtil::GetSecondaryDisplay().bounds().ToString()); | 244 display_manager()->GetSecondaryDisplay().bounds().ToString()); |
240 generator1.MoveMouseToInHost(39, 59); | 245 generator1.MoveMouseToInHost(39, 59); |
241 EXPECT_EQ("70,120", event_handler.GetLocationAndReset()); | 246 EXPECT_EQ("70,120", event_handler.GetLocationAndReset()); |
242 EXPECT_EQ(display::Display::ROTATE_180, | 247 EXPECT_EQ(display::Display::ROTATE_180, |
243 GetActiveDisplayRotation(display1.id())); | 248 GetActiveDisplayRotation(display1.id())); |
244 EXPECT_EQ(display::Display::ROTATE_270, | 249 EXPECT_EQ(display::Display::ROTATE_270, |
245 GetActiveDisplayRotation(display2_id)); | 250 GetActiveDisplayRotation(display2_id)); |
246 magnifier->SetEnabled(false); | 251 magnifier->SetEnabled(false); |
247 | 252 |
248 Shell::GetInstance()->RemovePreTargetHandler(&event_handler); | 253 Shell::GetInstance()->RemovePreTargetHandler(&event_handler); |
249 } | 254 } |
250 | 255 |
251 TEST_F(RootWindowTransformersTest, ScaleAndMagnify) { | 256 TEST_F(RootWindowTransformersTest, ScaleAndMagnify) { |
252 if (!SupportsMultipleDisplays()) | 257 if (!SupportsMultipleDisplays()) |
253 return; | 258 return; |
254 | 259 |
255 TestEventHandler event_handler; | 260 TestEventHandler event_handler; |
256 Shell::GetInstance()->AddPreTargetHandler(&event_handler); | 261 Shell::GetInstance()->AddPreTargetHandler(&event_handler); |
257 | 262 |
258 UpdateDisplay("600x400*2@1.5,500x300"); | 263 UpdateDisplay("600x400*2@1.5,500x300"); |
259 | 264 |
260 display::Display display1 = display::Screen::GetScreen()->GetPrimaryDisplay(); | 265 display::Display display1 = display::Screen::GetScreen()->GetPrimaryDisplay(); |
261 test::ScopedSetInternalDisplayId set_internal(display1.id()); | 266 test::ScopedSetInternalDisplayId set_internal(display_manager(), |
262 display::Display display2 = ScreenUtil::GetSecondaryDisplay(); | 267 display1.id()); |
| 268 display::Display display2 = display_manager()->GetSecondaryDisplay(); |
263 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); | 269 aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
264 MagnificationController* magnifier = | 270 MagnificationController* magnifier = |
265 Shell::GetInstance()->magnification_controller(); | 271 Shell::GetInstance()->magnification_controller(); |
266 | 272 |
267 magnifier->SetEnabled(true); | 273 magnifier->SetEnabled(true); |
268 EXPECT_EQ(2.0f, magnifier->GetScale()); | 274 EXPECT_EQ(2.0f, magnifier->GetScale()); |
269 EXPECT_EQ("0,0 450x300", display1.bounds().ToString()); | 275 EXPECT_EQ("0,0 450x300", display1.bounds().ToString()); |
270 EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString()); | 276 EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString()); |
271 EXPECT_EQ("450,0 500x300", display2.bounds().ToString()); | 277 EXPECT_EQ("450,0 500x300", display2.bounds().ToString()); |
272 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id())); | 278 EXPECT_EQ(1.5f, GetStoredUIScale(display1.id())); |
273 EXPECT_EQ(1.0f, GetStoredUIScale(display2.id())); | 279 EXPECT_EQ(1.0f, GetStoredUIScale(display2.id())); |
274 | 280 |
275 ui::test::EventGenerator generator(root_windows[0]); | 281 ui::test::EventGenerator generator(root_windows[0]); |
276 generator.MoveMouseToInHost(500, 200); | 282 generator.MoveMouseToInHost(500, 200); |
277 EXPECT_EQ("299,150", event_handler.GetLocationAndReset()); | 283 EXPECT_EQ("299,150", event_handler.GetLocationAndReset()); |
278 magnifier->SetEnabled(false); | 284 magnifier->SetEnabled(false); |
279 | 285 |
280 Shell::GetInstance()->display_manager()->SetDisplayUIScale(display1.id(), | 286 display_manager()->SetDisplayUIScale(display1.id(), 1.25f); |
281 1.25f); | |
282 display1 = display::Screen::GetScreen()->GetPrimaryDisplay(); | 287 display1 = display::Screen::GetScreen()->GetPrimaryDisplay(); |
283 display2 = ScreenUtil::GetSecondaryDisplay(); | 288 display2 = display_manager()->GetSecondaryDisplay(); |
284 magnifier->SetEnabled(true); | 289 magnifier->SetEnabled(true); |
285 EXPECT_EQ(2.0f, magnifier->GetScale()); | 290 EXPECT_EQ(2.0f, magnifier->GetScale()); |
286 EXPECT_EQ("0,0 375x250", display1.bounds().ToString()); | 291 EXPECT_EQ("0,0 375x250", display1.bounds().ToString()); |
287 EXPECT_EQ("0,0 375x250", root_windows[0]->bounds().ToString()); | 292 EXPECT_EQ("0,0 375x250", root_windows[0]->bounds().ToString()); |
288 EXPECT_EQ("375,0 500x300", display2.bounds().ToString()); | 293 EXPECT_EQ("375,0 500x300", display2.bounds().ToString()); |
289 EXPECT_EQ(1.25f, GetStoredUIScale(display1.id())); | 294 EXPECT_EQ(1.25f, GetStoredUIScale(display1.id())); |
290 EXPECT_EQ(1.0f, GetStoredUIScale(display2.id())); | 295 EXPECT_EQ(1.0f, GetStoredUIScale(display2.id())); |
291 magnifier->SetEnabled(false); | 296 magnifier->SetEnabled(false); |
292 | 297 |
293 Shell::GetInstance()->RemovePreTargetHandler(&event_handler); | 298 Shell::GetInstance()->RemovePreTargetHandler(&event_handler); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 magnifier->SetEnabled(false); | 417 magnifier->SetEnabled(false); |
413 EXPECT_FLOAT_EQ(1.0f, magnifier->GetScale()); | 418 EXPECT_FLOAT_EQ(1.0f, magnifier->GetScale()); |
414 | 419 |
415 Shell::GetInstance()->RemovePreTargetHandler(&event_handler); | 420 Shell::GetInstance()->RemovePreTargetHandler(&event_handler); |
416 } | 421 } |
417 | 422 |
418 TEST_F(RootWindowTransformersTest, LetterBoxPillarBox) { | 423 TEST_F(RootWindowTransformersTest, LetterBoxPillarBox) { |
419 if (!SupportsMultipleDisplays()) | 424 if (!SupportsMultipleDisplays()) |
420 return; | 425 return; |
421 test::MirrorWindowTestApi test_api; | 426 test::MirrorWindowTestApi test_api; |
422 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); | 427 display_manager()->SetMultiDisplayMode(DisplayManager::MIRRORING); |
423 display_manager->SetMultiDisplayMode(DisplayManager::MIRRORING); | |
424 UpdateDisplay("400x200,500x500"); | 428 UpdateDisplay("400x200,500x500"); |
425 std::unique_ptr<RootWindowTransformer> transformer( | 429 std::unique_ptr<RootWindowTransformer> transformer( |
426 CreateCurrentRootWindowTransformerForMirroring()); | 430 CreateCurrentRootWindowTransformerForMirroring()); |
427 // Y margin must be margin is (500 - 500/400 * 200) / 2 = 125. | 431 // Y margin must be margin is (500 - 500/400 * 200) / 2 = 125. |
428 EXPECT_EQ("0,125,0,125", transformer->GetHostInsets().ToString()); | 432 EXPECT_EQ("0,125,0,125", transformer->GetHostInsets().ToString()); |
429 | 433 |
430 UpdateDisplay("200x400,500x500"); | 434 UpdateDisplay("200x400,500x500"); |
431 // The aspect ratio is flipped, so X margin is now 125. | 435 // The aspect ratio is flipped, so X margin is now 125. |
432 transformer = CreateCurrentRootWindowTransformerForMirroring(); | 436 transformer = CreateCurrentRootWindowTransformerForMirroring(); |
433 EXPECT_EQ("125,0,125,0", transformer->GetHostInsets().ToString()); | 437 EXPECT_EQ("125,0,125,0", transformer->GetHostInsets().ToString()); |
434 } | 438 } |
435 | 439 |
436 } // namespace ash | 440 } // namespace ash |
OLD | NEW |