summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormiletus@chromium.org <miletus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-24 03:00:21 +0000
committermiletus@chromium.org <miletus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-24 03:00:21 +0000
commit7355993465b3cc0f0395ce5144c1a824af1346a0 (patch)
treecdde21b0687136cfccc690b10037db1b9fb2b99d
parent102b81cdfa43709db2b05af452415ccea48fb92f (diff)
downloadchromium_src-7355993465b3cc0f0395ce5144c1a824af1346a0.zip
chromium_src-7355993465b3cc0f0395ce5144c1a824af1346a0.tar.gz
chromium_src-7355993465b3cc0f0395ce5144c1a824af1346a0.tar.bz2
Scale touch event radius
Touch event's position resolution could be quite different than the display's resolution, e.g. the display could be set as 1920x1080 while the touchscreen is reporting touch position range at 32767x32767. Touch event's radius is reported in the units the same as touch position. While we are doing touch position scaling, we should also do the same for touch radius. BUG=392172, 233245 TEST=touch radius is scaled to be reasonable value for HP 23TM touch monitor. Review URL: https://codereview.chromium.org/412553005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285132 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/display/event_transformation_handler.cc93
-rw-r--r--ash/display/event_transformation_handler.h3
-rw-r--r--ash/touch/touch_transformer_controller.cc54
-rw-r--r--ash/touch/touch_transformer_controller.h4
-rw-r--r--ash/touch/touch_transformer_controller_unittest.cc14
-rw-r--r--ui/events/device_data_manager.cc17
-rw-r--r--ui/events/device_data_manager.h5
-rw-r--r--ui/events/x/device_data_manager_x11.cc4
-rw-r--r--ui/events/x/device_data_manager_x11.h3
-rw-r--r--ui/events/x/events_x.cc15
10 files changed, 113 insertions, 99 deletions
diff --git a/ash/display/event_transformation_handler.cc b/ash/display/event_transformation_handler.cc
index cd9961a..62a6fa1 100644
--- a/ash/display/event_transformation_handler.cc
+++ b/ash/display/event_transformation_handler.cc
@@ -18,71 +18,12 @@
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
-#if defined(OS_CHROMEOS)
-#include "ui/display/chromeos/display_configurator.h"
-#endif // defined(OS_CHROMEOS)
-
namespace ash {
namespace {
// Boost factor for non-integrated displays.
const float kBoostForNonIntegrated = 1.20f;
-#if defined(OS_CHROMEOS)
-gfx::Size GetNativeModeSize(const DisplayInfo& info) {
- const std::vector<DisplayMode>& modes = info.display_modes();
- for (size_t i = 0; i < modes.size(); ++i) {
- if (modes[i].native)
- return modes[i].size;
- }
-
- return gfx::Size();
-}
-
-float GetMirroredDisplayAreaRatio(const gfx::Size& current_size,
- const gfx::Size& native_size) {
- float area_ratio = 1.0f;
-
- if (current_size.IsEmpty() || native_size.IsEmpty())
- return area_ratio;
-
- float width_ratio = static_cast<float>(current_size.width()) /
- static_cast<float>(native_size.width());
- float height_ratio = static_cast<float>(current_size.height()) /
- static_cast<float>(native_size.height());
-
- area_ratio = width_ratio * height_ratio;
- return area_ratio;
-}
-
-// Key of the map is the touch display's id, and the value of the map is the
-// touch display's area ratio in mirror mode defined as:
-// mirror_mode_area / native_mode_area.
-// This is used for scaling touch event's radius when the touch display is in
-// mirror mode: new_touch_radius = sqrt(area_ratio) * old_touch_radius
-std::map<int, float> GetMirroredDisplayAreaRatioMap() {
- std::map<int, float> area_ratios;
- DisplayManager* display_manager =
- ash::Shell::GetInstance()->display_manager();
- const std::vector<gfx::Display>& displays = display_manager->displays();
- for (size_t i = 0; i < displays.size(); ++i) {
- const DisplayInfo& info = display_manager->GetDisplayInfo(
- displays[i].id());
- const gfx::Size current_size = info.size_in_pixel();
- const gfx::Size native_size = GetNativeModeSize(info);
-
- if (info.touch_support() == gfx::Display::TOUCH_SUPPORT_AVAILABLE &&
- current_size != native_size &&
- info.is_aspect_preserving_scaling()) {
- area_ratios[info.touch_device_id()] = GetMirroredDisplayAreaRatio(
- current_size, native_size);
- }
- }
-
- return area_ratios;
-}
-#endif // defined(OS_CHROMEOS)
-
} // namespace
EventTransformationHandler::EventTransformationHandler()
@@ -109,38 +50,4 @@ void EventTransformationHandler::OnScrollEvent(ui::ScrollEvent* event) {
event->Scale(kBoostForNonIntegrated);
}
-#if defined(OS_CHROMEOS)
-// This is to scale the TouchEvent's radius when the touch display is in
-// mirror mode. TouchEvent's radius is often reported in the touchscreen's
-// native resolution. In mirror mode, the touch display could be configured
-// at a lower resolution. We scale down the radius using the ratio defined as
-// the sqrt of
-// (mirror_width * mirror_height) / (native_width * native_height)
-void EventTransformationHandler::OnTouchEvent(ui::TouchEvent* event) {
- // Check display_configurator's output_state instead of checking
- // DisplayManager::IsMirrored() because the compositor based mirroring
- // won't cause the scaling issue.
- if (ash::Shell::GetInstance()->display_configurator()->display_state() !=
- ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR)
- return;
-
- const std::map<int, float> area_ratio_map = GetMirroredDisplayAreaRatioMap();
-
- // TODO(miletus): When there are more than 1 touchscreen (e.g. Link connected
- // to an external touchscreen), the correct way to do is to have a way
- // to find out which touchscreen is the event originating from and use the
- // area ratio of that touchscreen to scale the event's radius.
- // Tracked here crbug.com/233245
- if (area_ratio_map.size() != 1) {
- LOG(ERROR) << "Mirroring mode with " << area_ratio_map.size()
- << " touch display found";
- return;
- }
-
- float area_ratio_sqrt = std::sqrt(area_ratio_map.begin()->second);
- event->set_radius_x(event->radius_x() * area_ratio_sqrt);
- event->set_radius_y(event->radius_y() * area_ratio_sqrt);
-}
-#endif // defined(OS_CHROMEOS)
-
} // namespace ash
diff --git a/ash/display/event_transformation_handler.h b/ash/display/event_transformation_handler.h
index 0d3c7e0..cd38b95 100644
--- a/ash/display/event_transformation_handler.h
+++ b/ash/display/event_transformation_handler.h
@@ -31,9 +31,6 @@ class ASH_EXPORT EventTransformationHandler : public ui::EventHandler {
// Overridden from ui::EventHandler.
virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE;
-#if defined(OS_CHROMEOS)
- virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
-#endif // defined(OS_CHROMEOS)
private:
TransformationMode transformation_mode_;
diff --git a/ash/touch/touch_transformer_controller.cc b/ash/touch/touch_transformer_controller.cc
index 67cbab2..b99cb5a 100644
--- a/ash/touch/touch_transformer_controller.cc
+++ b/ash/touch/touch_transformer_controller.cc
@@ -13,6 +13,7 @@
#include "ui/display/chromeos/display_configurator.h"
#include "ui/display/types/chromeos/display_snapshot.h"
#include "ui/events/device_data_manager.h"
+#include "ui/events/x/device_data_manager_x11.h"
namespace ash {
@@ -24,6 +25,52 @@ DisplayManager* GetDisplayManager() {
} // 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 DisplayInfo& touch_display) const {
+ if (touch_display.touch_device_id() == 0)
+ return 1.0;
+
+ double min_x, max_x;
+ double min_y, max_y;
+ if (!ui::DeviceDataManagerX11::GetInstance()->GetDataRange(
+ touch_display.touch_device_id(),
+ ui::DeviceDataManagerX11::DT_TOUCH_POSITION_X,
+ &min_x, &max_x) ||
+ !ui::DeviceDataManagerX11::GetInstance()->GetDataRange(
+ touch_display.touch_device_id(),
+ ui::DeviceDataManagerX11::DT_TOUCH_POSITION_Y,
+ &min_y, &max_y)) {
+ return 1.0;
+ }
+
+ double width = touch_display.bounds_in_native().width();
+ double height = touch_display.bounds_in_native().height();
+
+ if (max_x == 0.0 || max_y == 0.0 || width == 0.0 || height == 0.0)
+ return 1.0;
+
+ // [0, max_x] -> touchscreen width = max_x + 1
+ // [0, max_y] -> touchscreen height = max_y + 1
+ max_x += 1.0;
+ max_y += 1.0;
+
+ double ratio = std::sqrt((width * height) / (max_x * max_y));
+
+ VLOG(2) << "Screen width/height: " << width << "/" << height
+ << ", Touchscreen width/height: " << max_x << "/" << max_y
+ << ", Touch radius scale ratio: " << ratio;
+ return ratio;
+}
+
// This function computes the extended mode TouchTransformer for
// |touch_display|. The TouchTransformer maps the touch event position
// from framebuffer size to the display size.
@@ -158,10 +205,17 @@ void TouchTransformerController::UpdateTouchTransformer() const {
display2_id != gfx::Display::kInvalidDisplayID);
display1 = GetDisplayManager()->GetDisplayInfo(display1_id);
display2 = GetDisplayManager()->GetDisplayInfo(display2_id);
+ device_manager->UpdateTouchRadiusScale(display1.touch_device_id(),
+ GetTouchResolutionScale(display1));
+ device_manager->UpdateTouchRadiusScale(display2.touch_device_id(),
+ GetTouchResolutionScale(display2));
} else {
single_display_id = GetDisplayManager()->first_display_id();
DCHECK(single_display_id != gfx::Display::kInvalidDisplayID);
single_display = GetDisplayManager()->GetDisplayInfo(single_display_id);
+ device_manager->UpdateTouchRadiusScale(
+ single_display.touch_device_id(),
+ GetTouchResolutionScale(single_display));
}
if (display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR) {
diff --git a/ash/touch/touch_transformer_controller.h b/ash/touch/touch_transformer_controller.h
index f06be29..8512186 100644
--- a/ash/touch/touch_transformer_controller.h
+++ b/ash/touch/touch_transformer_controller.h
@@ -34,6 +34,8 @@ class ASH_EXPORT TouchTransformerController
TouchTransformerMirrorModePillarboxing);
FRIEND_TEST_ALL_PREFIXES(TouchTransformerControllerTest,
TouchTransformerExtendedMode);
+ FRIEND_TEST_ALL_PREFIXES(TouchTransformerControllerTest,
+ TouchRadiusScale);
bool ShouldComputeMirrorModeTouchTransformer(
const DisplayInfo& touch_display) const ;
@@ -44,6 +46,8 @@ class ASH_EXPORT TouchTransformerController
gfx::Transform GetExtendedModeTouchTransformer(
const DisplayInfo& touch_display, const gfx::Size& fb_size) const;
+ double GetTouchResolutionScale(const DisplayInfo& touch_display) const;
+
// For unittests only.
bool force_compute_mirror_mode_touch_transformer_;
diff --git a/ash/touch/touch_transformer_controller_unittest.cc b/ash/touch/touch_transformer_controller_unittest.cc
index ca64baa..cff2c53 100644
--- a/ash/touch/touch_transformer_controller_unittest.cc
+++ b/ash/touch/touch_transformer_controller_unittest.cc
@@ -8,6 +8,7 @@
#include "ash/test/ash_test_base.h"
#include "ui/aura/window_tree_host.h"
#include "ui/events/device_data_manager.h"
+#include "ui/events/test/events_test_utils_x11.h"
#include "ui/gfx/display.h"
namespace ash {
@@ -203,4 +204,17 @@ TEST_F(TouchTransformerControllerTest, TouchTransformerExtendedMode) {
EXPECT_EQ(1599, static_cast<int>(y));
}
+TEST_F(TouchTransformerControllerTest, TouchRadiusScale) {
+ DisplayInfo display = CreateDisplayInfo(1, 5, gfx::Rect(0, 0, 2560, 1600));
+ std::vector<unsigned int> devices;
+ devices.push_back(5);
+ ui::SetUpTouchDevicesForTest(devices);
+
+ TouchTransformerController* tt_controller =
+ Shell::GetInstance()->touch_transformer_controller();
+ // Default touchscreen position range is 1001x1001;
+ EXPECT_EQ(sqrt((2560.0 * 1600.0) / (1001.0 * 1001.0)),
+ tt_controller->GetTouchResolutionScale(display));
+}
+
} // namespace ash
diff --git a/ui/events/device_data_manager.cc b/ui/events/device_data_manager.cc
index e4b6e39..e7eb114 100644
--- a/ui/events/device_data_manager.cc
+++ b/ui/events/device_data_manager.cc
@@ -22,8 +22,10 @@ DeviceDataManager::DeviceDataManager() {
base::AtExitManager::RegisterTask(
base::Bind(&base::DeletePointer<DeviceDataManager>, this));
- for (int i = 0; i < kMaxDeviceNum; ++i)
+ for (int i = 0; i < kMaxDeviceNum; ++i) {
touch_device_to_display_map_[i] = gfx::Display::kInvalidDisplayID;
+ touch_radius_scale_map_[i] = 1.0;
+ }
}
DeviceDataManager::~DeviceDataManager() {
@@ -57,6 +59,7 @@ void DeviceDataManager::ClearTouchTransformerRecord() {
for (int i = 0; i < kMaxDeviceNum; i++) {
touch_device_transformer_map_[i] = gfx::Transform();
touch_device_to_display_map_[i] = gfx::Display::kInvalidDisplayID;
+ touch_radius_scale_map_[i] = 1.0;
}
}
@@ -74,6 +77,18 @@ void DeviceDataManager::UpdateTouchInfoForDisplay(
}
}
+void DeviceDataManager::UpdateTouchRadiusScale(int touch_device_id,
+ double scale) {
+ if (IsTouchDeviceIdValid(touch_device_id))
+ touch_radius_scale_map_[touch_device_id] = scale;
+}
+
+void DeviceDataManager::ApplyTouchRadiusScale(int touch_device_id,
+ double* radius) {
+ if (IsTouchDeviceIdValid(touch_device_id))
+ *radius = (*radius) * touch_radius_scale_map_[touch_device_id];
+}
+
void DeviceDataManager::ApplyTouchTransformer(int touch_device_id,
float* x,
float* y) {
diff --git a/ui/events/device_data_manager.h b/ui/events/device_data_manager.h
index 7b2feaa..838ce67 100644
--- a/ui/events/device_data_manager.h
+++ b/ui/events/device_data_manager.h
@@ -30,6 +30,9 @@ class EVENTS_BASE_EXPORT DeviceDataManager {
void ApplyTouchTransformer(int touch_device_id, float* x, float* y);
int64_t GetDisplayForTouchDevice(int touch_device_id) const;
+ void UpdateTouchRadiusScale(int touch_device_id, double scale);
+ void ApplyTouchRadiusScale(int touch_device_id, double* radius);
+
protected:
DeviceDataManager();
@@ -42,6 +45,8 @@ class EVENTS_BASE_EXPORT DeviceDataManager {
bool IsTouchDeviceIdValid(int touch_device_id) const;
+ double touch_radius_scale_map_[kMaxDeviceNum];
+
// Table to keep track of which display id is mapped to which touch device.
int64_t touch_device_to_display_map_[kMaxDeviceNum];
// Index table to find the TouchTransformer for a touch device.
diff --git a/ui/events/x/device_data_manager_x11.cc b/ui/events/x/device_data_manager_x11.cc
index 3b8e1fa..1ed6fde 100644
--- a/ui/events/x/device_data_manager_x11.cc
+++ b/ui/events/x/device_data_manager_x11.cc
@@ -63,6 +63,8 @@
#define AXIS_LABEL_ABS_MT_TOUCH_MINOR "Abs MT Touch Minor"
#define AXIS_LABEL_ABS_MT_ORIENTATION "Abs MT Orientation"
#define AXIS_LABEL_ABS_MT_PRESSURE "Abs MT Pressure"
+#define AXIS_LABEL_ABS_MT_POSITION_X "Abs MT Position X"
+#define AXIS_LABEL_ABS_MT_POSITION_Y "Abs MT Position Y"
#define AXIS_LABEL_ABS_MT_TRACKING_ID "Abs MT Tracking ID"
#define AXIS_LABEL_TOUCH_TIMESTAMP "Touch Timestamp"
@@ -87,6 +89,8 @@ const char* kCachedAtoms[] = {
AXIS_LABEL_ABS_MT_TOUCH_MINOR,
AXIS_LABEL_ABS_MT_ORIENTATION,
AXIS_LABEL_ABS_MT_PRESSURE,
+ AXIS_LABEL_ABS_MT_POSITION_X,
+ AXIS_LABEL_ABS_MT_POSITION_Y,
AXIS_LABEL_ABS_MT_TRACKING_ID,
AXIS_LABEL_TOUCH_TIMESTAMP,
diff --git a/ui/events/x/device_data_manager_x11.h b/ui/events/x/device_data_manager_x11.h
index d26b58f..865af42 100644
--- a/ui/events/x/device_data_manager_x11.h
+++ b/ui/events/x/device_data_manager_x11.h
@@ -83,6 +83,9 @@ class EVENTS_BASE_EXPORT DeviceDataManagerX11 : public DeviceDataManager {
// touch area.
DT_TOUCH_PRESSURE, // Pressure of the touch contact.
+ DT_TOUCH_POSITION_X, // Touch X position.
+ DT_TOUCH_POSITION_Y, // Touch Y position.
+
// NOTE for XInput MT: 'Tracking ID' is provided in every touch event to
// track individual touch. 'Tracking ID' is an unsigned 32-bit value and
// is increased for each new touch. It will wrap back to 0 when reaching
diff --git a/ui/events/x/events_x.cc b/ui/events/x/events_x.cc
index c9780ec..419f426 100644
--- a/ui/events/x/events_x.cc
+++ b/ui/events/x/events_x.cc
@@ -286,6 +286,13 @@ double GetTouchParamFromXEvent(XEvent* xev,
return default_value;
}
+void ScaleTouchRadius(XEvent* xev, double* radius) {
+ DCHECK_EQ(GenericEvent, xev->type);
+ XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data);
+ ui::DeviceDataManagerX11::GetInstance()->ApplyTouchRadiusScale(
+ xiev->sourceid, radius);
+}
+
} // namespace
namespace ui {
@@ -704,13 +711,17 @@ int GetTouchId(const base::NativeEvent& xev) {
}
float GetTouchRadiusX(const base::NativeEvent& native_event) {
- return GetTouchParamFromXEvent(native_event,
+ double radius = GetTouchParamFromXEvent(native_event,
ui::DeviceDataManagerX11::DT_TOUCH_MAJOR, 0.0) / 2.0;
+ ScaleTouchRadius(native_event, &radius);
+ return radius;
}
float GetTouchRadiusY(const base::NativeEvent& native_event) {
- return GetTouchParamFromXEvent(native_event,
+ double radius = GetTouchParamFromXEvent(native_event,
ui::DeviceDataManagerX11::DT_TOUCH_MINOR, 0.0) / 2.0;
+ ScaleTouchRadius(native_event, &radius);
+ return radius;
}
float GetTouchAngle(const base::NativeEvent& native_event) {