widget/windows/nsScreenManagerWin.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

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 }

mercurial