Index: ui/gfx/screen_win.h |
diff --git a/ui/gfx/screen_win.h b/ui/gfx/screen_win.h |
index b1488ae05bb850b9cfc4cfa762219b56d47ff5d0..fc746909acd5ba8f97c5ad0889903c515920100e 100644 |
--- a/ui/gfx/screen_win.h |
+++ b/ui/gfx/screen_win.h |
@@ -16,10 +16,89 @@ |
namespace gfx { |
+class Point; |
+class Rect; |
+class Size; |
+ |
+// Windows historically has had a hard time handling displays of DPIs higher |
+// than 96. Handling multiple DPI displays means we have to deal with Windows' |
+// monitor physical coordinates and map into Chrome's DIP coordinates. |
+// |
+// To do this, ScreenWin reasons over monitors as a tree using the primary |
+// monitor as the root. Any monitor touching this root is considered a child. |
+// Subsequent generations are formed similarly, having preferring parents that |
+// are discovered earlier. As a result, if there is a monitor that touches two |
+// other monitors, the earliest discovered monitor is the parent. |
+// |
+// This also presumes that all monitors are connected components. Windows, by UI |
+// construction restricts the layout of monitors to connected components. |
+// |
+// All scaling transformations are performed with respect to this physical-DIP |
+// mapping. |
+// |
+// Note that this does not handle cases where a scaled display may have |
+// insufficent room to lay out its children. In these cases, a DIP point could |
+// map to multiple screen points due to overlap. The first discovered screen |
+// will take precedence. |
class GFX_EXPORT ScreenWin : public Screen { |
public: |
ScreenWin(); |
- ~ScreenWin() override; |
+ virtual ~ScreenWin() override; |
+ |
+ // Converts a screen pixel point to a DIP point. |
+ // The DPI scale is performed relative to the display containing the screen |
+ // pixel point maintaining a constant origin on both Screen and DIP (same as |
+ // Windows). |
+ static Point ScreenToDIPPoint(const Point& pixel_point); |
+ |
+ // Converts a DIP point to a screen pixel point. |
+ // The DPI scale is performed relative to the display containing the DIP point |
+ // maintaining a constant origin on both Screen and DIP (same as Windows). |
+ static Point DIPToScreenPoint(const Point& dip_point); |
+ |
+ // Converts a client pixel point relative to |hwnd| to a DIP point. |
+ // The DPI scale is performed relative to |hwnd| using an origin of (0, 0). |
+ static Point ClientToDIPPoint(HWND hwnd, const Point& client_point); |
+ |
+ // Converts a client DIP point relative to |hwnd| to a client pixel point. |
+ // The DPI scale is performed relative to |hwnd| using an origin of (0, 0). |
+ static Point DIPToClientPoint(HWND hwnd, const Point& dip_point); |
+ |
+ // WARNING: there is no right way to scale sizes and rects. The implementation |
+ // of these strives to maintain a constant size by scaling the size |
+ // independent of the origin. An alternative is to get the enclosing rect, |
+ // which is the right way for some situations. Understand which you need |
+ // before blindly assuming this is the right way. |
+ |
+ // Converts a screen rect to a DIP rect. |
+ // The DPI scale is performed relative to the display nearest to |hwnd| |
+ // maintaining a constant origin on both Screen and DIP (same as Windows). |
+ // If |hwnd| is null, scaling will be performed to the display nearest to |
+ // |pixel_bounds|. |
+ static Rect ScreenToDIPRect(HWND hwnd, const Rect& pixel_bounds); |
+ |
+ // Converts a DIP rect to a screen rect. |
+ // The DPI scale is performed relative to the display nearest to |hwnd| |
+ // maintaining a constant origin on both Screen and DIP (same as Windows). |
+ // If |hwnd| is null, scaling will be performed to the display nearest to |
+ // |dip_bounds|. |
+ static Rect DIPToScreenRect(HWND hwnd, const Rect& dip_bounds); |
+ |
+ // Converts a client rect to a DIP rect. |
+ // The DPI scale is performed relative to |hwnd| using an origin of (0, 0). |
+ static Rect ClientToDIPRect(HWND hwnd, const Rect& pixel_bounds); |
+ |
+ // Converts a DIP rect to a client rect. |
+ // The DPI scale is performed relative to |hwnd| using an origin of (0, 0). |
+ static Rect DIPToClientRect(HWND hwnd, const Rect& dip_bounds); |
+ |
+ // Converts a screen size to a DIP size. |
+ // The DPI scale is performed relative to the display nearest to |hwnd|. |
+ static Size ScreenToDIPSize(HWND hwnd, const Size& size_in_pixels); |
+ |
+ // Converts a DIP size to a screen size. |
+ // The DPI scale is performed relative to the display nearest to |hwnd|. |
+ static Size DIPToScreenSize(HWND hwnd, const Size& dip_size); |
// Returns the HWND associated with the NativeView. |
virtual HWND GetHWNDFromNativeView(NativeView window) const; |
@@ -28,7 +107,36 @@ class GFX_EXPORT ScreenWin : public Screen { |
virtual NativeWindow GetNativeWindowFromHWND(HWND hwnd) const; |
protected: |
- // Overridden from gfx::Screen: |
+ // Holds the parameters used to create a gfx::DisplayWin. |
+ class GFX_EXPORT DisplayInfo { |
+ public: |
+ DisplayInfo(HMONITOR monitor, float device_scale_factor); |
+ DisplayInfo(const MONITORINFOEX& monitor_info, |
+ gfx::Display::Rotation rotation, |
+ float device_scale_factor); |
+ |
+ int64_t id() const { return id_; } |
+ gfx::Display::Rotation rotation() const { return rotation_; } |
+ const gfx::Rect& screen_rect() const { return screen_rect_; } |
+ const gfx::Rect& screen_work_rect() const { return screen_work_rect_; } |
+ float device_scale_factor() const { return device_scale_factor_; } |
+ |
+ private: |
+ void InitializeFromMonitorInfo(const MONITORINFOEX& monitor_info); |
+ |
+ int64_t id_; |
+ gfx::Display::Rotation rotation_; |
+ gfx::Rect screen_rect_; |
+ gfx::Rect screen_work_rect_; |
+ float device_scale_factor_; |
+ }; |
+ |
+ // For Unit Tests. |
+ explicit ScreenWin(const std::vector<DisplayInfo>& display_infos); |
+ |
+ static int64_t HashDeviceName(const wchar_t* device_name); |
+ |
+ // Overridden from gfx::Screen. |
gfx::Point GetCursorScreenPoint() override; |
gfx::NativeWindow GetWindowUnderCursor() override; |
gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override; |
@@ -40,23 +148,53 @@ class GFX_EXPORT ScreenWin : public Screen { |
gfx::Display GetPrimaryDisplay() const override; |
void AddObserver(DisplayObserver* observer) override; |
void RemoveObserver(DisplayObserver* observer) override; |
+ gfx::Rect ScreenToDIPRectInWindow( |
+ NativeView view, const gfx::Rect& screen_rect) const override; |
+ gfx::Rect DIPToScreenRectInWindow( |
+ NativeView view, const gfx::Rect& dip_rect) const override; |
private: |
- FRIEND_TEST_ALL_PREFIXES(ScreenWinTest, SingleDisplay1x); |
- FRIEND_TEST_ALL_PREFIXES(ScreenWinTest, SingleDisplay2x); |
+ friend class TestScreenWinInitializer; |
+ |
+ // A gfx::Display that knows about its physical bounds. |
+ class DisplayWin; |
+ |
+ static DisplayWin GetDisplayNearestHWND(HWND hwnd); |
+ static DisplayWin GetDisplayNearestScreenRect(const Rect& screen_rect); |
+ static DisplayWin GetDisplayNearestScreenPoint(const Point& screen_point); |
+ static DisplayWin GetDisplayNearestDIPRect(const Rect& rect); |
+ static DisplayWin GetDisplayNearestDIPPoint(const Point& dip_point); |
+ static float GetScaleFactorForHWND(HWND hwnd); |
+ static float GetScaleFactorForScreenPoint(const Point& screen_point); |
+ static std::vector<DisplayInfo>::const_iterator FindTouchingDisplayInfo( |
+ const DisplayWin& display, const std::vector<DisplayInfo>& display_infos); |
+ static std::vector<DisplayWin> GetDisplaysFromDisplayInfos( |
+ const std::vector<DisplayInfo>& display_infos); |
+ static std::vector<DisplayWin> GetDisplayWins(); |
+ static BOOL CALLBACK EnumMonitorCallback(HMONITOR monitor, |
+ HDC hdc, |
+ LPRECT rect, |
+ LPARAM data); |
void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); |
- static std::vector<gfx::Display> GetDisplaysForMonitorInfos( |
- const std::vector<MONITORINFOEX>& monitor_infos); |
+ // For Unit Tests. |
+ virtual MONITORINFOEX MonitorInfoFromScreenPoint( |
+ const gfx::Point& screen_point) const; |
+ virtual MONITORINFOEX MonitorInfoFromScreenRect(const gfx::Rect& screen_rect) |
+ const; |
+ virtual MONITORINFOEX MonitorInfoFromWindow(HWND hwnd) const; |
+ virtual HWND GetRootWindow(HWND hwnd) const; |
+ |
+ DisplayWin GetDisplayWin(const MONITORINFOEX& monitor_info) const; |
// Helper implementing the DisplayObserver handling. |
gfx::DisplayChangeNotifier change_notifier_; |
scoped_ptr<SingletonHwndObserver> singleton_hwnd_observer_; |
- // Current list of displays. |
- std::vector<gfx::Display> displays_; |
+ // Current list of DisplayWins. |
+ std::vector<DisplayWin> display_wins_; |
DISALLOW_COPY_AND_ASSIGN(ScreenWin); |
}; |