Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsScreenManagerWin.h"
7 #include "nsScreenWin.h"
8 #include "gfxWindowsPlatform.h"
9 #include "nsIWidget.h"
12 BOOL CALLBACK CountMonitors ( HMONITOR, HDC, LPRECT, LPARAM ioCount ) ;
14 nsScreenManagerWin :: nsScreenManagerWin ( )
15 : mNumberOfScreens(0)
16 {
17 // nothing to do. I guess we could cache a bunch of information
18 // here, but we want to ask the device at runtime in case anything
19 // has changed.
20 }
23 nsScreenManagerWin :: ~nsScreenManagerWin()
24 {
25 }
28 // addref, release, QI
29 NS_IMPL_ISUPPORTS(nsScreenManagerWin, nsIScreenManager)
32 //
33 // CreateNewScreenObject
34 //
35 // Utility routine. Creates a new screen object from the given device handle
36 //
37 // NOTE: For this "single-monitor" impl, we just always return the cached primary
38 // screen. This should change when a multi-monitor impl is done.
39 //
40 nsIScreen*
41 nsScreenManagerWin :: CreateNewScreenObject ( HMONITOR inScreen )
42 {
43 nsIScreen* retScreen = nullptr;
45 // look through our screen list, hoping to find it. If it's not there,
46 // add it and return the new one.
47 for ( unsigned i = 0; i < mScreenList.Length(); ++i ) {
48 ScreenListItem& curr = mScreenList[i];
49 if ( inScreen == curr.mMon ) {
50 NS_IF_ADDREF(retScreen = curr.mScreen.get());
51 return retScreen;
52 }
53 } // for each screen.
55 retScreen = new nsScreenWin(inScreen);
56 mScreenList.AppendElement ( ScreenListItem ( inScreen, retScreen ) );
58 NS_IF_ADDREF(retScreen);
59 return retScreen;
60 }
63 //
64 // ScreenForRect
65 //
66 // Returns the screen that contains the rectangle. If the rect overlaps
67 // multiple screens, it picks the screen with the greatest area of intersection.
68 //
69 // The coordinates are in pixels (not twips) and in logical screen coordinates.
70 //
71 NS_IMETHODIMP
72 nsScreenManagerWin :: ScreenForRect ( int32_t inLeft, int32_t inTop, int32_t inWidth, int32_t inHeight,
73 nsIScreen **outScreen )
74 {
75 if ( !(inWidth || inHeight) ) {
76 NS_WARNING ( "trying to find screen for sizeless window, using primary monitor" );
77 *outScreen = CreateNewScreenObject ( nullptr ); // addrefs
78 return NS_OK;
79 }
81 // convert coordinates from logical to device pixels for MonitorFromRect
82 double dpiScale = nsIWidget::DefaultScaleOverride();
83 if (dpiScale <= 0.0) {
84 dpiScale = gfxWindowsPlatform::GetPlatform()->GetDPIScale();
85 }
86 RECT globalWindowBounds = {
87 NSToIntRound(dpiScale * inLeft),
88 NSToIntRound(dpiScale * inTop),
89 NSToIntRound(dpiScale * (inLeft + inWidth)),
90 NSToIntRound(dpiScale * (inTop + inHeight))
91 };
93 HMONITOR genScreen = ::MonitorFromRect( &globalWindowBounds, MONITOR_DEFAULTTOPRIMARY );
95 *outScreen = CreateNewScreenObject ( genScreen ); // addrefs
97 return NS_OK;
99 } // ScreenForRect
102 //
103 // GetPrimaryScreen
104 //
105 // The screen with the menubar/taskbar. This shouldn't be needed very
106 // often.
107 //
108 NS_IMETHODIMP
109 nsScreenManagerWin :: GetPrimaryScreen(nsIScreen** aPrimaryScreen)
110 {
111 *aPrimaryScreen = CreateNewScreenObject ( nullptr ); // addrefs
112 return NS_OK;
114 } // GetPrimaryScreen
117 //
118 // CountMonitors
119 //
120 // Will be called once for every monitor in the system. Just
121 // increments the parameter, which holds a ptr to a PRUin32 holding the
122 // count up to this point.
123 //
124 BOOL CALLBACK
125 CountMonitors ( HMONITOR, HDC, LPRECT, LPARAM ioParam )
126 {
127 uint32_t* countPtr = reinterpret_cast<uint32_t*>(ioParam);
128 ++(*countPtr);
130 return TRUE; // continue the enumeration
132 } // CountMonitors
135 //
136 // GetNumberOfScreens
137 //
138 // Returns how many physical screens are available.
139 //
140 NS_IMETHODIMP
141 nsScreenManagerWin :: GetNumberOfScreens(uint32_t *aNumberOfScreens)
142 {
143 if ( mNumberOfScreens )
144 *aNumberOfScreens = mNumberOfScreens;
145 else {
146 uint32_t count = 0;
147 BOOL result = ::EnumDisplayMonitors(nullptr, nullptr, (MONITORENUMPROC)CountMonitors, (LPARAM)&count);
148 if (!result)
149 return NS_ERROR_FAILURE;
150 *aNumberOfScreens = mNumberOfScreens = count;
151 }
153 return NS_OK;
155 } // GetNumberOfScreens
157 NS_IMETHODIMP
158 nsScreenManagerWin::GetSystemDefaultScale(float *aDefaultScale)
159 {
160 *aDefaultScale = float(gfxWindowsPlatform::GetPlatform()->GetDPIScale());
161 return NS_OK;
162 }
164 NS_IMETHODIMP
165 nsScreenManagerWin :: ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen)
166 {
167 HMONITOR mon = MonitorFromWindow ((HWND) aWidget, MONITOR_DEFAULTTOPRIMARY);
168 *outScreen = CreateNewScreenObject (mon);
169 return NS_OK;
170 }