summaryrefslogtreecommitdiffstats
path: root/ui/display/chromeos
diff options
context:
space:
mode:
authorrlp@chromium.org <rlp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-09 18:19:08 +0000
committerrlp@chromium.org <rlp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-09 18:19:08 +0000
commit08294a9c6545c8f75e9d7d43eaf05c9f2b3b5ab1 (patch)
tree6b720c121b6603d447dd53d96c39d412c6910630 /ui/display/chromeos
parentaad29ce82cf8273c5404262998c097c4036a8f4c (diff)
downloadchromium_src-08294a9c6545c8f75e9d7d43eaf05c9f2b3b5ab1.zip
chromium_src-08294a9c6545c8f75e9d7d43eaf05c9f2b3b5ab1.tar.gz
chromium_src-08294a9c6545c8f75e9d7d43eaf05c9f2b3b5ab1.tar.bz2
Revert 269371 "Move touch CTM from X into Chrome"
Failed compile on Linux Builder http://build.chromium.org/p/chromium.linux/builders/Linux%20Builder%20%28dbg%29%2832%29/builds/23859/steps/compile/logs/stdio FAILED: /b/build/goma/gomacc c++ -Wl,-z,now -Wl,-z,relro -Wl,--fatal-warnings -pthread -Wl,-z,noexecstack -fPIC -m32 -Wl,--no-as-needed -Wl,-rpath=\$ORIGIN/lib/ -Wl,-rpath-link=lib/ -o cast_unittests -Wl,--start-group obj/media/base/cast_unittests.run_all_unittests.o obj/media/cast/audio_receiver/cast_unittests.audio_decoder_unittest.o obj/media/cast/audio_receiver/cast_unittests.audio_receiver_unittest.o obj/media/cast/audio_sender/cast_unittests.audio_encoder_unittest.o obj/media/cast/audio_sender/cast_unittests.audio_sender_unittest.o obj/media/cast/congestion_control/cast_unittests.congestion_control_unittest.o obj/media/cast/framer/cast_unittests.cast_message_builder_unittest.o obj/media/cast/framer/cast_unittests.frame_buffer_unittest.o obj/media/cast/framer/cast_unittests.framer_unittest.o obj/media/cast/logging/cast_unittests.encoding_event_subscriber_unittest.o obj/media/cast/logging/cast_unittests.serialize_deserialize_test.o obj/media/cast/logging/cast_unittests.logging_impl_unittest.o obj/media/cast/logging/cast_unittests.logging_raw_unittest.o obj/media/cast/logging/cast_unittests.receiver_time_offset_estimator_impl_unittest.o obj/media/cast/logging/cast_unittests.simple_event_subscriber_unittest.o obj/media/cast/logging/cast_unittests.stats_event_subscriber_unittest.o obj/media/cast/rtcp/cast_unittests.mock_rtcp_receiver_feedback.o obj/media/cast/rtcp/cast_unittests.mock_rtcp_sender_feedback.o obj/media/cast/rtcp/cast_unittests.rtcp_receiver_unittest.o obj/media/cast/rtcp/cast_unittests.rtcp_sender_unittest.o obj/media/cast/rtcp/cast_unittests.rtcp_unittest.o obj/media/cast/rtcp/cast_unittests.receiver_rtcp_event_subscriber_unittest.o obj/media/cast/rtcp/cast_unittests.sender_rtcp_event_subscriber_unittest.o obj/media/cast/rtcp/cast_unittests.test_rtcp_packet_builder.o obj/media/cast/rtp_receiver/cast_unittests.mock_rtp_payload_feedback.o obj/media/cast/rtp_receiver/cast_unittests.receiver_stats_unittest.o obj/media/cast/rtp_receiver/rtp_parser/test/cast_unittests.rtp_packet_builder.o obj/media/cast/rtp_receiver/rtp_parser/cast_unittests.rtp_parser_unittest.o obj/media/cast/test/cast_unittests.end2end_unittest.o obj/media/cast/test/cast_unittests.fake_receiver_time_offset_estimator.o obj/media/cast/test/cast_unittests.fake_single_thread_task_runner.o obj/media/cast/test/cast_unittests.fake_video_encode_accelerator.o obj/media/cast/test/utility/cast_unittests.audio_utility_unittest.o obj/media/cast/test/utility/cast_unittests.barcode_unittest.o obj/media/cast/transport/cast_unittests.cast_transport_sender_impl_unittest.o obj/media/cast/transport/pacing/cast_unittests.mock_paced_packet_sender.o obj/media/cast/transport/pacing/cast_unittests.paced_sender_unittest.o obj/media/cast/transport/rtp_sender/packet_storage/cast_unittests.packet_storage_unittest.o obj/media/cast/transport/rtp_sender/rtp_packetizer/cast_unittests.rtp_packetizer_unittest.o obj/media/cast/transport/rtp_sender/rtp_packetizer/test/cast_unittests.rtp_header_parser.o obj/media/cast/transport/transport/cast_unittests.udp_transport_unittest.o obj/media/cast/video_receiver/cast_unittests.video_decoder_unittest.o obj/media/cast/video_receiver/cast_unittests.video_receiver_unittest.o obj/media/cast/video_sender/cast_unittests.external_video_encoder_unittest.o obj/media/cast/video_sender/cast_unittests.video_encoder_impl_unittest.o obj/media/cast/video_sender/cast_unittests.video_sender_unittest.o obj/media/cast/libcast_base.a obj/media/cast/libcast_receiver.a obj/media/cast/libcast_rtcp.a obj/media/cast/libcast_sender.a obj/media/cast/libcast_test_utility.a obj/media/cast/libcast_transport.a obj/base/libtest_support_base.a obj/testing/libgmock.a obj/testing/libgtest.a obj/media/cast/libcast_logging_proto.a obj/third_party/opus/libopus.a obj/third_party/libvpx/libvpx.a obj/third_party/libvpx/libvpx_asm_offsets_vp8.a obj/third_party/libvpx/libvpx_intrinsics_mmx.a obj/third_party/libvpx/libvpx_intrinsics_sse2.a obj/third_party/libvpx/libvpx_intrinsics_ssse3.a libyuv.a obj/third_party/libjpeg_turbo/libjpeg_turbo.a obj/base/libbase_static.a obj/third_party/libxml/libxml2.a obj/third_party/zlib/libchrome_zlib.a obj/base/third_party/dynamic_annotations/libdynamic_annotations.a lib/libicuuc.so lib/libnet.so lib/libbase.so lib/libgfx_geometry.so lib/libprotobuf_lite.so lib/libshared_memory_support.so lib/libmedia.so lib/libbase_i18n.so lib/libcrcrypto.so -Wl,--end-group -lrt -ldl -lasound lib//libevents_base.so: undefined reference to `ui::PlatformEventSource::RemovePlatformEventObserver(ui::PlatformEventObserver*)' lib//libevents_base.so: undefined reference to `ui::PlatformEventSource::GetInstance()' lib//libevents_base.so: undefined reference to `ui::PlatformEventSource::AddPlatformEventObserver(ui::PlatformEventObserver*)' collect2: ld returned 1 exit status ninja: build stopped: subcommand failed. > Move touch CTM from X into Chrome > > Currently we compute the touch CTM in OutputConfigurator > and push that into X. This CL makes computing the touch CTM > in DisplayController, and pushing it > into WindowTreeHostX11. This moves the functionality of > touch CTM from X into Chrome. > > Basically, when there is output configuration change, we > compute the TouchCTM for each touch device, and push the > TouchCTM into the WindowTreeHostX11 that is associated > with the touchscreen. Then when X events reaching root > window, we use the CTM to map the events coordinate in > framebuffer space into the root window's coordinate space. > > > BUG=351019, chrome-os-partner:25788 > TEST=tested on Pixel/Clapper with external touch/non-touch displays > on both extended/mirror mode. Touch events are correctly mapped to > chrome window or discarded if it is from blank region from letterboxing/pillarboxing mirror mode. > > Review URL: https://codereview.chromium.org/191223007 TBR=miletus@chromium.org Review URL: https://codereview.chromium.org/276013002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269376 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/display/chromeos')
-rw-r--r--ui/display/chromeos/display_configurator.cc99
-rw-r--r--ui/display/chromeos/display_configurator.h39
-rw-r--r--ui/display/chromeos/display_configurator_unittest.cc61
-rw-r--r--ui/display/chromeos/ozone/touchscreen_delegate_ozone.cc6
-rw-r--r--ui/display/chromeos/ozone/touchscreen_delegate_ozone.h3
-rw-r--r--ui/display/chromeos/x11/touchscreen_delegate_x11.cc50
-rw-r--r--ui/display/chromeos/x11/touchscreen_delegate_x11.h3
7 files changed, 255 insertions, 6 deletions
diff --git a/ui/display/chromeos/display_configurator.cc b/ui/display/chromeos/display_configurator.cc
index a2281a8..1283b58 100644
--- a/ui/display/chromeos/display_configurator.cc
+++ b/ui/display/chromeos/display_configurator.cc
@@ -89,6 +89,12 @@ int GetDisplayPower(
} // namespace
+DisplayConfigurator::CoordinateTransformation::CoordinateTransformation()
+ : x_scale(1.0),
+ x_offset(0.0),
+ y_scale(1.0),
+ y_offset(0.0) {}
+
DisplayConfigurator::DisplayState::DisplayState()
: display(NULL),
touch_device_id(0),
@@ -790,8 +796,11 @@ bool DisplayConfigurator::EnterState(MultipleDisplayState display_state,
DisplayState* state = &cached_displays_[i];
new_mode[i] = display_power[i] ? state->mirror_mode : NULL;
if (state->touch_device_id) {
+ // CTM needs to be calculated if aspect preserving scaling is used.
+ // Otherwise, assume it is full screen, and use identity CTM.
if (state->mirror_mode != state->display->native_mode() &&
state->display->is_aspect_preserving_scaling()) {
+ state->transform = GetMirrorModeCTM(*state);
mirrored_display_area_ratio_map_[state->touch_device_id] =
GetMirroredDisplayAreaRatio(*state);
}
@@ -824,6 +833,12 @@ bool DisplayConfigurator::EnterState(MultipleDisplayState display_state,
size.set_height(size.height() + (size.height() ? kVerticalGap : 0) +
mode_info->size().height());
}
+
+ for (size_t i = 0; i < cached_displays_.size(); ++i) {
+ DisplayState* state = &cached_displays_[i];
+ if (state->touch_device_id)
+ state->transform = GetExtendedModeCTM(*state, new_origins[i], size);
+ }
break;
}
}
@@ -871,8 +886,13 @@ bool DisplayConfigurator::EnterState(MultipleDisplayState display_state,
break;
}
- if (!configure_succeeded)
+ if (configure_succeeded) {
+ if (state.touch_device_id)
+ touchscreen_delegate_->ConfigureCTM(state.touch_device_id,
+ state.transform);
+ } else {
all_succeeded = false;
+ }
// If we are trying to set mirror mode and one of the modesets fails,
// then the two monitors will be mis-matched. In this case, return
@@ -887,7 +907,6 @@ bool DisplayConfigurator::EnterState(MultipleDisplayState display_state,
if (all_succeeded) {
display_state_ = display_state;
power_state_ = power_state;
- framebuffer_size_ = size;
}
return all_succeeded;
}
@@ -926,6 +945,82 @@ MultipleDisplayState DisplayConfigurator::ChooseDisplayState(
return MULTIPLE_DISPLAY_STATE_INVALID;
}
+DisplayConfigurator::CoordinateTransformation
+DisplayConfigurator::GetMirrorModeCTM(const DisplayState& display_state) {
+ CoordinateTransformation ctm; // Default to identity
+ const DisplayMode* native_mode_info = display_state.display->native_mode();
+ const DisplayMode* mirror_mode_info = display_state.mirror_mode;
+
+ if (!native_mode_info || !mirror_mode_info ||
+ native_mode_info->size().height() == 0 ||
+ mirror_mode_info->size().height() == 0 ||
+ native_mode_info->size().width() == 0 ||
+ mirror_mode_info->size().width() == 0)
+ return ctm;
+
+ float native_mode_ar = static_cast<float>(native_mode_info->size().width()) /
+ static_cast<float>(native_mode_info->size().height());
+ float mirror_mode_ar = static_cast<float>(mirror_mode_info->size().width()) /
+ static_cast<float>(mirror_mode_info->size().height());
+
+ if (mirror_mode_ar > native_mode_ar) { // Letterboxing
+ ctm.x_scale = 1.0;
+ ctm.x_offset = 0.0;
+ ctm.y_scale = mirror_mode_ar / native_mode_ar;
+ ctm.y_offset = (native_mode_ar / mirror_mode_ar - 1.0) * 0.5;
+ return ctm;
+ }
+ if (native_mode_ar > mirror_mode_ar) { // Pillarboxing
+ ctm.y_scale = 1.0;
+ ctm.y_offset = 0.0;
+ ctm.x_scale = native_mode_ar / mirror_mode_ar;
+ ctm.x_offset = (mirror_mode_ar / native_mode_ar - 1.0) * 0.5;
+ return ctm;
+ }
+
+ return ctm; // Same aspect ratio - return identity
+}
+
+DisplayConfigurator::CoordinateTransformation
+DisplayConfigurator::GetExtendedModeCTM(const DisplayState& display_state,
+ const gfx::Point& new_origin,
+ const gfx::Size& framebuffer_size) {
+ CoordinateTransformation ctm; // Default to identity
+ const DisplayMode* mode_info = display_state.selected_mode;
+ DCHECK(mode_info);
+ if (!mode_info)
+ return ctm;
+ // An example of how to calculate the CTM.
+ // Suppose we have 2 monitors, the first one has size 1366 x 768.
+ // The second one has size 2560 x 1600
+ // The total size of framebuffer is 2560 x 2428
+ // where 2428 = 768 + 60 (hidden gap) + 1600
+ // and the sceond monitor is translated to Point (0, 828) in the
+ // framebuffer.
+ // X will first map input event location to [0, 2560) x [0, 2428),
+ // then apply CTM on it.
+ // So to compute CTM, for monitor1, we have
+ // x_scale = (1366 - 1) / (2560 - 1)
+ // x_offset = 0 / (2560 - 1)
+ // y_scale = (768 - 1) / (2428 - 1)
+ // y_offset = 0 / (2428 -1)
+ // For Monitor 2, we have
+ // x_scale = (2560 - 1) / (2560 - 1)
+ // x_offset = 0 / (2560 - 1)
+ // y_scale = (1600 - 1) / (2428 - 1)
+ // y_offset = 828 / (2428 -1)
+ // See the unittest DisplayConfiguratorTest.CTMForMultiScreens.
+ ctm.x_scale = static_cast<float>(mode_info->size().width() - 1) /
+ (framebuffer_size.width() - 1);
+ ctm.x_offset =
+ static_cast<float>(new_origin.x()) / (framebuffer_size.width() - 1);
+ ctm.y_scale = static_cast<float>(mode_info->size().height() - 1) /
+ (framebuffer_size.height() - 1);
+ ctm.y_offset =
+ static_cast<float>(new_origin.y()) / (framebuffer_size.height() - 1);
+ return ctm;
+}
+
float DisplayConfigurator::GetMirroredDisplayAreaRatio(
const DisplayState& display_state) {
float area_ratio = 1.0f;
diff --git a/ui/display/chromeos/display_configurator.h b/ui/display/chromeos/display_configurator.h
index d0c9235..028a902 100644
--- a/ui/display/chromeos/display_configurator.h
+++ b/ui/display/chromeos/display_configurator.h
@@ -19,7 +19,6 @@
#include "ui/display/display_export.h"
#include "ui/display/types/chromeos/native_display_observer.h"
#include "ui/display/types/display_constants.h"
-#include "ui/gfx/geometry/size.h"
namespace gfx {
class Point;
@@ -37,6 +36,16 @@ class DISPLAY_EXPORT DisplayConfigurator : public NativeDisplayObserver {
typedef uint64_t ContentProtectionClientId;
static const ContentProtectionClientId kInvalidClientId = 0;
+ struct CoordinateTransformation {
+ // Initialized to the identity transformation.
+ CoordinateTransformation();
+
+ float x_scale;
+ float x_offset;
+ float y_scale;
+ float y_offset;
+ };
+
struct DisplayState {
DisplayState();
@@ -45,6 +54,8 @@ class DISPLAY_EXPORT DisplayConfigurator : public NativeDisplayObserver {
// XInput device ID or 0 if this display isn't a touchscreen.
int touch_device_id;
+ CoordinateTransformation transform;
+
// User-selected mode for the display.
const DisplayMode* selected_mode;
@@ -106,6 +117,14 @@ class DISPLAY_EXPORT DisplayConfigurator : public NativeDisplayObserver {
// If a touchscreen with same resolution as a display's native mode
// is detected, its id will be stored in this display.
virtual void AssociateTouchscreens(std::vector<DisplayState>* displays) = 0;
+
+ // Configures XInput's Coordinate Transformation Matrix property.
+ // |touch_device_id| the ID of the touchscreen device to configure.
+ // |ctm| contains the desired transformation parameters. The offsets
+ // in it should be normalized so that 1 corresponds to the X or Y axis
+ // size for the corresponding offset.
+ virtual void ConfigureCTM(int touch_device_id,
+ const CoordinateTransformation& ctm) = 0;
};
// Helper class used by tests.
@@ -152,7 +171,6 @@ class DISPLAY_EXPORT DisplayConfigurator : public NativeDisplayObserver {
MultipleDisplayState display_state() const { return display_state_; }
chromeos::DisplayPowerState power_state() const { return power_state_; }
- const gfx::Size framebuffer_size() const { return framebuffer_size_; }
const std::vector<DisplayState>& cached_displays() const {
return cached_displays_;
}
@@ -317,6 +335,21 @@ class DISPLAY_EXPORT DisplayConfigurator : public NativeDisplayObserver {
MultipleDisplayState ChooseDisplayState(
chromeos::DisplayPowerState power_state) const;
+ // Computes the relevant transformation for mirror mode.
+ // |display| is the display on which mirror mode is being applied.
+ // Returns the transformation or identity if computations fail.
+ CoordinateTransformation GetMirrorModeCTM(const DisplayState& display);
+
+ // Computes the relevant transformation for extended mode. |display| is the
+ // display on which extended mode is being applied. |new_origin| is the
+ // position of the display on the framebuffer. |framebuffer_size| is the
+ // size of the combined framebuffer.
+ // Returns the transformation or identity if computations fail.
+ CoordinateTransformation GetExtendedModeCTM(
+ const DisplayState& display,
+ const gfx::Point& new_origin,
+ const gfx::Size& framebuffer_size);
+
// Returns the ratio between mirrored mode area and native mode area:
// (mirror_mode_width * mirrow_mode_height) / (native_width * native_height)
float GetMirroredDisplayAreaRatio(const DisplayState& display);
@@ -350,8 +383,6 @@ class DISPLAY_EXPORT DisplayConfigurator : public NativeDisplayObserver {
// The current display state.
MultipleDisplayState display_state_;
- gfx::Size framebuffer_size_;
-
// The current power state.
chromeos::DisplayPowerState power_state_;
diff --git a/ui/display/chromeos/display_configurator_unittest.cc b/ui/display/chromeos/display_configurator_unittest.cc
index 1835d75..1790d66 100644
--- a/ui/display/chromeos/display_configurator_unittest.cc
+++ b/ui/display/chromeos/display_configurator_unittest.cc
@@ -82,6 +82,18 @@ std::string GetFramebufferAction(const gfx::Size& size,
out2 ? DisplaySnapshotToString(*out2).c_str() : "NULL");
}
+// Returns a string describing a TestNativeDisplayDelegate::ConfigureCTM() call.
+std::string GetCTMAction(
+ int device_id,
+ const DisplayConfigurator::CoordinateTransformation& ctm) {
+ return base::StringPrintf("ctm(id=%d,transform=(%f,%f,%f,%f))",
+ device_id,
+ ctm.x_scale,
+ ctm.x_offset,
+ ctm.y_scale,
+ ctm.y_offset);
+}
+
// Returns a string describing a TestNativeDisplayDelegate::SetHDCPState() call.
std::string GetSetHDCPStateAction(const DisplaySnapshot& output,
HDCPState state) {
@@ -142,6 +154,11 @@ class TestTouchscreenDelegate
configure_touchscreens_(false) {}
virtual ~TestTouchscreenDelegate() {}
+ const DisplayConfigurator::CoordinateTransformation& GetCTM(
+ int touch_device_id) {
+ return ctms_[touch_device_id];
+ }
+
void set_configure_touchscreens(bool state) {
configure_touchscreens_ = state;
}
@@ -154,12 +171,21 @@ class TestTouchscreenDelegate
(*outputs)[i].touch_device_id = i + 1;
}
}
+ virtual void ConfigureCTM(
+ int touch_device_id,
+ const DisplayConfigurator::CoordinateTransformation& ctm) OVERRIDE {
+ log_->AppendAction(GetCTMAction(touch_device_id, ctm));
+ ctms_[touch_device_id] = ctm;
+ }
private:
ActionLogger* log_; // Not owned.
bool configure_touchscreens_;
+ // Most-recently-configured transformation matrices, keyed by touch device ID.
+ std::map<int, DisplayConfigurator::CoordinateTransformation> ctms_;
+
DISALLOW_COPY_AND_ASSIGN(TestTouchscreenDelegate);
};
@@ -1216,6 +1242,41 @@ TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClients) {
log_->GetActionsAndClear());
}
+TEST_F(DisplayConfiguratorTest, CTMForMultiScreens) {
+ touchscreen_delegate_->set_configure_touchscreens(true);
+ UpdateOutputs(2, false);
+ configurator_.Init(false);
+ state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
+ configurator_.ForceInitialConfigure(0);
+
+ const int kDualHeight = small_mode_.size().height() +
+ DisplayConfigurator::kVerticalGap +
+ big_mode_.size().height();
+ const int kDualWidth = big_mode_.size().width();
+
+ DisplayConfigurator::CoordinateTransformation ctm1 =
+ touchscreen_delegate_->GetCTM(1);
+ DisplayConfigurator::CoordinateTransformation ctm2 =
+ touchscreen_delegate_->GetCTM(2);
+
+ EXPECT_EQ(small_mode_.size().height() - 1,
+ round((kDualHeight - 1) * ctm1.y_scale));
+ EXPECT_EQ(0, round((kDualHeight - 1) * ctm1.y_offset));
+
+ EXPECT_EQ(big_mode_.size().height() - 1,
+ round((kDualHeight - 1) * ctm2.y_scale));
+ EXPECT_EQ(small_mode_.size().height() + DisplayConfigurator::kVerticalGap,
+ round((kDualHeight - 1) * ctm2.y_offset));
+
+ EXPECT_EQ(small_mode_.size().width() - 1,
+ round((kDualWidth - 1) * ctm1.x_scale));
+ EXPECT_EQ(0, round((kDualWidth - 1) * ctm1.x_offset));
+
+ EXPECT_EQ(big_mode_.size().width() - 1,
+ round((kDualWidth - 1) * ctm2.x_scale));
+ EXPECT_EQ(0, round((kDualWidth - 1) * ctm2.x_offset));
+}
+
TEST_F(DisplayConfiguratorTest, HandleConfigureCrtcFailure) {
InitWithSingleOutput();
diff --git a/ui/display/chromeos/ozone/touchscreen_delegate_ozone.cc b/ui/display/chromeos/ozone/touchscreen_delegate_ozone.cc
index c302e2d..1705f8b 100644
--- a/ui/display/chromeos/ozone/touchscreen_delegate_ozone.cc
+++ b/ui/display/chromeos/ozone/touchscreen_delegate_ozone.cc
@@ -15,4 +15,10 @@ void TouchscreenDelegateOzone::AssociateTouchscreens(
NOTIMPLEMENTED();
}
+void TouchscreenDelegateOzone::ConfigureCTM(
+ int touch_device_id,
+ const DisplayConfigurator::CoordinateTransformation& ctm) {
+ NOTIMPLEMENTED();
+}
+
} // namespace ui
diff --git a/ui/display/chromeos/ozone/touchscreen_delegate_ozone.h b/ui/display/chromeos/ozone/touchscreen_delegate_ozone.h
index 7f33a03..729b3cb 100644
--- a/ui/display/chromeos/ozone/touchscreen_delegate_ozone.h
+++ b/ui/display/chromeos/ozone/touchscreen_delegate_ozone.h
@@ -18,6 +18,9 @@ class TouchscreenDelegateOzone
// DisplayConfigurator::TouchscreenDelegate overrides:
virtual void AssociateTouchscreens(
std::vector<DisplayConfigurator::DisplayState>* outputs) OVERRIDE;
+ virtual void ConfigureCTM(
+ int touch_device_id,
+ const DisplayConfigurator::CoordinateTransformation& ctm) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(TouchscreenDelegateOzone);
diff --git a/ui/display/chromeos/x11/touchscreen_delegate_x11.cc b/ui/display/chromeos/x11/touchscreen_delegate_x11.cc
index b76d62e..3b69d3a 100644
--- a/ui/display/chromeos/x11/touchscreen_delegate_x11.cc
+++ b/ui/display/chromeos/x11/touchscreen_delegate_x11.cc
@@ -129,4 +129,54 @@ void TouchscreenDelegateX11::AssociateTouchscreens(
XIFreeDeviceInfo(info);
}
+void TouchscreenDelegateX11::ConfigureCTM(
+ int touch_device_id,
+ const DisplayConfigurator::CoordinateTransformation& ctm) {
+ VLOG(1) << "ConfigureCTM: id=" << touch_device_id << " scale=" << ctm.x_scale
+ << "x" << ctm.y_scale << " offset=(" << ctm.x_offset << ", "
+ << ctm.y_offset << ")";
+ int ndevices = 0;
+ XIDeviceInfo* info = XIQueryDevice(display_, touch_device_id, &ndevices);
+ Atom prop = XInternAtom(display_, "Coordinate Transformation Matrix", False);
+ Atom float_atom = XInternAtom(display_, "FLOAT", False);
+ if (ndevices == 1 && prop != None && float_atom != None) {
+ Atom type;
+ int format;
+ unsigned long num_items;
+ unsigned long bytes_after;
+ unsigned char* data = NULL;
+ // Verify that the property exists with correct format, type, etc.
+ int status = XIGetProperty(display_,
+ info->deviceid,
+ prop,
+ 0,
+ 0,
+ False,
+ AnyPropertyType,
+ &type,
+ &format,
+ &num_items,
+ &bytes_after,
+ &data);
+ if (data)
+ XFree(data);
+ if (status == Success && type == float_atom && format == 32) {
+ float value[3][3] = {
+ { ctm.x_scale, 0.0, ctm.x_offset },
+ { 0.0, ctm.y_scale, ctm.y_offset },
+ { 0.0, 0.0, 1.0 }
+ };
+ XIChangeProperty(display_,
+ info->deviceid,
+ prop,
+ type,
+ format,
+ PropModeReplace,
+ reinterpret_cast<unsigned char*>(value),
+ 9);
+ }
+ }
+ XIFreeDeviceInfo(info);
+}
+
} // namespace ui
diff --git a/ui/display/chromeos/x11/touchscreen_delegate_x11.h b/ui/display/chromeos/x11/touchscreen_delegate_x11.h
index 7966ddf..434f55f 100644
--- a/ui/display/chromeos/x11/touchscreen_delegate_x11.h
+++ b/ui/display/chromeos/x11/touchscreen_delegate_x11.h
@@ -20,6 +20,9 @@ class TouchscreenDelegateX11 : public DisplayConfigurator::TouchscreenDelegate {
// DisplayConfigurator::TouchscreenDelegate implementation:
virtual void AssociateTouchscreens(
DisplayConfigurator::DisplayStateList* outputs) OVERRIDE;
+ virtual void ConfigureCTM(
+ int touch_device_id,
+ const DisplayConfigurator::CoordinateTransformation& ctm) OVERRIDE;
private:
Display* display_;