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