1 // Copyright (c) 2012 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.
5 #include "ash/wm/workspace/workspace_event_handler.h"
7 #include "ash/screen_ash.h"
9 #include "ash/shell_delegate.h"
10 #include "ash/wm/property_util.h"
11 #include "ash/wm/window_util.h"
12 #include "ash/wm/workspace/workspace_window_resizer.h"
13 #include "ui/aura/client/aura_constants.h"
14 #include "ui/aura/window.h"
15 #include "ui/aura/window_delegate.h"
16 #include "ui/base/events/event.h"
17 #include "ui/base/events/event_utils.h"
18 #include "ui/base/hit_test.h"
19 #include "ui/compositor/scoped_layer_animation_settings.h"
20 #include "ui/gfx/screen.h"
25 void SingleAxisMaximize(aura::Window
* window
, const gfx::Rect
& maximize_rect
) {
26 gfx::Rect bounds_in_screen
=
27 ScreenAsh::ConvertRectToScreen(window
->parent(), window
->bounds());
29 SetRestoreBoundsInScreen(window
, bounds_in_screen
);
30 window
->SetBounds(maximize_rect
);
33 void SingleAxisUnmaximize(aura::Window
* window
,
34 const gfx::Rect
& restore_bounds_in_screen
) {
35 gfx::Rect restore_bounds
= ScreenAsh::ConvertRectFromScreen(
36 window
->parent(), restore_bounds_in_screen
);
37 window
->SetBounds(restore_bounds
);
38 ClearRestoreBounds(window
);
41 void ToggleMaximizedState(aura::Window
* window
) {
42 if (GetRestoreBoundsInScreen(window
)) {
43 if (window
->GetProperty(aura::client::kShowStateKey
) ==
44 ui::SHOW_STATE_NORMAL
) {
45 window
->SetBounds(GetRestoreBoundsInParent(window
));
46 ClearRestoreBounds(window
);
48 window
->SetProperty(aura::client::kShowStateKey
, ui::SHOW_STATE_NORMAL
);
50 } else if (wm::CanMaximizeWindow(window
)) {
51 window
->SetProperty(aura::client::kShowStateKey
, ui::SHOW_STATE_MAXIMIZED
);
59 WorkspaceEventHandler::WorkspaceEventHandler(aura::Window
* owner
)
60 : ToplevelWindowEventHandler(owner
),
64 WorkspaceEventHandler::~WorkspaceEventHandler() {
69 void WorkspaceEventHandler::OnMouseEvent(ui::MouseEvent
* event
) {
70 aura::Window
* target
= static_cast<aura::Window
*>(event
->target());
71 switch (event
->type()) {
72 case ui::ET_MOUSE_MOVED
: {
74 target
->delegate()->GetNonClientComponent(event
->location());
75 multi_window_resize_controller_
.Show(target
, component
,
79 case ui::ET_MOUSE_ENTERED
:
81 case ui::ET_MOUSE_CAPTURE_CHANGED
:
82 case ui::ET_MOUSE_EXITED
:
84 case ui::ET_MOUSE_PRESSED
: {
85 // Maximize behavior is implemented as post-target handling so the target
87 if (ui::EventCanceledDefaultHandling(*event
)) {
88 ToplevelWindowEventHandler::OnMouseEvent(event
);
92 if (event
->flags() & ui::EF_IS_DOUBLE_CLICK
&&
93 target
->delegate()->GetNonClientComponent(event
->location()) ==
95 bool destroyed
= false;
96 destroyed_
= &destroyed
;
97 ash::Shell::GetInstance()->delegate()->RecordUserMetricsAction(
98 ash::UMA_TOGGLE_MAXIMIZE_CAPTION_CLICK
);
99 ToggleMaximizedState(target
);
104 multi_window_resize_controller_
.Hide();
105 HandleVerticalResizeDoubleClick(target
, event
);
111 ToplevelWindowEventHandler::OnMouseEvent(event
);
114 void WorkspaceEventHandler::OnGestureEvent(ui::GestureEvent
* event
) {
115 aura::Window
* target
= static_cast<aura::Window
*>(event
->target());
116 if (event
->type() == ui::ET_GESTURE_TAP
&&
117 event
->details().tap_count() == 2 &&
118 target
->delegate()->GetNonClientComponent(event
->location()) ==
120 ash::Shell::GetInstance()->delegate()->RecordUserMetricsAction(
121 ash::UMA_TOGGLE_MAXIMIZE_CAPTION_GESTURE
);
122 ToggleMaximizedState(target
); // |this| may be destroyed from here.
123 event
->StopPropagation();
126 ToplevelWindowEventHandler::OnGestureEvent(event
);
129 void WorkspaceEventHandler::HandleVerticalResizeDoubleClick(
130 aura::Window
* target
,
131 ui::MouseEvent
* event
) {
132 gfx::Rect
max_size(target
->delegate()->GetMaximumSize());
133 if (event
->flags() & ui::EF_IS_DOUBLE_CLICK
&&
134 !wm::IsWindowMaximized(target
)) {
136 target
->delegate()->GetNonClientComponent(event
->location());
137 gfx::Rect work_area
=
138 Shell::GetScreen()->GetDisplayNearestWindow(target
).work_area();
139 const gfx::Rect
* restore_bounds
=
140 GetRestoreBoundsInScreen(target
);
141 if (component
== HTBOTTOM
|| component
== HTTOP
) {
142 // Don't maximize vertically if the window has a max height defined.
143 if (max_size
.height() != 0)
145 if (restore_bounds
&&
146 (target
->bounds().height() == work_area
.height() &&
147 target
->bounds().y() == work_area
.y())) {
148 SingleAxisUnmaximize(target
, *restore_bounds
);
150 SingleAxisMaximize(target
,
151 gfx::Rect(target
->bounds().x(),
153 target
->bounds().width(),
154 work_area
.height()));
156 } else if (component
== HTLEFT
|| component
== HTRIGHT
) {
157 // Don't maximize horizontally if the window has a max width defined.
158 if (max_size
.width() != 0)
160 if (restore_bounds
&&
161 (target
->bounds().width() == work_area
.width() &&
162 target
->bounds().x() == work_area
.x())) {
163 SingleAxisUnmaximize(target
, *restore_bounds
);
165 SingleAxisMaximize(target
,
166 gfx::Rect(work_area
.x(),
167 target
->bounds().y(),
169 target
->bounds().height()));
175 } // namespace internal