Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Side by Side Diff: ash/wm/drag_window_controller.cc

Issue 1838003002: Create drag windows on all displays (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/wm/drag_window_controller.h" 5 #include "ash/wm/drag_window_controller.h"
6 6
7 #include <algorithm>
8
9 #include "ash/display/window_tree_host_manager.h"
10 #include "ash/screen_util.h"
11 #include "ash/shell.h"
7 #include "ash/shell_window_ids.h" 12 #include "ash/shell_window_ids.h"
8 #include "ash/wm/window_util.h" 13 #include "ash/wm/window_util.h"
14 #include "ui/aura/client/aura_constants.h"
9 #include "ui/aura/client/screen_position_client.h" 15 #include "ui/aura/client/screen_position_client.h"
10 #include "ui/aura/window.h" 16 #include "ui/aura/window.h"
17 #include "ui/aura/window_delegate.h"
11 #include "ui/aura/window_event_dispatcher.h" 18 #include "ui/aura/window_event_dispatcher.h"
19 #include "ui/base/hit_test.h"
12 #include "ui/compositor/layer.h" 20 #include "ui/compositor/layer.h"
13 #include "ui/compositor/layer_tree_owner.h" 21 #include "ui/compositor/layer_tree_owner.h"
14 #include "ui/compositor/scoped_layer_animation_settings.h" 22 #include "ui/compositor/scoped_layer_animation_settings.h"
15 #include "ui/views/view.h" 23 #include "ui/views/view.h"
16 #include "ui/views/widget/widget.h" 24 #include "ui/views/widget/widget.h"
17 #include "ui/wm/core/shadow_types.h" 25 #include "ui/wm/core/shadow_types.h"
18 #include "ui/wm/core/window_util.h" 26 #include "ui/wm/core/window_util.h"
19 27
20 namespace ash { 28 namespace ash {
21 29
30 // This keeps tack of the drag window's state. It creates/destory/updates bounds
31 // and opacity based on the current bounds.
32 class DragWindowController::DragWindowDetails : public aura::WindowDelegate {
33 public:
34 DragWindowDetails(const gfx::Display& display, aura::Window* original_window)
35 : root_window_(Shell::GetInstance()
36 ->window_tree_host_manager()
37 ->GetRootWindowForDisplayId(display.id())) {}
38
39 ~DragWindowDetails() override {
40 if (drag_window_) {
41 delete drag_window_;
stevenjb 2016/03/29 18:56:13 nit: I had to remind myself that this was safe, ma
42 drag_window_ = nullptr;
stevenjb 2016/03/29 18:56:13 This should be handled in OnWindowDestroying, rig
oshima 2016/03/30 21:21:02 Yep, changed to DCHECK.
43 }
44 }
45
46 void Update(aura::Window* original_window,
47 const gfx::Rect& bounds_in_screen,
48 const gfx::Point& drag_location_in_screen) {
49 gfx::Rect root_bounds_in_screen = root_window_->GetBoundsInScreen();
50 if (!root_bounds_in_screen.Intersects(bounds_in_screen)) {
51 delete drag_window_;
52 drag_window_ = nullptr;
stevenjb 2016/03/29 18:56:13 Same here? This pattern implies ownership. Perhaps
oshima 2016/03/30 21:21:02 per offline chat, I changed to DCHECK and added co
53 layer_owner_.reset();
54 return;
55 }
56 if (!drag_window_)
57 CreateDragWindow(original_window, bounds_in_screen);
58
59 gfx::Rect bounds_in_root = ScreenUtil::ConvertRectFromScreen(
60 drag_window_->parent(), bounds_in_screen);
61 drag_window_->SetBounds(bounds_in_root);
62 if (root_bounds_in_screen.Contains(drag_location_in_screen)) {
63 SetOpacity(original_window, 1.f);
64 } else {
65 drag_window_->SetBounds(bounds_in_root);
66 gfx::Rect visible_bounds = root_bounds_in_screen;
67 visible_bounds.Intersect(bounds_in_screen);
68 SetOpacity(original_window,
69 GetDragWindowOpacity(bounds_in_screen, visible_bounds));
70 }
71 }
72
73 private:
74 friend class DragWindowController;
75
76 void CreateDragWindow(aura::Window* original_window,
77 const gfx::Rect& bounds_in_screen) {
78 DCHECK(!drag_window_);
79 drag_window_ = new aura::Window(this);
80 int parent_id = original_window->parent()->id();
81 aura::Window* container = root_window_->GetChildById(parent_id);
82
83 drag_window_->SetType(ui::wm::WINDOW_TYPE_POPUP);
84 drag_window_->SetTransparent(true);
85 drag_window_->Init(ui::LAYER_TEXTURED);
86 drag_window_->SetName("DragWindow");
87 drag_window_->set_id(kShellWindowId_PhantomWindow);
88 drag_window_->SetProperty(aura::client::kAnimationsDisabledKey, true);
89 container->AddChild(drag_window_);
90 drag_window_->SetBounds(bounds_in_screen);
91 SetShadowType(drag_window_, ::wm::SHADOW_TYPE_RECTANGULAR);
92
93 RecreateWindowLayers(original_window);
94 layer_owner_->root()->SetVisible(true);
95 drag_window_->layer()->Add(layer_owner_->root());
96 drag_window_->layer()->StackAtTop(layer_owner_->root());
97
98 // Show the widget after all the setups.
99 drag_window_->Show();
100
101 // Fade the window in.
102 ui::Layer* drag_layer = drag_window_->layer();
103 drag_layer->SetOpacity(0);
104 ui::ScopedLayerAnimationSettings scoped_setter(drag_layer->GetAnimator());
105 drag_layer->SetOpacity(1);
106 }
107
108 void RecreateWindowLayers(aura::Window* original_window) {
109 DCHECK(!layer_owner_.get());
110 layer_owner_ = ::wm::RecreateLayers(original_window);
111 // TODO(oshima): Recreated child layers may not have been painted
112 // yet, and may not be able to paint to because it does not have
113 // its original delegate.
114 layer_owner_->root()->set_delegate(original_window->layer()->delegate());
115 // Place the layer at (0, 0) of the DragWindowController's window.
116 gfx::Rect layer_bounds = layer_owner_->root()->bounds();
117 layer_bounds.set_origin(gfx::Point(0, 0));
118 layer_owner_->root()->SetBounds(layer_bounds);
119 layer_owner_->root()->SetVisible(false);
120 // Detach it from the current container.
121 layer_owner_->root()->parent()->Remove(layer_owner_->root());
122 }
123
124 void SetOpacity(const aura::Window* original_window, float opacity) {
125 ui::Layer* layer = drag_window_->layer();
126 ui::ScopedLayerAnimationSettings scoped_setter(layer->GetAnimator());
127 layer->SetOpacity(opacity);
128 layer_owner_->root()->SetOpacity(1.0f);
129 }
130
131 // aura::WindowDelegate:
132 gfx::Size GetMinimumSize() const override { return gfx::Size(); }
133 gfx::Size GetMaximumSize() const override { return gfx::Size(); }
134 void OnBoundsChanged(const gfx::Rect& old_bounds,
135 const gfx::Rect& new_bounds) override {}
136 gfx::NativeCursor GetCursor(const gfx::Point& point) override {
137 return gfx::kNullCursor;
138 }
139 int GetNonClientComponent(const gfx::Point& point) const override {
140 return HTNOWHERE;
141 }
142 bool ShouldDescendIntoChildForEventHandling(
143 aura::Window* child,
144 const gfx::Point& location) override {
145 return false;
146 }
147 bool CanFocus() override { return false; }
148 void OnCaptureLost() override {}
149 void OnPaint(const ui::PaintContext& context) override {}
150 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
151 void OnWindowDestroyed(aura::Window* window) override {}
152 void OnWindowTargetVisibilityChanged(bool visible) override {}
153 bool HasHitTestMask() const override { return false; }
154 void GetHitTestMask(gfx::Path* mask) const override {}
155 void OnWindowDestroying(aura::Window* window) override {
156 DCHECK_EQ(drag_window_, window);
157 drag_window_ = nullptr;
158 }
159
160 aura::Window* root_window_;
161
162 aura::Window* drag_window_ = nullptr; // Owned by the container.
163
164 // The copy of window_->layer() and its descendants.
165 scoped_ptr<ui::LayerTreeOwner> layer_owner_;
166
167 DISALLOW_COPY_AND_ASSIGN(DragWindowDetails);
168 };
169
170 // static
171 float DragWindowController::GetDragWindowOpacity(
172 const gfx::Rect& window_bounds,
173 const gfx::Rect& visible_bounds) {
174 // The maximum opacity of the drag phantom window.
175 static const float kMaxOpacity = 0.8f;
176
177 return kMaxOpacity * visible_bounds.size().GetArea() /
178 window_bounds.size().GetArea();
179 }
180
22 DragWindowController::DragWindowController(aura::Window* window) 181 DragWindowController::DragWindowController(aura::Window* window)
23 : window_(window), 182 : window_(window) {
24 drag_widget_(NULL) { 183 DCHECK(drag_windows_.empty());
25 } 184 gfx::Screen* screen = gfx::Screen::GetScreen();
26 185 gfx::Display current = screen->GetDisplayNearestWindow(window_);
27 DragWindowController::~DragWindowController() { 186
28 Hide(); 187 for (const gfx::Display& display : screen->GetAllDisplays()) {
29 } 188 if (current.id() == display.id())
30 189 continue;
31 void DragWindowController::SetDestinationDisplay( 190 drag_windows_.push_back(
32 const gfx::Display& dst_display) { 191 make_scoped_ptr(new DragWindowDetails(display, window_)));
33 dst_display_ = dst_display; 192 }
34 } 193 }
35 194
36 void DragWindowController::Show() { 195 DragWindowController::~DragWindowController() {}
37 if (!drag_widget_) 196
38 CreateDragWidget(window_->GetBoundsInScreen()); 197 void DragWindowController::Update(const gfx::Rect& bounds_in_screen,
39 drag_widget_->Show(); 198 const gfx::Point& drag_location_in_screen) {
40 } 199 for (scoped_ptr<DragWindowDetails>& details : drag_windows_)
41 200 details->Update(window_, bounds_in_screen, drag_location_in_screen);
42 void DragWindowController::SetBounds(const gfx::Rect& bounds) { 201 }
43 DCHECK(drag_widget_); 202
44 bounds_ = bounds; 203 int DragWindowController::GetDragWindowsCountForTest() const {
45 SetBoundsInternal(bounds); 204 int count = 0;
46 } 205 for (const scoped_ptr<DragWindowDetails>& details : drag_windows_) {
47 206 if (details->drag_window_)
48 void DragWindowController::Hide() { 207 count++;
49 if (drag_widget_) { 208 }
50 drag_widget_->Close(); 209 return count;
51 drag_widget_ = NULL; 210 }
52 } 211
53 layer_owner_.reset(); 212 const aura::Window* DragWindowController::GetDragWindowForTest(
54 } 213 size_t index) const {
55 214 for (const scoped_ptr<DragWindowDetails>& details : drag_windows_) {
56 void DragWindowController::SetOpacity(float opacity) { 215 if (details->drag_window_) {
57 DCHECK(drag_widget_); 216 if (index == 0)
58 ui::Layer* layer = drag_widget_->GetNativeWindow()->layer(); 217 return details->drag_window_;
59 ui::ScopedLayerAnimationSettings scoped_setter(layer->GetAnimator()); 218 index--;
60 layer->SetOpacity(opacity); 219 }
61 } 220 }
62 221 return nullptr;
63 void DragWindowController::CreateDragWidget(const gfx::Rect& bounds) { 222 }
64 DCHECK(!drag_widget_); 223
65 drag_widget_ = new views::Widget; 224 const ui::LayerTreeOwner* DragWindowController::GetDragLayerOwnerForTest(
66 views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 225 size_t index) const {
67 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 226 for (const scoped_ptr<DragWindowDetails>& details : drag_windows_) {
68 params.parent = window_->parent(); 227 if (details->layer_owner_) {
69 params.keep_on_top = true; 228 if (index == 0)
70 drag_widget_->set_focus_on_creation(false); 229 return details->layer_owner_.get();
71 drag_widget_->Init(params); 230 index--;
72 drag_widget_->SetVisibilityChangedAnimationsEnabled(false); 231 }
73 drag_widget_->GetNativeWindow()->SetName("DragWindow"); 232 }
74 drag_widget_->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow); 233 return nullptr;
75 // Show shadow for the dragging window.
76 SetShadowType(drag_widget_->GetNativeWindow(),
77 ::wm::SHADOW_TYPE_RECTANGULAR);
78 SetBoundsInternal(bounds);
79 drag_widget_->StackAbove(window_);
80
81 RecreateWindowLayers();
82 aura::Window* window = drag_widget_->GetNativeWindow();
83 layer_owner_->root()->SetVisible(true);
84 window->layer()->Add(layer_owner_->root());
85 window->layer()->StackAtTop(layer_owner_->root());
86
87 // Show the widget after all the setups.
88 drag_widget_->Show();
89
90 // Fade the window in.
91 ui::Layer* widget_layer = drag_widget_->GetNativeWindow()->layer();
92 widget_layer->SetOpacity(0);
93 ui::ScopedLayerAnimationSettings scoped_setter(widget_layer->GetAnimator());
94 widget_layer->SetOpacity(1);
95 }
96
97 void DragWindowController::SetBoundsInternal(const gfx::Rect& bounds) {
98 aura::Window* window = drag_widget_->GetNativeWindow();
99 aura::client::ScreenPositionClient* screen_position_client =
100 aura::client::GetScreenPositionClient(window->GetRootWindow());
101 if (screen_position_client && dst_display_.is_valid())
102 screen_position_client->SetBounds(window, bounds, dst_display_);
103 else
104 drag_widget_->SetBounds(bounds);
105 }
106
107 void DragWindowController::RecreateWindowLayers() {
108 DCHECK(!layer_owner_.get());
109 layer_owner_ = ::wm::RecreateLayers(window_);
110 layer_owner_->root()->set_delegate(window_->layer()->delegate());
111 // Place the layer at (0, 0) of the DragWindowController's window.
112 gfx::Rect layer_bounds = layer_owner_->root()->bounds();
113 layer_bounds.set_origin(gfx::Point(0, 0));
114 layer_owner_->root()->SetBounds(layer_bounds);
115 layer_owner_->root()->SetVisible(false);
116 // Detach it from the current container.
117 layer_owner_->root()->parent()->Remove(layer_owner_->root());
118 } 234 }
119 235
120 } // namespace ash 236 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698