1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/windows/nsScreenManagerWin.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,170 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsScreenManagerWin.h" 1.10 +#include "nsScreenWin.h" 1.11 +#include "gfxWindowsPlatform.h" 1.12 +#include "nsIWidget.h" 1.13 + 1.14 + 1.15 +BOOL CALLBACK CountMonitors ( HMONITOR, HDC, LPRECT, LPARAM ioCount ) ; 1.16 + 1.17 +nsScreenManagerWin :: nsScreenManagerWin ( ) 1.18 + : mNumberOfScreens(0) 1.19 +{ 1.20 + // nothing to do. I guess we could cache a bunch of information 1.21 + // here, but we want to ask the device at runtime in case anything 1.22 + // has changed. 1.23 +} 1.24 + 1.25 + 1.26 +nsScreenManagerWin :: ~nsScreenManagerWin() 1.27 +{ 1.28 +} 1.29 + 1.30 + 1.31 +// addref, release, QI 1.32 +NS_IMPL_ISUPPORTS(nsScreenManagerWin, nsIScreenManager) 1.33 + 1.34 + 1.35 +// 1.36 +// CreateNewScreenObject 1.37 +// 1.38 +// Utility routine. Creates a new screen object from the given device handle 1.39 +// 1.40 +// NOTE: For this "single-monitor" impl, we just always return the cached primary 1.41 +// screen. This should change when a multi-monitor impl is done. 1.42 +// 1.43 +nsIScreen* 1.44 +nsScreenManagerWin :: CreateNewScreenObject ( HMONITOR inScreen ) 1.45 +{ 1.46 + nsIScreen* retScreen = nullptr; 1.47 + 1.48 + // look through our screen list, hoping to find it. If it's not there, 1.49 + // add it and return the new one. 1.50 + for ( unsigned i = 0; i < mScreenList.Length(); ++i ) { 1.51 + ScreenListItem& curr = mScreenList[i]; 1.52 + if ( inScreen == curr.mMon ) { 1.53 + NS_IF_ADDREF(retScreen = curr.mScreen.get()); 1.54 + return retScreen; 1.55 + } 1.56 + } // for each screen. 1.57 + 1.58 + retScreen = new nsScreenWin(inScreen); 1.59 + mScreenList.AppendElement ( ScreenListItem ( inScreen, retScreen ) ); 1.60 + 1.61 + NS_IF_ADDREF(retScreen); 1.62 + return retScreen; 1.63 +} 1.64 + 1.65 + 1.66 +// 1.67 +// ScreenForRect 1.68 +// 1.69 +// Returns the screen that contains the rectangle. If the rect overlaps 1.70 +// multiple screens, it picks the screen with the greatest area of intersection. 1.71 +// 1.72 +// The coordinates are in pixels (not twips) and in logical screen coordinates. 1.73 +// 1.74 +NS_IMETHODIMP 1.75 +nsScreenManagerWin :: ScreenForRect ( int32_t inLeft, int32_t inTop, int32_t inWidth, int32_t inHeight, 1.76 + nsIScreen **outScreen ) 1.77 +{ 1.78 + if ( !(inWidth || inHeight) ) { 1.79 + NS_WARNING ( "trying to find screen for sizeless window, using primary monitor" ); 1.80 + *outScreen = CreateNewScreenObject ( nullptr ); // addrefs 1.81 + return NS_OK; 1.82 + } 1.83 + 1.84 + // convert coordinates from logical to device pixels for MonitorFromRect 1.85 + double dpiScale = nsIWidget::DefaultScaleOverride(); 1.86 + if (dpiScale <= 0.0) { 1.87 + dpiScale = gfxWindowsPlatform::GetPlatform()->GetDPIScale(); 1.88 + } 1.89 + RECT globalWindowBounds = { 1.90 + NSToIntRound(dpiScale * inLeft), 1.91 + NSToIntRound(dpiScale * inTop), 1.92 + NSToIntRound(dpiScale * (inLeft + inWidth)), 1.93 + NSToIntRound(dpiScale * (inTop + inHeight)) 1.94 + }; 1.95 + 1.96 + HMONITOR genScreen = ::MonitorFromRect( &globalWindowBounds, MONITOR_DEFAULTTOPRIMARY ); 1.97 + 1.98 + *outScreen = CreateNewScreenObject ( genScreen ); // addrefs 1.99 + 1.100 + return NS_OK; 1.101 + 1.102 +} // ScreenForRect 1.103 + 1.104 + 1.105 +// 1.106 +// GetPrimaryScreen 1.107 +// 1.108 +// The screen with the menubar/taskbar. This shouldn't be needed very 1.109 +// often. 1.110 +// 1.111 +NS_IMETHODIMP 1.112 +nsScreenManagerWin :: GetPrimaryScreen(nsIScreen** aPrimaryScreen) 1.113 +{ 1.114 + *aPrimaryScreen = CreateNewScreenObject ( nullptr ); // addrefs 1.115 + return NS_OK; 1.116 + 1.117 +} // GetPrimaryScreen 1.118 + 1.119 + 1.120 +// 1.121 +// CountMonitors 1.122 +// 1.123 +// Will be called once for every monitor in the system. Just 1.124 +// increments the parameter, which holds a ptr to a PRUin32 holding the 1.125 +// count up to this point. 1.126 +// 1.127 +BOOL CALLBACK 1.128 +CountMonitors ( HMONITOR, HDC, LPRECT, LPARAM ioParam ) 1.129 +{ 1.130 + uint32_t* countPtr = reinterpret_cast<uint32_t*>(ioParam); 1.131 + ++(*countPtr); 1.132 + 1.133 + return TRUE; // continue the enumeration 1.134 + 1.135 +} // CountMonitors 1.136 + 1.137 + 1.138 +// 1.139 +// GetNumberOfScreens 1.140 +// 1.141 +// Returns how many physical screens are available. 1.142 +// 1.143 +NS_IMETHODIMP 1.144 +nsScreenManagerWin :: GetNumberOfScreens(uint32_t *aNumberOfScreens) 1.145 +{ 1.146 + if ( mNumberOfScreens ) 1.147 + *aNumberOfScreens = mNumberOfScreens; 1.148 + else { 1.149 + uint32_t count = 0; 1.150 + BOOL result = ::EnumDisplayMonitors(nullptr, nullptr, (MONITORENUMPROC)CountMonitors, (LPARAM)&count); 1.151 + if (!result) 1.152 + return NS_ERROR_FAILURE; 1.153 + *aNumberOfScreens = mNumberOfScreens = count; 1.154 + } 1.155 + 1.156 + return NS_OK; 1.157 + 1.158 +} // GetNumberOfScreens 1.159 + 1.160 +NS_IMETHODIMP 1.161 +nsScreenManagerWin::GetSystemDefaultScale(float *aDefaultScale) 1.162 +{ 1.163 + *aDefaultScale = float(gfxWindowsPlatform::GetPlatform()->GetDPIScale()); 1.164 + return NS_OK; 1.165 +} 1.166 + 1.167 +NS_IMETHODIMP 1.168 +nsScreenManagerWin :: ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen) 1.169 +{ 1.170 + HMONITOR mon = MonitorFromWindow ((HWND) aWidget, MONITOR_DEFAULTTOPRIMARY); 1.171 + *outScreen = CreateNewScreenObject (mon); 1.172 + return NS_OK; 1.173 +}