Commit 2a2a37d0 authored by Mitsuru Oshima's avatar Mitsuru Oshima Committed by Commit Bot

[ChromeOS] Make window opaque if the window isn't normal state.

* A window frame should have rounded corners only in normal state,
(floating state). All other state won't need them so can be
opaque window.

* Don't apply this logic if the opacity is explicitly specified (not kInferred)

* Old code removed the rounded corner only for maximized/fullscreen.
 Instead, this CL checks if it's normal.

* Consolidated the occlusion region update code for transparent window
 to WindowState.

* Update DCHECK in Window::SetOpaqueRegionsForOcclusion to allow resetting.

Bug: 1022544
Test: covered by unit tests. Also tested on the device. OOBE, login screen,
   arc windows works as intended.

Change-Id: Ia8e067945732b81294c3e6733121d433e3087f04
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2059089
Commit-Queue: Mitsuru Oshima (OOO) <oshima@chromium.org>
Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Reviewed-by: default avatarPeter Kasting <pkasting@chromium.org>
Cr-Commit-Position: refs/heads/master@{#743038}
parent 264278d7
......@@ -231,14 +231,9 @@ NonClientFrameViewAsh::NonClientFrameViewAsh(views::Widget* frame)
}
frame_window->SetProperty(kNonClientFrameViewAshKey, this);
frame_window->AddObserver(this);
}
NonClientFrameViewAsh::~NonClientFrameViewAsh() {
aura::Window* frame_window = frame_->GetNativeWindow();
if (frame_window && frame_window->HasObserver(this))
frame_window->RemoveObserver(this);
}
NonClientFrameViewAsh::~NonClientFrameViewAsh() = default;
// static
NonClientFrameViewAsh* NonClientFrameViewAsh::Get(aura::Window* window) {
......@@ -367,20 +362,6 @@ void NonClientFrameViewAsh::SetVisible(bool visible) {
InvalidateLayout();
}
void NonClientFrameViewAsh::OnWindowBoundsChanged(
aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) {
if (window->transparent())
window->SetOpaqueRegionsForOcclusion({gfx::Rect(new_bounds.size())});
}
void NonClientFrameViewAsh::OnWindowDestroying(aura::Window* window) {
DCHECK_EQ(window, frame_->GetNativeWindow());
window->RemoveObserver(this);
}
void NonClientFrameViewAsh::SetShouldPaintHeader(bool paint) {
header_view_->SetShouldPaintHeader(paint);
}
......
......@@ -14,7 +14,6 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/aura/window_observer.h"
#include "ui/views/window/non_client_view.h"
namespace views {
......@@ -33,8 +32,7 @@ class NonClientFrameViewAshImmersiveHelper;
// The window header overlay slides onscreen when the user hovers the mouse at
// the top of the screen. See also views::CustomFrameView and
// BrowserNonClientFrameViewAsh.
class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView,
public aura::WindowObserver {
class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView {
public:
// Internal class name.
static const char kViewClassName[];
......@@ -89,13 +87,6 @@ class ASH_EXPORT NonClientFrameViewAsh : public views::NonClientFrameView,
gfx::Size GetMaximumSize() const override;
void SetVisible(bool visible) override;
// aura::WindowObserver:
void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) override;
void OnWindowDestroying(aura::Window* window) override;
// If |paint| is false, we should not paint the header. Used for overview mode
// with OnOverviewModeStarting() and OnOverviewModeEnded() to hide/show the
// header of v2 and ARC apps.
......
......@@ -8,6 +8,7 @@
#include "ash/public/cpp/caption_buttons/caption_button_model.h"
#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/public/cpp/window_state_type.h"
#include "base/logging.h" // DCHECK
#include "third_party/skia/include/core/SkPath.h"
#include "ui/gfx/canvas.h"
......@@ -106,10 +107,11 @@ void DefaultFrameHeader::SetWidthInPixels(int width_in_pixels) {
}
void DefaultFrameHeader::UpdateFrameColors() {
aura::Window* target_window = GetTargetWindow();
const SkColor active_frame_color =
target_widget()->GetNativeWindow()->GetProperty(kFrameActiveColorKey);
target_window->GetProperty(kFrameActiveColorKey);
const SkColor inactive_frame_color =
target_widget()->GetNativeWindow()->GetProperty(kFrameInactiveColorKey);
target_window->GetProperty(kFrameInactiveColorKey);
bool updated = false;
if (active_frame_color_.target_color() != active_frame_color) {
......@@ -131,10 +133,10 @@ void DefaultFrameHeader::UpdateFrameColors() {
// DefaultFrameHeader, protected:
void DefaultFrameHeader::DoPaintHeader(gfx::Canvas* canvas) {
int corner_radius =
(target_widget()->IsMaximized() || target_widget()->IsFullscreen())
? 0
: kTopCornerRadiusWhenRestored;
int corner_radius = IsNormalWindowStateType(
GetTargetWindow()->GetProperty(kWindowStateTypeKey))
? kTopCornerRadiusWhenRestored
: 0;
cc::PaintFlags flags;
flags.setColor(color_utils::AlphaBlend(
......@@ -179,6 +181,10 @@ SkColor DefaultFrameHeader::GetTitleColor() const {
///////////////////////////////////////////////////////////////////////////////
// DefaultFrameHeader, private:
aura::Window* DefaultFrameHeader::GetTargetWindow() {
return target_widget()->GetNativeWindow();
}
SkColor DefaultFrameHeader::GetCurrentFrameColor() const {
return mode() == MODE_ACTIVE ? active_frame_color_.target_color()
: inactive_frame_color_.target_color();
......
......@@ -48,6 +48,9 @@ class ASH_PUBLIC_EXPORT DefaultFrameHeader : public FrameHeader {
private:
FRIEND_TEST_ALL_PREFIXES(DefaultFrameHeaderTest, FrameColors);
// Returns the window of the target widget.
aura::Window* GetTargetWindow();
gfx::SlideAnimation* GetAnimationForActiveFrameColorForTest();
SkColor GetActiveFrameColorForPaintForTest();
......
......@@ -5,6 +5,7 @@
#include "ash/public/cpp/frame_utils.h"
#include "ash/public/cpp/ash_constants.h"
#include "ash/public/cpp/window_properties.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/base/hit_test.h"
......@@ -16,6 +17,8 @@
namespace ash {
using WindowOpacity = views::Widget::InitParams::WindowOpacity;
int FrameBorderNonClientHitTest(views::NonClientFrameView* view,
const gfx::Point& point_in_widget) {
gfx::Rect expanded_bounds = view->bounds();
......@@ -61,4 +64,11 @@ int FrameBorderNonClientHitTest(views::NonClientFrameView* view,
return HTCAPTION;
}
void ResolveInferredOpacity(views::Widget::InitParams* params) {
DCHECK_EQ(params->opacity, WindowOpacity::kInferred);
params->init_properties_container.SetProperty(
ash::kWindowManagerManagesOpacityKey, true);
params->opacity = WindowOpacity::kTranslucent;
}
} // namespace ash
......@@ -7,6 +7,7 @@
#include "ash/public/cpp/ash_public_export.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/views/widget/widget.h"
namespace gfx {
class Point;
......@@ -23,6 +24,10 @@ ASH_PUBLIC_EXPORT int FrameBorderNonClientHitTest(
views::NonClientFrameView* view,
const gfx::Point& point_in_widget);
// Resolve the inferred opacity and updates the params.
ASH_PUBLIC_EXPORT void ResolveInferredOpacity(
views::Widget::InitParams* params);
} // namespace ash
#endif // ASH_PUBLIC_CPP_FRAME_UTILS_H_
......@@ -28,6 +28,7 @@ DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(WindowBackdrop, kWindowBackdropKey, nullptr)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kBlockedForAssistantSnapshotKey, false)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kCanAttachToAnotherWindowKey, true)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kCanConsumeSystemKeysKey, false)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kExcludeInMruKey, false)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kHideInOverviewKey, false)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kHideShelfWhenFullscreenKey, true)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kImmersiveImpliedByFullscreen, true)
......@@ -47,6 +48,7 @@ DEFINE_UI_CLASS_PROPERTY_KEY(bool, kForceVisibleInMiniViewKey, false)
DEFINE_UI_CLASS_PROPERTY_KEY(WindowStateType,
kPrePipWindowStateTypeKey,
WindowStateType::kDefault)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kWindowManagerManagesOpacityKey, false)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kPipOriginalWindowKey, false)
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(float, kPipSnapFractionKey, nullptr)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kRenderTitleAreaProperty, false)
......@@ -79,5 +81,4 @@ DEFINE_UI_CLASS_PROPERTY_KEY(WindowStateType,
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kWindowPipTypeKey, false)
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kExcludeInMruKey, false)
} // namespace ash
......@@ -63,6 +63,10 @@ ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
kCanConsumeSystemKeysKey;
// A property key to exclude the window in MruTracker.
ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
kExcludeInMruKey;
// A property key to indicate whether we should hide this window in overview
// mode and Alt + Tab.
ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
......@@ -118,6 +122,10 @@ ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
kForceVisibleInMiniViewKey;
// A property key to tell if the window's opacity should be managed by WM.
ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
kWindowManagerManagesOpacityKey;
// A property key to store the window state the window had before entering PIP.
ASH_PUBLIC_EXPORT extern const aura::WindowProperty<WindowStateType>* const
kPrePipWindowStateTypeKey;
......@@ -219,10 +227,6 @@ ASH_PUBLIC_EXPORT extern const aura::WindowProperty<WindowStateType>* const
ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
kWindowPipTypeKey;
// A property key to exclude the window in MruTracker.
ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
kExcludeInMruKey;
// Alphabetical sort.
} // namespace ash
......
......@@ -101,6 +101,10 @@ bool IsMinimizedWindowStateType(WindowStateType type) {
return type == WindowStateType::kMinimized;
}
bool IsNormalWindowStateType(WindowStateType type) {
return type == WindowStateType::kNormal || type == WindowStateType::kDefault;
}
bool IsValidWindowStateType(int64_t value) {
return value == int64_t(WindowStateType::kDefault) ||
value == int64_t(WindowStateType::kNormal) ||
......
......@@ -66,6 +66,9 @@ ASH_PUBLIC_EXPORT bool IsMaximizedOrFullscreenOrPinnedWindowStateType(
// Returns true if |type| is MINIMIZED.
ASH_PUBLIC_EXPORT bool IsMinimizedWindowStateType(WindowStateType type);
// Returns true if |type| is either NORMAL or DEFAULT.
ASH_PUBLIC_EXPORT bool IsNormalWindowStateType(WindowStateType type);
ASH_PUBLIC_EXPORT bool IsValidWindowStateType(int64_t value);
} // namespace ash
......
......@@ -4,6 +4,7 @@
#include "ash/test/ash_test_views_delegate.h"
#include "ash/public/cpp/frame_utils.h"
#include "ash/shell.h"
namespace ash {
......@@ -18,6 +19,9 @@ void AshTestViewsDelegate::OnBeforeWidgetInit(
if (!params->parent && !params->context)
params->context = Shell::GetRootWindowForNewWindows();
if (params->opacity == views::Widget::InitParams::WindowOpacity::kInferred)
ResolveInferredOpacity(params);
TestViewsDelegate::OnBeforeWidgetInit(params, delegate);
}
......
......@@ -654,6 +654,19 @@ void WindowState::UpdateWindowPropertiesFromStateType() {
base::AutoReset<bool> resetter(&ignore_property_change_, true);
window_->SetProperty(kWindowPinTypeKey, pin_type);
}
if (window_->GetProperty(ash::kWindowManagerManagesOpacityKey)) {
const gfx::Size& size = window_->bounds().size();
// WindowManager manages the window opacity. Make it opaque unless
// the window is in normal state whose frame has rounded corners.
if (IsNormalStateType()) {
window_->SetTransparent(true);
window_->SetOpaqueRegionsForOcclusion({gfx::Rect(size)});
} else {
window_->SetOpaqueRegionsForOcclusion({});
window_->SetTransparent(false);
}
}
}
void WindowState::NotifyPreStateTypeChange(
......@@ -947,4 +960,15 @@ void WindowState::OnWindowDestroying(aura::Window* window) {
delegate_.reset();
}
void WindowState::OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) {
DCHECK_EQ(this->window(), window);
if (window_->transparent() &&
window_->type() == aura::client::WINDOW_TYPE_NORMAL) {
window_->SetOpaqueRegionsForOcclusion({gfx::Rect(new_bounds.size())});
}
}
} // namespace ash
......@@ -453,6 +453,10 @@ class ASH_EXPORT WindowState : public aura::WindowObserver {
intptr_t old) override;
void OnWindowAddedToRootWindow(aura::Window* window) override;
void OnWindowDestroying(aura::Window* window) override;
void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) override;
// The owner of this window settings.
aura::Window* window_;
......
......@@ -22,6 +22,7 @@
#include "ui/base/hit_test.h"
#include "ui/display/screen.h"
#include "ui/events/test/event_generator.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/window_util.h"
using ash::WindowStateType;
......@@ -794,6 +795,52 @@ TEST_F(WindowStateTest, SetBoundsSnapsPipBoundsToScreenEdge) {
PipPositioner::GetPositionAfterMovementAreaChange(window_state));
}
// Make sure the window is transparent only when it is in normal state.
TEST_F(WindowStateTest, OpacityChange) {
std::unique_ptr<aura::Window> window = CreateAppWindow();
WindowState* window_state = WindowState::Get(window.get());
EXPECT_TRUE(window_state->IsNormalStateType());
EXPECT_TRUE(window->transparent());
window_state->Maximize();
EXPECT_TRUE(window_state->IsMaximized());
EXPECT_FALSE(window->transparent());
window_state->Restore();
EXPECT_TRUE(window_state->IsNormalStateType());
EXPECT_TRUE(window->transparent());
window_state->Minimize();
EXPECT_TRUE(window_state->IsMinimized());
EXPECT_FALSE(window->transparent());
window_state->Unminimize();
EXPECT_TRUE(window_state->IsNormalStateType());
EXPECT_TRUE(window->transparent());
ToggleFullScreen(window_state, nullptr);
ASSERT_TRUE(window_state->IsFullscreen());
EXPECT_FALSE(window->transparent());
window_state->Restore();
EXPECT_TRUE(window_state->IsNormalStateType());
EXPECT_TRUE(window->transparent());
const WMEvent snap_left(WM_EVENT_SNAP_LEFT);
window_state->OnWMEvent(&snap_left);
EXPECT_FALSE(window->transparent());
window_state->Restore();
EXPECT_TRUE(window->transparent());
const WMEvent snap_right(WM_EVENT_SNAP_RIGHT);
window_state->OnWMEvent(&snap_left);
EXPECT_FALSE(window->transparent());
window_state->OnWMEvent(&snap_left);
EXPECT_FALSE(window->transparent());
}
// TODO(skuhne): Add more unit test to verify the correctness for the restore
// operation.
......
......@@ -23,6 +23,7 @@
#if defined(OS_CHROMEOS)
#include "ash/public/cpp/app_types.h"
#include "ash/public/cpp/frame_utils.h"
#include "chrome/browser/ui/views/touch_selection_menu_runner_chromeos.h"
#include "ui/aura/client/aura_constants.h"
#endif
......@@ -170,8 +171,13 @@ void ChromeViewsDelegate::OnBeforeWidgetInit(
#endif // defined(OS_CHROMEOS)
// We need to determine opacity if it's not already specified.
if (params->opacity == views::Widget::InitParams::WindowOpacity::kInferred)
params->opacity = GetOpacityForInitParams(*params);
if (params->opacity == views::Widget::InitParams::WindowOpacity::kInferred) {
#if defined(OS_CHROMEOS)
ash::ResolveInferredOpacity(params);
#else
params->opacity = views::Widget::InitParams::WindowOpacity::kOpaque;
#endif
}
// If we already have a native_widget, we don't have to try to come
// up with one.
......@@ -198,11 +204,3 @@ ui::ContextFactoryPrivate* ChromeViewsDelegate::GetContextFactoryPrivate() {
std::string ChromeViewsDelegate::GetApplicationName() {
return version_info::GetProductName();
}
#if !defined(OS_CHROMEOS)
views::Widget::InitParams::WindowOpacity
ChromeViewsDelegate::GetOpacityForInitParams(
const views::Widget::InitParams& params) {
return views::Widget::InitParams::WindowOpacity::kOpaque;
}
#endif
......@@ -77,11 +77,6 @@ class ChromeViewsDelegate : public views::ViewsDelegate {
gfx::Rect* bounds) const;
#endif
// Function to retrieve default opacity value mainly based on platform
// and desktop context.
views::Widget::InitParams::WindowOpacity GetOpacityForInitParams(
const views::Widget::InitParams& params);
views::NativeWidget* CreateNativeWidget(
views::Widget::InitParams* params,
views::internal::NativeWidgetDelegate* delegate);
......
......@@ -52,12 +52,6 @@ void ChromeViewsDelegate::AdjustSavedWindowPlacementChromeOS(
bounds->AdjustToFit(display.work_area());
}
views::Widget::InitParams::WindowOpacity
ChromeViewsDelegate::GetOpacityForInitParams(
const views::Widget::InitParams& params) {
return views::Widget::InitParams::WindowOpacity::kTranslucent;
}
views::NativeWidget* ChromeViewsDelegate::CreateNativeWidget(
views::Widget::InitParams* params,
views::internal::NativeWidgetDelegate* delegate) {
......
......@@ -85,15 +85,6 @@ void BrowserFrameAsh::OnWidgetInitDone() {
window_state->SetCanConsumeSystemKeys(browser->deprecated_is_app());
}
void BrowserFrameAsh::OnBoundsChanged(const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) {
NativeWidgetAura::OnBoundsChanged(old_bounds, new_bounds);
if (GetNativeWindow()->transparent()) {
GetNativeWindow()->SetOpaqueRegionsForOcclusion(
{gfx::Rect(new_bounds.size())});
}
}
void BrowserFrameAsh::OnWindowTargetVisibilityChanged(bool visible) {
if (visible) {
// Once the window has been shown we know the requested bounds
......
......@@ -24,8 +24,6 @@ class BrowserFrameAsh : public views::NativeWidgetAura,
// Overridden from views::NativeWidgetAura:
void OnWidgetInitDone() override;
void OnBoundsChanged(const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) override;
void OnWindowTargetVisibilityChanged(bool visible) override;
// Overridden from NativeBrowserFrame:
......
......@@ -8,6 +8,8 @@
#include "ash/public/cpp/caption_buttons/frame_caption_button_container_view.h"
#include "ash/public/cpp/frame_utils.h"
#include "ash/public/cpp/tablet_mode.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/public/cpp/window_state_type.h"
#include "base/logging.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "third_party/skia/include/core/SkCanvas.h"
......@@ -188,9 +190,11 @@ void BrowserFrameHeaderAsh::PaintFrameImages(gfx::Canvas* canvas, bool active) {
gfx::ImageSkia frame_overlay_image =
appearance_provider_->GetFrameHeaderOverlayImage(active);
int corner_radius = 0;
if (!target_widget()->IsMaximized() && !target_widget()->IsFullscreen())
corner_radius = ash::kTopCornerRadiusWhenRestored;
ash::WindowStateType state_type =
target_widget()->GetNativeWindow()->GetProperty(ash::kWindowStateTypeKey);
int corner_radius = ash::IsNormalWindowStateType(state_type)
? ash::kTopCornerRadiusWhenRestored
: 0;
PaintFrameImagesInRoundRect(canvas, frame_image, frame_overlay_image,
appearance_provider_->GetFrameHeaderColor(active),
......
......@@ -1276,7 +1276,7 @@ const char* Window::OcclusionStateToString(OcclusionState state) {
void Window::SetOpaqueRegionsForOcclusion(
const std::vector<gfx::Rect>& opaque_regions_for_occlusion) {
// Only transparent windows should try to set opaque regions for occlusion.
DCHECK(transparent());
DCHECK(transparent() || opaque_regions_for_occlusion.empty());
if (opaque_regions_for_occlusion == opaque_regions_for_occlusion_)
return;
opaque_regions_for_occlusion_ = opaque_regions_for_occlusion;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment