blob: 2037b6fa5a151b5ced13a7b3dea5e5dabf9e659f [file] [log] [blame]
// Copyright 2016 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 "services/ui/ws/touch_controller.h"
#include <set>
#include <vector>
#include "base/logging.h"
#include "services/ui/ws/display.h"
#include "services/ui/ws/display_manager.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/events/devices/touchscreen_device.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/transform.h"
namespace ui {
namespace ws {
namespace {
// Computes the scale ratio for the TouchEvent's radius.
double ComputeTouchResolutionScale(const Display* touch_display,
const ui::TouchscreenDevice& touch_device) {
gfx::Size touch_display_size = touch_display->GetSize();
if (touch_device.size.IsEmpty() || touch_display_size.IsEmpty())
return 1.0;
double display_area = touch_display_size.GetArea();
double touch_area = touch_device.size.GetArea();
double ratio = std::sqrt(display_area / touch_area);
return ratio;
}
// Computes a touch transform that maps from window bounds to touchscreen size.
// Assumes scale factor of 1.0.
gfx::Transform ComputeTouchTransform(
const Display* touch_display,
const ui::TouchscreenDevice& touch_device) {
gfx::Size touch_display_size = touch_display->GetSize();
gfx::SizeF current_size(touch_display_size);
gfx::SizeF touch_area(touch_device.size);
gfx::Transform transform;
if (current_size.IsEmpty() || touch_area.IsEmpty())
return transform;
// Take care of scaling between touchscreen area and display resolution.
transform.Scale(current_size.width() / touch_area.width(),
current_size.height() / touch_area.height());
return transform;
}
} // namespace
TouchController::TouchController(DisplayManager* display_manager)
: display_manager_(display_manager) {
DCHECK(display_manager_);
ui::DeviceDataManager::GetInstance()->AddObserver(this);
}
TouchController::~TouchController() {
ui::DeviceDataManager::GetInstance()->RemoveObserver(this);
}
void TouchController::UpdateTouchTransforms() const {
ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
device_manager->ClearTouchDeviceAssociations();
const std::set<Display*>& touch_displays = display_manager_->displays();
const std::vector<ui::TouchscreenDevice>& touch_devices =
device_manager->GetTouchscreenDevices();
// Mash can only handle a single display so this doesn't implement support for
// matching touchscreens with multiple displays.
// TODO(kylechar): Implement support for multiple displays when needed.
if (touch_displays.size() == 1 && touch_devices.size() == 1) {
const Display* touch_display = *touch_displays.begin();
const ui::TouchscreenDevice& touch_device = touch_devices[0];
int64_t touch_display_id = touch_display->GetId();
int touch_device_id = touch_device.id;
if (touch_device_id != ui::InputDevice::kInvalidId) {
device_manager->UpdateTouchRadiusScale(
touch_device_id,
ComputeTouchResolutionScale(touch_display, touch_device));
device_manager->UpdateTouchInfoForDisplay(
touch_display_id, touch_device_id,
ComputeTouchTransform(touch_display, touch_device));
}
}
}
void TouchController::OnTouchscreenDeviceConfigurationChanged() {
UpdateTouchTransforms();
}
} // namespace ws
} // namespace ui