blob: 1276c82b91030b07ee38eb6973f8321b2a006ceb [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 "ui/views/corewm/capture_controller.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
namespace views {
namespace corewm {
////////////////////////////////////////////////////////////////////////////////
// CaptureController, public:
void CaptureController::Attach(aura::RootWindow* root) {
DCHECK_EQ(0u, root_windows_.count(root));
root_windows_.insert(root);
aura::client::SetCaptureClient(root, this);
}
void CaptureController::Detach(aura::RootWindow* root) {
root_windows_.erase(root);
aura::client::SetCaptureClient(root, NULL);
}
////////////////////////////////////////////////////////////////////////////////
// CaptureController, aura::client::CaptureClient implementation:
void CaptureController::SetCapture(aura::Window* new_capture_window) {
if (capture_window_ == new_capture_window)
return;
// Make sure window has a root window.
DCHECK(!new_capture_window || new_capture_window->GetRootWindow());
DCHECK(!capture_window_ || capture_window_->GetRootWindow());
aura::Window* old_capture_window = capture_window_;
aura::RootWindow* old_capture_root = old_capture_window ?
old_capture_window->GetRootWindow() : NULL;
// Copy the list in case it's modified out from under us.
RootWindows root_windows(root_windows_);
// If we're actually starting capture, then cancel any touches/gestures
// that aren't already locked to the new window, and transfer any on the
// old capture window to the new one. When capture is released we have no
// distinction between the touches/gestures that were in the window all
// along (and so shouldn't be canceled) and those that got moved, so
// just leave them all where they are.
if (new_capture_window) {
ui::GestureRecognizer::Get()->TransferEventsTo(old_capture_window,
new_capture_window);
}
capture_window_ = new_capture_window;
for (RootWindows::const_iterator i = root_windows.begin();
i != root_windows.end(); ++i) {
aura::client::CaptureDelegate* delegate = *i;
delegate->UpdateCapture(old_capture_window, new_capture_window);
}
aura::RootWindow* capture_root =
capture_window_ ? capture_window_->GetRootWindow() : NULL;
if (capture_root != old_capture_root) {
if (old_capture_root) {
aura::client::CaptureDelegate* delegate = old_capture_root;
delegate->ReleaseNativeCapture();
}
if (capture_root) {
aura::client::CaptureDelegate* delegate = capture_root;
delegate->SetNativeCapture();
}
}
}
void CaptureController::ReleaseCapture(aura::Window* window) {
if (capture_window_ != window)
return;
SetCapture(NULL);
}
aura::Window* CaptureController::GetCaptureWindow() {
return capture_window_;
}
////////////////////////////////////////////////////////////////////////////////
// CaptureController, private:
CaptureController::CaptureController()
: capture_window_(NULL) {
}
CaptureController::~CaptureController() {
}
////////////////////////////////////////////////////////////////////////////////
// ScopedCaptureClient:
// static
CaptureController* ScopedCaptureClient::capture_controller_ = NULL;
ScopedCaptureClient::ScopedCaptureClient(aura::RootWindow* root)
: root_window_(root) {
root->AddObserver(this);
if (!capture_controller_)
capture_controller_ = new CaptureController;
capture_controller_->Attach(root);
}
ScopedCaptureClient::~ScopedCaptureClient() {
Shutdown();
}
// static
bool ScopedCaptureClient::IsActive() {
return capture_controller_ && capture_controller_->is_active();
}
void ScopedCaptureClient::OnWindowDestroyed(aura::Window* window) {
DCHECK_EQ(window, root_window_);
Shutdown();
}
void ScopedCaptureClient::Shutdown() {
if (!root_window_)
return;
root_window_->RemoveObserver(this);
capture_controller_->Detach(root_window_);
if (!capture_controller_->is_active()) {
delete capture_controller_;
capture_controller_ = NULL;
}
root_window_ = NULL;
}
} // namespace corewm
} // namespace views