michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsScreenManagerWin.h" michael@0: #include "nsScreenWin.h" michael@0: #include "gfxWindowsPlatform.h" michael@0: #include "nsIWidget.h" michael@0: michael@0: michael@0: BOOL CALLBACK CountMonitors ( HMONITOR, HDC, LPRECT, LPARAM ioCount ) ; michael@0: michael@0: nsScreenManagerWin :: nsScreenManagerWin ( ) michael@0: : mNumberOfScreens(0) michael@0: { michael@0: // nothing to do. I guess we could cache a bunch of information michael@0: // here, but we want to ask the device at runtime in case anything michael@0: // has changed. michael@0: } michael@0: michael@0: michael@0: nsScreenManagerWin :: ~nsScreenManagerWin() michael@0: { michael@0: } michael@0: michael@0: michael@0: // addref, release, QI michael@0: NS_IMPL_ISUPPORTS(nsScreenManagerWin, nsIScreenManager) michael@0: michael@0: michael@0: // michael@0: // CreateNewScreenObject michael@0: // michael@0: // Utility routine. Creates a new screen object from the given device handle michael@0: // michael@0: // NOTE: For this "single-monitor" impl, we just always return the cached primary michael@0: // screen. This should change when a multi-monitor impl is done. michael@0: // michael@0: nsIScreen* michael@0: nsScreenManagerWin :: CreateNewScreenObject ( HMONITOR inScreen ) michael@0: { michael@0: nsIScreen* retScreen = nullptr; michael@0: michael@0: // look through our screen list, hoping to find it. If it's not there, michael@0: // add it and return the new one. michael@0: for ( unsigned i = 0; i < mScreenList.Length(); ++i ) { michael@0: ScreenListItem& curr = mScreenList[i]; michael@0: if ( inScreen == curr.mMon ) { michael@0: NS_IF_ADDREF(retScreen = curr.mScreen.get()); michael@0: return retScreen; michael@0: } michael@0: } // for each screen. michael@0: michael@0: retScreen = new nsScreenWin(inScreen); michael@0: mScreenList.AppendElement ( ScreenListItem ( inScreen, retScreen ) ); michael@0: michael@0: NS_IF_ADDREF(retScreen); michael@0: return retScreen; michael@0: } michael@0: michael@0: michael@0: // michael@0: // ScreenForRect michael@0: // michael@0: // Returns the screen that contains the rectangle. If the rect overlaps michael@0: // multiple screens, it picks the screen with the greatest area of intersection. michael@0: // michael@0: // The coordinates are in pixels (not twips) and in logical screen coordinates. michael@0: // michael@0: NS_IMETHODIMP michael@0: nsScreenManagerWin :: ScreenForRect ( int32_t inLeft, int32_t inTop, int32_t inWidth, int32_t inHeight, michael@0: nsIScreen **outScreen ) michael@0: { michael@0: if ( !(inWidth || inHeight) ) { michael@0: NS_WARNING ( "trying to find screen for sizeless window, using primary monitor" ); michael@0: *outScreen = CreateNewScreenObject ( nullptr ); // addrefs michael@0: return NS_OK; michael@0: } michael@0: michael@0: // convert coordinates from logical to device pixels for MonitorFromRect michael@0: double dpiScale = nsIWidget::DefaultScaleOverride(); michael@0: if (dpiScale <= 0.0) { michael@0: dpiScale = gfxWindowsPlatform::GetPlatform()->GetDPIScale(); michael@0: } michael@0: RECT globalWindowBounds = { michael@0: NSToIntRound(dpiScale * inLeft), michael@0: NSToIntRound(dpiScale * inTop), michael@0: NSToIntRound(dpiScale * (inLeft + inWidth)), michael@0: NSToIntRound(dpiScale * (inTop + inHeight)) michael@0: }; michael@0: michael@0: HMONITOR genScreen = ::MonitorFromRect( &globalWindowBounds, MONITOR_DEFAULTTOPRIMARY ); michael@0: michael@0: *outScreen = CreateNewScreenObject ( genScreen ); // addrefs michael@0: michael@0: return NS_OK; michael@0: michael@0: } // ScreenForRect michael@0: michael@0: michael@0: // michael@0: // GetPrimaryScreen michael@0: // michael@0: // The screen with the menubar/taskbar. This shouldn't be needed very michael@0: // often. michael@0: // michael@0: NS_IMETHODIMP michael@0: nsScreenManagerWin :: GetPrimaryScreen(nsIScreen** aPrimaryScreen) michael@0: { michael@0: *aPrimaryScreen = CreateNewScreenObject ( nullptr ); // addrefs michael@0: return NS_OK; michael@0: michael@0: } // GetPrimaryScreen michael@0: michael@0: michael@0: // michael@0: // CountMonitors michael@0: // michael@0: // Will be called once for every monitor in the system. Just michael@0: // increments the parameter, which holds a ptr to a PRUin32 holding the michael@0: // count up to this point. michael@0: // michael@0: BOOL CALLBACK michael@0: CountMonitors ( HMONITOR, HDC, LPRECT, LPARAM ioParam ) michael@0: { michael@0: uint32_t* countPtr = reinterpret_cast(ioParam); michael@0: ++(*countPtr); michael@0: michael@0: return TRUE; // continue the enumeration michael@0: michael@0: } // CountMonitors michael@0: michael@0: michael@0: // michael@0: // GetNumberOfScreens michael@0: // michael@0: // Returns how many physical screens are available. michael@0: // michael@0: NS_IMETHODIMP michael@0: nsScreenManagerWin :: GetNumberOfScreens(uint32_t *aNumberOfScreens) michael@0: { michael@0: if ( mNumberOfScreens ) michael@0: *aNumberOfScreens = mNumberOfScreens; michael@0: else { michael@0: uint32_t count = 0; michael@0: BOOL result = ::EnumDisplayMonitors(nullptr, nullptr, (MONITORENUMPROC)CountMonitors, (LPARAM)&count); michael@0: if (!result) michael@0: return NS_ERROR_FAILURE; michael@0: *aNumberOfScreens = mNumberOfScreens = count; michael@0: } michael@0: michael@0: return NS_OK; michael@0: michael@0: } // GetNumberOfScreens michael@0: michael@0: NS_IMETHODIMP michael@0: nsScreenManagerWin::GetSystemDefaultScale(float *aDefaultScale) michael@0: { michael@0: *aDefaultScale = float(gfxWindowsPlatform::GetPlatform()->GetDPIScale()); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsScreenManagerWin :: ScreenForNativeWidget(void *aWidget, nsIScreen **outScreen) michael@0: { michael@0: HMONITOR mon = MonitorFromWindow ((HWND) aWidget, MONITOR_DEFAULTTOPRIMARY); michael@0: *outScreen = CreateNewScreenObject (mon); michael@0: return NS_OK; michael@0: }