OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "ui/views/widget/native_widget_aura.h" | 5 #include "ui/views/widget/native_widget_aura.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
9 #include "ui/aura/client/activation_client.h" | 9 #include "ui/aura/client/activation_client.h" |
10 #include "ui/aura/client/aura_constants.h" | 10 #include "ui/aura/client/aura_constants.h" |
11 #include "ui/aura/client/drag_drop_client.h" | 11 #include "ui/aura/client/drag_drop_client.h" |
| 12 #include "ui/aura/client/window_types.h" |
12 #include "ui/aura/event.h" | 13 #include "ui/aura/event.h" |
13 #include "ui/aura/root_window.h" | 14 #include "ui/aura/root_window.h" |
14 #include "ui/aura/window.h" | 15 #include "ui/aura/window.h" |
15 #include "ui/aura/window_observer.h" | 16 #include "ui/aura/window_observer.h" |
16 #include "ui/aura/window_types.h" | |
17 #include "ui/base/dragdrop/os_exchange_data.h" | 17 #include "ui/base/dragdrop/os_exchange_data.h" |
18 #include "ui/base/ui_base_types.h" | 18 #include "ui/base/ui_base_types.h" |
19 #include "ui/gfx/canvas.h" | 19 #include "ui/gfx/canvas.h" |
20 #include "ui/gfx/compositor/layer.h" | 20 #include "ui/gfx/compositor/layer.h" |
21 #include "ui/gfx/font.h" | 21 #include "ui/gfx/font.h" |
22 #include "ui/gfx/screen.h" | 22 #include "ui/gfx/screen.h" |
23 #include "ui/views/widget/drop_helper.h" | 23 #include "ui/views/widget/drop_helper.h" |
24 #include "ui/views/widget/native_widget_delegate.h" | 24 #include "ui/views/widget/native_widget_delegate.h" |
25 #include "ui/views/widget/tooltip_manager_aura.h" | 25 #include "ui/views/widget/tooltip_manager_aura.h" |
26 #include "ui/views/widget/widget_delegate.h" | 26 #include "ui/views/widget/widget_delegate.h" |
27 | 27 |
28 #if defined(OS_WIN) | 28 #if defined(OS_WIN) |
29 #include "base/win/scoped_gdi_object.h" | 29 #include "base/win/scoped_gdi_object.h" |
30 #include "base/win/win_util.h" | 30 #include "base/win/win_util.h" |
31 #include "ui/base/l10n/l10n_util_win.h" | 31 #include "ui/base/l10n/l10n_util_win.h" |
32 #endif | 32 #endif |
33 | 33 |
34 #if defined(HAVE_IBUS) | 34 #if defined(HAVE_IBUS) |
35 #include "ui/views/ime/input_method_ibus.h" | 35 #include "ui/views/ime/input_method_ibus.h" |
36 #else | 36 #else |
37 #include "ui/views/ime/mock_input_method.h" | 37 #include "ui/views/ime/mock_input_method.h" |
38 #endif | 38 #endif |
39 | 39 |
40 namespace views { | 40 namespace views { |
41 | 41 |
42 namespace { | 42 namespace { |
43 | 43 |
44 aura::WindowType GetAuraWindowTypeForWidgetType(Widget::InitParams::Type type) { | 44 aura::client::WindowType GetAuraWindowTypeForWidgetType( |
| 45 Widget::InitParams::Type type) { |
45 switch (type) { | 46 switch (type) { |
46 case Widget::InitParams::TYPE_WINDOW: | 47 case Widget::InitParams::TYPE_WINDOW: |
47 return aura::WINDOW_TYPE_NORMAL; | 48 return aura::client::WINDOW_TYPE_NORMAL; |
48 case Widget::InitParams::TYPE_WINDOW_FRAMELESS: | 49 case Widget::InitParams::TYPE_WINDOW_FRAMELESS: |
49 case Widget::InitParams::TYPE_CONTROL: | 50 case Widget::InitParams::TYPE_CONTROL: |
50 case Widget::InitParams::TYPE_POPUP: | 51 case Widget::InitParams::TYPE_POPUP: |
51 case Widget::InitParams::TYPE_BUBBLE: | 52 case Widget::InitParams::TYPE_BUBBLE: |
52 return aura::WINDOW_TYPE_POPUP; | 53 return aura::client::WINDOW_TYPE_POPUP; |
53 case Widget::InitParams::TYPE_MENU: | 54 case Widget::InitParams::TYPE_MENU: |
54 return aura::WINDOW_TYPE_MENU; | 55 return aura::client::WINDOW_TYPE_MENU; |
55 case Widget::InitParams::TYPE_TOOLTIP: | 56 case Widget::InitParams::TYPE_TOOLTIP: |
56 return aura::WINDOW_TYPE_TOOLTIP; | 57 return aura::client::WINDOW_TYPE_TOOLTIP; |
57 default: | 58 default: |
58 NOTREACHED() << "Unhandled widget type " << type; | 59 NOTREACHED() << "Unhandled widget type " << type; |
59 return aura::WINDOW_TYPE_UNKNOWN; | 60 return aura::client::WINDOW_TYPE_UNKNOWN; |
60 } | 61 } |
61 } | 62 } |
62 | 63 |
63 void NotifyLocaleChangedInternal(aura::Window* window) { | 64 void NotifyLocaleChangedInternal(aura::Window* window) { |
64 Widget* widget = Widget::GetWidgetForNativeWindow(window); | 65 Widget* widget = Widget::GetWidgetForNativeWindow(window); |
65 if (widget) | 66 if (widget) |
66 widget->LocaleChanged(); | 67 widget->LocaleChanged(); |
67 | 68 |
68 const aura::Window::Windows& children = window->children(); | 69 const aura::Window::Windows& children = window->children(); |
69 for (aura::Window::Windows::const_iterator it = children.begin(); | 70 for (aura::Window::Windows::const_iterator it = children.begin(); |
(...skipping 12 matching lines...) Expand all Loading... |
82 aura::RootWindow::GetInstance()->AddObserver(this); | 83 aura::RootWindow::GetInstance()->AddObserver(this); |
83 } | 84 } |
84 virtual ~ActiveWindowObserver() { | 85 virtual ~ActiveWindowObserver() { |
85 aura::RootWindow::GetInstance()->RemoveObserver(this); | 86 aura::RootWindow::GetInstance()->RemoveObserver(this); |
86 } | 87 } |
87 | 88 |
88 // Overridden from aura::WindowObserver: | 89 // Overridden from aura::WindowObserver: |
89 virtual void OnWindowPropertyChanged(aura::Window* window, | 90 virtual void OnWindowPropertyChanged(aura::Window* window, |
90 const char* key, | 91 const char* key, |
91 void* old) OVERRIDE { | 92 void* old) OVERRIDE { |
92 if (key != aura::kRootWindowActiveWindow) | 93 if (key != aura::client::kRootWindowActiveWindow) |
93 return; | 94 return; |
94 aura::Window* active = | 95 aura::Window* active = |
95 aura::client::GetActivationClient()->GetActiveWindow(); | 96 aura::client::GetActivationClient()->GetActiveWindow(); |
96 if (!active || (active != host_->window_ && | 97 if (!active || (active != host_->window_ && |
97 active->transient_parent() != host_->window_)) { | 98 active->transient_parent() != host_->window_)) { |
98 host_->delegate_->EnableInactiveRendering(); | 99 host_->delegate_->EnableInactiveRendering(); |
99 } | 100 } |
100 } | 101 } |
101 | 102 |
102 private: | 103 private: |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 //////////////////////////////////////////////////////////////////////////////// | 144 //////////////////////////////////////////////////////////////////////////////// |
144 // NativeWidgetAura, internal::NativeWidgetPrivate implementation: | 145 // NativeWidgetAura, internal::NativeWidgetPrivate implementation: |
145 | 146 |
146 void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) { | 147 void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) { |
147 ownership_ = params.ownership; | 148 ownership_ = params.ownership; |
148 window_->set_user_data(this); | 149 window_->set_user_data(this); |
149 Widget::InitParams::Type window_type = | 150 Widget::InitParams::Type window_type = |
150 params.child ? Widget::InitParams::TYPE_CONTROL : params.type; | 151 params.child ? Widget::InitParams::TYPE_CONTROL : params.type; |
151 window_->SetType(GetAuraWindowTypeForWidgetType(window_type)); | 152 window_->SetType(GetAuraWindowTypeForWidgetType(window_type)); |
152 // TODO(jamescook): Should this use params.show_state instead? | 153 // TODO(jamescook): Should this use params.show_state instead? |
153 window_->SetIntProperty(aura::kShowStateKey, ui::SHOW_STATE_NORMAL); | 154 window_->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); |
154 window_->Init(params.create_texture_for_layer ? | 155 window_->Init(params.create_texture_for_layer ? |
155 ui::Layer::LAYER_HAS_TEXTURE : | 156 ui::Layer::LAYER_HAS_TEXTURE : |
156 ui::Layer::LAYER_HAS_NO_TEXTURE); | 157 ui::Layer::LAYER_HAS_NO_TEXTURE); |
157 if (window_type == Widget::InitParams::TYPE_CONTROL) | 158 if (window_type == Widget::InitParams::TYPE_CONTROL) |
158 window_->Show(); | 159 window_->Show(); |
159 | 160 |
160 window_->layer()->SetFillsBoundsOpaquely(!params.transparent); | 161 window_->layer()->SetFillsBoundsOpaquely(!params.transparent); |
161 delegate_->OnNativeWidgetCreated(); | 162 delegate_->OnNativeWidgetCreated(); |
162 window_->SetBounds(params.bounds); | 163 window_->SetBounds(params.bounds); |
163 if (window_type == Widget::InitParams::TYPE_CONTROL) { | 164 if (window_type == Widget::InitParams::TYPE_CONTROL) { |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 size.width(), | 311 size.width(), |
311 size.height())); | 312 size.height())); |
312 } | 313 } |
313 | 314 |
314 void NativeWidgetAura::GetWindowPlacement( | 315 void NativeWidgetAura::GetWindowPlacement( |
315 gfx::Rect* bounds, | 316 gfx::Rect* bounds, |
316 ui::WindowShowState* show_state) const { | 317 ui::WindowShowState* show_state) const { |
317 // The interface specifies returning restored bounds, not current bounds. | 318 // The interface specifies returning restored bounds, not current bounds. |
318 *bounds = GetRestoredBounds(); | 319 *bounds = GetRestoredBounds(); |
319 *show_state = static_cast<ui::WindowShowState>( | 320 *show_state = static_cast<ui::WindowShowState>( |
320 window_->GetIntProperty(aura::kShowStateKey)); | 321 window_->GetIntProperty(aura::client::kShowStateKey)); |
321 } | 322 } |
322 | 323 |
323 void NativeWidgetAura::SetWindowTitle(const string16& title) { | 324 void NativeWidgetAura::SetWindowTitle(const string16& title) { |
324 window_->set_title(title); | 325 window_->set_title(title); |
325 } | 326 } |
326 | 327 |
327 void NativeWidgetAura::SetWindowIcons(const SkBitmap& window_icon, | 328 void NativeWidgetAura::SetWindowIcons(const SkBitmap& window_icon, |
328 const SkBitmap& app_icon) { | 329 const SkBitmap& app_icon) { |
329 // Aura doesn't have window icons. | 330 // Aura doesn't have window icons. |
330 } | 331 } |
331 | 332 |
332 void NativeWidgetAura::SetAccessibleName(const string16& name) { | 333 void NativeWidgetAura::SetAccessibleName(const string16& name) { |
333 // http://crbug.com/102570 | 334 // http://crbug.com/102570 |
334 //NOTIMPLEMENTED(); | 335 //NOTIMPLEMENTED(); |
335 } | 336 } |
336 | 337 |
337 void NativeWidgetAura::SetAccessibleRole(ui::AccessibilityTypes::Role role) { | 338 void NativeWidgetAura::SetAccessibleRole(ui::AccessibilityTypes::Role role) { |
338 // http://crbug.com/102570 | 339 // http://crbug.com/102570 |
339 //NOTIMPLEMENTED(); | 340 //NOTIMPLEMENTED(); |
340 } | 341 } |
341 | 342 |
342 void NativeWidgetAura::SetAccessibleState(ui::AccessibilityTypes::State state) { | 343 void NativeWidgetAura::SetAccessibleState(ui::AccessibilityTypes::State state) { |
343 // http://crbug.com/102570 | 344 // http://crbug.com/102570 |
344 //NOTIMPLEMENTED(); | 345 //NOTIMPLEMENTED(); |
345 } | 346 } |
346 | 347 |
347 void NativeWidgetAura::BecomeModal() { | 348 void NativeWidgetAura::BecomeModal() { |
348 window_->SetIntProperty(aura::kModalKey, 1); | 349 window_->SetIntProperty(aura::client::kModalKey, 1); |
349 } | 350 } |
350 | 351 |
351 gfx::Rect NativeWidgetAura::GetWindowScreenBounds() const { | 352 gfx::Rect NativeWidgetAura::GetWindowScreenBounds() const { |
352 return window_->GetScreenBounds(); | 353 return window_->GetScreenBounds(); |
353 } | 354 } |
354 | 355 |
355 gfx::Rect NativeWidgetAura::GetClientAreaScreenBounds() const { | 356 gfx::Rect NativeWidgetAura::GetClientAreaScreenBounds() const { |
356 // In Aura, the entire window is the client area. | 357 // In Aura, the entire window is the client area. |
357 return window_->GetScreenBounds(); | 358 return window_->GetScreenBounds(); |
358 } | 359 } |
359 | 360 |
360 gfx::Rect NativeWidgetAura::GetRestoredBounds() const { | 361 gfx::Rect NativeWidgetAura::GetRestoredBounds() const { |
361 gfx::Rect* restore_bounds = reinterpret_cast<gfx::Rect*>( | 362 gfx::Rect* restore_bounds = reinterpret_cast<gfx::Rect*>( |
362 window_->GetProperty(aura::kRestoreBoundsKey)); | 363 window_->GetProperty(aura::client::kRestoreBoundsKey)); |
363 return restore_bounds ? *restore_bounds : window_->bounds(); | 364 return restore_bounds ? *restore_bounds : window_->bounds(); |
364 } | 365 } |
365 | 366 |
366 void NativeWidgetAura::SetBounds(const gfx::Rect& bounds) { | 367 void NativeWidgetAura::SetBounds(const gfx::Rect& bounds) { |
367 window_->SetBounds(bounds); | 368 window_->SetBounds(bounds); |
368 } | 369 } |
369 | 370 |
370 void NativeWidgetAura::SetSize(const gfx::Size& size) { | 371 void NativeWidgetAura::SetSize(const gfx::Size& size) { |
371 window_->SetBounds(gfx::Rect(window_->bounds().origin(), size)); | 372 window_->SetBounds(gfx::Rect(window_->bounds().origin(), size)); |
372 } | 373 } |
(...skipping 12 matching lines...) Expand all Loading... |
385 } | 386 } |
386 | 387 |
387 void NativeWidgetAura::Close() { | 388 void NativeWidgetAura::Close() { |
388 // |window_| may already be deleted by parent window. This can happen | 389 // |window_| may already be deleted by parent window. This can happen |
389 // when this widget is child widget or has transient parent | 390 // when this widget is child widget or has transient parent |
390 // and ownership is WIDGET_OWNS_NATIVE_WIDGET. | 391 // and ownership is WIDGET_OWNS_NATIVE_WIDGET. |
391 DCHECK(window_ || | 392 DCHECK(window_ || |
392 ownership_ == Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET); | 393 ownership_ == Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET); |
393 if (window_) { | 394 if (window_) { |
394 Hide(); | 395 Hide(); |
395 window_->SetIntProperty(aura::kModalKey, 0); | 396 window_->SetIntProperty(aura::client::kModalKey, 0); |
396 } | 397 } |
397 | 398 |
398 if (!close_widget_factory_.HasWeakPtrs()) { | 399 if (!close_widget_factory_.HasWeakPtrs()) { |
399 MessageLoop::current()->PostTask( | 400 MessageLoop::current()->PostTask( |
400 FROM_HERE, | 401 FROM_HERE, |
401 base::Bind(&NativeWidgetAura::CloseNow, | 402 base::Bind(&NativeWidgetAura::CloseNow, |
402 close_widget_factory_.GetWeakPtr())); | 403 close_widget_factory_.GetWeakPtr())); |
403 } | 404 } |
404 } | 405 } |
405 | 406 |
(...skipping 11 matching lines...) Expand all Loading... |
417 | 418 |
418 void NativeWidgetAura::ShowMaximizedWithBounds( | 419 void NativeWidgetAura::ShowMaximizedWithBounds( |
419 const gfx::Rect& restored_bounds) { | 420 const gfx::Rect& restored_bounds) { |
420 window_->SetBounds(restored_bounds); | 421 window_->SetBounds(restored_bounds); |
421 ShowWithWindowState(ui::SHOW_STATE_MAXIMIZED); | 422 ShowWithWindowState(ui::SHOW_STATE_MAXIMIZED); |
422 } | 423 } |
423 | 424 |
424 void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) { | 425 void NativeWidgetAura::ShowWithWindowState(ui::WindowShowState state) { |
425 if (state == ui::SHOW_STATE_MAXIMIZED || | 426 if (state == ui::SHOW_STATE_MAXIMIZED || |
426 state == ui::SHOW_STATE_FULLSCREEN) { | 427 state == ui::SHOW_STATE_FULLSCREEN) { |
427 window_->SetIntProperty(aura::kShowStateKey, state); | 428 window_->SetIntProperty(aura::client::kShowStateKey, state); |
428 } | 429 } |
429 window_->Show(); | 430 window_->Show(); |
430 if (can_activate_ && (state != ui::SHOW_STATE_INACTIVE || | 431 if (can_activate_ && (state != ui::SHOW_STATE_INACTIVE || |
431 !GetWidget()->SetInitialFocus())) { | 432 !GetWidget()->SetInitialFocus())) { |
432 Activate(); | 433 Activate(); |
433 } | 434 } |
434 } | 435 } |
435 | 436 |
436 bool NativeWidgetAura::IsVisible() const { | 437 bool NativeWidgetAura::IsVisible() const { |
437 return window_->IsVisible(); | 438 return window_->IsVisible(); |
438 } | 439 } |
439 | 440 |
440 void NativeWidgetAura::Activate() { | 441 void NativeWidgetAura::Activate() { |
441 aura::client::GetActivationClient()->ActivateWindow(window_); | 442 aura::client::GetActivationClient()->ActivateWindow(window_); |
442 } | 443 } |
443 | 444 |
444 void NativeWidgetAura::Deactivate() { | 445 void NativeWidgetAura::Deactivate() { |
445 aura::client::GetActivationClient()->DeactivateWindow(window_); | 446 aura::client::GetActivationClient()->DeactivateWindow(window_); |
446 } | 447 } |
447 | 448 |
448 bool NativeWidgetAura::IsActive() const { | 449 bool NativeWidgetAura::IsActive() const { |
449 return aura::client::GetActivationClient()->GetActiveWindow() == window_; | 450 return aura::client::GetActivationClient()->GetActiveWindow() == window_; |
450 } | 451 } |
451 | 452 |
452 void NativeWidgetAura::SetAlwaysOnTop(bool on_top) { | 453 void NativeWidgetAura::SetAlwaysOnTop(bool on_top) { |
453 window_->SetIntProperty(aura::kAlwaysOnTopKey, on_top); | 454 window_->SetIntProperty(aura::client::kAlwaysOnTopKey, on_top); |
454 } | 455 } |
455 | 456 |
456 void NativeWidgetAura::Maximize() { | 457 void NativeWidgetAura::Maximize() { |
457 window_->SetIntProperty(aura::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); | 458 window_->SetIntProperty(aura::client::kShowStateKey, |
| 459 ui::SHOW_STATE_MAXIMIZED); |
458 } | 460 } |
459 | 461 |
460 void NativeWidgetAura::Minimize() { | 462 void NativeWidgetAura::Minimize() { |
461 // No minimized window for aura. crbug.com/104571. | 463 // No minimized window for aura. crbug.com/104571. |
462 NOTREACHED(); | 464 NOTREACHED(); |
463 } | 465 } |
464 | 466 |
465 bool NativeWidgetAura::IsMaximized() const { | 467 bool NativeWidgetAura::IsMaximized() const { |
466 return window_->GetIntProperty(aura::kShowStateKey) == | 468 return window_->GetIntProperty(aura::client::kShowStateKey) == |
467 ui::SHOW_STATE_MAXIMIZED; | 469 ui::SHOW_STATE_MAXIMIZED; |
468 } | 470 } |
469 | 471 |
470 bool NativeWidgetAura::IsMinimized() const { | 472 bool NativeWidgetAura::IsMinimized() const { |
471 return window_->GetIntProperty(aura::kShowStateKey) == | 473 return window_->GetIntProperty(aura::client::kShowStateKey) == |
472 ui::SHOW_STATE_MINIMIZED; | 474 ui::SHOW_STATE_MINIMIZED; |
473 } | 475 } |
474 | 476 |
475 void NativeWidgetAura::Restore() { | 477 void NativeWidgetAura::Restore() { |
476 window_->SetIntProperty(aura::kShowStateKey, ui::SHOW_STATE_NORMAL); | 478 window_->SetIntProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); |
477 } | 479 } |
478 | 480 |
479 void NativeWidgetAura::SetFullscreen(bool fullscreen) { | 481 void NativeWidgetAura::SetFullscreen(bool fullscreen) { |
480 window_->SetIntProperty( | 482 window_->SetIntProperty( |
481 aura::kShowStateKey, | 483 aura::client::kShowStateKey, |
482 fullscreen ? ui::SHOW_STATE_FULLSCREEN : ui::SHOW_STATE_NORMAL); | 484 fullscreen ? ui::SHOW_STATE_FULLSCREEN : ui::SHOW_STATE_NORMAL); |
483 } | 485 } |
484 | 486 |
485 bool NativeWidgetAura::IsFullscreen() const { | 487 bool NativeWidgetAura::IsFullscreen() const { |
486 return window_->GetIntProperty(aura::kShowStateKey) == | 488 return window_->GetIntProperty(aura::client::kShowStateKey) == |
487 ui::SHOW_STATE_FULLSCREEN; | 489 ui::SHOW_STATE_FULLSCREEN; |
488 } | 490 } |
489 | 491 |
490 void NativeWidgetAura::SetOpacity(unsigned char opacity) { | 492 void NativeWidgetAura::SetOpacity(unsigned char opacity) { |
491 window_->layer()->SetOpacity(opacity / 255.0); | 493 window_->layer()->SetOpacity(opacity / 255.0); |
492 } | 494 } |
493 | 495 |
494 void NativeWidgetAura::SetUseDragFrame(bool use_drag_frame) { | 496 void NativeWidgetAura::SetUseDragFrame(bool use_drag_frame) { |
495 NOTIMPLEMENTED(); | 497 NOTIMPLEMENTED(); |
496 } | 498 } |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
847 } | 849 } |
848 } | 850 } |
849 | 851 |
850 // static | 852 // static |
851 bool NativeWidgetPrivate::IsMouseButtonDown() { | 853 bool NativeWidgetPrivate::IsMouseButtonDown() { |
852 return aura::RootWindow::GetInstance()->IsMouseButtonDown(); | 854 return aura::RootWindow::GetInstance()->IsMouseButtonDown(); |
853 } | 855 } |
854 | 856 |
855 } // namespace internal | 857 } // namespace internal |
856 } // namespace views | 858 } // namespace views |
OLD | NEW |