Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Unified Diff: components/exo/shell_surface.cc

Issue 2548653005: exo: Add initial support for service side decorations. (Closed)
Patch Set: fix typo Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/exo/shell_surface.h ('k') | components/exo/shell_surface_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/exo/shell_surface.cc
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc
index 315de70cfa845207ce8afbf2d0e6c04766d20788..6598b78799ee67fc46d7fc43193080483c9e9968 100644
--- a/components/exo/shell_surface.cc
+++ b/components/exo/shell_surface.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "ash/aura/wm_window_aura.h"
+#include "ash/common/frame/custom_frame_view_ash.h"
#include "ash/common/shelf/wm_shelf.h"
#include "ash/common/wm/window_resizer.h"
#include "ash/common/wm/window_state.h"
@@ -37,6 +38,7 @@
#include "ui/wm/core/shadow.h"
#include "ui/wm/core/shadow_controller.h"
#include "ui/wm/core/shadow_types.h"
+#include "ui/wm/core/window_animations.h"
#include "ui/wm/core/window_util.h"
#if defined(OS_CHROMEOS)
@@ -100,6 +102,15 @@ class CustomWindowTargeter : public aura::WindowTargeter {
gfx::Point local_point = event.location();
+ if (window->parent()) {
+ aura::Window::ConvertPointToTarget(window->parent(), window,
+ &local_point);
+ }
+
+ int component = widget_->non_client_view()->NonClientHitTest(local_point);
+ if (component != HTNOWHERE && component != HTCLIENT)
+ return true;
+
// If there is an underlay, test against it's bounds instead since it will
// be equal or larger than the surface's bounds.
aura::Window* shadow_underlay =
@@ -107,16 +118,10 @@ class CustomWindowTargeter : public aura::WindowTargeter {
widget_->widget_delegate()->GetContentsView())
->shadow_underlay();
if (shadow_underlay) {
- if (window->parent())
- aura::Window::ConvertPointToTarget(window->parent(), shadow_underlay,
- &local_point);
+ aura::Window::ConvertPointToTarget(window, shadow_underlay, &local_point);
return gfx::Rect(shadow_underlay->layer()->size()).Contains(local_point);
}
- if (window->parent())
- aura::Window::ConvertPointToTarget(window->parent(), window,
- &local_point);
-
aura::Window::ConvertPointToTarget(window, surface->window(), &local_point);
return surface->HitTestRect(gfx::Rect(local_point, gfx::Size(1, 1)));
}
@@ -133,9 +138,8 @@ class CustomWindowTargeter : public aura::WindowTargeter {
->shadow_underlay();
if (surface && event->IsLocatedEvent() && shadow_underlay) {
gfx::Point local_point = event->AsLocatedEvent()->location();
- aura::Window::ConvertPointToTarget(window, surface->window(),
- &local_point);
- if (!surface->HitTestRect(gfx::Rect(local_point, gfx::Size(1, 1))))
+ int component = widget_->non_client_view()->NonClientHitTest(local_point);
+ if (component == HTNOWHERE)
return shadow_underlay;
}
return aura::WindowTargeter::FindTargetForEvent(root, event);
@@ -333,12 +337,14 @@ ShellSurface::ShellSurface(Surface* surface,
ShellSurface* parent,
const gfx::Rect& initial_bounds,
bool activatable,
+ bool can_minimize,
int container)
: widget_(nullptr),
surface_(surface),
parent_(parent ? parent->GetWidget()->GetNativeWindow() : nullptr),
initial_bounds_(initial_bounds),
activatable_(activatable),
+ can_minimize_(can_minimize),
container_(container) {
WMHelper::GetInstance()->AddActivationObserver(this);
surface_->SetSurfaceDelegate(this);
@@ -354,6 +360,7 @@ ShellSurface::ShellSurface(Surface* surface)
nullptr,
gfx::Rect(),
true,
+ true,
ash::kShellWindowId_DefaultContainer) {}
ShellSurface::~ShellSurface() {
@@ -578,9 +585,16 @@ void ShellSurface::SetGeometry(const gfx::Rect& geometry) {
pending_geometry_ = geometry;
}
-void ShellSurface::SetRectangularShadow(const gfx::Rect& content_bounds) {
- TRACE_EVENT1("exo", "ShellSurface::SetRectangularShadow", "content_bounds",
- content_bounds.ToString());
+void ShellSurface::SetRectangularShadow(bool enabled) {
+ TRACE_EVENT1("exo", "ShellSurface::SetRectangularShadow", "enabled", enabled);
+
+ shadow_enabled_ = enabled;
+}
+
+void ShellSurface::SetRectangularShadowContentBounds(
+ const gfx::Rect& content_bounds) {
+ TRACE_EVENT1("exo", "ShellSurface::SetRectangularShadowContentBounds",
+ "content_bounds", content_bounds.ToString());
shadow_content_bounds_ = content_bounds;
}
@@ -589,7 +603,13 @@ void ShellSurface::SetRectangularShadowBackgroundOpacity(float opacity) {
TRACE_EVENT1("exo", "ShellSurface::SetRectangularShadowBackgroundOpacity",
"opacity", opacity);
- rectangular_shadow_background_opacity_ = opacity;
+ shadow_background_opacity_ = opacity;
+}
+
+void ShellSurface::SetFrame(bool enabled) {
+ TRACE_EVENT1("exo", "ShellSurface::SetFrame", "enabled", enabled);
+
+ frame_enabled_ = enabled;
}
void ShellSurface::SetScale(double scale) {
@@ -615,11 +635,10 @@ void ShellSurface::SetOrigin(const gfx::Point& origin) {
initial_bounds_ = gfx::Rect(origin, gfx::Size(1, 1));
}
-void ShellSurface::SetActivatable(bool activatable) {
- TRACE_EVENT1("exo", "ShellSurface::SetActivatable", "activatable",
- activatable);
+void ShellSurface::SetContainer(int container) {
+ TRACE_EVENT1("exo", "ShellSurface::SetContainer", "container", container);
- activatable_ = activatable;
+ container_ = container;
}
// static
@@ -676,15 +695,12 @@ void ShellSurface::OnSurfaceCommit() {
top_inset_height_ = pending_top_inset_height_;
}
- gfx::Point surface_origin = GetSurfaceOrigin();
-
// System modal container is used by clients to implement overlay
// windows using a single ShellSurface instance. If hit-test
// region is empty, then it is non interactive window and won't be
// activated.
if (container_ == ash::kShellWindowId_SystemModalContainer) {
- gfx::Rect hit_test_bounds =
- surface_->GetHitTestBounds() + surface_origin.OffsetFromOrigin();
+ gfx::Rect hit_test_bounds = surface_->GetHitTestBounds();
// Prevent window from being activated when hit test bounds are empty.
bool activatable = activatable_ && !hit_test_bounds.IsEmpty();
@@ -698,9 +714,13 @@ void ShellSurface::OnSurfaceCommit() {
}
}
+ gfx::Rect client_view_bounds =
+ widget_->non_client_view()->frame_view()->GetBoundsForClientView();
+
// Update surface bounds.
surface_->window()->SetBounds(
- gfx::Rect(surface_origin, surface_->window()->layer()->size()));
+ gfx::Rect(GetSurfaceOrigin() + client_view_bounds.OffsetFromOrigin(),
+ surface_->window()->layer()->size()));
// Update surface scale.
if (pending_scale_ != scale_) {
@@ -758,12 +778,15 @@ bool ShellSurface::CanResize() const {
bool ShellSurface::CanMaximize() const {
// Shell surfaces in system modal container cannot be maximized.
- return container_ != ash::kShellWindowId_SystemModalContainer;
+ if (container_ == ash::kShellWindowId_SystemModalContainer)
+ return false;
+
+ // Non-transient shell surfaces can be maximized.
+ return !parent_;
}
bool ShellSurface::CanMinimize() const {
- // Shell surfaces in system modal container cannot be minimized.
- return container_ != ash::kShellWindowId_SystemModalContainer;
+ return can_minimize_;
}
base::string16 ShellSurface::GetWindowTitle() const {
@@ -793,6 +816,15 @@ views::View* ShellSurface::GetContentsView() {
views::NonClientFrameView* ShellSurface::CreateNonClientFrameView(
views::Widget* widget) {
+ aura::Window* window = widget_->GetNativeWindow();
+ ash::wm::WindowState* window_state = ash::wm::GetWindowState(window);
+ // Set delegate for handling of fullscreening.
+ window_state->SetDelegate(std::unique_ptr<ash::wm::WindowStateDelegate>(
+ new CustomWindowStateDelegate(widget_)));
+
+ if (frame_enabled_)
+ return new ash::CustomFrameViewAsh(widget);
+
return new CustomFrameView(widget);
}
@@ -817,6 +849,10 @@ gfx::Size ShellSurface::GetPreferredSize() const {
return surface_ ? surface_->window()->layer()->size() : gfx::Size();
}
+gfx::Size ShellSurface::GetMinimumSize() const {
+ return gfx::Size(1, 1);
+}
+
////////////////////////////////////////////////////////////////////////////////
// ash::wm::WindowStateObserver overrides:
@@ -877,8 +913,13 @@ void ShellSurface::OnWindowBoundsChanged(aura::Window* window,
pending_origin_config_offset_ += origin_offset;
origin_ -= origin_offset;
+ gfx::Rect client_view_bounds =
+ widget_->non_client_view()->frame_view()->GetBoundsForClientView();
+
+ // Update surface bounds.
surface_->window()->SetBounds(
- gfx::Rect(GetSurfaceOrigin(), surface_->window()->layer()->size()));
+ gfx::Rect(GetSurfaceOrigin() + client_view_bounds.OffsetFromOrigin(),
+ surface_->window()->layer()->size()));
// The shadow size may be updated to match the widget. Change it back
// to the shadow content size.
@@ -1065,13 +1106,11 @@ void ShellSurface::CreateShellSurfaceWidget(ui::WindowShowState show_state) {
// AutoHide shelf in fullscreen state.
window_state->set_hide_shelf_when_fullscreen(false);
- // Allow Ash to manage the position of a top-level shell surfaces if show
- // state is one that allows auto positioning and |initial_bounds_| has
- // not been set.
- window_state->set_window_position_managed(
- ash::wm::ToWindowShowState(ash::wm::WINDOW_STATE_TYPE_AUTO_POSITIONED) ==
- show_state &&
- initial_bounds_.IsEmpty());
+ // Fade visibility animations for non-activatable windows.
+ if (!activatable_) {
+ wm::SetWindowVisibilityAnimationType(
+ window, wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
+ }
// Register close window accelerators.
views::FocusManager* focus_manager = widget_->GetFocusManager();
@@ -1081,10 +1120,6 @@ void ShellSurface::CreateShellSurfaceWidget(ui::WindowShowState show_state) {
ui::AcceleratorManager::kNormalPriority, this);
}
- // Set delegate for handling of fullscreening.
- window_state->SetDelegate(std::unique_ptr<ash::wm::WindowStateDelegate>(
- new CustomWindowStateDelegate(widget_)));
-
// Receive accessibility changes to update shadow underlay.
WMHelper::GetInstance()->AddAccessibilityObserver(this);
@@ -1104,21 +1139,29 @@ void ShellSurface::Configure() {
gfx::Vector2d origin_offset = pending_origin_config_offset_;
pending_origin_config_offset_ = gfx::Vector2d();
+ ash::wm::WindowState* window_state =
+ ash::wm::GetWindowState(widget_->GetNativeWindow());
+
// If surface is being resized, save the resize direction.
- int resize_component =
- resizer_ ? resizer_->details().window_component : HTCAPTION;
+ int resize_component = window_state->is_dragged()
+ ? window_state->drag_details()->window_component
+ : HTCAPTION;
+
+ uint32_t serial = 0;
+ if (!configure_callback_.is_null()) {
+ const views::NonClientView* non_client_view = widget_->non_client_view();
+ serial = configure_callback_.Run(
+ non_client_view->frame_view()->GetBoundsForClientView().size(),
+ ash::wm::GetWindowState(widget_->GetNativeWindow())->GetStateType(),
+ IsResizing(), widget_->IsActive());
+ }
- if (configure_callback_.is_null()) {
+ if (!serial) {
pending_origin_offset_ += origin_offset;
pending_resize_component_ = resize_component;
return;
}
- uint32_t serial = configure_callback_.Run(
- widget_->GetWindowBoundsInScreen().size(),
- ash::wm::GetWindowState(widget_->GetNativeWindow())->GetStateType(),
- IsResizing(), widget_->IsActive());
-
// Apply origin offset and resize component at the first Commit() after this
// configure request has been acknowledged.
pending_configs_.push_back({serial, origin_offset, resize_component});
@@ -1226,10 +1269,12 @@ void ShellSurface::EndDrag(bool revert) {
}
bool ShellSurface::IsResizing() const {
- if (!resizer_)
+ ash::wm::WindowState* window_state =
+ ash::wm::GetWindowState(widget_->GetNativeWindow());
+ if (!window_state->is_dragged())
return false;
- return resizer_->details().bounds_change &
+ return window_state->drag_details()->bounds_change &
ash::WindowResizer::kBoundsChange_Resizes;
}
@@ -1240,17 +1285,17 @@ gfx::Rect ShellSurface::GetVisibleBounds() const {
}
gfx::Point ShellSurface::GetSurfaceOrigin() const {
- gfx::Rect window_bounds = widget_->GetNativeWindow()->bounds();
-
// If initial bounds were specified then surface origin is always relative
// to those bounds.
if (!initial_bounds_.IsEmpty()) {
- gfx::Point origin = window_bounds.origin();
+ gfx::Point origin = widget_->GetNativeWindow()->bounds().origin();
wm::ConvertPointToScreen(widget_->GetNativeWindow()->parent(), &origin);
return initial_bounds_.origin() - origin.OffsetFromOrigin();
}
gfx::Rect visible_bounds = GetVisibleBounds();
+ gfx::Rect client_bounds =
+ widget_->non_client_view()->frame_view()->GetBoundsForClientView();
switch (resize_component_) {
case HTCAPTION:
return origin_ - visible_bounds.OffsetFromOrigin();
@@ -1260,16 +1305,16 @@ gfx::Point ShellSurface::GetSurfaceOrigin() const {
return gfx::Point() - visible_bounds.OffsetFromOrigin();
case HTTOP:
case HTTOPRIGHT:
- return gfx::Point(0, window_bounds.height() - visible_bounds.height()) -
+ return gfx::Point(0, client_bounds.height() - visible_bounds.height()) -
visible_bounds.OffsetFromOrigin();
break;
case HTLEFT:
case HTBOTTOMLEFT:
- return gfx::Point(window_bounds.width() - visible_bounds.width(), 0) -
+ return gfx::Point(client_bounds.width() - visible_bounds.width(), 0) -
visible_bounds.OffsetFromOrigin();
case HTTOPLEFT:
- return gfx::Point(window_bounds.width() - visible_bounds.width(),
- window_bounds.height() - visible_bounds.height()) -
+ return gfx::Point(client_bounds.width() - visible_bounds.width(),
+ client_bounds.height() - visible_bounds.height()) -
visible_bounds.OffsetFromOrigin();
default:
NOTREACHED();
@@ -1299,7 +1344,9 @@ void ShellSurface::UpdateWidgetBounds() {
return;
gfx::Rect visible_bounds = GetVisibleBounds();
- gfx::Rect new_widget_bounds = visible_bounds;
+ gfx::Rect new_widget_bounds =
+ widget_->non_client_view()->GetWindowBoundsForClientBounds(
+ visible_bounds);
// Avoid changing widget origin unless initial bounds were specified and
// widget origin is always relative to it.
@@ -1328,28 +1375,36 @@ void ShellSurface::UpdateWidgetBounds() {
widget_->SetBounds(new_widget_bounds);
ignore_window_bounds_changes_ = false;
+ gfx::Rect client_view_bounds =
+ widget_->non_client_view()->frame_view()->GetBoundsForClientView();
+
// A change to the widget size requires surface bounds to be re-adjusted.
surface_->window()->SetBounds(
- gfx::Rect(GetSurfaceOrigin(), surface_->window()->layer()->size()));
+ gfx::Rect(GetSurfaceOrigin() + client_view_bounds.OffsetFromOrigin(),
+ surface_->window()->layer()->size()));
}
void ShellSurface::UpdateShadow() {
if (!widget_)
return;
aura::Window* window = widget_->GetNativeWindow();
- if (shadow_content_bounds_.IsEmpty()) {
+ if (!shadow_enabled_) {
wm::SetShadowType(window, wm::SHADOW_TYPE_NONE);
if (shadow_underlay_)
shadow_underlay_->Hide();
} else {
wm::SetShadowType(window, wm::SHADOW_TYPE_RECTANGULAR);
+ gfx::Rect shadow_content_bounds = shadow_content_bounds_;
+ if (shadow_content_bounds.IsEmpty())
+ shadow_content_bounds = window->bounds();
+
// TODO(oshima): Adjust the coordinates from client screen to
// chromeos screen when multi displays are supported.
gfx::Point origin = window->bounds().origin();
- gfx::Point shadow_origin = shadow_content_bounds_.origin();
+ gfx::Point shadow_origin = shadow_content_bounds.origin();
shadow_origin -= origin.OffsetFromOrigin();
- gfx::Rect shadow_bounds(shadow_origin, shadow_content_bounds_.size());
+ gfx::Rect shadow_bounds(shadow_origin, shadow_content_bounds.size());
// Always create and show the underlay, even in maximized/fullscreen.
if (!shadow_underlay_) {
@@ -1373,7 +1428,7 @@ void ShellSurface::UpdateShadow() {
WMHelper::GetInstance()->IsSpokenFeedbackEnabled() &&
widget_->IsActive();
- float shadow_underlay_opacity = rectangular_shadow_background_opacity_;
+ float shadow_underlay_opacity = shadow_background_opacity_;
// Put the black background layer behind the window if
// 1) the window is in immersive fullscreen or is active with
// spoken feedback enabled.
@@ -1391,7 +1446,16 @@ void ShellSurface::UpdateShadow() {
shadow_underlay_opacity = 1.0f;
}
- shadow_underlay_->SetBounds(shadow_bounds);
+ gfx::Rect shadow_underlay_bounds = shadow_bounds;
+
+ // Constrain the underlay bounds to the client area in case shell surface
+ // frame is enabled.
+ if (frame_enabled_) {
+ shadow_underlay_bounds.Intersect(
+ widget_->non_client_view()->frame_view()->GetBoundsForClientView());
+ }
+
+ shadow_underlay_->SetBounds(shadow_underlay_bounds);
// TODO(oshima): Setting to the same value should be no-op.
// crbug.com/642223.
@@ -1418,6 +1482,10 @@ void ShellSurface::UpdateShadow() {
}
shadow_overlay_->SetBounds(shadow_bounds);
shadow->SetContentBounds(gfx::Rect(shadow_bounds.size()));
+ // Surfaces that can't be activated are usually menus and tooltips. Use a
+ // small style shadow for them.
+ if (!activatable_)
+ shadow->SetStyle(wm::Shadow::STYLE_SMALL);
}
}
« no previous file with comments | « components/exo/shell_surface.h ('k') | components/exo/shell_surface_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698