This source file includes following definitions.
- HitTestButton
- snap_type_
- OnMousePressed
- OnMouseDragged
- OnMouseReleased
- OnMouseCaptureLost
- OnMouseMoved
- OnGestureEvent
- StartSetButtonsToSnapModeTimer
- AnimateButtonsToSnapMode
- SetButtonsToSnapMode
- UpdateSnapType
- GetButtonToHover
- CommitSnap
- SetButtonsToNormalMode
#include "ash/frame/caption_buttons/alternate_frame_size_button.h"
#include "ash/metrics/user_metrics_recorder.h"
#include "ash/screen_util.h"
#include "ash/shell.h"
#include "ash/touch/touch_uma.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h"
#include "ash/wm/workspace/phantom_window_controller.h"
#include "base/i18n/rtl.h"
#include "ui/gfx/vector2d.h"
#include "ui/views/widget/widget.h"
namespace {
const int kSetButtonsToSnapModeDelayMs = 150;
const int kMaxOvershootX = 200;
const int kMaxOvershootY = 50;
bool HitTestButton(const ash::FrameCaptionButton* button,
const gfx::Point& location_in_screen) {
gfx::Rect expanded_bounds_in_screen = button->GetBoundsInScreen();
if (button->state() == views::Button::STATE_HOVERED ||
button->state() == views::Button::STATE_PRESSED) {
expanded_bounds_in_screen.Inset(-kMaxOvershootX, -kMaxOvershootY);
}
return expanded_bounds_in_screen.Contains(location_in_screen);
}
}
namespace ash {
AlternateFrameSizeButton::AlternateFrameSizeButton(
views::ButtonListener* listener,
views::Widget* frame,
AlternateFrameSizeButtonDelegate* delegate)
: FrameCaptionButton(listener, CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE),
frame_(frame),
delegate_(delegate),
set_buttons_to_snap_mode_delay_ms_(kSetButtonsToSnapModeDelayMs),
in_snap_mode_(false),
snap_type_(SNAP_NONE) {
}
AlternateFrameSizeButton::~AlternateFrameSizeButton() {
}
bool AlternateFrameSizeButton::OnMousePressed(const ui::MouseEvent& event) {
if (IsTriggerableEvent(event) &&
!in_snap_mode_ &&
delegate_->IsMinimizeButtonVisible()) {
StartSetButtonsToSnapModeTimer(event);
}
FrameCaptionButton::OnMousePressed(event);
return true;
}
bool AlternateFrameSizeButton::OnMouseDragged(const ui::MouseEvent& event) {
UpdateSnapType(event);
if (!in_snap_mode_)
FrameCaptionButton::OnMouseDragged(event);
return true;
}
void AlternateFrameSizeButton::OnMouseReleased(const ui::MouseEvent& event) {
if (!IsTriggerableEvent(event) || !CommitSnap(event))
FrameCaptionButton::OnMouseReleased(event);
}
void AlternateFrameSizeButton::OnMouseCaptureLost() {
SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES);
FrameCaptionButton::OnMouseCaptureLost();
}
void AlternateFrameSizeButton::OnMouseMoved(const ui::MouseEvent& event) {
if (!in_snap_mode_)
FrameCaptionButton::OnMouseMoved(event);
}
void AlternateFrameSizeButton::OnGestureEvent(ui::GestureEvent* event) {
if (event->details().touch_points() > 1) {
SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES);
return;
}
if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
StartSetButtonsToSnapModeTimer(*event);
FrameCaptionButton::OnGestureEvent(event);
return;
}
if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
event->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
UpdateSnapType(*event);
event->SetHandled();
return;
}
if (event->type() == ui::ET_GESTURE_TAP ||
event->type() == ui::ET_GESTURE_SCROLL_END ||
event->type() == ui::ET_SCROLL_FLING_START ||
event->type() == ui::ET_GESTURE_END) {
if (CommitSnap(*event)) {
if (event->type() == ui::ET_GESTURE_TAP) {
TouchUMA::GetInstance()->RecordGestureAction(
TouchUMA::GESTURE_FRAMEMAXIMIZE_TAP);
}
event->SetHandled();
return;
}
}
FrameCaptionButton::OnGestureEvent(event);
}
void AlternateFrameSizeButton::StartSetButtonsToSnapModeTimer(
const ui::LocatedEvent& event) {
set_buttons_to_snap_mode_timer_event_location_ = event.location();
if (set_buttons_to_snap_mode_delay_ms_ == 0) {
AnimateButtonsToSnapMode();
} else {
set_buttons_to_snap_mode_timer_.Start(
FROM_HERE,
base::TimeDelta::FromMilliseconds(set_buttons_to_snap_mode_delay_ms_),
this,
&AlternateFrameSizeButton::AnimateButtonsToSnapMode);
}
}
void AlternateFrameSizeButton::AnimateButtonsToSnapMode() {
SetButtonsToSnapMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES);
}
void AlternateFrameSizeButton::SetButtonsToSnapMode(
AlternateFrameSizeButtonDelegate::Animate animate) {
in_snap_mode_ = true;
if (base::i18n::IsRTL()) {
delegate_->SetButtonIcons(CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
CAPTION_BUTTON_ICON_LEFT_SNAPPED,
animate);
} else {
delegate_->SetButtonIcons(CAPTION_BUTTON_ICON_LEFT_SNAPPED,
CAPTION_BUTTON_ICON_RIGHT_SNAPPED,
animate);
}
}
void AlternateFrameSizeButton::UpdateSnapType(const ui::LocatedEvent& event) {
if (!in_snap_mode_) {
gfx::Vector2d delta(
event.location() - set_buttons_to_snap_mode_timer_event_location_);
if (!set_buttons_to_snap_mode_timer_.IsRunning() ||
!views::View::ExceededDragThreshold(delta)) {
return;
}
AnimateButtonsToSnapMode();
}
gfx::Point event_location_in_screen(event.location());
views::View::ConvertPointToScreen(this, &event_location_in_screen);
const FrameCaptionButton* to_hover =
GetButtonToHover(event_location_in_screen);
bool press_size_button =
to_hover || HitTestButton(this, event_location_in_screen);
if (to_hover) {
SetButtonsToSnapMode(AlternateFrameSizeButtonDelegate::ANIMATE_NO);
}
delegate_->SetHoveredAndPressedButtons(
to_hover, press_size_button ? this : NULL);
snap_type_ = SNAP_NONE;
if (to_hover) {
switch (to_hover->icon()) {
case CAPTION_BUTTON_ICON_LEFT_SNAPPED:
snap_type_ = SNAP_LEFT;
break;
case CAPTION_BUTTON_ICON_RIGHT_SNAPPED:
snap_type_ = SNAP_RIGHT;
break;
case CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE:
case CAPTION_BUTTON_ICON_MINIMIZE:
case CAPTION_BUTTON_ICON_CLOSE:
case CAPTION_BUTTON_ICON_COUNT:
NOTREACHED();
break;
}
}
if (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT) {
aura::Window* window = frame_->GetNativeWindow();
if (!phantom_window_controller_.get()) {
phantom_window_controller_.reset(new PhantomWindowController(window));
}
gfx::Rect phantom_bounds_in_parent = (snap_type_ == SNAP_LEFT) ?
wm::GetDefaultLeftSnappedWindowBoundsInParent(window) :
wm::GetDefaultRightSnappedWindowBoundsInParent(window);
phantom_window_controller_->Show(ScreenUtil::ConvertRectToScreen(
window->parent(), phantom_bounds_in_parent));
} else {
phantom_window_controller_.reset();
}
}
const FrameCaptionButton* AlternateFrameSizeButton::GetButtonToHover(
const gfx::Point& event_location_in_screen) const {
const FrameCaptionButton* closest_button = delegate_->GetButtonClosestTo(
event_location_in_screen);
if ((closest_button->icon() == CAPTION_BUTTON_ICON_LEFT_SNAPPED ||
closest_button->icon() == CAPTION_BUTTON_ICON_RIGHT_SNAPPED) &&
HitTestButton(closest_button, event_location_in_screen)) {
return closest_button;
}
return NULL;
}
bool AlternateFrameSizeButton::CommitSnap(const ui::LocatedEvent& event) {
UpdateSnapType(event);
if (in_snap_mode_ &&
(snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) {
wm::WindowState* window_state =
wm::GetWindowState(frame_->GetNativeWindow());
UserMetricsRecorder* metrics = Shell::GetInstance()->metrics();
const wm::WMEvent snap_event(
snap_type_ == SNAP_LEFT ?
wm::WM_EVENT_SNAP_LEFT : wm::WM_EVENT_SNAP_RIGHT);
window_state->OnWMEvent(&snap_event);
metrics->RecordUserMetricsAction(
snap_type_ == SNAP_LEFT ?
UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT :
UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT);
SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_NO);
return true;
}
SetButtonsToNormalMode(AlternateFrameSizeButtonDelegate::ANIMATE_YES);
return false;
}
void AlternateFrameSizeButton::SetButtonsToNormalMode(
AlternateFrameSizeButtonDelegate::Animate animate) {
in_snap_mode_ = false;
snap_type_ = SNAP_NONE;
set_buttons_to_snap_mode_timer_.Stop();
delegate_->SetButtonsToNormal(animate);
phantom_window_controller_.reset();
}
}