Index: ash/mus/non_client_frame_controller.cc |
diff --git a/ash/mus/non_client_frame_controller.cc b/ash/mus/non_client_frame_controller.cc |
index 1f46aa8c23255f2854162a9f5b9e5df11e7cf150..070f2b27ffa2d941c0396fbb939623a263f52144 100644 |
--- a/ash/mus/non_client_frame_controller.cc |
+++ b/ash/mus/non_client_frame_controller.cc |
@@ -14,15 +14,19 @@ |
#include "ash/common/ash_layout_constants.h" |
#include "ash/common/frame/custom_frame_view_ash.h" |
#include "ash/mus/bridge/wm_window_mus.h" |
+#include "ash/mus/frame/custom_frame_view_mus.h" |
+#include "ash/mus/frame/detached_title_area_renderer.h" |
#include "ash/mus/move_event_handler.h" |
#include "ash/mus/property_util.h" |
#include "ash/mus/shadow.h" |
+#include "ash/shared/immersive_fullscreen_controller_delegate.h" |
#include "base/macros.h" |
#include "base/strings/utf_string_conversions.h" |
#include "services/ui/public/cpp/property_type_converters.h" |
#include "services/ui/public/cpp/window.h" |
#include "services/ui/public/cpp/window_manager_delegate.h" |
#include "services/ui/public/cpp/window_property.h" |
+#include "services/ui/public/cpp/window_tree_client.h" |
#include "services/ui/public/interfaces/window_manager.mojom.h" |
#include "services/ui/public/interfaces/window_tree_host.mojom.h" |
#include "ui/aura/layout_manager.h" |
@@ -110,6 +114,109 @@ class EmptyDraggableNonClientFrameView : public views::NonClientFrameView { |
DISALLOW_COPY_AND_ASSIGN(EmptyDraggableNonClientFrameView); |
}; |
+// Creates a ui::Window to host the top container when in immersive mode. The |
+// top container contains a DetachedTitleAreaRenderer, which handles drawing and |
+// events. |
+class ImmersiveFullscreenControllerDelegateMus |
+ : public ImmersiveFullscreenControllerDelegate, |
+ public DetachedTitleAreaRendererHost { |
+ public: |
+ ImmersiveFullscreenControllerDelegateMus(views::Widget* frame, |
+ ui::Window* frame_window) |
+ : frame_(frame), frame_window_(frame_window) {} |
+ ~ImmersiveFullscreenControllerDelegateMus() override { |
+ DestroyTitleAreaWindow(); |
+ } |
+ |
+ // WmImmersiveFullscreenControllerDelegate: |
+ void OnImmersiveRevealStarted() override { |
+ CreateTitleAreaWindow(); |
+ SetVisibleFraction(0); |
+ } |
+ void OnImmersiveRevealEnded() override { DestroyTitleAreaWindow(); } |
+ void OnImmersiveFullscreenExited() override { DestroyTitleAreaWindow(); } |
+ void SetVisibleFraction(double visible_fraction) override { |
+ if (!title_area_window_) |
+ return; |
+ gfx::Rect bounds = title_area_window_->bounds(); |
+ bounds.set_y(frame_window_->bounds().y() - bounds.height() + |
+ visible_fraction * bounds.height()); |
+ title_area_window_->SetBounds(bounds); |
+ } |
+ std::vector<gfx::Rect> GetVisibleBoundsInScreen() const override { |
+ std::vector<gfx::Rect> result; |
+ if (!title_area_window_) |
+ return result; |
+ |
+ // Clip the bounds of the title area to that of the |frame_window_|. |
+ gfx::Rect visible_bounds = title_area_window_->bounds(); |
+ visible_bounds.Intersect(frame_window_->bounds()); |
+ // The intersection is in the coordinates of |title_area_window_|'s parent, |
+ // convert to be in |title_area_window_| and then to screen. |
+ visible_bounds -= title_area_window_->bounds().origin().OffsetFromOrigin(); |
+ // TODO: this needs updating when parent of |title_area_window| is changed, |
+ // DCHECK is to ensure when parent changes this code is updated. |
+ // http://crbug.com/640392. |
+ DCHECK_EQ(frame_window_->parent(), title_area_window_->parent()); |
+ result.push_back(WmWindowMus::Get(title_area_window_) |
+ ->ConvertRectToScreen(visible_bounds)); |
+ return result; |
+ } |
+ |
+ // DetachedTitleAreaRendererHost: |
+ void OnDetachedTitleAreaRendererDestroyed( |
+ DetachedTitleAreaRenderer* renderer) override { |
+ title_area_renderer_ = nullptr; |
+ title_area_window_ = nullptr; |
+ } |
+ |
+ private: |
+ void CreateTitleAreaWindow() { |
+ if (title_area_window_) |
+ return; |
+ |
+ title_area_window_ = frame_window_->window_tree()->NewWindow(); |
+ // TODO(sky): bounds aren't right here. Need to convert to display. |
+ gfx::Rect bounds = frame_window_->bounds(); |
+ // Use the preferred size as when fullscreen the client area is generally |
+ // set to 0. |
+ bounds.set_height( |
+ NonClientFrameController::GetPreferredClientAreaInsets().top()); |
+ bounds.set_y(bounds.y() - bounds.height()); |
+ title_area_window_->SetBounds(bounds); |
+ // TODO: making the reveal window a sibling is likely problematic. |
+ // http://crbug.com/640392, see also comment in GetVisibleBoundsInScreen(). |
+ frame_window_->parent()->AddChild(title_area_window_); |
+ title_area_window_->Reorder(frame_window_, |
+ ui::mojom::OrderDirection::ABOVE); |
+ title_area_renderer_ = |
+ new DetachedTitleAreaRenderer(this, frame_, title_area_window_, |
+ DetachedTitleAreaRenderer::Source::MASH); |
+ } |
+ |
+ void DestroyTitleAreaWindow() { |
+ if (!title_area_window_) |
+ return; |
+ title_area_renderer_->Destroy(); |
+ title_area_renderer_ = nullptr; |
+ // TitleAreaRevealer ends up owning window. |
+ title_area_window_ = nullptr; |
+ } |
+ |
+ // The Widget immersive mode is operating on. |
+ views::Widget* frame_; |
+ |
+ // The ui::Window associated with |frame_|. |
+ ui::Window* frame_window_; |
+ |
+ // The window hosting the title area. |
+ ui::Window* title_area_window_ = nullptr; |
+ |
+ DetachedTitleAreaRenderer* title_area_renderer_ = nullptr; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ImmersiveFullscreenControllerDelegateMus); |
+}; |
+ |
class WmNativeWidgetMus : public views::NativeWidgetMus { |
public: |
WmNativeWidgetMus(views::internal::NativeWidgetDelegate* delegate, |
@@ -125,7 +232,15 @@ class WmNativeWidgetMus : public views::NativeWidgetMus { |
window(), window_manager_client_, GetNativeView())); |
if (ShouldRemoveStandardFrame(window())) |
return new EmptyDraggableNonClientFrameView(); |
- return new CustomFrameViewAsh(GetWidget()); |
+ immersive_delegate_.reset( |
+ new ImmersiveFullscreenControllerDelegateMus(GetWidget(), window())); |
+ const bool enable_immersive = |
+ !window()->HasSharedProperty( |
+ ui::mojom::WindowManager::kDisableImmersive_Property) || |
+ !window()->GetSharedProperty<bool>( |
+ ui::mojom::WindowManager::kDisableImmersive_Property); |
+ return new CustomFrameViewMus(GetWidget(), immersive_delegate_.get(), |
+ enable_immersive); |
} |
void InitNativeWidget(const views::Widget::InitParams& params) override { |
views::NativeWidgetMus::InitNativeWidget(params); |
@@ -152,6 +267,8 @@ class WmNativeWidgetMus : public views::NativeWidgetMus { |
ui::WindowManagerClient* window_manager_client_; |
+ std::unique_ptr<ImmersiveFullscreenControllerDelegateMus> immersive_delegate_; |
+ |
DISALLOW_COPY_AND_ASSIGN(WmNativeWidgetMus); |
}; |
@@ -190,12 +307,10 @@ gfx::Insets GetExtendedHitRegion() { |
// static |
void NonClientFrameController::Create( |
- shell::Connector* connector, |
ui::Window* parent, |
ui::Window* window, |
ui::WindowManagerClient* window_manager_client) { |
- new NonClientFrameController(connector, parent, window, |
- window_manager_client); |
+ new NonClientFrameController(parent, window, window_manager_client); |
} |
// static |
@@ -217,7 +332,6 @@ int NonClientFrameController::GetMaxTitleBarButtonWidth() { |
} |
NonClientFrameController::NonClientFrameController( |
- shell::Connector* connector, |
ui::Window* parent, |
ui::Window* window, |
ui::WindowManagerClient* window_manager_client) |
@@ -254,6 +368,14 @@ NonClientFrameController::NonClientFrameController( |
NonClientFrameController::~NonClientFrameController() { |
if (window_) |
window_->RemoveObserver(this); |
+ if (detached_title_area_renderer_) |
+ detached_title_area_renderer_->Destroy(); |
+} |
+ |
+void NonClientFrameController::OnDetachedTitleAreaRendererDestroyed( |
+ DetachedTitleAreaRenderer* renderer) { |
+ DCHECK_EQ(detached_title_area_renderer_, renderer); |
+ detached_title_area_renderer_ = nullptr; |
} |
base::string16 NonClientFrameController::GetWindowTitle() const { |
@@ -304,6 +426,19 @@ views::ClientView* NonClientFrameController::CreateClientView( |
return new ClientViewMus(widget, GetContentsView(), this); |
} |
+void NonClientFrameController::OnTreeChanged(const TreeChangeParams& params) { |
+ if (params.new_parent != window_ || |
+ !ShouldRenderParentTitleArea(params.target)) { |
+ return; |
+ } |
+ if (detached_title_area_renderer_) { |
+ detached_title_area_renderer_->Destroy(); |
+ detached_title_area_renderer_ = nullptr; |
+ } |
+ detached_title_area_renderer_ = new DetachedTitleAreaRenderer( |
+ this, widget_, params.target, DetachedTitleAreaRenderer::Source::CLIENT); |
+} |
+ |
void NonClientFrameController::OnWindowSharedPropertyChanged( |
ui::Window* window, |
const std::string& name, |