blob: 5c4d9578433bf66b9d6efe8f5758529c7ee49e4c [file] [log] [blame]
// Copyright (c) 2012 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/wm/toplevel_window_event_handler.h"
#include "ash/aura/wm_window_aura.h"
#include "ash/shell.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/hit_test.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/gestures/gesture_recognizer.h"
namespace ash {
ToplevelWindowEventHandler::ToplevelWindowEventHandler(WmShell* shell)
: wm_toplevel_window_event_handler_(shell), weak_factory_(this) {}
ToplevelWindowEventHandler::~ToplevelWindowEventHandler() {}
void ToplevelWindowEventHandler::OnKeyEvent(ui::KeyEvent* event) {
wm_toplevel_window_event_handler_.OnKeyEvent(event);
}
void ToplevelWindowEventHandler::OnMouseEvent(ui::MouseEvent* event) {
aura::Window* target = static_cast<aura::Window*>(event->target());
wm_toplevel_window_event_handler_.OnMouseEvent(event,
WmWindowAura::Get(target));
}
void ToplevelWindowEventHandler::OnGestureEvent(ui::GestureEvent* event) {
aura::Window* target = static_cast<aura::Window*>(event->target());
wm_toplevel_window_event_handler_.OnGestureEvent(event,
WmWindowAura::Get(target));
}
aura::client::WindowMoveResult ToplevelWindowEventHandler::RunMoveLoop(
aura::Window* source,
const gfx::Vector2d& drag_offset,
aura::client::WindowMoveSource move_source) {
DCHECK(!in_move_loop_); // Can only handle one nested loop at a time.
aura::Window* root_window = source->GetRootWindow();
DCHECK(root_window);
gfx::Point drag_location;
if (move_source == aura::client::WINDOW_MOVE_SOURCE_TOUCH &&
aura::Env::GetInstance()->is_touch_down()) {
gfx::PointF drag_location_f;
bool has_point = ui::GestureRecognizer::Get()->GetLastTouchPointForTarget(
source, &drag_location_f);
drag_location = gfx::ToFlooredPoint(drag_location_f);
DCHECK(has_point);
} else {
drag_location =
root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot();
aura::Window::ConvertPointToTarget(root_window, source->parent(),
&drag_location);
}
// Set the cursor before calling AttemptToStartDrag(), as that will
// eventually call LockCursor() and prevent the cursor from changing.
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(root_window);
if (cursor_client)
cursor_client->SetCursor(ui::kCursorPointer);
base::RunLoop run_loop;
wm::WmToplevelWindowEventHandler::DragResult result =
wm::WmToplevelWindowEventHandler::DragResult::SUCCESS;
if (!wm_toplevel_window_event_handler_.AttemptToStartDrag(
WmWindowAura::Get(source), drag_location, HTCAPTION, move_source,
base::Bind(&ToplevelWindowEventHandler::OnDragCompleted,
weak_factory_.GetWeakPtr(), &result, &run_loop))) {
return aura::client::MOVE_CANCELED;
}
in_move_loop_ = true;
base::WeakPtr<ToplevelWindowEventHandler> weak_ptr(
weak_factory_.GetWeakPtr());
base::MessageLoop* loop = base::MessageLoop::current();
base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop);
run_loop.Run();
if (!weak_ptr)
return aura::client::MOVE_CANCELED;
in_move_loop_ = false;
return result == wm::WmToplevelWindowEventHandler::DragResult::SUCCESS
? aura::client::MOVE_SUCCESSFUL
: aura::client::MOVE_CANCELED;
}
void ToplevelWindowEventHandler::EndMoveLoop() {
if (in_move_loop_)
wm_toplevel_window_event_handler_.RevertDrag();
}
void ToplevelWindowEventHandler::OnDragCompleted(
wm::WmToplevelWindowEventHandler::DragResult* result_return_value,
base::RunLoop* run_loop,
wm::WmToplevelWindowEventHandler::DragResult result) {
*result_return_value = result;
run_loop->Quit();
}
} // namespace ash