Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(708)

Unified Diff: ash/touch/touch_transformer_controller.cc

Issue 191223007: Move touch CTM from X into Chrome (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: move the logic of if a touch event should be dispatched to a root window into CanDispatchEvent() Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ash/touch/touch_transformer_controller.cc
diff --git a/ash/touch/touch_transformer_controller.cc b/ash/touch/touch_transformer_controller.cc
new file mode 100644
index 0000000000000000000000000000000000000000..49558a30f7476fe21d3710fc778bf32e99d5480f
--- /dev/null
+++ b/ash/touch/touch_transformer_controller.cc
@@ -0,0 +1,222 @@
+// Copyright (c) 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/display_controller.h"
+#include "ash/display/display_manager.h"
+#include "ash/shell.h"
+#include "ui/aura/window_tree_host.h"
+#include "ui/display/chromeos/display_configurator.h"
+#include "ui/display/types/chromeos/display_snapshot.h"
+#include "ui/events/x/device_data_manager.h"
+
+namespace ash {
+
+namespace {
+
+DisplayManager* GetDisplayManager() {
+ return Shell::GetInstance()->display_manager();
+}
+
+} // namespace
+
+// This function computes the extended mode TouchTransformer for
+// |touch_display|. The TouchTransformer maps the touch event position
+// from framebuffer size to the display size.
+ui::TouchTransformer
+TouchTransformerController::GetExtendedModeTouchTransformer(
+ const DisplayInfo& touch_display, const gfx::Size& fb_size) {
+ ui::TouchTransformer ctm;
+ if (touch_display.touch_device_id() == 0 ||
+ fb_size.width() == 0.0 ||
+ fb_size.height() == 0.0)
+ return ctm;
+ float width = touch_display.bounds_in_native().width();
+ float height = touch_display.bounds_in_native().height();
+ ctm.x_scale = width / fb_size.width();
+ ctm.x_offset = 0;
+ ctm.y_scale = height / fb_size.height();
+ ctm.y_offset = 0;
+ return ctm;
+}
+
+bool TouchTransformerController::ShouldComputeMirrorModeTouchTransformer(
+ const DisplayInfo& touch_display) {
+ if (force_compute_mirror_mode_touch_transformer_)
+ return true;
+
+ if (touch_display.touch_device_id() == 0)
+ return false;
+
+ const ui::DisplayConfigurator::DisplayState* state = NULL;
+ const std::vector<ui::DisplayConfigurator::DisplayState>& cached_displays =
+ Shell::GetInstance()->display_configurator()->cached_displays();
+ for (size_t i = 0; i < cached_displays.size(); i++) {
+ if (cached_displays[i].touch_device_id == touch_display.touch_device_id()) {
+ state = &cached_displays[i];
+ break;
+ }
+ }
+
+ if (!state || state->mirror_mode == state->display->native_mode() ||
+ !state->display->is_aspect_preserving_scaling()) {
+ return false;
+ }
+ return true;
+}
+
+// This function computes the mirror mode TouchTransformer for |touch_display|.
+// When internal monitor is applied a resolution that does not have
+// the same aspect ratio as its native resolution, there would be
+// blank regions in the letterboxing/pillarboxing mode.
+// The TouchTransformer will make sure the touch events on the blank region
+// have negative coordinates and touch events within the chrome region
+// have the correct positive coordinates.
+ui::TouchTransformer TouchTransformerController::GetMirrorModeTouchTransformer(
+ const DisplayInfo& touch_display) {
+ ui::TouchTransformer ctm;
+ if (!ShouldComputeMirrorModeTouchTransformer(touch_display))
+ return ctm;
+
+ float mirror_width = touch_display.bounds_in_native().width();
+ float mirror_height = touch_display.bounds_in_native().height();
+ float native_width = 0;
+ float native_height = 0;
+
+ std::vector<DisplayMode> modes = touch_display.display_modes();
+ for (size_t i = 0; i < modes.size(); i++) {
+ if (modes[i].native) {
+ native_width = modes[i].size.width();
+ native_height = modes[i].size.height();
+ break;
+ }
+ }
+
+ if (native_height == 0.0 || mirror_height == 0.0 ||
+ native_width == 0.0 || mirror_width == 0.0)
+ return ctm;
+
+ float native_ar = static_cast<float>(native_width) /
+ static_cast<float>(native_height);
+ float mirror_ar = static_cast<float>(mirror_width) /
+ static_cast<float>(mirror_height);
+
+ if (mirror_ar > native_ar) { // Letterboxing
+ ctm.y_scale = mirror_ar / native_ar;
+ ctm.y_offset = (1.0 / mirror_ar - 1.0 / native_ar) * 0.5 * mirror_width;
+ return ctm;
+ }
+
+ if (native_ar > mirror_ar) { // Pillarboxing
+ ctm.x_scale = native_ar / mirror_ar;
+ ctm.x_offset = (mirror_ar - native_ar) * 0.5 * mirror_height;
+ return ctm;
+ }
+
+ return ctm; // Same aspect ratio - return identity
+}
+
+TouchTransformerController::TouchTransformerController() :
+ force_compute_mirror_mode_touch_transformer_ (false) {
+ Shell::GetInstance()->display_controller()->AddObserver(this);
+}
+
+TouchTransformerController::~TouchTransformerController() {
+ Shell::GetInstance()->display_controller()->RemoveObserver(this);
+}
+
+void TouchTransformerController::UpdateTouchTransformer() {
+ ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
+ device_manager->ClearTouchTransformerRecord();
+
+ // Display IDs and DisplayInfo for mirror or extended mode.
+ int64 display1_id = gfx::Display::kInvalidDisplayID;
+ int64 display2_id = gfx::Display::kInvalidDisplayID;
+ DisplayInfo display1;
+ DisplayInfo display2;
+ // Display ID and DisplayInfo for single display mode.
+ int64 single_display_id = gfx::Display::kInvalidDisplayID;
+ DisplayInfo single_display;
+
+ DisplayController* display_controller =
+ Shell::GetInstance()->display_controller();
+ ui::MultipleDisplayState display_state =
+ Shell::GetInstance()->display_configurator()->display_state();
oshima 2014/05/01 09:35:42 what value does this return for software mirror mo
Yufeng Shen (Slow to review) 2014/05/01 22:43:48 hmm, I actually don't know what is software mirror
oshima 2014/05/01 23:07:56 I just want to make sure things doesn't break in s
ynovikov 2014/05/01 23:16:10 AFAIK, the old code would treat software mirror mo
Yufeng Shen (Slow to review) 2014/05/02 00:03:39 no, touch events from second display also gets dis
+ if (display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR ||
+ display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) {
+ DisplayIdPair id_pair = GetDisplayManager()->GetCurrentDisplayIdPair();
+ display1_id = id_pair.first;
+ display2_id = id_pair.second;
+ if (display1_id == gfx::Display::kInvalidDisplayID ||
+ display2_id == gfx::Display::kInvalidDisplayID)
+ return;
oshima 2014/05/01 09:35:42 I believe this should not happen. Did you hit this
Yufeng Shen (Slow to review) 2014/05/01 22:43:48 Done.
+ display1 = GetDisplayManager()->GetDisplayInfo(display1_id);
+ display2 = GetDisplayManager()->GetDisplayInfo(display2_id);
+ } else {
+ single_display_id = GetDisplayManager()->first_display_id();
+ if (single_display_id == gfx::Display::kInvalidDisplayID)
+ return;
oshima 2014/05/01 09:35:42 same here
Yufeng Shen (Slow to review) 2014/05/01 22:43:48 Done.
+ single_display = GetDisplayManager()->GetDisplayInfo(single_display_id);
+ }
+
+ if (display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR) {
+ // In mirror mode, both displays share the same root window so
+ // both display ids are associated with the root window.
+ aura::Window* root = display_controller->GetPrimaryRootWindow();
+ root->GetHost()->UpdateDisplayID(display1_id, display2_id);
+ device_manager->UpdateTouchInfoForDisplay(
+ display1_id,
+ display1.touch_device_id(),
+ GetMirrorModeTouchTransformer(display1));
+ device_manager->UpdateTouchInfoForDisplay(
+ display2_id,
+ display2.touch_device_id(),
+ GetMirrorModeTouchTransformer(display2));
+ return;
+ }
+
+ if (display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) {
+ // In extended mode, each display is associated with one root window.
+ aura::Window* root1 =
+ display_controller->GetRootWindowForDisplayId(display1_id);
+ aura::Window* root2 =
+ display_controller->GetRootWindowForDisplayId(display2_id);
+ root1->GetHost()->UpdateDisplayID(display1_id,
+ gfx::Display::kInvalidDisplayID);
+ root2->GetHost()->UpdateDisplayID(display2_id,
+ gfx::Display::kInvalidDisplayID);
+
+ gfx::Size fb_size =
+ Shell::GetInstance()->display_configurator()->framebuffer_size();
+ device_manager->UpdateTouchInfoForDisplay(
+ display1_id,
+ display1.touch_device_id(),
+ GetExtendedModeTouchTransformer(display1, fb_size));
+ device_manager->UpdateTouchInfoForDisplay(
+ display2_id,
+ display2.touch_device_id(),
+ GetExtendedModeTouchTransformer(display2, fb_size));
+ return;
+ }
+
+ // Single display mode. The root window has one associated display id.
+ aura::Window* root =
+ display_controller->GetRootWindowForDisplayId(single_display.id());
+ root->GetHost()->UpdateDisplayID(single_display.id(),
+ gfx::Display::kInvalidDisplayID);
+ device_manager->UpdateTouchInfoForDisplay(single_display_id,
+ single_display.touch_device_id(),
+ ui::TouchTransformer());
+}
+
+void TouchTransformerController::OnDisplaysInitialized() {
+ UpdateTouchTransformer();
+}
+
+void TouchTransformerController::OnDisplayConfigurationChanged() {
+ UpdateTouchTransformer();
+}
+
+} // namespace ash

Powered by Google App Engine
This is Rietveld 408576698