OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "ash/touch/touch_transformer_controller.h" |
| 6 |
| 7 #include "ash/display/display_controller.h" |
| 8 #include "ash/display/display_manager.h" |
| 9 #include "ash/host/ash_window_tree_host.h" |
| 10 #include "ash/root_window_controller.h" |
| 11 #include "ash/shell.h" |
| 12 #include "ui/aura/window_tree_host.h" |
| 13 #include "ui/display/chromeos/display_configurator.h" |
| 14 #include "ui/display/types/chromeos/display_snapshot.h" |
| 15 #include "ui/events/x/device_data_manager.h" |
| 16 |
| 17 namespace ash { |
| 18 |
| 19 namespace { |
| 20 |
| 21 DisplayManager* GetDisplayManager() { |
| 22 return Shell::GetInstance()->display_manager(); |
| 23 } |
| 24 |
| 25 } // namespace |
| 26 |
| 27 // This function computes the extended mode TouchTransformer for |
| 28 // |touch_display|. The TouchTransformer maps the touch event position |
| 29 // from framebuffer size to the display size. |
| 30 ui::TouchTransformer |
| 31 TouchTransformerController::GetExtendedModeTouchTransformer( |
| 32 const DisplayInfo& touch_display, const gfx::Size& fb_size) const { |
| 33 ui::TouchTransformer ctm; |
| 34 if (touch_display.touch_device_id() == 0 || |
| 35 fb_size.width() == 0.0 || |
| 36 fb_size.height() == 0.0) |
| 37 return ctm; |
| 38 float width = touch_display.bounds_in_native().width(); |
| 39 float height = touch_display.bounds_in_native().height(); |
| 40 ctm.x_scale = width / fb_size.width(); |
| 41 ctm.x_offset = 0; |
| 42 ctm.y_scale = height / fb_size.height(); |
| 43 ctm.y_offset = 0; |
| 44 return ctm; |
| 45 } |
| 46 |
| 47 bool TouchTransformerController::ShouldComputeMirrorModeTouchTransformer( |
| 48 const DisplayInfo& touch_display) const { |
| 49 if (force_compute_mirror_mode_touch_transformer_) |
| 50 return true; |
| 51 |
| 52 if (touch_display.touch_device_id() == 0) |
| 53 return false; |
| 54 |
| 55 const ui::DisplayConfigurator::DisplayState* state = NULL; |
| 56 const std::vector<ui::DisplayConfigurator::DisplayState>& cached_displays = |
| 57 Shell::GetInstance()->display_configurator()->cached_displays(); |
| 58 for (size_t i = 0; i < cached_displays.size(); i++) { |
| 59 if (cached_displays[i].touch_device_id == touch_display.touch_device_id()) { |
| 60 state = &cached_displays[i]; |
| 61 break; |
| 62 } |
| 63 } |
| 64 |
| 65 if (!state || state->mirror_mode == state->display->native_mode() || |
| 66 !state->display->is_aspect_preserving_scaling()) { |
| 67 return false; |
| 68 } |
| 69 return true; |
| 70 } |
| 71 |
| 72 // This function computes the mirror mode TouchTransformer for |touch_display|. |
| 73 // When internal monitor is applied a resolution that does not have |
| 74 // the same aspect ratio as its native resolution, there would be |
| 75 // blank regions in the letterboxing/pillarboxing mode. |
| 76 // The TouchTransformer will make sure the touch events on the blank region |
| 77 // have negative coordinates and touch events within the chrome region |
| 78 // have the correct positive coordinates. |
| 79 ui::TouchTransformer TouchTransformerController::GetMirrorModeTouchTransformer( |
| 80 const DisplayInfo& touch_display) const { |
| 81 ui::TouchTransformer ctm; |
| 82 if (!ShouldComputeMirrorModeTouchTransformer(touch_display)) |
| 83 return ctm; |
| 84 |
| 85 float mirror_width = touch_display.bounds_in_native().width(); |
| 86 float mirror_height = touch_display.bounds_in_native().height(); |
| 87 float native_width = 0; |
| 88 float native_height = 0; |
| 89 |
| 90 std::vector<DisplayMode> modes = touch_display.display_modes(); |
| 91 for (size_t i = 0; i < modes.size(); i++) { |
| 92 if (modes[i].native) { |
| 93 native_width = modes[i].size.width(); |
| 94 native_height = modes[i].size.height(); |
| 95 break; |
| 96 } |
| 97 } |
| 98 |
| 99 if (native_height == 0.0 || mirror_height == 0.0 || |
| 100 native_width == 0.0 || mirror_width == 0.0) |
| 101 return ctm; |
| 102 |
| 103 float native_ar = static_cast<float>(native_width) / |
| 104 static_cast<float>(native_height); |
| 105 float mirror_ar = static_cast<float>(mirror_width) / |
| 106 static_cast<float>(mirror_height); |
| 107 |
| 108 if (mirror_ar > native_ar) { // Letterboxing |
| 109 ctm.y_scale = mirror_ar / native_ar; |
| 110 ctm.y_offset = (1.0 - mirror_ar / native_ar) * 0.5 * mirror_height; |
| 111 return ctm; |
| 112 } |
| 113 |
| 114 if (native_ar > mirror_ar) { // Pillarboxing |
| 115 ctm.x_scale = native_ar / mirror_ar; |
| 116 ctm.x_offset = (1.0 - native_ar / mirror_ar) * 0.5 * mirror_width; |
| 117 return ctm; |
| 118 } |
| 119 |
| 120 return ctm; // Same aspect ratio - return identity |
| 121 } |
| 122 |
| 123 TouchTransformerController::TouchTransformerController() : |
| 124 force_compute_mirror_mode_touch_transformer_ (false) { |
| 125 Shell::GetInstance()->display_controller()->AddObserver(this); |
| 126 } |
| 127 |
| 128 TouchTransformerController::~TouchTransformerController() { |
| 129 Shell::GetInstance()->display_controller()->RemoveObserver(this); |
| 130 } |
| 131 |
| 132 void TouchTransformerController::UpdateTouchTransformer() const { |
| 133 ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance(); |
| 134 device_manager->ClearTouchTransformerRecord(); |
| 135 |
| 136 // Display IDs and DisplayInfo for mirror or extended mode. |
| 137 int64 display1_id = gfx::Display::kInvalidDisplayID; |
| 138 int64 display2_id = gfx::Display::kInvalidDisplayID; |
| 139 DisplayInfo display1; |
| 140 DisplayInfo display2; |
| 141 // Display ID and DisplayInfo for single display mode. |
| 142 int64 single_display_id = gfx::Display::kInvalidDisplayID; |
| 143 DisplayInfo single_display; |
| 144 |
| 145 DisplayController* display_controller = |
| 146 Shell::GetInstance()->display_controller(); |
| 147 ui::MultipleDisplayState display_state = |
| 148 Shell::GetInstance()->display_configurator()->display_state(); |
| 149 if (display_state == ui::MULTIPLE_DISPLAY_STATE_INVALID || |
| 150 display_state == ui::MULTIPLE_DISPLAY_STATE_HEADLESS) { |
| 151 return; |
| 152 } else if (display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR || |
| 153 display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) { |
| 154 // TODO(miletus) : Handle DUAL_EXTENDED with software mirroring. |
| 155 DisplayIdPair id_pair = GetDisplayManager()->GetCurrentDisplayIdPair(); |
| 156 display1_id = id_pair.first; |
| 157 display2_id = id_pair.second; |
| 158 DCHECK(display1_id != gfx::Display::kInvalidDisplayID && |
| 159 display2_id != gfx::Display::kInvalidDisplayID); |
| 160 display1 = GetDisplayManager()->GetDisplayInfo(display1_id); |
| 161 display2 = GetDisplayManager()->GetDisplayInfo(display2_id); |
| 162 } else { |
| 163 single_display_id = GetDisplayManager()->first_display_id(); |
| 164 DCHECK(single_display_id != gfx::Display::kInvalidDisplayID); |
| 165 single_display = GetDisplayManager()->GetDisplayInfo(single_display_id); |
| 166 } |
| 167 |
| 168 if (display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR) { |
| 169 // In mirror mode, both displays share the same root window so |
| 170 // both display ids are associated with the root window. |
| 171 aura::Window* root = display_controller->GetPrimaryRootWindow(); |
| 172 RootWindowController::ForWindow(root)->ash_host()->UpdateDisplayID( |
| 173 display1_id, display2_id); |
| 174 device_manager->UpdateTouchInfoForDisplay( |
| 175 display1_id, |
| 176 display1.touch_device_id(), |
| 177 GetMirrorModeTouchTransformer(display1)); |
| 178 device_manager->UpdateTouchInfoForDisplay( |
| 179 display2_id, |
| 180 display2.touch_device_id(), |
| 181 GetMirrorModeTouchTransformer(display2)); |
| 182 return; |
| 183 } |
| 184 |
| 185 if (display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) { |
| 186 // In extended mode, each display is associated with one root window. |
| 187 aura::Window* root1 = |
| 188 display_controller->GetRootWindowForDisplayId(display1_id); |
| 189 aura::Window* root2 = |
| 190 display_controller->GetRootWindowForDisplayId(display2_id); |
| 191 RootWindowController::ForWindow(root1)->ash_host()->UpdateDisplayID( |
| 192 display1_id, gfx::Display::kInvalidDisplayID); |
| 193 RootWindowController::ForWindow(root2)->ash_host()->UpdateDisplayID( |
| 194 display2_id, gfx::Display::kInvalidDisplayID); |
| 195 gfx::Size fb_size = |
| 196 Shell::GetInstance()->display_configurator()->framebuffer_size(); |
| 197 device_manager->UpdateTouchInfoForDisplay( |
| 198 display1_id, |
| 199 display1.touch_device_id(), |
| 200 GetExtendedModeTouchTransformer(display1, fb_size)); |
| 201 device_manager->UpdateTouchInfoForDisplay( |
| 202 display2_id, |
| 203 display2.touch_device_id(), |
| 204 GetExtendedModeTouchTransformer(display2, fb_size)); |
| 205 return; |
| 206 } |
| 207 |
| 208 // Single display mode. The root window has one associated display id. |
| 209 aura::Window* root = |
| 210 display_controller->GetRootWindowForDisplayId(single_display.id()); |
| 211 RootWindowController::ForWindow(root)->ash_host()->UpdateDisplayID( |
| 212 single_display.id(), gfx::Display::kInvalidDisplayID); |
| 213 device_manager->UpdateTouchInfoForDisplay(single_display_id, |
| 214 single_display.touch_device_id(), |
| 215 ui::TouchTransformer()); |
| 216 } |
| 217 |
| 218 void TouchTransformerController::OnDisplaysInitialized() { |
| 219 UpdateTouchTransformer(); |
| 220 } |
| 221 |
| 222 void TouchTransformerController::OnDisplayConfigurationChanged() { |
| 223 UpdateTouchTransformer(); |
| 224 } |
| 225 |
| 226 } // namespace ash |
OLD | NEW |