blob: 079f90f2dc05f0675b315645000775bffa3db786 [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/magnifier/partial_magnification_controller.h"
#include "ash/magnifier/magnifier_glass.h"
#include "ash/shell.h"
#include "ash/system/palette/palette_utils.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/types/event_type.h"
#include "ui/wm/core/coordinate_conversion.h"
namespace ash {
namespace {
// Ratio of magnifier scale.
constexpr float kMagnificationScale = 2.f;
// Radius of the magnifying glass in DIP. This does not include the thickness
// of the magnifying glass shadow and border.
constexpr int kMagnifierRadius = 188;
aura::Window* GetCurrentRootWindow() {
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
for (aura::Window* root_window : root_windows) {
if (root_window->ContainsPointInRoot(
root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot()))
return root_window;
}
return nullptr;
}
} // namespace
PartialMagnificationController::PartialMagnificationController() {
Shell::Get()->AddPreTargetHandler(this);
MagnifierGlass::Params params = {kMagnificationScale, kMagnifierRadius};
magnifier_glass_ = std::make_unique<MagnifierGlass>(std::move(params));
}
PartialMagnificationController::~PartialMagnificationController() {
Shell::Get()->RemovePreTargetHandler(this);
}
void PartialMagnificationController::SetEnabled(bool enabled) {
is_enabled_ = enabled;
SetActive(false);
}
void PartialMagnificationController::SwitchTargetRootWindowIfNeeded(
aura::Window* new_root_window) {
if (!new_root_window)
new_root_window = GetCurrentRootWindow();
if (is_enabled_ && is_active_) {
magnifier_glass_->ShowFor(
new_root_window,
new_root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot());
}
}
void PartialMagnificationController::OnTouchEvent(ui::TouchEvent* event) {
OnLocatedEvent(event, event->pointer_details());
}
void PartialMagnificationController::SetActive(bool active) {
// Fail if we're trying to activate while disabled.
DCHECK(is_enabled_ || !active);
is_active_ = active;
if (is_active_) {
aura::Window* root_window = GetCurrentRootWindow();
magnifier_glass_->ShowFor(
root_window,
root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot());
} else {
magnifier_glass_->Close();
}
}
void PartialMagnificationController::OnLocatedEvent(
ui::LocatedEvent* event,
const ui::PointerDetails& pointer_details) {
if (!is_enabled_)
return;
if (pointer_details.pointer_type != ui::EventPointerType::kPen)
return;
// Compute the event location in screen space.
aura::Window* target = static_cast<aura::Window*>(event->target());
aura::Window* event_root = target->GetRootWindow();
gfx::Point screen_point = event->root_location();
wm::ConvertPointToScreen(event_root, &screen_point);
// If the stylus is pressed on the palette icon or widget, do not activate.
if (event->type() == ui::ET_TOUCH_PRESSED &&
!palette_utils::PaletteContainsPointInScreen(screen_point)) {
SetActive(true);
}
if (event->type() == ui::ET_TOUCH_RELEASED)
SetActive(false);
if (!is_active_)
return;
aura::Window* root_window = GetCurrentRootWindow();
// |root_window| could be null, e.g. current mouse/touch point is beyond the
// bounds of the displays. Deactivate and return.
if (!root_window) {
SetActive(false);
return;
}
// Remap point from where it was captured to the display it is actually on.
gfx::Point point = event->root_location();
aura::Window::ConvertPointToTarget(event_root, root_window, &point);
magnifier_glass_->ShowFor(root_window, point);
// If the stylus is over the palette icon or widget, do not consume the event.
if (!palette_utils::PaletteContainsPointInScreen(screen_point))
event->StopPropagation();
}
} // namespace ash