1 // Copyright 2020 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/public/cpp/external_arc/overlay/arc_overlay_controller_impl.h"
6
7 #include "components/exo/shell_surface_util.h"
8 #include "components/exo/surface.h"
9 #include "ui/aura/window_targeter.h"
10 #include "ui/views/widget/widget.h"
11
12 namespace ash {
13
ArcOverlayControllerImpl(aura::Window * host_window)14 ArcOverlayControllerImpl::ArcOverlayControllerImpl(aura::Window* host_window)
15 : host_window_(host_window) {
16 DCHECK(host_window_);
17
18 VLOG(1) << "Host is " << host_window_->GetName();
19
20 host_window_observer_.Observe(host_window_);
21
22 overlay_container_ = new views::NativeViewHost();
23 overlay_container_observer_.Observe(overlay_container_);
24
25 auto* const widget = views::Widget::GetWidgetForNativeWindow(
26 host_window_->GetToplevelWindow());
27 DCHECK(widget);
28 DCHECK(widget->GetContentsView());
29 widget->GetContentsView()->AddChildView(overlay_container_);
30 }
31
32 ArcOverlayControllerImpl::~ArcOverlayControllerImpl() = default;
33
AttachOverlay(aura::Window * overlay_window)34 void ArcOverlayControllerImpl::AttachOverlay(aura::Window* overlay_window) {
35 if (!overlay_container_ || !host_window_)
36 return;
37
38 DCHECK(overlay_window);
39 DCHECK(!overlay_container_->native_view())
40 << "An overlay is already attached";
41
42 VLOG(1) << "Attaching overlay " << overlay_window->GetName() << " to host "
43 << host_window_->GetName();
44
45 overlay_window_ = overlay_window;
46 overlay_window_observer_.Observe(overlay_window);
47
48 overlay_container_->Attach(overlay_window_);
49 overlay_container_->GetNativeViewContainer()->SetEventTargeter(
50 std::make_unique<aura::WindowTargeter>());
51
52 UpdateHostBounds();
53 }
54
OnWindowDestroying(aura::Window * window)55 void ArcOverlayControllerImpl::OnWindowDestroying(aura::Window* window) {
56 if (host_window_observer_.IsObservingSource(window)) {
57 host_window_ = nullptr;
58 host_window_observer_.RemoveObservation();
59 }
60 if (overlay_window_observer_.IsObservingSource(window)) {
61 overlay_window_ = nullptr;
62 overlay_window_observer_.RemoveObservation();
63 }
64 }
65
OnViewIsDeleting(views::View * observed_view)66 void ArcOverlayControllerImpl::OnViewIsDeleting(views::View* observed_view) {
67 if (overlay_container_observer_.IsObservingSource(observed_view)) {
68 overlay_container_ = nullptr;
69 overlay_container_observer_.RemoveObservation();
70 }
71 }
72
OnWindowBoundsChanged(aura::Window * window,const gfx::Rect & old_bounds,const gfx::Rect & new_bounds,ui::PropertyChangeReason reason)73 void ArcOverlayControllerImpl::OnWindowBoundsChanged(
74 aura::Window* window,
75 const gfx::Rect& old_bounds,
76 const gfx::Rect& new_bounds,
77 ui::PropertyChangeReason reason) {
78 if (host_window_observer_.IsObservingSource(window) &&
79 old_bounds.size() != new_bounds.size()) {
80 UpdateHostBounds();
81 }
82 }
83
UpdateHostBounds()84 void ArcOverlayControllerImpl::UpdateHostBounds() {
85 if (!overlay_container_observer_.IsObserving()) {
86 LOG(ERROR) << "No container to resize";
87 return;
88 }
89
90 gfx::Point origin;
91 gfx::Size size = host_window_->bounds().size();
92 ConvertPointFromWindow(host_window_, &origin);
93 overlay_container_->SetBounds(origin.x(), origin.y(), size.width(),
94 size.height());
95 }
96
ConvertPointFromWindow(aura::Window * window,gfx::Point * point)97 void ArcOverlayControllerImpl::ConvertPointFromWindow(aura::Window* window,
98 gfx::Point* point) {
99 views::Widget* const widget = overlay_container_->GetWidget();
100 aura::Window::ConvertPointToTarget(window, widget->GetNativeWindow(), point);
101 views::View::ConvertPointFromWidget(widget->GetContentsView(), point);
102 }
103
104 } // namespace ash
105