OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/display/display_controller.h" | 5 #include "ash/display/display_controller.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <map> | 9 #include <map> |
10 | 10 |
(...skipping 17 matching lines...) Expand all Loading... | |
28 #include "ui/aura/client/capture_client.h" | 28 #include "ui/aura/client/capture_client.h" |
29 #include "ui/aura/client/focus_client.h" | 29 #include "ui/aura/client/focus_client.h" |
30 #include "ui/aura/client/screen_position_client.h" | 30 #include "ui/aura/client/screen_position_client.h" |
31 #include "ui/aura/root_window_transformer.h" | 31 #include "ui/aura/root_window_transformer.h" |
32 #include "ui/aura/window.h" | 32 #include "ui/aura/window.h" |
33 #include "ui/aura/window_event_dispatcher.h" | 33 #include "ui/aura/window_event_dispatcher.h" |
34 #include "ui/aura/window_property.h" | 34 #include "ui/aura/window_property.h" |
35 #include "ui/aura/window_tracker.h" | 35 #include "ui/aura/window_tracker.h" |
36 #include "ui/compositor/compositor.h" | 36 #include "ui/compositor/compositor.h" |
37 #include "ui/compositor/compositor_vsync_manager.h" | 37 #include "ui/compositor/compositor_vsync_manager.h" |
38 #include "ui/events/touch_ctm.h" | |
38 #include "ui/gfx/display.h" | 39 #include "ui/gfx/display.h" |
39 #include "ui/gfx/screen.h" | 40 #include "ui/gfx/screen.h" |
40 | 41 |
41 #if defined(OS_CHROMEOS) | 42 #if defined(OS_CHROMEOS) |
42 #include "base/sys_info.h" | 43 #include "base/sys_info.h" |
43 #include "base/time/time.h" | 44 #include "base/time/time.h" |
44 #if defined(USE_X11) | 45 #if defined(USE_X11) |
45 #include "ash/display/output_configurator_animation.h" | 46 #include "ash/display/output_configurator_animation.h" |
46 #include "chromeos/display/output_configurator.h" | 47 #include "chromeos/display/output_configurator.h" |
47 #include "ui/base/x/x11_util.h" | 48 #include "ui/base/x/x11_util.h" |
49 #include "ui/events/x/device_data_manager.h" | |
48 #include "ui/gfx/x/x11_types.h" | 50 #include "ui/gfx/x/x11_types.h" |
49 | 51 |
50 // Including this at the bottom to avoid other | 52 // Including this at the bottom to avoid other |
51 // potential conflict with chrome headers. | 53 // potential conflict with chrome headers. |
52 #include <X11/extensions/Xrandr.h> | 54 #include <X11/extensions/Xrandr.h> |
53 #undef RootWindow | 55 #undef RootWindow |
54 #endif // defined(USE_X11) | 56 #endif // defined(USE_X11) |
55 #endif // defined(OS_CHROMEOS) | 57 #endif // defined(OS_CHROMEOS) |
56 | 58 |
57 namespace ash { | 59 namespace ash { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
125 | 127 |
126 internal::DisplayMode mode; | 128 internal::DisplayMode mode; |
127 if (GetDisplayManager()->GetSelectedModeForDisplayId(display.id(), &mode) && | 129 if (GetDisplayManager()->GetSelectedModeForDisplayId(display.id(), &mode) && |
128 mode.refresh_rate > 0.0f) { | 130 mode.refresh_rate > 0.0f) { |
129 host->compositor()->vsync_manager()->SetAuthoritativeVSyncInterval( | 131 host->compositor()->vsync_manager()->SetAuthoritativeVSyncInterval( |
130 base::TimeDelta::FromMicroseconds( | 132 base::TimeDelta::FromMicroseconds( |
131 base::Time::kMicrosecondsPerSecond / mode.refresh_rate)); | 133 base::Time::kMicrosecondsPerSecond / mode.refresh_rate)); |
132 } | 134 } |
133 } | 135 } |
134 | 136 |
137 #if defined(OS_CHROMEOS) && defined(USE_X11) | |
138 // This function computes the extended mode TouchCTM for |touch_display|. | |
139 // An example of how to calculate the extended CTM. | |
140 // Suppose we have 2 monitors, the first one has size 1366 x 768. | |
141 // The second one has size 2560 x 1600 | |
142 // The total size of framebuffer is 2560 x 2428 | |
143 // where 2428 = 768 + 60 (hidden gap) + 1600 | |
144 // and the sceond monitor is translated to Point (0, 828) in the | |
145 // framebuffer. | |
146 // X will first map input event location to [0, 2560) x [0, 2428), | |
147 // Then the TouchCTM should map touch events from framebuffer space | |
148 // to root window space. | |
149 // For monitor1, we have | |
150 // x_scale = (1366 - 1) / (2560 - 1) | |
151 // x_offset = 0 | |
152 // y_scale = (768 - 1) / (2428 - 1) | |
153 // y_offset = 0 | |
154 // For Monitor 2, we have | |
155 // x_scale = (2560 - 1) / (2560 - 1) | |
156 // x_offset = 0 | |
157 // y_scale = (1600 - 1) / (2428 - 1) | |
158 // y_offset = 0 | |
159 // See DisplayControllerTest.TouchCTMExtendedMode for the test. | |
160 ui::TouchCTM GetExtendedModeTouchCTM( | |
161 const internal::DisplayInfo& touch_display, | |
162 const internal::DisplayInfo& second_display) { | |
163 ui::TouchCTM ctm; | |
164 float width = touch_display.bounds_in_native().width(); | |
165 float height = touch_display.bounds_in_native().height(); | |
166 // float origin_x = touch_display.bounds_in_native().origin().x(); | |
167 // float origin_y = touch_display.bounds_in_native().origin().y(); | |
168 float framebuffer_width = std::max<int>( | |
169 width, second_display.bounds_in_native().width()); | |
170 float framebuffer_height = | |
171 height + chromeos::OutputConfigurator::kVerticalGap + | |
172 second_display.bounds_in_native().height(); | |
173 ctm.x_scale = (width - 1) / (framebuffer_width - 1); | |
174 ctm.x_offset = 0; | |
175 ctm.y_scale = (height -1) / (framebuffer_height - 1); | |
176 ctm.y_offset = 0; | |
177 return ctm; | |
178 } | |
179 | |
180 // This function computes the mirror mode TouchCTM for |touch_display|. | |
181 // When internal monitor is applied a resolution that does not have | |
182 // the same aspect ratio as its native resolution, there would be | |
183 // blank regions in the letterboxing/pillarboxing mode. | |
184 // The TouchCTM will make sure the touch events on the blank region | |
185 // have negative coordinates and touch events within the chrome region | |
186 // have the correct positive coordinates. | |
187 ui::TouchCTM GetMirrorModeTouchCTM( | |
188 const internal::DisplayInfo& touch_display) { | |
189 ui::TouchCTM ctm; | |
190 // For external monitor, assuming no letterboxing or pillarboxing | |
191 // and just use the default TouchCTM. | |
192 if (touch_display.id() != gfx::Display::InternalDisplayId()) | |
193 return ctm; | |
194 | |
195 float mirror_width = touch_display.bounds_in_native().width(); | |
196 float mirror_height = touch_display.bounds_in_native().height(); | |
197 float native_width = 0; | |
198 float native_height = 0; | |
199 | |
200 internal::DisplayMode native_mode; | |
201 std::vector<internal::DisplayMode> modes = touch_display.display_modes(); | |
202 for (size_t i = 0; i < modes.size(); i++) { | |
203 if (modes[i].native) { | |
204 native_width = modes[i].size.width(); | |
205 native_height = modes[i].size.height(); | |
206 break; | |
207 } | |
208 } | |
209 | |
210 if (native_height == 0.0 || mirror_height == 0.0 || | |
211 native_width == 0.0 || mirror_width == 0.0) | |
212 return ctm; | |
213 | |
214 float native_ar = static_cast<float>(native_width) / | |
215 static_cast<float>(native_height); | |
216 float mirror_ar = static_cast<float>(mirror_width) / | |
217 static_cast<float>(mirror_height); | |
218 | |
219 if (mirror_ar > native_ar) { // Letterboxing | |
220 ctm.x_scale = 1.0; | |
221 ctm.x_offset = 0.0; | |
222 ctm.y_scale = mirror_ar / native_ar; | |
223 ctm.y_offset = (1.0 / mirror_ar - 1.0 / native_ar) * 0.5 * mirror_width; | |
224 return ctm; | |
225 } | |
226 | |
227 if (native_ar > mirror_ar) { // Pillarboxing | |
228 ctm.y_scale = 1.0; | |
229 ctm.y_offset = 0.0; | |
230 ctm.x_scale = native_ar / mirror_ar; | |
231 ctm.x_offset = (mirror_ar - native_ar) * 0.5 * mirror_height; | |
232 return ctm; | |
233 } | |
234 | |
235 return ctm; // Same aspect ratio - return identity | |
236 } | |
237 #endif // defined(OS_CHROMEOS) && defined(USE_X11) | |
238 | |
135 } // namespace | 239 } // namespace |
136 | 240 |
137 namespace internal { | 241 namespace internal { |
138 | 242 |
139 // A utility class to store/restore focused/active window | 243 // A utility class to store/restore focused/active window |
140 // when the display configuration has changed. | 244 // when the display configuration has changed. |
141 class FocusActivationStore { | 245 class FocusActivationStore { |
142 public: | 246 public: |
143 FocusActivationStore() | 247 FocusActivationStore() |
144 : activation_client_(NULL), | 248 : activation_client_(NULL), |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 DCHECK(controller); | 377 DCHECK(controller); |
274 delete controller; | 378 delete controller; |
275 } | 379 } |
276 } | 380 } |
277 | 381 |
278 void DisplayController::InitPrimaryDisplay() { | 382 void DisplayController::InitPrimaryDisplay() { |
279 const gfx::Display& primary_candidate = | 383 const gfx::Display& primary_candidate = |
280 GetDisplayManager()->GetPrimaryDisplayCandidate(); | 384 GetDisplayManager()->GetPrimaryDisplayCandidate(); |
281 primary_display_id = primary_candidate.id(); | 385 primary_display_id = primary_candidate.id(); |
282 AddWindowTreeHostForDisplay(primary_candidate); | 386 AddWindowTreeHostForDisplay(primary_candidate); |
387 UpdateTouchCTM(); | |
283 } | 388 } |
284 | 389 |
285 void DisplayController::InitSecondaryDisplays() { | 390 void DisplayController::InitSecondaryDisplays() { |
286 internal::DisplayManager* display_manager = GetDisplayManager(); | 391 internal::DisplayManager* display_manager = GetDisplayManager(); |
287 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { | 392 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { |
288 const gfx::Display& display = display_manager->GetDisplayAt(i); | 393 const gfx::Display& display = display_manager->GetDisplayAt(i); |
289 if (primary_display_id != display.id()) { | 394 if (primary_display_id != display.id()) { |
290 aura::WindowTreeHost* host = AddWindowTreeHostForDisplay(display); | 395 aura::WindowTreeHost* host = AddWindowTreeHostForDisplay(display); |
291 internal::RootWindowController::CreateForSecondaryDisplay(host); | 396 internal::RootWindowController::CreateForSecondaryDisplay(host); |
292 } | 397 } |
293 } | 398 } |
294 UpdateHostWindowNames(); | 399 UpdateHostWindowNames(); |
400 UpdateTouchCTM(); | |
295 } | 401 } |
296 | 402 |
297 void DisplayController::AddObserver(Observer* observer) { | 403 void DisplayController::AddObserver(Observer* observer) { |
298 observers_.AddObserver(observer); | 404 observers_.AddObserver(observer); |
299 } | 405 } |
300 | 406 |
301 void DisplayController::RemoveObserver(Observer* observer) { | 407 void DisplayController::RemoveObserver(Observer* observer) { |
302 observers_.RemoveObserver(observer); | 408 observers_.RemoveObserver(observer); |
303 } | 409 } |
304 | 410 |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
682 primary_id == gfx::Display::kInvalidDisplayID ? | 788 primary_id == gfx::Display::kInvalidDisplayID ? |
683 pair.first : primary_id); | 789 pair.first : primary_id); |
684 // Update the primary_id in case the above call is | 790 // Update the primary_id in case the above call is |
685 // ignored. Happens when a) default layout's primary id | 791 // ignored. Happens when a) default layout's primary id |
686 // doesn't exist, or b) the primary_id has already been | 792 // doesn't exist, or b) the primary_id has already been |
687 // set to the same and didn't update it. | 793 // set to the same and didn't update it. |
688 layout_store->UpdatePrimaryDisplayId( | 794 layout_store->UpdatePrimaryDisplayId( |
689 pair, Shell::GetScreen()->GetPrimaryDisplay().id()); | 795 pair, Shell::GetScreen()->GetPrimaryDisplay().id()); |
690 } | 796 } |
691 } | 797 } |
692 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged()); | 798 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged()); |
oshima
2014/03/13 20:43:54
Looks like new code don't have to be in DisplayCon
Yufeng Shen (Slow to review)
2014/03/13 20:55:46
but is OnDisplayConfigurationChanged() is always c
oshima
2014/03/13 21:34:48
It's always called when display configuration chan
| |
693 UpdateHostWindowNames(); | 799 UpdateHostWindowNames(); |
694 EnsurePointerInDisplays(); | 800 EnsurePointerInDisplays(); |
801 UpdateTouchCTM(); | |
802 } | |
803 | |
804 void DisplayController::UpdateTouchCTM() { | |
805 #if defined(OS_CHROMEOS) && defined(USE_X11) | |
806 ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance(); | |
807 device_manager->ClearTouchCTM(); | |
808 device_manager->ClearTouchDeviceToDisplayMap(); | |
809 | |
810 // Display IDs and DisplayInfo for mirror or extended mode. | |
811 int64 display1_id = gfx::Display::kInvalidDisplayID; | |
812 int64 display2_id = gfx::Display::kInvalidDisplayID; | |
813 internal::DisplayInfo display1; | |
814 internal::DisplayInfo display2; | |
815 // Display ID and DisplayInfo for single display mode. | |
816 int64 single_display_id = gfx::Display::kInvalidDisplayID; | |
817 internal::DisplayInfo single_display; | |
818 | |
819 ui::OutputState output_state = | |
820 Shell::GetInstance()->output_configurator()->output_state(); | |
821 if (output_state == ui::OUTPUT_STATE_DUAL_MIRROR || | |
822 output_state == ui::OUTPUT_STATE_DUAL_EXTENDED) { | |
823 DisplayIdPair id_pair = GetDisplayManager()->GetCurrentDisplayIdPair(); | |
824 display1_id = id_pair.first; | |
825 display2_id = id_pair.second; | |
826 if (display1_id == gfx::Display::kInvalidDisplayID || | |
827 display2_id == gfx::Display::kInvalidDisplayID) | |
828 return; | |
829 display1 = GetDisplayManager()->GetDisplayInfo(display1_id); | |
830 display2 = GetDisplayManager()->GetDisplayInfo(display2_id); | |
831 } else { | |
832 single_display_id = GetDisplayManager()->first_display_id(); | |
833 if (single_display_id == gfx::Display::kInvalidDisplayID) | |
834 return; | |
835 single_display = GetDisplayManager()->GetDisplayInfo(single_display_id); | |
836 } | |
837 | |
838 if (output_state == ui::OUTPUT_STATE_DUAL_MIRROR) { | |
839 std::map<int64, aura::Window*>::iterator it = root_windows_.begin(); | |
840 // In mirror mode, both displays share the same root window so | |
841 // both display ids are associated with the root window. | |
842 for (; it != root_windows_.end(); it++) | |
843 it->second->GetHost()->UpdateDisplayID(display1_id, display2_id); | |
844 // Update the associated display id and TouchCTM in device manager | |
845 // if the display is a touch device. | |
846 if (display1.touch_device_id() != 0) { | |
847 device_manager->MapTouchDeviceToDisplay(display1.touch_device_id(), | |
848 display1.id()); | |
849 device_manager->SetTouchCTM(display1.touch_device_id(), | |
850 GetMirrorModeTouchCTM(display1)); | |
851 } | |
852 if (display2.touch_device_id() != 0) { | |
853 device_manager->MapTouchDeviceToDisplay(display2.touch_device_id(), | |
854 display2.id()); | |
855 device_manager->SetTouchCTM(display2.touch_device_id(), | |
856 GetMirrorModeTouchCTM(display2)); | |
857 } | |
858 return; | |
859 } | |
860 | |
861 if (output_state == ui::OUTPUT_STATE_DUAL_EXTENDED) { | |
862 std::map<int64, aura::Window*>::iterator it = root_windows_.begin(); | |
863 // In extended mode, each display has one associated root window. | |
864 for (; it != root_windows_.end(); it++) { | |
865 if (it->first == display1_id) { | |
866 it->second->GetHost()->UpdateDisplayID(display1_id, | |
867 gfx::Display::kInvalidDisplayID); | |
868 } else if (it->first == display2_id) { | |
869 it->second->GetHost()->UpdateDisplayID(display2_id, | |
870 gfx::Display::kInvalidDisplayID); | |
871 } | |
872 } | |
873 // Update the associated display id and TouchCTM in device manager | |
874 // if the display is a touch device. | |
875 if (display1.touch_device_id() != 0) { | |
876 device_manager->MapTouchDeviceToDisplay(display1.touch_device_id(), | |
877 display1.id()); | |
878 device_manager->SetTouchCTM(display1.touch_device_id(), | |
879 GetExtendedModeTouchCTM(display1, display2)); | |
880 } | |
881 if (display2.touch_device_id() != 0) { | |
882 device_manager->MapTouchDeviceToDisplay(display2.touch_device_id(), | |
883 display2.id()); | |
884 device_manager->SetTouchCTM(display2.touch_device_id(), | |
885 GetExtendedModeTouchCTM(display2, display1)); | |
886 } | |
887 return; | |
888 } | |
889 | |
890 // Single display mode. The root window has one associated display id. | |
891 std::map<int64, aura::Window*>::iterator it = root_windows_.begin(); | |
892 for (; it != root_windows_.end(); it++) { | |
893 if (it->first == single_display.id()) { | |
894 it->second->GetHost()->UpdateDisplayID(single_display.id(), | |
895 gfx::Display::kInvalidDisplayID); | |
896 } | |
897 } | |
898 // If the display is a touch display, we add a deafult TouchCTM to the | |
899 // according root window. | |
900 if (single_display.touch_device_id() != 0) { | |
901 device_manager->MapTouchDeviceToDisplay(single_display.touch_device_id(), | |
902 single_display.id()); | |
903 device_manager->SetTouchCTM(single_display.touch_device_id(), | |
904 ui::TouchCTM()); | |
905 } | |
906 #endif | |
695 } | 907 } |
696 | 908 |
697 aura::WindowTreeHost* DisplayController::AddWindowTreeHostForDisplay( | 909 aura::WindowTreeHost* DisplayController::AddWindowTreeHostForDisplay( |
698 const gfx::Display& display) { | 910 const gfx::Display& display) { |
699 static int host_count = 0; | 911 static int host_count = 0; |
700 const internal::DisplayInfo& display_info = | 912 const internal::DisplayInfo& display_info = |
701 GetDisplayManager()->GetDisplayInfo(display.id()); | 913 GetDisplayManager()->GetDisplayInfo(display.id()); |
702 const gfx::Rect& bounds_in_native = display_info.bounds_in_native(); | 914 const gfx::Rect& bounds_in_native = display_info.bounds_in_native(); |
703 aura::WindowTreeHost* host = | 915 aura::WindowTreeHost* host = |
704 Shell::GetInstance()->window_tree_host_factory()->CreateWindowTreeHost( | 916 Shell::GetInstance()->window_tree_host_factory()->CreateWindowTreeHost( |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
742 std::string name = | 954 std::string name = |
743 root_windows[i] == primary ? "aura_root_0" : "aura_root_x"; | 955 root_windows[i] == primary ? "aura_root_0" : "aura_root_x"; |
744 gfx::AcceleratedWidget xwindow = | 956 gfx::AcceleratedWidget xwindow = |
745 root_windows[i]->GetHost()->GetAcceleratedWidget(); | 957 root_windows[i]->GetHost()->GetAcceleratedWidget(); |
746 XStoreName(gfx::GetXDisplay(), xwindow, name.c_str()); | 958 XStoreName(gfx::GetXDisplay(), xwindow, name.c_str()); |
747 } | 959 } |
748 #endif | 960 #endif |
749 } | 961 } |
750 | 962 |
751 } // namespace ash | 963 } // namespace ash |
OLD | NEW |