| 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 "ui/gfx/screen_win.h" | 5 #include "ui/gfx/screen_win.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 11 #include "ui/gfx/display.h" | 11 #include "ui/gfx/display.h" |
| 12 #include "ui/gfx/display_layout.h" |
| 13 #include "ui/gfx/display_layout_builder.h" |
| 12 #include "ui/gfx/geometry/point.h" | 14 #include "ui/gfx/geometry/point.h" |
| 13 #include "ui/gfx/geometry/point_conversions.h" | 15 #include "ui/gfx/geometry/point_conversions.h" |
| 14 #include "ui/gfx/geometry/rect.h" | 16 #include "ui/gfx/geometry/rect.h" |
| 15 #include "ui/gfx/geometry/size.h" | 17 #include "ui/gfx/geometry/size.h" |
| 16 #include "ui/gfx/geometry/vector2d.h" | 18 #include "ui/gfx/geometry/vector2d.h" |
| 17 #include "ui/gfx/win/display_info.h" | 19 #include "ui/gfx/win/display_info.h" |
| 18 #include "ui/gfx/win/dpi.h" | 20 #include "ui/gfx/win/dpi.h" |
| 19 #include "ui/gfx/win/rect_util.h" | 21 #include "ui/gfx/win/scaling_util.h" |
| 20 #include "ui/gfx/win/screen_win_display.h" | 22 #include "ui/gfx/win/screen_win_display.h" |
| 21 | 23 |
| 22 namespace { | 24 namespace { |
| 23 | 25 |
| 24 gfx::ScreenWin* g_screen_win_instance = nullptr; | 26 gfx::ScreenWin* g_screen_win_instance = nullptr; |
| 25 | 27 |
| 26 std::vector<gfx::win::DisplayInfo>::const_iterator FindTouchingDisplayInfo( | 28 std::vector<gfx::win::DisplayInfo>::const_iterator FindTouchingDisplayInfo( |
| 27 const gfx::win::ScreenWinDisplay& screen_win_display, | 29 const gfx::win::DisplayInfo& display_info, |
| 28 const std::vector<gfx::win::DisplayInfo>& display_infos) { | 30 const std::vector<gfx::win::DisplayInfo>& display_infos) { |
| 29 auto end = display_infos.end(); | 31 auto end = display_infos.end(); |
| 30 for (auto display_info_iter = display_infos.begin(); | 32 for (auto display_info_iter = display_infos.begin(); |
| 31 display_info_iter != end; | 33 display_info_iter != end; |
| 32 display_info_iter++) { | 34 display_info_iter++) { |
| 33 gfx::win::RectEdge edge = | 35 if (gfx::win::DisplayInfosTouch(display_info, *display_info_iter)) |
| 34 gfx::win::FindTouchingRectEdge(screen_win_display.pixel_bounds(), | |
| 35 display_info_iter->screen_rect()); | |
| 36 if (edge != gfx::win::RectEdge::NONE) | |
| 37 return display_info_iter; | 36 return display_info_iter; |
| 38 } | 37 } |
| 39 return end; | 38 return end; |
| 40 } | 39 } |
| 41 | 40 |
| 41 gfx::Display CreateDisplayFromDisplayInfo( |
| 42 const gfx::win::DisplayInfo& display_info) { |
| 43 gfx::Display display(display_info.id()); |
| 44 float scale_factor = display_info.device_scale_factor(); |
| 45 display.set_device_scale_factor(scale_factor); |
| 46 display.set_work_area( |
| 47 gfx::ScaleToEnclosingRect(display_info.screen_work_rect(), |
| 48 1.0f / scale_factor)); |
| 49 display.set_bounds(gfx::ScaleToEnclosingRect(display_info.screen_rect(), |
| 50 1.0f / scale_factor)); |
| 51 display.set_rotation(display_info.rotation()); |
| 52 return display; |
| 53 } |
| 54 |
| 42 // Windows historically has had a hard time handling displays of DPIs higher | 55 // Windows historically has had a hard time handling displays of DPIs higher |
| 43 // than 96. Handling multiple DPI displays means we have to deal with Windows' | 56 // than 96. Handling multiple DPI displays means we have to deal with Windows' |
| 44 // monitor physical coordinates and map into Chrome's DIP coordinates. | 57 // monitor physical coordinates and map into Chrome's DIP coordinates. |
| 45 // | 58 // |
| 46 // To do this, DisplayInfosToScreenWinDisplays reasons over monitors as a tree | 59 // To do this, DisplayInfosToScreenWinDisplays reasons over monitors as a tree |
| 47 // using the primary monitor as the root. Any monitor touching this root is | 60 // using the primary monitor as the root. Any monitor touching this root is |
| 48 // considered a child. Subsequent generations are formed similarly, having | 61 // considered a child. Subsequent generations are formed similarly, having |
| 49 // preferring parents that are discovered earlier. As a result, if there is a | 62 // preferring parents that are discovered earlier. As a result, if there is a |
| 50 // monitor that touches two other monitors, the earliest discovered monitor is | 63 // monitor that touches two other monitors, the earliest discovered monitor is |
| 51 // the parent. | 64 // the parent. |
| 52 // | 65 // |
| 53 // This also presumes that all monitors are connected components. Windows, by UI | 66 // This also presumes that all monitors are connected components. Windows, by UI |
| 54 // construction restricts the layout of monitors to connected components except | 67 // construction restricts the layout of monitors to connected components except |
| 55 // when DPI virtualization is happening. When this happens, we scale relative | 68 // when DPI virtualization is happening. When this happens, we scale relative |
| 56 // to (0, 0) like before. | 69 // to (0, 0) like before. |
| 57 // | 70 // |
| 58 // All subsequent scaling transformations are performed with respect to the | 71 // All subsequent scaling transformations are performed with respect to the |
| 59 // calculated physical-DIP mapping on ScreenWinDisplay. | 72 // calculated physical-DIP mapping on ScreenWinDisplay. |
| 60 // | 73 // |
| 61 // Note that this does not handle cases where a scaled display may have | 74 // Note that this does not handle cases where a scaled display may have |
| 62 // insufficient room to lay out its children. In these cases, a DIP point could | 75 // insufficient room to lay out its children. In these cases, a DIP point could |
| 63 // map to multiple screen points due to overlap. The first discovered screen | 76 // map to multiple screen points due to overlap. The first discovered screen |
| 64 // will take precedence. | 77 // will take precedence. |
| 65 std::vector<gfx::win::ScreenWinDisplay> DisplayInfosToScreenWinDisplays( | 78 std::vector<gfx::win::ScreenWinDisplay> DisplayInfosToScreenWinDisplays( |
| 66 const std::vector<gfx::win::DisplayInfo>& display_infos) { | 79 const std::vector<gfx::win::DisplayInfo>& display_infos) { |
| 67 std::vector<gfx::win::DisplayInfo> display_infos_remaining = display_infos; | |
| 68 | 80 |
| 69 // Seed the primary display to layout all the other displays. | 81 // DisplayLayout reasons over gfx::Displays and we need to add on pixel info |
| 70 std::vector<gfx::win::ScreenWinDisplay> screen_win_displays; | 82 // after it finishes its layout. As a result, create a vector of displays now |
| 71 for (auto current = display_infos_remaining.begin(); | 83 // for mutation to maintain this gfx::Display - gfx::win::DisplayInfo |
| 72 current != display_infos_remaining.end(); | 84 // correspondence to construct a ScreenWinDisplay. |
| 73 current++) { | 85 |
| 74 if (current->screen_rect().origin().IsOrigin()) { | 86 // Stage 1: display_infos <--> displays |
| 75 screen_win_displays.push_back(gfx::win::ScreenWinDisplay(*current)); | 87 // Stage 2: Layout |
| 76 display_infos_remaining.erase(current); | 88 // Stage 3: display_infos + displays -> ScreenWinDisplay |
| 89 |
| 90 // Find and extract the primary display. |
| 91 size_t primary_display_index = 0; |
| 92 int64_t primary_display_id = 0; |
| 93 const size_t num_displays = display_infos.size(); |
| 94 for (size_t i = 0; i < num_displays; ++i) { |
| 95 if (display_infos[i].screen_rect().origin().IsOrigin()) { |
| 96 primary_display_index = i; |
| 77 break; | 97 break; |
| 78 } | 98 } |
| 79 } | 99 } |
| 80 | 100 |
| 81 // Scale touching display_infos relative to each other. | 101 std::vector<gfx::win::DisplayInfo> display_infos_remaining = display_infos; |
| 82 // If the DisplayInfo count doesn't change through one cycle of the loop, it | 102 display_infos_remaining.erase( |
| 83 // either means we're done or we have non-touching DisplayInfos in the vector. | 103 display_infos_remaining.begin() + primary_display_id); |
| 104 std::vector<gfx::win::DisplayInfo> rooted_display_infos; |
| 105 rooted_display_infos.push_back(display_infos[primary_display_index]); |
| 106 gfx::DisplayLayoutBuilder builder(display_infos[primary_display_id].id()); |
| 107 |
| 84 size_t display_infos_at_cycle_start = 0; | 108 size_t display_infos_at_cycle_start = 0; |
| 85 while ((display_infos_remaining.size() > 0) && | 109 while ((display_infos_remaining.size() > 0) && |
| 86 (display_infos_remaining.size() != display_infos_at_cycle_start)) { | 110 (display_infos_remaining.size() != display_infos_at_cycle_start)) { |
| 87 display_infos_at_cycle_start = display_infos_remaining.size(); | 111 display_infos_at_cycle_start = display_infos_remaining.size(); |
| 88 for (const auto& screen_win_display : screen_win_displays) { | 112 for (const auto& rooted_display_info : rooted_display_infos) { |
| 89 auto display_info = FindTouchingDisplayInfo(screen_win_display, | 113 auto display_info_iter = FindTouchingDisplayInfo(rooted_display_info, |
| 90 display_infos_remaining); | 114 display_infos_remaining); |
| 91 if (display_info != display_infos_remaining.end()) { | 115 if (display_info_iter != display_infos_remaining.end()) { |
| 92 screen_win_displays.push_back( | 116 builder.AddDisplayPlacement( |
| 93 gfx::win::ScreenWinDisplay(screen_win_display, *display_info)); | 117 gfx::win::CalculateDisplayPlacement(rooted_display_info, |
| 94 display_infos_remaining.erase(display_info); | 118 *display_info_iter)); |
| 119 rooted_display_infos.push_back(*display_info_iter); |
| 120 display_infos_remaining.erase(display_info_iter); |
| 95 break; | 121 break; |
| 96 } | 122 } |
| 97 } | 123 } |
| 98 } | 124 } |
| 99 | 125 |
| 100 // Under Windows DPI virtualization, not all display_infos touch, so scale | 126 std::vector<gfx::Display> displays; |
| 101 // the remaining display infos relative to the origin. | 127 for (const auto& display_info : display_infos) |
| 102 for (const auto& display_info : display_infos_remaining) | 128 displays.push_back(CreateDisplayFromDisplayInfo(display_info)); |
| 103 screen_win_displays.push_back(gfx::win::ScreenWinDisplay(display_info)); | 129 |
| 130 scoped_ptr<gfx::DisplayLayout> layout(builder.Build()); |
| 131 layout->ApplyToDisplayList(&displays, nullptr, 0); |
| 132 |
| 133 std::vector<gfx::win::ScreenWinDisplay> screen_win_displays; |
| 134 for (size_t i = 0; i < num_displays; ++i) |
| 135 screen_win_displays.emplace_back(displays[i], display_infos[i]); |
| 104 | 136 |
| 105 return screen_win_displays; | 137 return screen_win_displays; |
| 106 } | 138 } |
| 107 | 139 |
| 108 std::vector<gfx::Display> ScreenWinDisplaysToDisplays( | 140 std::vector<gfx::Display> ScreenWinDisplaysToDisplays( |
| 109 const std::vector<gfx::win::ScreenWinDisplay>& screen_win_displays) { | 141 const std::vector<gfx::win::ScreenWinDisplay>& screen_win_displays) { |
| 110 std::vector<gfx::Display> displays; | 142 std::vector<gfx::Display> displays; |
| 111 for (const auto& screen_win_display : screen_win_displays) | 143 for (const auto& screen_win_display : screen_win_displays) |
| 112 displays.push_back(screen_win_display.display()); | 144 displays.push_back(screen_win_display.display()); |
| 113 | 145 |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 template <typename Getter, typename GetterType> | 516 template <typename Getter, typename GetterType> |
| 485 gfx::win::ScreenWinDisplay ScreenWin::GetScreenWinDisplayVia(Getter getter, | 517 gfx::win::ScreenWinDisplay ScreenWin::GetScreenWinDisplayVia(Getter getter, |
| 486 GetterType value) { | 518 GetterType value) { |
| 487 if (!g_screen_win_instance) | 519 if (!g_screen_win_instance) |
| 488 return gfx::win::ScreenWinDisplay(); | 520 return gfx::win::ScreenWinDisplay(); |
| 489 | 521 |
| 490 return (g_screen_win_instance->*getter)(value); | 522 return (g_screen_win_instance->*getter)(value); |
| 491 } | 523 } |
| 492 | 524 |
| 493 } // namespace gfx | 525 } // namespace gfx |
| OLD | NEW |