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 - 1.0 / native_ar) * 0.5 * mirror_width; | |
ynovikov
2014/05/02 00:43:20
Nit: I think the formula looks prettier (symmetric
Yufeng Shen (Slow to review)
2014/05/02 15:14:08
of course :)
| |
111 return ctm; | |
112 } | |
113 | |
114 if (native_ar > mirror_ar) { // Pillarboxing | |
115 ctm.x_scale = native_ar / mirror_ar; | |
116 ctm.x_offset = (mirror_ar - native_ar) * 0.5 * mirror_height; | |
ynovikov
2014/05/02 00:43:20
And
ctm.x_offset = (1.0 - native_ar / mirror_ar) *
| |
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 // TODO(miletus) : Handle DUAL_EXTENDED with software mirroring. | |
150 if (display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR || | |
151 display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) { | |
152 DisplayIdPair id_pair = GetDisplayManager()->GetCurrentDisplayIdPair(); | |
153 display1_id = id_pair.first; | |
154 display2_id = id_pair.second; | |
155 DCHECK(display1_id != gfx::Display::kInvalidDisplayID && | |
156 display2_id != gfx::Display::kInvalidDisplayID); | |
157 display1 = GetDisplayManager()->GetDisplayInfo(display1_id); | |
158 display2 = GetDisplayManager()->GetDisplayInfo(display2_id); | |
159 } else { | |
160 single_display_id = GetDisplayManager()->first_display_id(); | |
161 DCHECK(single_display_id != gfx::Display::kInvalidDisplayID); | |
162 single_display = GetDisplayManager()->GetDisplayInfo(single_display_id); | |
163 } | |
164 | |
165 if (display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR) { | |
166 // In mirror mode, both displays share the same root window so | |
167 // both display ids are associated with the root window. | |
168 aura::Window* root = display_controller->GetPrimaryRootWindow(); | |
169 RootWindowController::ForWindow(root)->ash_host()->UpdateDisplayID( | |
170 display1_id, display2_id); | |
171 device_manager->UpdateTouchInfoForDisplay( | |
172 display1_id, | |
173 display1.touch_device_id(), | |
174 GetMirrorModeTouchTransformer(display1)); | |
175 device_manager->UpdateTouchInfoForDisplay( | |
176 display2_id, | |
177 display2.touch_device_id(), | |
178 GetMirrorModeTouchTransformer(display2)); | |
179 return; | |
180 } | |
181 | |
182 if (display_state == ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED) { | |
183 // In extended mode, each display is associated with one root window. | |
184 aura::Window* root1 = | |
185 display_controller->GetRootWindowForDisplayId(display1_id); | |
186 aura::Window* root2 = | |
187 display_controller->GetRootWindowForDisplayId(display2_id); | |
188 RootWindowController::ForWindow(root1)->ash_host()->UpdateDisplayID( | |
189 display1_id, gfx::Display::kInvalidDisplayID); | |
190 RootWindowController::ForWindow(root2)->ash_host()->UpdateDisplayID( | |
191 display2_id, gfx::Display::kInvalidDisplayID); | |
192 gfx::Size fb_size = | |
193 Shell::GetInstance()->display_configurator()->framebuffer_size(); | |
194 device_manager->UpdateTouchInfoForDisplay( | |
195 display1_id, | |
196 display1.touch_device_id(), | |
197 GetExtendedModeTouchTransformer(display1, fb_size)); | |
198 device_manager->UpdateTouchInfoForDisplay( | |
199 display2_id, | |
200 display2.touch_device_id(), | |
201 GetExtendedModeTouchTransformer(display2, fb_size)); | |
202 return; | |
203 } | |
204 | |
205 // Single display mode. The root window has one associated display id. | |
206 aura::Window* root = | |
207 display_controller->GetRootWindowForDisplayId(single_display.id()); | |
208 RootWindowController::ForWindow(root)->ash_host()->UpdateDisplayID( | |
209 single_display.id(), gfx::Display::kInvalidDisplayID); | |
210 device_manager->UpdateTouchInfoForDisplay(single_display_id, | |
211 single_display.touch_device_id(), | |
212 ui::TouchTransformer()); | |
213 } | |
214 | |
215 void TouchTransformerController::OnDisplaysInitialized() { | |
216 UpdateTouchTransformer(); | |
217 } | |
218 | |
219 void TouchTransformerController::OnDisplayConfigurationChanged() { | |
220 UpdateTouchTransformer(); | |
221 } | |
222 | |
223 } // namespace ash | |
OLD | NEW |