Index: ash/touch/touch_transformer_controller.cc |
diff --git a/ash/touch/touch_transformer_controller.cc b/ash/touch/touch_transformer_controller.cc |
deleted file mode 100644 |
index d253fc6ff52fd27721a4083af552af5ccbd39cb8..0000000000000000000000000000000000000000 |
--- a/ash/touch/touch_transformer_controller.cc |
+++ /dev/null |
@@ -1,386 +0,0 @@ |
-// 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 "ash/touch/touch_transformer_controller.h" |
- |
-#include "ash/display/window_tree_host_manager.h" |
-#include "ash/host/ash_window_tree_host.h" |
-#include "ash/root_window_controller.h" |
-#include "ash/shell.h" |
-#include "third_party/skia/include/core/SkMatrix44.h" |
-#include "ui/aura/window_tree_host.h" |
-#include "ui/display/display_layout.h" |
-#include "ui/display/manager/chromeos/display_configurator.h" |
-#include "ui/display/manager/display_manager.h" |
-#include "ui/display/types/display_constants.h" |
-#include "ui/display/types/display_snapshot.h" |
-#include "ui/events/devices/device_data_manager.h" |
- |
-namespace ash { |
- |
-namespace { |
- |
-display::DisplayManager* GetDisplayManager() { |
- return Shell::GetInstance()->display_manager(); |
-} |
- |
-ui::TouchscreenDevice FindTouchscreenById(int id) { |
- const std::vector<ui::TouchscreenDevice>& touchscreens = |
- ui::DeviceDataManager::GetInstance()->GetTouchscreenDevices(); |
- for (const auto& touchscreen : touchscreens) { |
- if (touchscreen.id == id) |
- return touchscreen; |
- } |
- |
- return ui::TouchscreenDevice(); |
-} |
- |
-// Given an array of touch point and display point pairs, this function computes |
-// and returns the constants(defined below) using a least fit algorithm. |
-// If (xt, yt) is a touch point then its corresponding (xd, yd) would be defined |
-// by the following 2 equations: |
-// xd = xt * A + yt * B + C |
-// yd = xt * D + yt * E + F |
-// This function computes A, B, C, D, E and F and sets |ctm| with the calibrated |
-// transform matrix. In case the computation fails, the function will return |
-// false. |
-// See http://crbug.com/672293 |
-bool GetCalibratedTransform( |
- std::array<std::pair<gfx::Point, gfx::Point>, 4> touch_point_pairs, |
- const gfx::Transform& pre_calibration_tm, |
- gfx::Transform* ctm) { |
- // Transform the display points before solving the equation. |
- // If the calibration was performed at a resolution that is 0.5 times the |
- // current resolution, then the display points (x, y) for a given touch point |
- // now represents a display point at (2 * x, 2 * y). This and other kinds of |
- // similar tranforms can be applied using |pre_calibration_tm|. |
- for (int row = 0; row < 4; row++) |
- pre_calibration_tm.TransformPoint(&touch_point_pairs[row].first); |
- |
- // Vector of the X-coordinate of display points corresponding to each of the |
- // touch points. |
- SkVector4 display_points_x( |
- touch_point_pairs[0].first.x(), touch_point_pairs[1].first.x(), |
- touch_point_pairs[2].first.x(), touch_point_pairs[3].first.x()); |
- // Vector of the Y-coordinate of display points corresponding to each of the |
- // touch points. |
- SkVector4 display_points_y( |
- touch_point_pairs[0].first.y(), touch_point_pairs[1].first.y(), |
- touch_point_pairs[2].first.y(), touch_point_pairs[3].first.y()); |
- |
- // Initialize |touch_point_matrix| |
- // If {(xt_1, yt_1), (xt_2, yt_2), (xt_3, yt_3)....} are a set of touch points |
- // received during calibration, then the |touch_point_matrix| would be defined |
- // as: |
- // |xt_1 yt_1 1 0| |
- // |xt_2 yt_2 1 0| |
- // |xt_3 yt_3 1 0| |
- // |xt_4 yt_4 1 0| |
- SkMatrix44 touch_point_matrix; |
- for (int row = 0; row < 4; row++) { |
- touch_point_matrix.set(row, 0, touch_point_pairs[row].second.x()); |
- touch_point_matrix.set(row, 1, touch_point_pairs[row].second.y()); |
- touch_point_matrix.set(row, 2, 1); |
- touch_point_matrix.set(row, 3, 0); |
- } |
- SkMatrix44 touch_point_matrix_transpose(touch_point_matrix); |
- touch_point_matrix_transpose.transpose(); |
- |
- SkMatrix44 product_matrix = touch_point_matrix_transpose * touch_point_matrix; |
- |
- // Set (3, 3) = 1 so that |determinent| of the matrix is != 0 and the inverse |
- // can be calculated. |
- product_matrix.set(3, 3, 1); |
- |
- SkMatrix44 product_matrix_inverse; |
- |
- // NOTE: If the determinent is zero then the inverse cannot be computed. The |
- // only solution is to restart touch calibration and get new points from user. |
- if (!product_matrix.invert(&product_matrix_inverse)) { |
- NOTREACHED() << "Touch Calibration failed. Determinent is zero."; |
- return false; |
- } |
- |
- product_matrix_inverse.set(3, 3, 0); |
- |
- product_matrix = product_matrix_inverse * touch_point_matrix_transpose; |
- |
- // Constants [A, B, C, 0] used to calibrate the x-coordinate of touch input. |
- // x_new = x_old * A + y_old * B + C; |
- SkVector4 x_constants = product_matrix * display_points_x; |
- // Constants [D, E, F, 0] used to calibrate the y-coordinate of touch input. |
- // y_new = x_old * D + y_old * E + F; |
- SkVector4 y_constants = product_matrix * display_points_y; |
- |
- // Create a transform matrix using the touch calibration data. |
- ctm->ConcatTransform(gfx::Transform( |
- x_constants.fData[0], x_constants.fData[1], 0, x_constants.fData[2], |
- y_constants.fData[0], y_constants.fData[1], 0, y_constants.fData[2], 0, 0, |
- 1, 0, 0, 0, 0, 1)); |
- return true; |
-} |
- |
-// Returns an uncalibrated touch transform. |
-gfx::Transform GetUncalibratedTransform( |
- const gfx::Transform& tm, |
- const display::ManagedDisplayInfo& display, |
- const display::ManagedDisplayInfo& touch_display, |
- const gfx::SizeF& touch_area, |
- const gfx::SizeF& touch_native_size) { |
- gfx::SizeF current_size(display.bounds_in_native().size()); |
- gfx::Transform ctm(tm); |
- // Take care of panel fitting only if supported. Panel fitting is emulated |
- // in software mirroring mode (display != touch_display). |
- // If panel fitting is enabled then the aspect ratio is preserved and the |
- // display is scaled acordingly. In this case blank regions would be present |
- // in order to center the displayed area. |
- if (display.is_aspect_preserving_scaling() || |
- display.id() != touch_display.id()) { |
- float touch_calib_ar = |
- touch_native_size.width() / touch_native_size.height(); |
- float current_ar = current_size.width() / current_size.height(); |
- |
- if (current_ar > touch_calib_ar) { // Letterboxing |
- ctm.Translate( |
- 0, (1 - current_ar / touch_calib_ar) * 0.5 * current_size.height()); |
- ctm.Scale(1, current_ar / touch_calib_ar); |
- } else if (touch_calib_ar > current_ar) { // Pillarboxing |
- ctm.Translate( |
- (1 - touch_calib_ar / current_ar) * 0.5 * current_size.width(), 0); |
- ctm.Scale(touch_calib_ar / current_ar, 1); |
- } |
- } |
- // Take care of scaling between touchscreen area and display resolution. |
- ctm.Scale(current_size.width() / touch_area.width(), |
- current_size.height() / touch_area.height()); |
- return ctm; |
-} |
- |
-} // namespace |
- |
-// This is to compute the scale ratio for the TouchEvent's radius. The |
-// configured resolution of the display is not always the same as the touch |
-// screen's reporting resolution, e.g. the display could be set as |
-// 1920x1080 while the touchscreen is reporting touch position range at |
-// 32767x32767. Touch radius is reported in the units the same as touch position |
-// so we need to scale the touch radius to be compatible with the display's |
-// resolution. We compute the scale as |
-// sqrt of (display_area / touchscreen_area) |
-double TouchTransformerController::GetTouchResolutionScale( |
- const display::ManagedDisplayInfo& touch_display, |
- const ui::TouchscreenDevice& touch_device) const { |
- if (touch_device.id == ui::InputDevice::kInvalidId || |
- touch_device.size.IsEmpty() || |
- touch_display.bounds_in_native().size().IsEmpty()) |
- return 1.0; |
- |
- double display_area = touch_display.bounds_in_native().size().GetArea(); |
- double touch_area = touch_device.size.GetArea(); |
- double ratio = std::sqrt(display_area / touch_area); |
- |
- VLOG(2) << "Display size: " |
- << touch_display.bounds_in_native().size().ToString() |
- << ", Touchscreen size: " << touch_device.size.ToString() |
- << ", Touch radius scale ratio: " << ratio; |
- return ratio; |
-} |
- |
-gfx::Transform TouchTransformerController::GetTouchTransform( |
- const display::ManagedDisplayInfo& display, |
- const display::ManagedDisplayInfo& touch_display, |
- const ui::TouchscreenDevice& touchscreen, |
- const gfx::Size& framebuffer_size) const { |
- auto current_size = gfx::SizeF(display.bounds_in_native().size()); |
- auto touch_native_size = gfx::SizeF(touch_display.GetNativeModeSize()); |
-#if defined(USE_OZONE) |
- auto touch_area = gfx::SizeF(touchscreen.size); |
-#elif defined(USE_X11) |
- // On X11 touches are reported in the framebuffer coordinate space. |
- auto touch_area = gfx::SizeF(framebuffer_size); |
-#endif |
- |
- gfx::Transform ctm; |
- |
- if (current_size.IsEmpty() || touch_native_size.IsEmpty() || |
- touch_area.IsEmpty() || touchscreen.id == ui::InputDevice::kInvalidId) |
- return ctm; |
- |
-#if defined(USE_OZONE) |
- // Translate the touch so that it falls within the display bounds. This |
- // should not be performed if the displays are mirrored. |
- if (display.id() == touch_display.id()) { |
- ctm.Translate(display.bounds_in_native().x(), |
- display.bounds_in_native().y()); |
- } |
-#endif |
- |
- // If touch calibration data is unavailable, use naive approach. |
- if (!touch_display.has_touch_calibration_data()) { |
- return GetUncalibratedTransform(ctm, display, touch_display, touch_area, |
- touch_native_size); |
- } |
- |
- // The resolution at which the touch calibration was performed. |
- gfx::SizeF touch_calib_size(touch_display.GetTouchCalibrationData().bounds); |
- |
- // Any additional transfomration that needs to be applied to the display |
- // points, before we solve for the final transform. |
- gfx::Transform pre_transform; |
- |
- if (display.id() != touch_display.id() || |
- display.is_aspect_preserving_scaling()) { |
- // Case of displays being mirrored or in panel fitting mode. |
- // Aspect ratio of the touch display's resolution during calibration. |
- float calib_ar = touch_calib_size.width() / touch_calib_size.height(); |
- // Aspect ratio of the display that is being mirrored. |
- float current_ar = current_size.width() / current_size.height(); |
- |
- if (current_ar < calib_ar) { |
- pre_transform.Scale(current_size.height() / touch_calib_size.height(), |
- current_size.height() / touch_calib_size.height()); |
- pre_transform.Translate( |
- (current_ar / calib_ar - 1.f) * touch_calib_size.width() * 0.5f, 0); |
- } else { |
- pre_transform.Scale(current_size.width() / touch_calib_size.width(), |
- current_size.width() / touch_calib_size.width()); |
- pre_transform.Translate( |
- 0, (calib_ar / current_ar - 1.f) * touch_calib_size.height() * 0.5f); |
- } |
- } else { |
- // Case of current resolution being different from the resolution when the |
- // touch calibration was performed. |
- pre_transform.Scale(current_size.width() / touch_calib_size.width(), |
- current_size.height() / touch_calib_size.height()); |
- } |
- // Solve for coefficients and compute transform matrix. |
- gfx::Transform stored_ctm; |
- if (!GetCalibratedTransform( |
- touch_display.GetTouchCalibrationData().point_pairs, pre_transform, |
- &stored_ctm)) { |
- // TODO(malaykeshav): This can be checked at the calibration step before |
- // storing the calibration associated data. This will allow us to explicitly |
- // inform the user with proper UX. |
- |
- // Clear stored calibration data. |
- GetDisplayManager()->ClearTouchCalibrationData(touch_display.id()); |
- |
- // Return uncalibrated transform. |
- return GetUncalibratedTransform(ctm, display, touch_display, touch_area, |
- touch_native_size); |
- } |
- |
- stored_ctm.ConcatTransform(ctm); |
- return stored_ctm; |
-} |
- |
-TouchTransformerController::TouchTransformerController() { |
- Shell::GetInstance()->window_tree_host_manager()->AddObserver(this); |
-} |
- |
-TouchTransformerController::~TouchTransformerController() { |
- Shell::GetInstance()->window_tree_host_manager()->RemoveObserver(this); |
-} |
- |
-void TouchTransformerController::UpdateTouchRadius( |
- const display::ManagedDisplayInfo& display) const { |
- ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance(); |
- for (const auto& device_id : display.input_devices()) { |
- device_manager->UpdateTouchRadiusScale( |
- device_id, |
- GetTouchResolutionScale(display, FindTouchscreenById(device_id))); |
- } |
-} |
- |
-void TouchTransformerController::UpdateTouchTransform( |
- int64_t target_display_id, |
- const display::ManagedDisplayInfo& touch_display, |
- const display::ManagedDisplayInfo& target_display) const { |
- ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance(); |
- gfx::Size fb_size = |
- Shell::GetInstance()->display_configurator()->framebuffer_size(); |
- for (const auto& device_id : touch_display.input_devices()) { |
- device_manager->UpdateTouchInfoForDisplay( |
- target_display_id, device_id, |
- GetTouchTransform(target_display, touch_display, |
- FindTouchscreenById(device_id), fb_size)); |
- } |
-} |
- |
-void TouchTransformerController::UpdateTouchTransformer() const { |
- ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance(); |
- device_manager->ClearTouchDeviceAssociations(); |
- |
- // Display IDs and display::ManagedDisplayInfo for mirror or extended mode. |
- int64_t display1_id = display::kInvalidDisplayId; |
- int64_t display2_id = display::kInvalidDisplayId; |
- display::ManagedDisplayInfo display1; |
- display::ManagedDisplayInfo display2; |
- // Display ID and display::ManagedDisplayInfo for single display mode. |
- int64_t single_display_id = display::kInvalidDisplayId; |
- display::ManagedDisplayInfo single_display; |
- |
- WindowTreeHostManager* window_tree_host_manager = |
- Shell::GetInstance()->window_tree_host_manager(); |
- display::DisplayManager* display_manager = GetDisplayManager(); |
- if (display_manager->num_connected_displays() == 0) { |
- return; |
- } else if (display_manager->num_connected_displays() == 1 || |
- display_manager->IsInUnifiedMode()) { |
- single_display_id = display_manager->first_display_id(); |
- DCHECK(single_display_id != display::kInvalidDisplayId); |
- single_display = display_manager->GetDisplayInfo(single_display_id); |
- UpdateTouchRadius(single_display); |
- } else { |
- display::DisplayIdList list = display_manager->GetCurrentDisplayIdList(); |
- display1_id = list[0]; |
- display2_id = list[1]; |
- DCHECK(display1_id != display::kInvalidDisplayId && |
- display2_id != display::kInvalidDisplayId); |
- display1 = display_manager->GetDisplayInfo(display1_id); |
- display2 = display_manager->GetDisplayInfo(display2_id); |
- UpdateTouchRadius(display1); |
- UpdateTouchRadius(display2); |
- } |
- |
- if (display_manager->IsInMirrorMode()) { |
- int64_t primary_display_id = |
- window_tree_host_manager->GetPrimaryDisplayId(); |
- if (GetDisplayManager()->SoftwareMirroringEnabled()) { |
- // In extended but software mirroring mode, there is a WindowTreeHost for |
- // each display, but all touches are forwarded to the primary root |
- // window's WindowTreeHost. |
- display::ManagedDisplayInfo target_display = |
- primary_display_id == display1_id ? display1 : display2; |
- UpdateTouchTransform(target_display.id(), display1, target_display); |
- UpdateTouchTransform(target_display.id(), display2, target_display); |
- } else { |
- // In mirror mode, there is just one WindowTreeHost and two displays. Make |
- // the WindowTreeHost accept touch events from both displays. |
- UpdateTouchTransform(primary_display_id, display1, display1); |
- UpdateTouchTransform(primary_display_id, display2, display2); |
- } |
- return; |
- } |
- |
- if (display_manager->num_connected_displays() > 1) { |
- // In actual extended mode, each display is associated with one |
- // WindowTreeHost. |
- UpdateTouchTransform(display1_id, display1, display1); |
- UpdateTouchTransform(display2_id, display2, display2); |
- return; |
- } |
- |
- // Single display mode. The WindowTreeHost has one associated display id. |
- UpdateTouchTransform(single_display_id, single_display, single_display); |
-} |
- |
-void TouchTransformerController::OnDisplaysInitialized() { |
- UpdateTouchTransformer(); |
-} |
- |
-void TouchTransformerController::OnDisplayConfigurationChanged() { |
- UpdateTouchTransformer(); |
-} |
- |
-} // namespace ash |