123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/frame/wide_frame_view.h"
- #include <memory>
- #include "ash/frame/header_view.h"
- #include "ash/frame/non_client_frame_view_ash.h"
- #include "ash/public/cpp/window_properties.h"
- #include "ash/screen_util.h"
- #include "ash/shell.h"
- #include "ash/wm/overview/overview_controller.h"
- #include "ash/wm/window_state.h"
- #include "ash/wm/wm_event.h"
- #include "base/bind.h"
- #include "base/metrics/user_metrics.h"
- #include "chromeos/ui/frame/caption_buttons/frame_caption_button_container_view.h"
- #include "chromeos/ui/frame/default_frame_header.h"
- #include "chromeos/ui/frame/immersive/immersive_fullscreen_controller.h"
- #include "ui/aura/window.h"
- #include "ui/aura/window_targeter.h"
- #include "ui/display/display.h"
- #include "ui/display/screen.h"
- #include "ui/views/widget/widget.h"
- #include "ui/views/window/caption_button_layout_constants.h"
- namespace ash {
- namespace {
- using ::chromeos::ImmersiveFullscreenController;
- class WideFrameTargeter : public aura::WindowTargeter {
- public:
- explicit WideFrameTargeter(HeaderView* header_view)
- : header_view_(header_view) {}
- WideFrameTargeter(const WideFrameTargeter&) = delete;
- WideFrameTargeter& operator=(const WideFrameTargeter&) = delete;
- ~WideFrameTargeter() override = default;
- // aura::WindowTargeter:
- bool GetHitTestRects(aura::Window* target,
- gfx::Rect* hit_test_rect_mouse,
- gfx::Rect* hit_test_rect_touch) const override {
- if (header_view_->in_immersive_mode() && !header_view_->is_revealed()) {
- aura::Window* source = header_view_->GetWidget()->GetNativeWindow();
- *hit_test_rect_mouse = source->bounds();
- aura::Window::ConvertRectToTarget(source, target->parent(),
- hit_test_rect_mouse);
- hit_test_rect_mouse->set_y(target->bounds().y());
- hit_test_rect_mouse->set_height(1);
- hit_test_rect_touch->SetRect(0, 0, 0, 0);
- return true;
- }
- return aura::WindowTargeter::GetHitTestRects(target, hit_test_rect_mouse,
- hit_test_rect_touch);
- }
- private:
- HeaderView* header_view_;
- };
- } // namespace
- // static
- gfx::Rect WideFrameView::GetFrameBounds(views::Widget* target) {
- static const int kFrameHeight =
- views::GetCaptionButtonLayoutSize(
- views::CaptionButtonLayoutSize::kNonBrowserCaption)
- .height();
- aura::Window* target_window = target->GetNativeWindow();
- gfx::Rect bounds =
- screen_util::GetIdealBoundsForMaximizedOrFullscreenOrPinnedState(
- target_window);
- bounds.set_height(kFrameHeight);
- return bounds;
- }
- void WideFrameView::Init(ImmersiveFullscreenController* controller) {
- DCHECK(target_);
- controller->Init(this, target_, header_view_);
- }
- void WideFrameView::SetCaptionButtonModel(
- std::unique_ptr<chromeos::CaptionButtonModel> model) {
- header_view_->caption_button_container()->SetModel(std::move(model));
- header_view_->UpdateCaptionButtons();
- }
- WideFrameView::WideFrameView(views::Widget* target)
- : target_(target),
- frame_context_menu_controller_(
- std::make_unique<FrameContextMenuController>(target_, this)) {
- // WideFrameView is owned by its client, not by Views.
- SetOwnedByWidget(false);
- aura::Window* target_window = target->GetNativeWindow();
- target_window->AddObserver(this);
- // Use the HeaderView itself as a frame view because WideFrameView is
- // is the frame only.
- header_view_ = AddChildView(
- std::make_unique<HeaderView>(target, /*frame view=*/nullptr));
- header_view_->Init();
- GetTargetHeaderView()->SetShouldPaintHeader(false);
- header_view_->set_context_menu_controller(
- frame_context_menu_controller_.get());
- views::Widget::InitParams params;
- params.type = views::Widget::InitParams::TYPE_POPUP;
- params.delegate = this;
- params.bounds = GetFrameBounds(target);
- params.name = "WideFrameView";
- params.parent = target->GetNativeWindow();
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- // Setup Opacity Control.
- // WideFrame should be used only when the rounded corner is not necessary.
- params.opacity = views::Widget::InitParams::WindowOpacity::kOpaque;
- auto widget = std::make_unique<views::Widget>();
- widget->Init(std::move(params));
- widget_ = std::move(widget);
- aura::Window* window = widget_->GetNativeWindow();
- // Overview normally clips the caption container which exists on the same
- // window. But this WideFrameView exists as a separate window, which we hide
- // in overview using the `kHideInOverviewKey` property. However, we still want
- // to show it in the desks mini_views.
- window->SetProperty(kHideInOverviewKey, true);
- window->SetProperty(kForceVisibleInMiniViewKey, true);
- window->SetEventTargeter(std::make_unique<WideFrameTargeter>(header_view()));
- set_owned_by_client();
- WindowState::Get(window)->set_allow_set_bounds_direct(true);
- paint_as_active_subscription_ =
- target_->RegisterPaintAsActiveChangedCallback(base::BindRepeating(
- &WideFrameView::PaintAsActiveChanged, base::Unretained(this)));
- PaintAsActiveChanged();
- }
- WideFrameView::~WideFrameView() {
- if (widget_)
- widget_->CloseNow();
- if (target_) {
- HeaderView* target_header_view = GetTargetHeaderView();
- target_header_view->SetShouldPaintHeader(true);
- target_header_view->GetFrameHeader()->UpdateFrameHeaderKey();
- target_->GetNativeWindow()->RemoveObserver(this);
- }
- }
- void WideFrameView::Layout() {
- int onscreen_height = header_view_->GetPreferredOnScreenHeight();
- if (onscreen_height == 0 || !GetVisible()) {
- header_view_->SetVisible(false);
- } else {
- const int height = header_view_->GetPreferredHeight();
- header_view_->SetBounds(0, onscreen_height - height, width(), height);
- header_view_->SetVisible(true);
- }
- }
- void WideFrameView::OnMouseEvent(ui::MouseEvent* event) {
- if (event->IsOnlyLeftMouseButton()) {
- if ((event->flags() & ui::EF_IS_DOUBLE_CLICK)) {
- base::RecordAction(
- base::UserMetricsAction("Caption_ClickTogglesMaximize"));
- const WMEvent wm_event(WM_EVENT_TOGGLE_MAXIMIZE_CAPTION);
- WindowState::Get(target_->GetNativeWindow())->OnWMEvent(&wm_event);
- }
- event->SetHandled();
- }
- }
- void WideFrameView::OnWindowDestroying(aura::Window* window) {
- window->RemoveObserver(this);
- target_ = nullptr;
- }
- void WideFrameView::OnDisplayMetricsChanged(const display::Display& display,
- uint32_t changed_metrics) {
- aura::Window* target_window = target_->GetNativeWindow();
- // The target window is detached from the tree when the window is being moved
- // to another desks, or another display, and it may trigger the display
- // metrics change if the target window is in fullscreen. Do not try to layout
- // in this case. The it'll be layout when the window is added back.
- // (crbug.com/1267128)
- if (!target_window->GetRootWindow())
- return;
- display::Screen* screen = display::Screen::GetScreen();
- if (screen->GetDisplayNearestWindow(target_->GetNativeWindow()).id() !=
- display.id() ||
- !widget_) {
- return;
- }
- DCHECK(target_);
- // Ignore if this is called when the targe window state is nor proper
- // state. This can happen when switching the state to other states, in which
- // case, the wide frame will be removed.
- if (!WindowState::Get(target_window)->IsMaximizedOrFullscreenOrPinned()) {
- return;
- }
- GetWidget()->SetBounds(GetFrameBounds(target_));
- }
- void WideFrameView::OnImmersiveRevealStarted() {
- header_view_->OnImmersiveRevealStarted();
- }
- void WideFrameView::OnImmersiveRevealEnded() {
- header_view_->OnImmersiveRevealEnded();
- }
- void WideFrameView::OnImmersiveFullscreenEntered() {
- header_view_->OnImmersiveFullscreenEntered();
- widget_->GetNativeWindow()->SetTransparent(true);
- if (target_)
- GetTargetHeaderView()->OnImmersiveFullscreenEntered();
- }
- void WideFrameView::OnImmersiveFullscreenExited() {
- header_view_->OnImmersiveFullscreenExited();
- widget_->GetNativeWindow()->SetTransparent(false);
- if (target_)
- GetTargetHeaderView()->OnImmersiveFullscreenExited();
- Layout();
- }
- void WideFrameView::SetVisibleFraction(double visible_fraction) {
- header_view_->SetVisibleFraction(visible_fraction);
- }
- std::vector<gfx::Rect> WideFrameView::GetVisibleBoundsInScreen() const {
- return header_view_->GetVisibleBoundsInScreen();
- }
- bool WideFrameView::ShouldShowContextMenu(
- View* source,
- const gfx::Point& screen_coords_point) {
- gfx::Point point_in_header_coords(screen_coords_point);
- views::View::ConvertPointToTarget(this, header_view_,
- &point_in_header_coords);
- return header_view_->HitTestRect(
- gfx::Rect(point_in_header_coords, gfx::Size(1, 1)));
- }
- HeaderView* WideFrameView::GetTargetHeaderView() {
- auto* frame_view = static_cast<NonClientFrameViewAsh*>(
- target_->non_client_view()->frame_view());
- return frame_view->GetHeaderView();
- }
- void WideFrameView::PaintAsActiveChanged() {
- header_view_->GetFrameHeader()->SetPaintAsActive(
- target_->ShouldPaintAsActive());
- }
- } // namespace ash
|