Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 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_ctm_controller.h" | |
| 6 | |
| 7 #include "ash/display/display_controller.h" | |
| 8 #include "ash/display/display_manager.h" | |
| 9 #include "ash/shell.h" | |
| 10 #include "ui/aura/window_tree_host.h" | |
| 11 #include "ui/events/touch_ctm.h" | |
| 12 | |
| 13 #if defined(OS_CHROMEOS) && defined(USE_X11) | |
|
oshima
2014/03/14 21:53:53
Since this make sense only on chromeos + x11, it's
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
Done.
| |
| 14 #include "ui/events/x/device_data_manager.h" | |
| 15 #endif // defined(OS_CHROMEOS) && defined(USE_X11) | |
| 16 | |
| 17 namespace ash { | |
| 18 | |
| 19 namespace { | |
| 20 | |
| 21 internal::DisplayManager* GetDisplayManager() { | |
| 22 return Shell::GetInstance()->display_manager(); | |
| 23 } | |
| 24 | |
| 25 #if defined(OS_CHROMEOS) && defined(USE_X11) | |
| 26 // This function computes the extended mode TouchCTM for |touch_display|. | |
| 27 // An example of how to calculate the extended CTM. | |
| 28 // Suppose we have 2 monitors, the first one has size 1366 x 768. | |
| 29 // The second one has size 2560 x 1600 | |
| 30 // The total size of framebuffer is 2560 x 2428 | |
| 31 // where 2428 = 768 + 60 (hidden gap) + 1600 | |
| 32 // and the sceond monitor is translated to Point (0, 828) in the | |
|
sadrul
2014/03/15 19:32:51
second
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
comments removed.
| |
| 33 // framebuffer. | |
| 34 // X will first map input event location to [0, 2560) x [0, 2428), | |
|
spang
2014/03/24 18:52:31
Is this really a half-open interval?
AFAIK aura e
ynovikov
2014/03/24 19:02:41
No, but I think the numbers make more sense this w
spang
2014/03/24 19:05:31
No it's [0, 2560] x [0, 2428]. That's the point.
spang
2014/03/26 17:30:34
sadrul has fixed my understanding of the coordinat
| |
| 35 // Then the TouchCTM should map touch events from framebuffer space | |
| 36 // to root window space. | |
| 37 // For monitor1, we have | |
| 38 // x_scale = (1366 - 1) / (2560 - 1) | |
| 39 // x_offset = 0 | |
| 40 // y_scale = (768 - 1) / (2428 - 1) | |
| 41 // y_offset = 0 | |
| 42 // For Monitor 2, we have | |
| 43 // x_scale = (2560 - 1) / (2560 - 1) | |
| 44 // x_offset = 0 | |
| 45 // y_scale = (1600 - 1) / (2428 - 1) | |
| 46 // y_offset = 0 | |
|
ynovikov
2014/03/27 23:35:53
This used to be:
// y_offset = 828 / (2428 -1)
Th
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
Done.
| |
| 47 // See DisplayControllerTest.TouchCTMExtendedMode for the test. | |
| 48 ui::TouchCTM GetExtendedModeTouchCTM( | |
| 49 const internal::DisplayInfo& touch_display, | |
| 50 const internal::DisplayInfo& second_display) { | |
| 51 ui::TouchCTM ctm; | |
| 52 float width = touch_display.bounds_in_native().width(); | |
| 53 float height = touch_display.bounds_in_native().height(); | |
| 54 // float origin_x = touch_display.bounds_in_native().origin().x(); | |
| 55 // float origin_y = touch_display.bounds_in_native().origin().y(); | |
|
ynovikov
2014/03/27 23:35:53
This comment is misleading, please remove.
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
Done.
| |
| 56 float framebuffer_width = std::max<int>( | |
| 57 width, second_display.bounds_in_native().width()); | |
| 58 float framebuffer_height = | |
| 59 height + chromeos::OutputConfigurator::kVerticalGap + | |
| 60 second_display.bounds_in_native().height(); | |
|
ynovikov
2014/03/27 23:35:53
I don't think this computation is appropriate here
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
Done.
| |
| 61 ctm.x_scale = (width - 1) / (framebuffer_width - 1); | |
|
spang
2014/03/26 17:30:34
I think this should be:
width / framebuffer_width
ynovikov
2014/03/27 23:35:53
No, as the comment states for Monitor 2, in case w
spang
2014/03/28 16:49:31
Agree completely. However note x/x == (x-1)/(x-1)
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
OK, changed to use width / framebuffer_width.
The
| |
| 62 ctm.x_offset = 0; | |
| 63 ctm.y_scale = (height -1) / (framebuffer_height - 1); | |
|
spang
2014/03/26 17:30:34
Same here.
ynovikov
2014/03/27 23:35:53
Nit, add space in (height -1)
| |
| 64 ctm.y_offset = 0; | |
| 65 return ctm; | |
| 66 } | |
| 67 | |
| 68 // This function computes the mirror mode TouchCTM for |touch_display|. | |
| 69 // When internal monitor is applied a resolution that does not have | |
| 70 // the same aspect ratio as its native resolution, there would be | |
| 71 // blank regions in the letterboxing/pillarboxing mode. | |
| 72 // The TouchCTM will make sure the touch events on the blank region | |
| 73 // have negative coordinates and touch events within the chrome region | |
| 74 // have the correct positive coordinates. | |
| 75 ui::TouchCTM GetMirrorModeTouchCTM( | |
| 76 const internal::DisplayInfo& touch_display) { | |
| 77 ui::TouchCTM ctm; | |
| 78 // For external monitor, assuming no letterboxing or pillarboxing | |
| 79 // and just use the default TouchCTM. | |
|
ynovikov
2014/03/27 23:35:53
Why? Double checking that aspect ratio hasn't chan
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
Done.
| |
| 80 if (touch_display.id() != gfx::Display::InternalDisplayId()) | |
| 81 return ctm; | |
| 82 | |
| 83 float mirror_width = touch_display.bounds_in_native().width(); | |
| 84 float mirror_height = touch_display.bounds_in_native().height(); | |
| 85 float native_width = 0; | |
| 86 float native_height = 0; | |
| 87 | |
| 88 internal::DisplayMode native_mode; | |
| 89 std::vector<internal::DisplayMode> modes = touch_display.display_modes(); | |
| 90 for (size_t i = 0; i < modes.size(); i++) { | |
| 91 if (modes[i].native) { | |
| 92 native_width = modes[i].size.width(); | |
| 93 native_height = modes[i].size.height(); | |
| 94 break; | |
| 95 } | |
| 96 } | |
| 97 | |
| 98 if (native_height == 0.0 || mirror_height == 0.0 || | |
| 99 native_width == 0.0 || mirror_width == 0.0) | |
| 100 return ctm; | |
| 101 | |
| 102 float native_ar = static_cast<float>(native_width) / | |
| 103 static_cast<float>(native_height); | |
| 104 float mirror_ar = static_cast<float>(mirror_width) / | |
| 105 static_cast<float>(mirror_height); | |
| 106 | |
| 107 if (mirror_ar > native_ar) { // Letterboxing | |
| 108 ctm.x_scale = 1.0; | |
| 109 ctm.x_offset = 0.0; | |
| 110 ctm.y_scale = mirror_ar / native_ar; | |
| 111 ctm.y_offset = (1.0 / mirror_ar - 1.0 / native_ar) * 0.5 * mirror_width; | |
| 112 return ctm; | |
| 113 } | |
| 114 | |
| 115 if (native_ar > mirror_ar) { // Pillarboxing | |
| 116 ctm.y_scale = 1.0; | |
| 117 ctm.y_offset = 0.0; | |
| 118 ctm.x_scale = native_ar / mirror_ar; | |
| 119 ctm.x_offset = (mirror_ar - native_ar) * 0.5 * mirror_height; | |
| 120 return ctm; | |
| 121 } | |
| 122 | |
| 123 return ctm; // Same aspect ratio - return identity | |
| 124 } | |
| 125 #endif // defined(OS_CHROMEOS) && defined(USE_X11) | |
| 126 | |
| 127 } // namespace | |
| 128 | |
| 129 TouchCTMController::TouchCTMController() { | |
| 130 Shell::GetInstance()->display_controller()->AddObserver(this); | |
| 131 } | |
| 132 | |
| 133 TouchCTMController::~TouchCTMController() { | |
| 134 Shell::GetInstance()->display_controller()->RemoveObserver(this); | |
| 135 } | |
| 136 | |
| 137 void TouchCTMController::UpdateTouchCTM() { | |
| 138 #if defined(OS_CHROMEOS) && defined(USE_X11) | |
| 139 ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance(); | |
| 140 device_manager->ClearTouchCTM(); | |
| 141 device_manager->ClearTouchDeviceToDisplayMap(); | |
| 142 | |
| 143 // Display IDs and DisplayInfo for mirror or extended mode. | |
| 144 int64 display1_id = gfx::Display::kInvalidDisplayID; | |
| 145 int64 display2_id = gfx::Display::kInvalidDisplayID; | |
| 146 internal::DisplayInfo display1; | |
| 147 internal::DisplayInfo display2; | |
| 148 // Display ID and DisplayInfo for single display mode. | |
| 149 int64 single_display_id = gfx::Display::kInvalidDisplayID; | |
| 150 internal::DisplayInfo single_display; | |
| 151 | |
| 152 const std::map<int64, aura::Window*>& root_windows = | |
| 153 Shell::GetInstance()->display_controller()->root_windows(); | |
| 154 | |
| 155 ui::OutputState output_state = | |
| 156 Shell::GetInstance()->output_configurator()->output_state(); | |
| 157 if (output_state == ui::OUTPUT_STATE_DUAL_MIRROR || | |
| 158 output_state == ui::OUTPUT_STATE_DUAL_EXTENDED) { | |
| 159 DisplayIdPair id_pair = GetDisplayManager()->GetCurrentDisplayIdPair(); | |
| 160 display1_id = id_pair.first; | |
| 161 display2_id = id_pair.second; | |
| 162 if (display1_id == gfx::Display::kInvalidDisplayID || | |
| 163 display2_id == gfx::Display::kInvalidDisplayID) | |
| 164 return; | |
| 165 display1 = GetDisplayManager()->GetDisplayInfo(display1_id); | |
| 166 display2 = GetDisplayManager()->GetDisplayInfo(display2_id); | |
| 167 } else { | |
| 168 single_display_id = GetDisplayManager()->first_display_id(); | |
| 169 if (single_display_id == gfx::Display::kInvalidDisplayID) | |
| 170 return; | |
| 171 single_display = GetDisplayManager()->GetDisplayInfo(single_display_id); | |
| 172 } | |
| 173 | |
| 174 if (output_state == ui::OUTPUT_STATE_DUAL_MIRROR) { | |
| 175 std::map<int64, aura::Window*>::const_iterator it = root_windows.begin(); | |
|
sadrul
2014/03/15 19:32:51
In this case, is root_windows.size() == 1?
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
reworked, ptal.
| |
| 176 // In mirror mode, both displays share the same root window so | |
| 177 // both display ids are associated with the root window. | |
| 178 for (; it != root_windows.end(); it++) | |
| 179 it->second->GetHost()->UpdateDisplayID(display1_id, display2_id); | |
| 180 // Update the associated display id and TouchCTM in device manager | |
| 181 // if the display is a touch device. | |
| 182 if (display1.touch_device_id() != 0) { | |
| 183 device_manager->MapTouchDeviceToDisplay(display1.touch_device_id(), | |
| 184 display1.id()); | |
| 185 device_manager->SetTouchCTM(display1.touch_device_id(), | |
| 186 GetMirrorModeTouchCTM(display1)); | |
| 187 } | |
|
sadrul
2014/03/15 19:32:51
This block of code should be in DeviceDataManager,
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
done.
| |
| 188 if (display2.touch_device_id() != 0) { | |
| 189 device_manager->MapTouchDeviceToDisplay(display2.touch_device_id(), | |
| 190 display2.id()); | |
| 191 device_manager->SetTouchCTM(display2.touch_device_id(), | |
| 192 GetMirrorModeTouchCTM(display2)); | |
| 193 } | |
| 194 return; | |
| 195 } | |
| 196 | |
| 197 if (output_state == ui::OUTPUT_STATE_DUAL_EXTENDED) { | |
| 198 std::map<int64, aura::Window*>::const_iterator it = root_windows.begin(); | |
| 199 // In extended mode, each display has one associated root window. | |
| 200 for (; it != root_windows.end(); it++) { | |
| 201 if (it->first == display1_id) { | |
| 202 it->second->GetHost()->UpdateDisplayID(display1_id, | |
| 203 gfx::Display::kInvalidDisplayID); | |
| 204 } else if (it->first == display2_id) { | |
| 205 it->second->GetHost()->UpdateDisplayID(display2_id, | |
| 206 gfx::Display::kInvalidDisplayID); | |
| 207 } | |
| 208 } | |
| 209 // Update the associated display id and TouchCTM in device manager | |
| 210 // if the display is a touch device. | |
| 211 if (display1.touch_device_id() != 0) { | |
| 212 device_manager->MapTouchDeviceToDisplay(display1.touch_device_id(), | |
| 213 display1.id()); | |
| 214 device_manager->SetTouchCTM(display1.touch_device_id(), | |
| 215 GetExtendedModeTouchCTM(display1, display2)); | |
| 216 } | |
| 217 if (display2.touch_device_id() != 0) { | |
| 218 device_manager->MapTouchDeviceToDisplay(display2.touch_device_id(), | |
| 219 display2.id()); | |
| 220 device_manager->SetTouchCTM(display2.touch_device_id(), | |
| 221 GetExtendedModeTouchCTM(display2, display1)); | |
| 222 } | |
| 223 return; | |
| 224 } | |
| 225 | |
| 226 // Single display mode. The root window has one associated display id. | |
| 227 std::map<int64, aura::Window*>::const_iterator it = root_windows.begin(); | |
| 228 for (; it != root_windows.end(); it++) { | |
| 229 if (it->first == single_display.id()) { | |
| 230 it->second->GetHost()->UpdateDisplayID(single_display.id(), | |
| 231 gfx::Display::kInvalidDisplayID); | |
| 232 } | |
| 233 } | |
| 234 // If the display is a touch display, we add a deafult TouchCTM to the | |
|
ynovikov
2014/03/27 23:35:53
default
Yufeng Shen (Slow to review)
2014/04/29 20:34:18
Done.
| |
| 235 // according root window. | |
| 236 if (single_display.touch_device_id() != 0) { | |
| 237 device_manager->MapTouchDeviceToDisplay(single_display.touch_device_id(), | |
| 238 single_display.id()); | |
| 239 device_manager->SetTouchCTM(single_display.touch_device_id(), | |
| 240 ui::TouchCTM()); | |
| 241 } | |
| 242 #endif | |
| 243 } | |
| 244 | |
| 245 void TouchCTMController::OnDisplayConfigurationChanged() { | |
| 246 UpdateTouchCTM(); | |
| 247 } | |
| 248 | |
| 249 } // namespace ash | |
| OLD | NEW |