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