|
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/. */ |
|
5 |
|
6 #include "nsScreenManagerWin.h" |
|
7 #include "nsScreenWin.h" |
|
8 #include "gfxWindowsPlatform.h" |
|
9 #include "nsIWidget.h" |
|
10 |
|
11 |
|
12 BOOL CALLBACK CountMonitors ( HMONITOR, HDC, LPRECT, LPARAM ioCount ) ; |
|
13 |
|
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 } |
|
21 |
|
22 |
|
23 nsScreenManagerWin :: ~nsScreenManagerWin() |
|
24 { |
|
25 } |
|
26 |
|
27 |
|
28 // addref, release, QI |
|
29 NS_IMPL_ISUPPORTS(nsScreenManagerWin, nsIScreenManager) |
|
30 |
|
31 |
|
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; |
|
44 |
|
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. |
|
54 |
|
55 retScreen = new nsScreenWin(inScreen); |
|
56 mScreenList.AppendElement ( ScreenListItem ( inScreen, retScreen ) ); |
|
57 |
|
58 NS_IF_ADDREF(retScreen); |
|
59 return retScreen; |
|
60 } |
|
61 |
|
62 |
|
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 } |
|
80 |
|
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 }; |
|
92 |
|
93 HMONITOR genScreen = ::MonitorFromRect( &globalWindowBounds, MONITOR_DEFAULTTOPRIMARY ); |
|
94 |
|
95 *outScreen = CreateNewScreenObject ( genScreen ); // addrefs |
|
96 |
|
97 return NS_OK; |
|
98 |
|
99 } // ScreenForRect |
|
100 |
|
101 |
|
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; |
|
113 |
|
114 } // GetPrimaryScreen |
|
115 |
|
116 |
|
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); |
|
129 |
|
130 return TRUE; // continue the enumeration |
|
131 |
|
132 } // CountMonitors |
|
133 |
|
134 |
|
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 } |
|
152 |
|
153 return NS_OK; |
|
154 |
|
155 } // GetNumberOfScreens |
|
156 |
|
157 NS_IMETHODIMP |
|
158 nsScreenManagerWin::GetSystemDefaultScale(float *aDefaultScale) |
|
159 { |
|
160 *aDefaultScale = float(gfxWindowsPlatform::GetPlatform()->GetDPIScale()); |
|
161 return NS_OK; |
|
162 } |
|
163 |
|
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 } |