diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /widget/cocoa/ScreenHelperCocoa.mm | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | widget/cocoa/ScreenHelperCocoa.mm | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/widget/cocoa/ScreenHelperCocoa.mm b/widget/cocoa/ScreenHelperCocoa.mm new file mode 100644 index 0000000000..af4c201f14 --- /dev/null +++ b/widget/cocoa/ScreenHelperCocoa.mm @@ -0,0 +1,156 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "ScreenHelperCocoa.h" + +#import <Cocoa/Cocoa.h> + +#include "mozilla/Logging.h" +#include "nsCocoaUtils.h" +#include "nsObjCExceptions.h" + +using namespace mozilla; + +static LazyLogModule sScreenLog("WidgetScreen"); + +@interface ScreenHelperDelegate : NSObject { + @private + mozilla::widget::ScreenHelperCocoa* mHelper; +} + +- (id)initWithScreenHelper:(mozilla::widget::ScreenHelperCocoa*)aScreenHelper; +- (void)didChangeScreenParameters:(NSNotification*)aNotification; +@end + +@implementation ScreenHelperDelegate +- (id)initWithScreenHelper:(mozilla::widget::ScreenHelperCocoa*)aScreenHelper { + if ((self = [self init])) { + mHelper = aScreenHelper; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(didChangeScreenParameters:) + name:NSApplicationDidChangeScreenParametersNotification + object:nil]; + } + + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (void)didChangeScreenParameters:(NSNotification*)aNotification { + MOZ_LOG(sScreenLog, LogLevel::Debug, + ("Received NSApplicationDidChangeScreenParametersNotification")); + + mHelper->RefreshScreens(); +} +@end + +namespace mozilla { +namespace widget { + +ScreenHelperCocoa::ScreenHelperCocoa() { + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + + MOZ_LOG(sScreenLog, LogLevel::Debug, ("ScreenHelperCocoa created")); + + mDelegate = [[ScreenHelperDelegate alloc] initWithScreenHelper:this]; + + RefreshScreens(); + + NS_OBJC_END_TRY_ABORT_BLOCK; +} + +ScreenHelperCocoa::~ScreenHelperCocoa() { + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + + [mDelegate release]; + + NS_OBJC_END_TRY_ABORT_BLOCK; +} + +static already_AddRefed<Screen> MakeScreen(NSScreen* aScreen) { + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; + + DesktopToLayoutDeviceScale contentsScaleFactor(nsCocoaUtils::GetBackingScaleFactor(aScreen)); + CSSToLayoutDeviceScale defaultCssScaleFactor(contentsScaleFactor.scale); + NSRect frame = [aScreen frame]; + LayoutDeviceIntRect rect = + nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, contentsScaleFactor.scale); + frame = [aScreen visibleFrame]; + LayoutDeviceIntRect availRect = + nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, contentsScaleFactor.scale); + NSWindowDepth depth = [aScreen depth]; + uint32_t pixelDepth = NSBitsPerPixelFromDepth(depth); + float dpi = 96.0f; + CGDirectDisplayID displayID = + [[[aScreen deviceDescription] objectForKey:@"NSScreenNumber"] intValue]; + CGFloat heightMM = ::CGDisplayScreenSize(displayID).height; + if (heightMM > 0) { + dpi = rect.height / (heightMM / MM_PER_INCH_FLOAT); + } + MOZ_LOG(sScreenLog, LogLevel::Debug, + ("New screen [%d %d %d %d (%d %d %d %d) %d %f %f %f]", rect.x, rect.y, rect.width, + rect.height, availRect.x, availRect.y, availRect.width, availRect.height, pixelDepth, + contentsScaleFactor.scale, defaultCssScaleFactor.scale, dpi)); + + RefPtr<Screen> screen = new Screen(rect, availRect, pixelDepth, pixelDepth, contentsScaleFactor, + defaultCssScaleFactor, dpi); + return screen.forget(); + + NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(nullptr); +} + +void ScreenHelperCocoa::RefreshScreens() { + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + + MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refreshing screens")); + + AutoTArray<RefPtr<Screen>, 4> screens; + + for (NSScreen* screen in [NSScreen screens]) { + NSDictionary* desc = [screen deviceDescription]; + if ([desc objectForKey:NSDeviceIsScreen] == nil) { + continue; + } + screens.AppendElement(MakeScreen(screen)); + } + + ScreenManager& screenManager = ScreenManager::GetSingleton(); + screenManager.Refresh(std::move(screens)); + + NS_OBJC_END_TRY_ABORT_BLOCK; +} + +NSScreen* ScreenHelperCocoa::CocoaScreenForScreen(nsIScreen* aScreen) { + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; + + for (NSScreen* screen in [NSScreen screens]) { + NSDictionary* desc = [screen deviceDescription]; + if ([desc objectForKey:NSDeviceIsScreen] == nil) { + continue; + } + LayoutDeviceIntRect rect; + double scale; + aScreen->GetRect(&rect.x, &rect.y, &rect.width, &rect.height); + aScreen->GetContentsScaleFactor(&scale); + NSRect frame = [screen frame]; + LayoutDeviceIntRect frameRect = nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, scale); + if (rect == frameRect) { + return screen; + } + } + return [NSScreen mainScreen]; + + NS_OBJC_END_TRY_ABORT_BLOCK_NIL; +} + +} // namespace widget +} // namespace mozilla |