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