widget/windows/nsScreenManagerWin.cpp

changeset 0
6474c204b198
     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 +}

mercurial