1 // Copyright 2018 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 "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
6
7 #include <memory>
8 #include <string>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/threading/thread_task_runner_handle.h"
13 #include "base/time/time.h"
14 #include "ui/aura/client/aura_constants.h"
15 #include "ui/aura/client/drag_drop_client.h"
16 #include "ui/aura/client/focus_client.h"
17 #include "ui/aura/client/transient_window_client.h"
18 #include "ui/base/hit_test.h"
19 #include "ui/base/ui_base_features.h"
20 #include "ui/display/display.h"
21 #include "ui/display/screen.h"
22 #include "ui/gfx/geometry/dip_util.h"
23 #include "ui/platform_window/extensions/workspace_extension.h"
24 #include "ui/platform_window/platform_window.h"
25 #include "ui/platform_window/platform_window_init_properties.h"
26 #include "ui/platform_window/wm/wm_move_loop_handler.h"
27 #include "ui/views/corewm/tooltip_aura.h"
28 #include "ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h"
29 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
30 #include "ui/views/widget/widget_aura_utils.h"
31 #include "ui/views/window/native_frame_view.h"
32 #include "ui/wm/core/window_util.h"
33 #include "ui/wm/public/window_move_client.h"
34
35 DEFINE_UI_CLASS_PROPERTY_TYPE(views::DesktopWindowTreeHostPlatform*)
36
37 namespace views {
38
39 DEFINE_UI_CLASS_PROPERTY_KEY(DesktopWindowTreeHostPlatform*,
40 kHostForRootWindow,
41 nullptr)
42
43 namespace {
44
DetermineInactivity(ui::WindowShowState show_state)45 bool DetermineInactivity(ui::WindowShowState show_state) {
46 if (show_state != ui::SHOW_STATE_DEFAULT &&
47 show_state != ui::SHOW_STATE_NORMAL &&
48 show_state != ui::SHOW_STATE_INACTIVE &&
49 show_state != ui::SHOW_STATE_MAXIMIZED) {
50 // It will behave like SHOW_STATE_NORMAL.
51 NOTIMPLEMENTED_LOG_ONCE();
52 }
53
54 // See comment in PlatformWindow::Show().
55 return show_state == ui::SHOW_STATE_INACTIVE;
56 }
57
GetPlatformWindowOpacity(Widget::InitParams::WindowOpacity opacity)58 ui::PlatformWindowOpacity GetPlatformWindowOpacity(
59 Widget::InitParams::WindowOpacity opacity) {
60 switch (opacity) {
61 case Widget::InitParams::WindowOpacity::kInferred:
62 return ui::PlatformWindowOpacity::kInferOpacity;
63 case Widget::InitParams::WindowOpacity::kOpaque:
64 return ui::PlatformWindowOpacity::kOpaqueWindow;
65 case Widget::InitParams::WindowOpacity::kTranslucent:
66 return ui::PlatformWindowOpacity::kTranslucentWindow;
67 }
68 return ui::PlatformWindowOpacity::kOpaqueWindow;
69 }
70
GetPlatformWindowType(Widget::InitParams::Type window_type)71 ui::PlatformWindowType GetPlatformWindowType(
72 Widget::InitParams::Type window_type) {
73 switch (window_type) {
74 case Widget::InitParams::TYPE_WINDOW:
75 return ui::PlatformWindowType::kWindow;
76 case Widget::InitParams::TYPE_MENU:
77 return ui::PlatformWindowType::kMenu;
78 case Widget::InitParams::TYPE_TOOLTIP:
79 return ui::PlatformWindowType::kTooltip;
80 case Widget::InitParams::TYPE_DRAG:
81 return ui::PlatformWindowType::kDrag;
82 case Widget::InitParams::TYPE_BUBBLE:
83 return ui::PlatformWindowType::kBubble;
84 default:
85 return ui::PlatformWindowType::kPopup;
86 }
87 NOTREACHED();
88 return ui::PlatformWindowType::kPopup;
89 }
90
ConvertWidgetInitParamsToInitProperties(const Widget::InitParams & params)91 ui::PlatformWindowInitProperties ConvertWidgetInitParamsToInitProperties(
92 const Widget::InitParams& params) {
93 ui::PlatformWindowInitProperties properties;
94 properties.type = GetPlatformWindowType(params.type);
95 properties.activatable =
96 params.activatable == Widget::InitParams::ACTIVATABLE_YES;
97 properties.force_show_in_taskbar = params.force_show_in_taskbar;
98 properties.keep_on_top =
99 params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal;
100 properties.visible_on_all_workspaces = params.visible_on_all_workspaces;
101 properties.remove_standard_frame = params.remove_standard_frame;
102 properties.workspace = params.workspace;
103 properties.opacity = GetPlatformWindowOpacity(params.opacity);
104
105 if (params.parent && params.parent->GetHost())
106 properties.parent_widget = params.parent->GetHost()->GetAcceleratedWidget();
107
108 return properties;
109 }
110
111 } // namespace
112
113 ////////////////////////////////////////////////////////////////////////////////
114 // DesktopWindowTreeHostPlatform:
115
DesktopWindowTreeHostPlatform(internal::NativeWidgetDelegate * native_widget_delegate,DesktopNativeWidgetAura * desktop_native_widget_aura)116 DesktopWindowTreeHostPlatform::DesktopWindowTreeHostPlatform(
117 internal::NativeWidgetDelegate* native_widget_delegate,
118 DesktopNativeWidgetAura* desktop_native_widget_aura)
119 : native_widget_delegate_(native_widget_delegate),
120 desktop_native_widget_aura_(desktop_native_widget_aura),
121 window_move_client_(this) {}
122
~DesktopWindowTreeHostPlatform()123 DesktopWindowTreeHostPlatform::~DesktopWindowTreeHostPlatform() {
124 window()->ClearProperty(kHostForRootWindow);
125 DCHECK(!platform_window()) << "The host must be closed before destroying it.";
126 desktop_native_widget_aura_->OnDesktopWindowTreeHostDestroyed(this);
127 DestroyDispatcher();
128 }
129
130 // static
GetContentWindowForWidget(gfx::AcceleratedWidget widget)131 aura::Window* DesktopWindowTreeHostPlatform::GetContentWindowForWidget(
132 gfx::AcceleratedWidget widget) {
133 auto* host = DesktopWindowTreeHostPlatform::GetHostForWidget(widget);
134 return host ? host->GetContentWindow() : nullptr;
135 }
136
137 // static
GetHostForWidget(gfx::AcceleratedWidget widget)138 DesktopWindowTreeHostPlatform* DesktopWindowTreeHostPlatform::GetHostForWidget(
139 gfx::AcceleratedWidget widget) {
140 aura::WindowTreeHost* host =
141 aura::WindowTreeHost::GetForAcceleratedWidget(widget);
142 return host ? host->window()->GetProperty(kHostForRootWindow) : nullptr;
143 }
144
GetContentWindow()145 aura::Window* DesktopWindowTreeHostPlatform::GetContentWindow() {
146 return desktop_native_widget_aura_->content_window();
147 }
148
Init(const Widget::InitParams & params)149 void DesktopWindowTreeHostPlatform::Init(const Widget::InitParams& params) {
150 if (params.type == Widget::InitParams::TYPE_WINDOW)
151 GetContentWindow()->SetProperty(aura::client::kAnimationsDisabledKey, true);
152
153 // If we have a parent, record the parent/child relationship. We use this
154 // data during destruction to make sure that when we try to close a parent
155 // window, we also destroy all child windows.
156 if (params.parent && params.parent->GetHost()) {
157 window_parent_ =
158 static_cast<DesktopWindowTreeHostPlatform*>(params.parent->GetHost());
159 DCHECK(window_parent_);
160 window_parent_->window_children_.insert(this);
161 }
162
163 ui::PlatformWindowInitProperties properties =
164 ConvertWidgetInitParamsToInitProperties(params);
165 AddAdditionalInitProperties(params, &properties);
166
167 // Calculate initial bounds.
168 properties.bounds = ToPixelRect(params.bounds);
169
170 // Set extensions delegate.
171 DCHECK(!properties.workspace_extension_delegate);
172 properties.workspace_extension_delegate = this;
173
174 CreateAndSetPlatformWindow(std::move(properties));
175
176 // Disable compositing on tooltips as a workaround for
177 // https://crbug.com/442111.
178 CreateCompositor(viz::FrameSinkId(),
179 params.force_software_compositing ||
180 params.type == Widget::InitParams::TYPE_TOOLTIP);
181
182 WindowTreeHost::OnAcceleratedWidgetAvailable();
183 InitHost();
184 window()->Show();
185 }
186
OnNativeWidgetCreated(const Widget::InitParams & params)187 void DesktopWindowTreeHostPlatform::OnNativeWidgetCreated(
188 const Widget::InitParams& params) {
189 window()->SetProperty(kHostForRootWindow, this);
190 // This reroutes RunMoveLoop requests to the DesktopWindowTreeHostPlatform.
191 // The availability of this feature depends on a platform (PlatformWindow)
192 // that implements RunMoveLoop.
193 wm::SetWindowMoveClient(window(), &window_move_client_);
194 platform_window()->SetUseNativeFrame(params.type ==
195 Widget::InitParams::TYPE_WINDOW &&
196 !params.remove_standard_frame);
197
198 native_widget_delegate_->OnNativeWidgetCreated();
199 }
200
OnWidgetInitDone()201 void DesktopWindowTreeHostPlatform::OnWidgetInitDone() {}
202
OnActiveWindowChanged(bool active)203 void DesktopWindowTreeHostPlatform::OnActiveWindowChanged(bool active) {}
204
205 std::unique_ptr<corewm::Tooltip>
CreateTooltip()206 DesktopWindowTreeHostPlatform::CreateTooltip() {
207 return std::make_unique<corewm::TooltipAura>();
208 }
209
210 std::unique_ptr<aura::client::DragDropClient>
CreateDragDropClient(DesktopNativeCursorManager * cursor_manager)211 DesktopWindowTreeHostPlatform::CreateDragDropClient(
212 DesktopNativeCursorManager* cursor_manager) {
213 ui::WmDragHandler* drag_handler = ui::GetWmDragHandler(*(platform_window()));
214 std::unique_ptr<DesktopDragDropClientOzone> drag_drop_client =
215 std::make_unique<DesktopDragDropClientOzone>(window(), cursor_manager,
216 drag_handler);
217 // Set a class property key, which allows |drag_drop_client| to be used for
218 // drop action.
219 SetWmDropHandler(platform_window(), drag_drop_client.get());
220 return std::move(drag_drop_client);
221 }
222
Close()223 void DesktopWindowTreeHostPlatform::Close() {
224 // If we are in process of closing or the PlatformWindow has already been
225 // closed, do nothing.
226 if (close_widget_factory_.HasWeakPtrs() || !platform_window())
227 return;
228
229 GetContentWindow()->Hide();
230
231 // Hide while waiting for the close.
232 // Please note that it's better to call WindowTreeHost::Hide, which also calls
233 // PlatformWindow::Hide and Compositor::SetVisible(false).
234 Hide();
235
236 // And we delay the close so that if we are called from an ATL callback,
237 // we don't destroy the window before the callback returned (as the caller
238 // may delete ourselves on destroy and the ATL callback would still
239 // dereference us when the callback returns).
240 base::ThreadTaskRunnerHandle::Get()->PostTask(
241 FROM_HERE, base::BindOnce(&DesktopWindowTreeHostPlatform::CloseNow,
242 close_widget_factory_.GetWeakPtr()));
243 }
244
CloseNow()245 void DesktopWindowTreeHostPlatform::CloseNow() {
246 if (!platform_window())
247 return;
248
249 #if defined(USE_OZONE)
250 if (features::IsUsingOzonePlatform())
251 SetWmDropHandler(platform_window(), nullptr);
252 #endif
253
254 platform_window()->PrepareForShutdown();
255
256 ReleaseCapture();
257 native_widget_delegate_->OnNativeWidgetDestroying();
258
259 // If we have children, close them. Use a copy for iteration because they'll
260 // remove themselves.
261 std::set<DesktopWindowTreeHostPlatform*> window_children_copy =
262 window_children_;
263 for (auto* child : window_children_copy)
264 child->CloseNow();
265 DCHECK(window_children_.empty());
266
267 // If we have a parent, remove ourselves from its children list.
268 if (window_parent_) {
269 window_parent_->window_children_.erase(this);
270 window_parent_ = nullptr;
271 }
272
273 // Destroy the compositor before destroying the |platform_window()| since
274 // shutdown may try to swap, and the swap without a window may cause an error
275 // in X Server or Wayland, which causes a crash with in-process renderer, for
276 // example.
277 DestroyCompositor();
278
279 platform_window()->Close();
280 }
281
AsWindowTreeHost()282 aura::WindowTreeHost* DesktopWindowTreeHostPlatform::AsWindowTreeHost() {
283 return this;
284 }
285
Show(ui::WindowShowState show_state,const gfx::Rect & restore_bounds)286 void DesktopWindowTreeHostPlatform::Show(ui::WindowShowState show_state,
287 const gfx::Rect& restore_bounds) {
288 if (compositor())
289 SetVisible(true);
290
291 platform_window()->Show(DetermineInactivity(show_state));
292
293 switch (show_state) {
294 case ui::SHOW_STATE_MAXIMIZED:
295 platform_window()->Maximize();
296 if (!restore_bounds.IsEmpty()) {
297 // Enforce |restored_bounds_in_pixels_| since calling Maximize() could
298 // have reset it.
299 platform_window()->SetRestoredBoundsInPixels(
300 ToPixelRect(restore_bounds));
301 }
302 break;
303 case ui::SHOW_STATE_MINIMIZED:
304 platform_window()->Minimize();
305 break;
306 case ui::SHOW_STATE_FULLSCREEN:
307 SetFullscreen(true);
308 break;
309 default:
310 break;
311 }
312
313 if (native_widget_delegate_->CanActivate()) {
314 if (show_state != ui::SHOW_STATE_INACTIVE)
315 Activate();
316
317 // SetInitialFocus() should be always be called, even for
318 // SHOW_STATE_INACTIVE. If the window has to stay inactive, the method will
319 // do the right thing.
320 // Activate() might fail if the window is non-activatable. In this case, we
321 // should pass SHOW_STATE_INACTIVE to SetInitialFocus() to stop the initial
322 // focused view from getting focused. See https://crbug.com/515594 for
323 // example.
324 native_widget_delegate_->SetInitialFocus(
325 IsActive() ? show_state : ui::SHOW_STATE_INACTIVE);
326 }
327
328 GetContentWindow()->Show();
329 }
330
IsVisible() const331 bool DesktopWindowTreeHostPlatform::IsVisible() const {
332 return platform_window()->IsVisible();
333 }
334
SetSize(const gfx::Size & size)335 void DesktopWindowTreeHostPlatform::SetSize(const gfx::Size& size) {
336 gfx::Size size_in_pixels = ToPixelRect(gfx::Rect(size)).size();
337 auto bounds_in_pixels = GetBoundsInPixels();
338 bounds_in_pixels.set_size(size_in_pixels);
339 WindowTreeHostPlatform::SetBoundsInPixels(bounds_in_pixels);
340 }
341
StackAbove(aura::Window * window)342 void DesktopWindowTreeHostPlatform::StackAbove(aura::Window* window) {
343 if (!window || !window->GetRootWindow())
344 return;
345
346 platform_window()->StackAbove(window->GetHost()->GetAcceleratedWidget());
347 }
348
StackAtTop()349 void DesktopWindowTreeHostPlatform::StackAtTop() {
350 platform_window()->StackAtTop();
351 }
352
CenterWindow(const gfx::Size & size)353 void DesktopWindowTreeHostPlatform::CenterWindow(const gfx::Size& size) {
354 gfx::Size size_in_pixels = ToPixelRect(gfx::Rect(size)).size();
355 gfx::Rect parent_bounds_in_pixels = ToPixelRect(GetWorkAreaBoundsInScreen());
356
357 // If |window_|'s transient parent bounds are big enough to contain |size|,
358 // use them instead.
359 if (wm::GetTransientParent(GetContentWindow())) {
360 gfx::Rect transient_parent_rect =
361 wm::GetTransientParent(GetContentWindow())->GetBoundsInScreen();
362 if (transient_parent_rect.height() >= size.height() &&
363 transient_parent_rect.width() >= size.width()) {
364 parent_bounds_in_pixels = ToPixelRect(transient_parent_rect);
365 }
366 }
367
368 gfx::Rect window_bounds_in_pixels(
369 parent_bounds_in_pixels.x() +
370 (parent_bounds_in_pixels.width() - size_in_pixels.width()) / 2,
371 parent_bounds_in_pixels.y() +
372 (parent_bounds_in_pixels.height() - size_in_pixels.height()) / 2,
373 size_in_pixels.width(), size_in_pixels.height());
374 // Don't size the window bigger than the parent, otherwise the user may not be
375 // able to close or move it.
376 window_bounds_in_pixels.AdjustToFit(parent_bounds_in_pixels);
377
378 SetBoundsInPixels(window_bounds_in_pixels);
379 }
380
GetWindowPlacement(gfx::Rect * bounds,ui::WindowShowState * show_state) const381 void DesktopWindowTreeHostPlatform::GetWindowPlacement(
382 gfx::Rect* bounds,
383 ui::WindowShowState* show_state) const {
384 *bounds = GetRestoredBounds();
385
386 if (IsFullscreen())
387 *show_state = ui::SHOW_STATE_FULLSCREEN;
388 else if (IsMinimized())
389 *show_state = ui::SHOW_STATE_MINIMIZED;
390 else if (IsMaximized())
391 *show_state = ui::SHOW_STATE_MAXIMIZED;
392 else if (!IsActive())
393 *show_state = ui::SHOW_STATE_INACTIVE;
394 else
395 *show_state = ui::SHOW_STATE_NORMAL;
396 }
397
GetWindowBoundsInScreen() const398 gfx::Rect DesktopWindowTreeHostPlatform::GetWindowBoundsInScreen() const {
399 return ToDIPRect(GetBoundsInPixels());
400 }
401
GetClientAreaBoundsInScreen() const402 gfx::Rect DesktopWindowTreeHostPlatform::GetClientAreaBoundsInScreen() const {
403 // Attempts to calculate the rect by asking the NonClientFrameView what it
404 // thought its GetBoundsForClientView() were broke combobox drop down
405 // placement.
406 return GetWindowBoundsInScreen();
407 }
408
GetRestoredBounds() const409 gfx::Rect DesktopWindowTreeHostPlatform::GetRestoredBounds() const {
410 // We can't reliably track the restored bounds of a window, but we can get
411 // the 90% case down. When *chrome* is the process that requests maximizing
412 // or restoring bounds, we can record the current bounds before we request
413 // maximization, and clear it when we detect a state change.
414 gfx::Rect restored_bounds = platform_window()->GetRestoredBoundsInPixels();
415
416 // When window is resized, |restored bounds| is not set and empty.
417 // If |restored bounds| is empty, it returns the current window size.
418 if (!restored_bounds.IsEmpty())
419 return ToDIPRect(restored_bounds);
420
421 return GetWindowBoundsInScreen();
422 }
423
GetWorkspace() const424 std::string DesktopWindowTreeHostPlatform::GetWorkspace() const {
425 auto* workspace_extension = ui::GetWorkspaceExtension(*platform_window());
426 return workspace_extension ? workspace_extension->GetWorkspace()
427 : std::string();
428 }
429
GetWorkAreaBoundsInScreen() const430 gfx::Rect DesktopWindowTreeHostPlatform::GetWorkAreaBoundsInScreen() const {
431 // TODO(sky): GetDisplayNearestWindow() should take a const aura::Window*.
432 return display::Screen::GetScreen()
433 ->GetDisplayNearestWindow(const_cast<aura::Window*>(window()))
434 .work_area();
435 }
436
SetShape(std::unique_ptr<Widget::ShapeRects> native_shape)437 void DesktopWindowTreeHostPlatform::SetShape(
438 std::unique_ptr<Widget::ShapeRects> native_shape) {
439 platform_window()->SetShape(std::move(native_shape), GetRootTransform());
440 }
441
Activate()442 void DesktopWindowTreeHostPlatform::Activate() {
443 platform_window()->Activate();
444 }
445
Deactivate()446 void DesktopWindowTreeHostPlatform::Deactivate() {
447 ReleaseCapture();
448 platform_window()->Deactivate();
449 }
450
IsActive() const451 bool DesktopWindowTreeHostPlatform::IsActive() const {
452 return is_active_;
453 }
454
Maximize()455 void DesktopWindowTreeHostPlatform::Maximize() {
456 platform_window()->Maximize();
457 if (IsMinimized())
458 Show(ui::SHOW_STATE_NORMAL, gfx::Rect());
459 }
460
Minimize()461 void DesktopWindowTreeHostPlatform::Minimize() {
462 ReleaseCapture();
463 platform_window()->Minimize();
464 }
465
Restore()466 void DesktopWindowTreeHostPlatform::Restore() {
467 platform_window()->Restore();
468 Show(ui::SHOW_STATE_NORMAL, gfx::Rect());
469 }
470
IsMaximized() const471 bool DesktopWindowTreeHostPlatform::IsMaximized() const {
472 return platform_window()->GetPlatformWindowState() ==
473 ui::PlatformWindowState::kMaximized;
474 }
475
IsMinimized() const476 bool DesktopWindowTreeHostPlatform::IsMinimized() const {
477 return platform_window()->GetPlatformWindowState() ==
478 ui::PlatformWindowState::kMinimized;
479 }
480
HasCapture() const481 bool DesktopWindowTreeHostPlatform::HasCapture() const {
482 return platform_window()->HasCapture();
483 }
484
SetZOrderLevel(ui::ZOrderLevel order)485 void DesktopWindowTreeHostPlatform::SetZOrderLevel(ui::ZOrderLevel order) {
486 platform_window()->SetZOrderLevel(order);
487 }
488
GetZOrderLevel() const489 ui::ZOrderLevel DesktopWindowTreeHostPlatform::GetZOrderLevel() const {
490 return platform_window()->GetZOrderLevel();
491 }
492
SetVisibleOnAllWorkspaces(bool always_visible)493 void DesktopWindowTreeHostPlatform::SetVisibleOnAllWorkspaces(
494 bool always_visible) {
495 auto* workspace_extension = ui::GetWorkspaceExtension(*platform_window());
496 if (workspace_extension)
497 workspace_extension->SetVisibleOnAllWorkspaces(always_visible);
498 }
499
IsVisibleOnAllWorkspaces() const500 bool DesktopWindowTreeHostPlatform::IsVisibleOnAllWorkspaces() const {
501 auto* workspace_extension = ui::GetWorkspaceExtension(*platform_window());
502 return workspace_extension ? workspace_extension->IsVisibleOnAllWorkspaces()
503 : false;
504 }
505
SetWindowTitle(const base::string16 & title)506 bool DesktopWindowTreeHostPlatform::SetWindowTitle(
507 const base::string16& title) {
508 if (window_title_ == title)
509 return false;
510
511 window_title_ = title;
512 platform_window()->SetTitle(window_title_);
513 return true;
514 }
515
ClearNativeFocus()516 void DesktopWindowTreeHostPlatform::ClearNativeFocus() {
517 // This method is weird and misnamed. Instead of clearing the native focus,
518 // it sets the focus to our content_window, which will trigger a cascade
519 // of focus changes into views.
520 if (GetContentWindow() && aura::client::GetFocusClient(GetContentWindow()) &&
521 GetContentWindow()->Contains(
522 aura::client::GetFocusClient(GetContentWindow())
523 ->GetFocusedWindow())) {
524 aura::client::GetFocusClient(GetContentWindow())
525 ->FocusWindow(GetContentWindow());
526 }
527 }
528
RunMoveLoop(const gfx::Vector2d & drag_offset,Widget::MoveLoopSource source,Widget::MoveLoopEscapeBehavior escape_behavior)529 Widget::MoveLoopResult DesktopWindowTreeHostPlatform::RunMoveLoop(
530 const gfx::Vector2d& drag_offset,
531 Widget::MoveLoopSource source,
532 Widget::MoveLoopEscapeBehavior escape_behavior) {
533 auto* move_loop_handler = ui::GetWmMoveLoopHandler(*platform_window());
534 if (move_loop_handler && move_loop_handler->RunMoveLoop(drag_offset))
535 return Widget::MOVE_LOOP_SUCCESSFUL;
536 return Widget::MOVE_LOOP_CANCELED;
537 }
538
EndMoveLoop()539 void DesktopWindowTreeHostPlatform::EndMoveLoop() {
540 auto* move_loop_handler = ui::GetWmMoveLoopHandler(*platform_window());
541 if (move_loop_handler)
542 move_loop_handler->EndMoveLoop();
543 }
544
SetVisibilityChangedAnimationsEnabled(bool value)545 void DesktopWindowTreeHostPlatform::SetVisibilityChangedAnimationsEnabled(
546 bool value) {
547 platform_window()->SetVisibilityChangedAnimationsEnabled(value);
548 }
549
550 std::unique_ptr<NonClientFrameView>
CreateNonClientFrameView()551 DesktopWindowTreeHostPlatform::CreateNonClientFrameView() {
552 return ShouldUseNativeFrame() ? std::make_unique<NativeFrameView>(GetWidget())
553 : nullptr;
554 }
555
ShouldUseNativeFrame() const556 bool DesktopWindowTreeHostPlatform::ShouldUseNativeFrame() const {
557 return platform_window()->ShouldUseNativeFrame();
558 }
559
ShouldWindowContentsBeTransparent() const560 bool DesktopWindowTreeHostPlatform::ShouldWindowContentsBeTransparent() const {
561 return platform_window()->ShouldWindowContentsBeTransparent();
562 }
563
FrameTypeChanged()564 void DesktopWindowTreeHostPlatform::FrameTypeChanged() {
565 Widget::FrameType new_type =
566 native_widget_delegate_->AsWidget()->frame_type();
567 if (new_type == Widget::FrameType::kDefault) {
568 // The default is determined by Widget::InitParams::remove_standard_frame
569 // and does not change.
570 return;
571 }
572 platform_window()->SetUseNativeFrame(new_type ==
573 Widget::FrameType::kForceNative);
574
575 // Replace the frame and layout the contents. Even though we don't have a
576 // swappable glass frame like on Windows, we still replace the frame because
577 // the button assets don't update otherwise.
578 if (GetWidget()->non_client_view())
579 GetWidget()->non_client_view()->UpdateFrame();
580 }
581
SetFullscreen(bool fullscreen)582 void DesktopWindowTreeHostPlatform::SetFullscreen(bool fullscreen) {
583 if (IsFullscreen() == fullscreen)
584 return;
585
586 platform_window()->ToggleFullscreen();
587
588 // The state must change synchronously to let media react on fullscreen
589 // changes.
590 DCHECK_EQ(fullscreen, IsFullscreen());
591
592 if (IsFullscreen() == fullscreen)
593 ScheduleRelayout();
594 // Else: the widget will be relaid out either when the window bounds change
595 // or when |platform_window|'s fullscreen state changes.
596 }
597
IsFullscreen() const598 bool DesktopWindowTreeHostPlatform::IsFullscreen() const {
599 return platform_window()->GetPlatformWindowState() ==
600 ui::PlatformWindowState::kFullScreen;
601 }
602
SetOpacity(float opacity)603 void DesktopWindowTreeHostPlatform::SetOpacity(float opacity) {
604 GetContentWindow()->layer()->SetOpacity(opacity);
605 platform_window()->SetOpacity(opacity);
606 }
607
SetAspectRatio(const gfx::SizeF & aspect_ratio)608 void DesktopWindowTreeHostPlatform::SetAspectRatio(
609 const gfx::SizeF& aspect_ratio) {
610 platform_window()->SetAspectRatio(aspect_ratio);
611 }
612
SetWindowIcons(const gfx::ImageSkia & window_icon,const gfx::ImageSkia & app_icon)613 void DesktopWindowTreeHostPlatform::SetWindowIcons(
614 const gfx::ImageSkia& window_icon,
615 const gfx::ImageSkia& app_icon) {
616 platform_window()->SetWindowIcons(window_icon, app_icon);
617 }
618
InitModalType(ui::ModalType modal_type)619 void DesktopWindowTreeHostPlatform::InitModalType(ui::ModalType modal_type) {
620 NOTIMPLEMENTED_LOG_ONCE();
621 }
622
FlashFrame(bool flash_frame)623 void DesktopWindowTreeHostPlatform::FlashFrame(bool flash_frame) {
624 platform_window()->FlashFrame(flash_frame);
625 }
626
IsAnimatingClosed() const627 bool DesktopWindowTreeHostPlatform::IsAnimatingClosed() const {
628 return platform_window()->IsAnimatingClosed();
629 }
630
IsTranslucentWindowOpacitySupported() const631 bool DesktopWindowTreeHostPlatform::IsTranslucentWindowOpacitySupported()
632 const {
633 return platform_window()->IsTranslucentWindowOpacitySupported();
634 }
635
SizeConstraintsChanged()636 void DesktopWindowTreeHostPlatform::SizeConstraintsChanged() {
637 platform_window()->SizeConstraintsChanged();
638 }
639
ShouldUpdateWindowTransparency() const640 bool DesktopWindowTreeHostPlatform::ShouldUpdateWindowTransparency() const {
641 return true;
642 }
643
ShouldUseDesktopNativeCursorManager() const644 bool DesktopWindowTreeHostPlatform::ShouldUseDesktopNativeCursorManager()
645 const {
646 return true;
647 }
648
ShouldCreateVisibilityController() const649 bool DesktopWindowTreeHostPlatform::ShouldCreateVisibilityController() const {
650 return true;
651 }
652
GetRootTransform() const653 gfx::Transform DesktopWindowTreeHostPlatform::GetRootTransform() const {
654 display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
655 // This might be called before the |platform_window| is created. Thus,
656 // explicitly check if that exists before trying to access its visibility and
657 // the display where it is shown.
658 if (platform_window() && IsVisible()) {
659 display = display::Screen::GetScreen()->GetDisplayNearestWindow(
660 GetWidget()->GetNativeWindow());
661 }
662
663 float scale = display.device_scale_factor();
664 gfx::Transform transform;
665 transform.Scale(scale, scale);
666 return transform;
667 }
668
ShowImpl()669 void DesktopWindowTreeHostPlatform::ShowImpl() {
670 Show(ui::SHOW_STATE_NORMAL, gfx::Rect());
671 }
672
HideImpl()673 void DesktopWindowTreeHostPlatform::HideImpl() {
674 WindowTreeHostPlatform::HideImpl();
675 native_widget_delegate_->OnNativeWidgetVisibilityChanged(false);
676 }
677
OnClosed()678 void DesktopWindowTreeHostPlatform::OnClosed() {
679 wm::SetWindowMoveClient(window(), nullptr);
680 SetWmDropHandler(platform_window(), nullptr);
681 desktop_native_widget_aura_->OnHostWillClose();
682 SetPlatformWindow(nullptr);
683 desktop_native_widget_aura_->OnHostClosed();
684 }
685
OnWindowStateChanged(ui::PlatformWindowState new_state)686 void DesktopWindowTreeHostPlatform::OnWindowStateChanged(
687 ui::PlatformWindowState new_state) {
688 bool was_minimized = old_state_ == ui::PlatformWindowState::kMinimized;
689 bool is_minimized = new_state == ui::PlatformWindowState::kMinimized;
690
691 // Propagate minimization/restore to compositor to avoid drawing 'blank'
692 // frames that could be treated as previews, which show content even if a
693 // window is minimized.
694 if (is_minimized != was_minimized) {
695 if (is_minimized) {
696 SetVisible(false);
697 GetContentWindow()->Hide();
698 } else {
699 GetContentWindow()->Show();
700 SetVisible(true);
701 }
702 }
703
704 old_state_ = new_state;
705
706 // Now that we have different window properties, we may need to relayout the
707 // window. (The windows code doesn't need this because their window change is
708 // synchronous.)
709 ScheduleRelayout();
710 }
711
OnCloseRequest()712 void DesktopWindowTreeHostPlatform::OnCloseRequest() {
713 GetWidget()->Close();
714 }
715
OnWillDestroyAcceleratedWidget()716 void DesktopWindowTreeHostPlatform::OnWillDestroyAcceleratedWidget() {
717 desktop_native_widget_aura_->OnHostWillClose();
718 }
719
OnActivationChanged(bool active)720 void DesktopWindowTreeHostPlatform::OnActivationChanged(bool active) {
721 if (is_active_ == active)
722 return;
723 is_active_ = active;
724 aura::WindowTreeHostPlatform::OnActivationChanged(active);
725 desktop_native_widget_aura_->HandleActivationChanged(active);
726 ScheduleRelayout();
727 }
728
729 base::Optional<gfx::Size>
GetMinimumSizeForWindow()730 DesktopWindowTreeHostPlatform::GetMinimumSizeForWindow() {
731 return ToPixelRect(gfx::Rect(native_widget_delegate()->GetMinimumSize()))
732 .size();
733 }
734
735 base::Optional<gfx::Size>
GetMaximumSizeForWindow()736 DesktopWindowTreeHostPlatform::GetMaximumSizeForWindow() {
737 return ToPixelRect(gfx::Rect(native_widget_delegate()->GetMaximumSize()))
738 .size();
739 }
740
OnWorkspaceChanged()741 void DesktopWindowTreeHostPlatform::OnWorkspaceChanged() {
742 OnHostWorkspaceChanged();
743 }
744
ToDIPRect(const gfx::Rect & rect_in_pixels) const745 gfx::Rect DesktopWindowTreeHostPlatform::ToDIPRect(
746 const gfx::Rect& rect_in_pixels) const {
747 gfx::RectF rect_in_dip = gfx::RectF(rect_in_pixels);
748 GetRootTransform().TransformRectReverse(&rect_in_dip);
749 return gfx::ToEnclosingRect(rect_in_dip);
750 }
751
ToPixelRect(const gfx::Rect & rect_in_dip) const752 gfx::Rect DesktopWindowTreeHostPlatform::ToPixelRect(
753 const gfx::Rect& rect_in_dip) const {
754 gfx::RectF rect_in_pixels = gfx::RectF(rect_in_dip);
755 GetRootTransform().TransformRect(&rect_in_pixels);
756 return gfx::ToEnclosingRect(rect_in_pixels);
757 }
758
ScheduleRelayout()759 void DesktopWindowTreeHostPlatform::ScheduleRelayout() {
760 Widget* widget = native_widget_delegate_->AsWidget();
761 NonClientView* non_client_view = widget->non_client_view();
762 // non_client_view may be NULL, especially during creation.
763 if (non_client_view) {
764 if (non_client_view->frame_view())
765 non_client_view->frame_view()->InvalidateLayout();
766 non_client_view->client_view()->InvalidateLayout();
767 non_client_view->InvalidateLayout();
768 }
769 }
770
GetWidget()771 Widget* DesktopWindowTreeHostPlatform::GetWidget() {
772 return native_widget_delegate_->AsWidget();
773 }
774
GetWidget() const775 const Widget* DesktopWindowTreeHostPlatform::GetWidget() const {
776 return native_widget_delegate_->AsWidget();
777 }
778
SetVisible(bool visible)779 void DesktopWindowTreeHostPlatform::SetVisible(bool visible) {
780 if (compositor())
781 compositor()->SetVisible(visible);
782
783 native_widget_delegate()->OnNativeWidgetVisibilityChanged(visible);
784 }
785
AddAdditionalInitProperties(const Widget::InitParams & params,ui::PlatformWindowInitProperties * properties)786 void DesktopWindowTreeHostPlatform::AddAdditionalInitProperties(
787 const Widget::InitParams& params,
788 ui::PlatformWindowInitProperties* properties) {}
789
790 ////////////////////////////////////////////////////////////////////////////////
791 // DesktopWindowTreeHost:
792
793 // Linux subclasses this host and adds some Linux specific bits.
794 #if !defined(OS_LINUX) && !defined(OS_CHROMEOS) && !defined(OS_BSD)
795 // static
Create(internal::NativeWidgetDelegate * native_widget_delegate,DesktopNativeWidgetAura * desktop_native_widget_aura)796 DesktopWindowTreeHost* DesktopWindowTreeHost::Create(
797 internal::NativeWidgetDelegate* native_widget_delegate,
798 DesktopNativeWidgetAura* desktop_native_widget_aura) {
799 return new DesktopWindowTreeHostPlatform(native_widget_delegate,
800 desktop_native_widget_aura);
801 }
802 #endif
803
804 } // namespace views
805