Index: ui/ozone/platform/dri/touch_converter.cc |
diff --git a/ui/ozone/platform/dri/touch_converter.cc b/ui/ozone/platform/dri/touch_converter.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d5ec8f2aaa5d5884b7ed5132443dcd8f2f867930 |
--- /dev/null |
+++ b/ui/ozone/platform/dri/touch_converter.cc |
@@ -0,0 +1,150 @@ |
+// Copyright 2014 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/ozone/platform/dri/touch_converter.h" |
+ |
+#include "base/command_line.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "base/strings/string_util.h" |
+#include "ui/display/types/display_snapshot.h" |
+#include "ui/events/device_data_manager.h" |
+#include "ui/events/event.h" |
+#include "ui/events/event_switches.h" |
+#include "ui/gfx/display.h" |
+#include "ui/gfx/geometry/point3_f.h" |
+#include "ui/ozone/platform/dri/display_manager.h" |
+#include "ui/ozone/platform/dri/dri_window.h" |
+ |
+namespace ui { |
+ |
+namespace { |
+ |
+TouchscreenDevice FindTouchscreenDevice(int64_t id) { |
+ const std::vector<TouchscreenDevice>& touchscreens = |
+ DeviceDataManager::GetInstance()->touchscreen_devices(); |
+ for (size_t i = 0; i < touchscreens.size(); ++i) |
+ if (touchscreens[i].id == id) |
+ return touchscreens[i]; |
+ |
+ NOTREACHED(); |
+ return TouchscreenDevice(TouchscreenDevice::kInvalidId, gfx::Size(), false); |
+} |
+ |
+} // namespace |
+ |
+TouchConverter::TouchConverter(DriWindow* window, |
+ DisplayManager* display_manager) |
+ : window_(window), display_manager_(display_manager) { |
+ GetTouchCalibration(); |
+} |
+ |
+TouchConverter::~TouchConverter() { |
+} |
+ |
+bool TouchConverter::CanHandleEvent(const TouchEvent& event) { |
+ int64_t touch_display_id = |
+ DeviceDataManager::GetInstance()->GetDisplayForTouchDevice( |
+ event.source_device_id()); |
+ |
+ DisplaySnapshot* display = display_manager_->GetDisplay(touch_display_id); |
+ // Suppress touch events that don't have a display associated with them. |
+ if (!display || !display->current_mode()) |
+ return false; |
+ |
+ // Touchscreens are associated with a specific display. Since windows can |
+ // move between displays we want to make sure that the window is on the |
+ // correct display. |
+ gfx::Rect display_bounds(display->origin(), display->current_mode()->size()); |
+ return display_bounds == window_->GetBounds(); |
+} |
+ |
+void TouchConverter::RewriteTouchEvent(TouchEvent* event) { |
+ if (cached_touchscreen_id_ != event->source_device_id()) { |
+ cached_touchscreen_id_ = event->source_device_id(); |
+ UpdateTransform(); |
+ } |
+ |
+ gfx::Point3F location(event->location_f()); |
+ transform_.TransformPoint(&location); |
+ |
+ event->set_location(location.AsPointF()); |
+ event->set_root_location(location.AsPointF()); |
+ |
+ event->set_radius_x(event->radius_x() * scale_factor_); |
+ event->set_radius_y(event->radius_y() * scale_factor_); |
+} |
+ |
+void TouchConverter::UpdateTransform() { |
+ if (cached_touchscreen_id_ == TouchscreenDevice::kInvalidId) |
+ return; |
+ |
+ TouchscreenDevice touchscreen = |
+ FindTouchscreenDevice(cached_touchscreen_id_); |
+ DisplaySnapshot* display = display_manager_->GetDisplay( |
+ DeviceDataManager::GetInstance()->GetDisplayForTouchDevice( |
+ cached_touchscreen_id_)); |
+ |
+ if (touchscreen.id == TouchscreenDevice::kInvalidId || |
+ !display || !display->native_mode()) |
+ return; |
+ |
+ transform_.MakeIdentity(); |
+ |
+ gfx::SizeF current_size = window_->GetBounds().size(); |
+ gfx::SizeF native_size = display->native_mode()->size(); |
+ gfx::SizeF touch_area = touchscreen.size; |
+ |
+ // For now only the internal display has bezel configuration support. |
+ if (display->display_id() == gfx::Display::InternalDisplayId()) { |
+ touch_area.Enlarge( |
+ -touch_calibration_.bezel_left - touch_calibration_.bezel_right, |
+ -touch_calibration_.bezel_top - touch_calibration_.bezel_bottom); |
+ |
+ transform_.Translate(-touch_calibration_.bezel_left, |
+ -touch_calibration_.bezel_top); |
+ } |
+ |
+ float scale_x = 1; |
+ float scale_y = 1; |
+ // Take care of panel fitting only if supported. |
+ if (display->is_aspect_preserving_scaling()) { |
+ float native_ar = native_size.width() / native_size.height(); |
+ float current_ar = current_size.width() / current_size.height(); |
+ |
+ if (current_ar > native_ar) { // Letterboxing |
+ transform_.Translate( |
+ 0, (1 - current_ar / native_ar) * 0.5 * current_size.height()); |
+ scale_y = current_ar / native_ar; |
+ } else if (native_ar > current_ar) { // Pillarboxing |
+ transform_.Translate( |
+ (1 - native_ar / current_ar) * 0.5 * current_size.width(), 0); |
+ scale_x = native_ar / current_ar; |
+ } |
+ } |
+ |
+ // Take care of scaling between touchscreen area and display resolution. |
+ scale_x *= current_size.width() / touch_area.width(); |
+ scale_y *= current_size.height() / touch_area.height(); |
+ transform_.Scale(scale_x, scale_y); |
+ scale_factor_ = std::sqrt(scale_x * scale_y); |
+} |
+ |
+void TouchConverter::GetTouchCalibration() { |
+ std::vector<std::string> parts; |
+ if (Tokenize(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
+ switches::kTouchCalibration), |
+ ",", |
+ &parts) >= 4) { |
+ if (!base::StringToInt(parts[0], &touch_calibration_.bezel_left)) |
+ DLOG(ERROR) << "Incorrect left border calibration value passed."; |
+ if (!base::StringToInt(parts[1], &touch_calibration_.bezel_right)) |
+ DLOG(ERROR) << "Incorrect right border calibration value passed."; |
+ if (!base::StringToInt(parts[2], &touch_calibration_.bezel_top)) |
+ DLOG(ERROR) << "Incorrect top border calibration value passed."; |
+ if (!base::StringToInt(parts[3], &touch_calibration_.bezel_bottom)) |
+ DLOG(ERROR) << "Incorrect bottom border calibration value passed."; |
+ } |
+} |
+ |
+} // namespace ui |