| 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 11 matching lines...) Expand all Loading... |
| 22 #include "ash/shell.h" | 22 #include "ash/shell.h" |
| 23 #include "ash/shell_delegate.h" | 23 #include "ash/shell_delegate.h" |
| 24 #include "ash/wm/coordinate_conversion.h" | 24 #include "ash/wm/coordinate_conversion.h" |
| 25 #include "base/command_line.h" | 25 #include "base/command_line.h" |
| 26 #include "base/strings/stringprintf.h" | 26 #include "base/strings/stringprintf.h" |
| 27 #include "ui/aura/client/activation_client.h" | 27 #include "ui/aura/client/activation_client.h" |
| 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/touch_ctm.h" |
| 32 #include "ui/aura/window.h" | 33 #include "ui/aura/window.h" |
| 33 #include "ui/aura/window_event_dispatcher.h" | 34 #include "ui/aura/window_event_dispatcher.h" |
| 34 #include "ui/aura/window_property.h" | 35 #include "ui/aura/window_property.h" |
| 35 #include "ui/aura/window_tracker.h" | 36 #include "ui/aura/window_tracker.h" |
| 36 #include "ui/compositor/compositor.h" | 37 #include "ui/compositor/compositor.h" |
| 37 #include "ui/compositor/compositor_vsync_manager.h" | 38 #include "ui/compositor/compositor_vsync_manager.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) |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 internal::DisplayMode mode; | 127 internal::DisplayMode mode; |
| 127 if (GetDisplayManager()->GetSelectedModeForDisplayId(display.id(), &mode) && | 128 if (GetDisplayManager()->GetSelectedModeForDisplayId(display.id(), &mode) && |
| 128 mode.refresh_rate > 0.0f) { | 129 mode.refresh_rate > 0.0f) { |
| 129 dispatcher->host()->compositor()->vsync_manager()-> | 130 dispatcher->host()->compositor()->vsync_manager()-> |
| 130 SetAuthoritativeVSyncInterval( | 131 SetAuthoritativeVSyncInterval( |
| 131 base::TimeDelta::FromMicroseconds( | 132 base::TimeDelta::FromMicroseconds( |
| 132 base::Time::kMicrosecondsPerSecond / mode.refresh_rate)); | 133 base::Time::kMicrosecondsPerSecond / mode.refresh_rate)); |
| 133 } | 134 } |
| 134 } | 135 } |
| 135 | 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 // So to compute CTM, for monitor1, we have |
| 148 // x_scale = (1366 - 1) / (2560 - 1) |
| 149 // x_offset = 0 |
| 150 // y_scale = (768 - 1) / (2428 - 1) |
| 151 // y_offset = 0 |
| 152 // For Monitor 2, we have |
| 153 // x_scale = (2560 - 1) / (2560 - 1) |
| 154 // x_offset = 0 |
| 155 // y_scale = (1600 - 1) / (2428 - 1) |
| 156 // y_offset = 828 |
| 157 // See DisplayControllerTest.TouchCTMExtendedMode for the test. |
| 158 aura::TouchCTM GetExtendedModeTouchCTM( |
| 159 const internal::DisplayInfo& touch_display, |
| 160 const internal::DisplayInfo& second_display) { |
| 161 aura::TouchCTM ctm; |
| 162 float width = touch_display.bounds_in_native().width(); |
| 163 float height = touch_display.bounds_in_native().height(); |
| 164 float origin_x = touch_display.bounds_in_native().origin().x(); |
| 165 float origin_y = touch_display.bounds_in_native().origin().y(); |
| 166 float framebuffer_width = std::max<int>( |
| 167 width, second_display.bounds_in_native().width()); |
| 168 float framebuffer_height = |
| 169 height + chromeos::OutputConfigurator::kVerticalGap + |
| 170 second_display.bounds_in_native().height(); |
| 171 ctm.x_scale = (width - 1) / (framebuffer_width - 1); |
| 172 ctm.x_offset = origin_x; |
| 173 ctm.y_scale = (height -1) / (framebuffer_height - 1); |
| 174 ctm.y_offset = origin_y; |
| 175 return ctm; |
| 176 } |
| 177 |
| 178 // This function computes the mirror mode TouchCTM for |touch_display|. |
| 179 // When internal monitor is applied a resolution that does not have |
| 180 // the same aspect ratio as its native resolution, there would be |
| 181 // blank regions in the letterboxing/pillarboxing mode. |
| 182 // The TouchCTM will make sure the touch events on the blank region |
| 183 // have negative coordinates and touch events within the chrome region |
| 184 // have the correct positive coordinates. |
| 185 aura::TouchCTM GetMirrorModeTouchCTM( |
| 186 const internal::DisplayInfo& touch_display) { |
| 187 aura::TouchCTM ctm; |
| 188 // For external monitor, assuming no letterboxing or pillarboxing |
| 189 // and just use the default TouchCTM. |
| 190 if (touch_display.id() != gfx::Display::InternalDisplayId()) |
| 191 return ctm; |
| 192 |
| 193 float mirror_width = touch_display.bounds_in_native().width(); |
| 194 float mirror_height = touch_display.bounds_in_native().height(); |
| 195 float native_width = 0; |
| 196 float native_height = 0; |
| 197 |
| 198 internal::DisplayMode native_mode; |
| 199 std::vector<internal::DisplayMode> modes = touch_display.display_modes(); |
| 200 for (size_t i = 0; i < modes.size(); i++) { |
| 201 if (modes[i].native) { |
| 202 native_width = modes[i].size.width(); |
| 203 native_height = modes[i].size.height(); |
| 204 break; |
| 205 } |
| 206 } |
| 207 |
| 208 if (native_height == 0.0 || mirror_height == 0.0 || |
| 209 native_width == 0.0 || mirror_width == 0.0) |
| 210 return ctm; |
| 211 |
| 212 float native_ar = static_cast<float>(native_width) / |
| 213 static_cast<float>(native_height); |
| 214 float mirror_ar = static_cast<float>(mirror_width) / |
| 215 static_cast<float>(mirror_height); |
| 216 |
| 217 if (mirror_ar > native_ar) { // Letterboxing |
| 218 ctm.x_scale = 1.0; |
| 219 ctm.x_offset = 0.0; |
| 220 ctm.y_scale = mirror_ar / native_ar; |
| 221 ctm.y_offset = (1.0 / mirror_ar - 1.0 / native_ar) * 0.5 * mirror_width; |
| 222 return ctm; |
| 223 } |
| 224 |
| 225 if (native_ar > mirror_ar) { // Pillarboxing |
| 226 ctm.y_scale = 1.0; |
| 227 ctm.y_offset = 0.0; |
| 228 ctm.x_scale = native_ar / mirror_ar; |
| 229 ctm.x_offset = (mirror_ar - native_ar) * 0.5 * mirror_height; |
| 230 return ctm; |
| 231 } |
| 232 |
| 233 return ctm; // Same aspect ratio - return identity |
| 234 } |
| 235 #endif |
| 236 |
| 136 } // namespace | 237 } // namespace |
| 137 | 238 |
| 138 namespace internal { | 239 namespace internal { |
| 139 | 240 |
| 140 // A utility class to store/restore focused/active window | 241 // A utility class to store/restore focused/active window |
| 141 // when the display configuration has changed. | 242 // when the display configuration has changed. |
| 142 class FocusActivationStore { | 243 class FocusActivationStore { |
| 143 public: | 244 public: |
| 144 FocusActivationStore() | 245 FocusActivationStore() |
| 145 : activation_client_(NULL), | 246 : activation_client_(NULL), |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 DCHECK(controller); | 375 DCHECK(controller); |
| 275 delete controller; | 376 delete controller; |
| 276 } | 377 } |
| 277 } | 378 } |
| 278 | 379 |
| 279 void DisplayController::InitPrimaryDisplay() { | 380 void DisplayController::InitPrimaryDisplay() { |
| 280 const gfx::Display& primary_candidate = | 381 const gfx::Display& primary_candidate = |
| 281 GetDisplayManager()->GetPrimaryDisplayCandidate(); | 382 GetDisplayManager()->GetPrimaryDisplayCandidate(); |
| 282 primary_display_id = primary_candidate.id(); | 383 primary_display_id = primary_candidate.id(); |
| 283 AddRootWindowForDisplay(primary_candidate); | 384 AddRootWindowForDisplay(primary_candidate); |
| 385 UpdateTouchCTM(); |
| 284 } | 386 } |
| 285 | 387 |
| 286 void DisplayController::InitSecondaryDisplays() { | 388 void DisplayController::InitSecondaryDisplays() { |
| 287 internal::DisplayManager* display_manager = GetDisplayManager(); | 389 internal::DisplayManager* display_manager = GetDisplayManager(); |
| 288 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { | 390 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { |
| 289 const gfx::Display& display = display_manager->GetDisplayAt(i); | 391 const gfx::Display& display = display_manager->GetDisplayAt(i); |
| 290 if (primary_display_id != display.id()) { | 392 if (primary_display_id != display.id()) { |
| 291 aura::WindowEventDispatcher* dispatcher = | 393 aura::WindowEventDispatcher* dispatcher = |
| 292 AddRootWindowForDisplay(display); | 394 AddRootWindowForDisplay(display); |
| 293 internal::RootWindowController::CreateForSecondaryDisplay(dispatcher); | 395 internal::RootWindowController::CreateForSecondaryDisplay(dispatcher); |
| 294 } | 396 } |
| 295 } | 397 } |
| 296 UpdateHostWindowNames(); | 398 UpdateHostWindowNames(); |
| 399 UpdateTouchCTM(); |
| 297 } | 400 } |
| 298 | 401 |
| 299 void DisplayController::AddObserver(Observer* observer) { | 402 void DisplayController::AddObserver(Observer* observer) { |
| 300 observers_.AddObserver(observer); | 403 observers_.AddObserver(observer); |
| 301 } | 404 } |
| 302 | 405 |
| 303 void DisplayController::RemoveObserver(Observer* observer) { | 406 void DisplayController::RemoveObserver(Observer* observer) { |
| 304 observers_.RemoveObserver(observer); | 407 observers_.RemoveObserver(observer); |
| 305 } | 408 } |
| 306 | 409 |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 // ignored. Happens when a) default layout's primary id | 797 // ignored. Happens when a) default layout's primary id |
| 695 // doesn't exist, or b) the primary_id has already been | 798 // doesn't exist, or b) the primary_id has already been |
| 696 // set to the same and didn't update it. | 799 // set to the same and didn't update it. |
| 697 layout_store->UpdatePrimaryDisplayId( | 800 layout_store->UpdatePrimaryDisplayId( |
| 698 pair, Shell::GetScreen()->GetPrimaryDisplay().id()); | 801 pair, Shell::GetScreen()->GetPrimaryDisplay().id()); |
| 699 } | 802 } |
| 700 } | 803 } |
| 701 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged()); | 804 FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged()); |
| 702 UpdateHostWindowNames(); | 805 UpdateHostWindowNames(); |
| 703 EnsurePointerInDisplays(); | 806 EnsurePointerInDisplays(); |
| 807 UpdateTouchCTM(); |
| 808 } |
| 809 |
| 810 void DisplayController::UpdateTouchCTM() { |
| 811 #if defined(OS_CHROMEOS) && defined(USE_X11) |
| 812 // Clear all the old TouchCTM on all the root windows. |
| 813 std::map<int64, aura::Window*>::iterator it = root_windows_.begin(); |
| 814 for (; it != root_windows_.end(); it++) |
| 815 it->second->GetDispatcher()->host()->ClearTouchCTM(); |
| 816 |
| 817 ui::OutputState output_state = |
| 818 Shell::GetInstance()->output_configurator()->output_state(); |
| 819 if (output_state == ui::OUTPUT_STATE_DUAL_MIRROR || |
| 820 output_state == ui::OUTPUT_STATE_DUAL_EXTENDED) { |
| 821 DisplayIdPair id_pair = GetDisplayManager()->GetCurrentDisplayIdPair(); |
| 822 internal::DisplayInfo display1 = |
| 823 GetDisplayManager()->GetDisplayInfo(id_pair.first); |
| 824 internal::DisplayInfo display2 = |
| 825 GetDisplayManager()->GetDisplayInfo(id_pair.second); |
| 826 // For mirror mode, there is one root window shared by two displays. |
| 827 // We add the TouchCTM of the touch display to the only one root window. |
| 828 // For extended mode, there is one root window for each display. |
| 829 // We add the TouchCTM of the touch display to the according root window. |
| 830 if (display1.id() != gfx::Display::kInvalidDisplayID && |
| 831 display1.touch_device_id() != 0) { |
| 832 std::map<int64, aura::Window*>::iterator it = root_windows_.begin(); |
| 833 for (; it != root_windows_.end(); it++) { |
| 834 if (output_state == ui::OUTPUT_STATE_DUAL_MIRROR) { |
| 835 it->second->GetDispatcher()->host()->SetTouchCTM( |
| 836 display1.touch_device_id(), |
| 837 GetMirrorModeTouchCTM(display1)); |
| 838 } else if (output_state == ui::OUTPUT_STATE_DUAL_EXTENDED && |
| 839 it->first == display1.id()) { |
| 840 it->second->GetDispatcher()->host()->SetTouchCTM( |
| 841 display1.touch_device_id(), |
| 842 GetExtendedModeTouchCTM(display1, display2)); |
| 843 } |
| 844 } |
| 845 } |
| 846 |
| 847 if (display2.id() != gfx::Display::kInvalidDisplayID && |
| 848 display2.touch_device_id() != 0) { |
| 849 std::map<int64, aura::Window*>::iterator it = root_windows_.begin(); |
| 850 for (; it != root_windows_.end(); it++) { |
| 851 if (output_state == ui::OUTPUT_STATE_DUAL_MIRROR) { |
| 852 it->second->GetDispatcher()->host()->SetTouchCTM( |
| 853 display2.touch_device_id(), |
| 854 GetMirrorModeTouchCTM(display2)); |
| 855 } else if (output_state == ui::OUTPUT_STATE_DUAL_EXTENDED && |
| 856 it->first == display2.id()) { |
| 857 it->second->GetDispatcher()->host()->SetTouchCTM( |
| 858 display2.touch_device_id(), |
| 859 GetExtendedModeTouchCTM(display2, display1)); |
| 860 } |
| 861 } |
| 862 } |
| 863 } else { |
| 864 // Single display mode. If the display is a touch display, we add a deafult |
| 865 // TouchCTM to the according root window. |
| 866 int64 display_id = GetDisplayManager()->first_display_id(); |
| 867 if (display_id != gfx::Display::kInvalidDisplayID) { |
| 868 internal::DisplayInfo display = |
| 869 GetDisplayManager()->GetDisplayInfo(display_id); |
| 870 std::map<int64, aura::Window*>::iterator it = root_windows_.begin(); |
| 871 for (; it != root_windows_.end(); it++) { |
| 872 if (it->first == display_id && display.touch_device_id() != 0) { |
| 873 it->second->GetDispatcher()->host()->SetTouchCTM( |
| 874 display.touch_device_id(), |
| 875 aura::TouchCTM()); |
| 876 } |
| 877 } |
| 878 } |
| 879 } |
| 880 #endif |
| 704 } | 881 } |
| 705 | 882 |
| 706 aura::WindowEventDispatcher* DisplayController::AddRootWindowForDisplay( | 883 aura::WindowEventDispatcher* DisplayController::AddRootWindowForDisplay( |
| 707 const gfx::Display& display) { | 884 const gfx::Display& display) { |
| 708 static int dispatcher_count = 0; | 885 static int dispatcher_count = 0; |
| 709 const internal::DisplayInfo& display_info = | 886 const internal::DisplayInfo& display_info = |
| 710 GetDisplayManager()->GetDisplayInfo(display.id()); | 887 GetDisplayManager()->GetDisplayInfo(display.id()); |
| 711 const gfx::Rect& bounds_in_native = display_info.bounds_in_native(); | 888 const gfx::Rect& bounds_in_native = display_info.bounds_in_native(); |
| 712 aura::WindowEventDispatcher::CreateParams params(bounds_in_native); | 889 aura::WindowEventDispatcher::CreateParams params(bounds_in_native); |
| 713 params.host = Shell::GetInstance()->window_tree_host_factory()-> | 890 params.host = Shell::GetInstance()->window_tree_host_factory()-> |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 std::string name = | 932 std::string name = |
| 756 root_windows[i] == primary ? "aura_root_0" : "aura_root_x"; | 933 root_windows[i] == primary ? "aura_root_0" : "aura_root_x"; |
| 757 gfx::AcceleratedWidget xwindow = | 934 gfx::AcceleratedWidget xwindow = |
| 758 root_windows[i]->GetDispatcher()->host()->GetAcceleratedWidget(); | 935 root_windows[i]->GetDispatcher()->host()->GetAcceleratedWidget(); |
| 759 XStoreName(gfx::GetXDisplay(), xwindow, name.c_str()); | 936 XStoreName(gfx::GetXDisplay(), xwindow, name.c_str()); |
| 760 } | 937 } |
| 761 #endif | 938 #endif |
| 762 } | 939 } |
| 763 | 940 |
| 764 } // namespace ash | 941 } // namespace ash |
| OLD | NEW |