Bug 588664. Cache DPI in nsCocoaWindow. r=joshmoz,a=blocking
authorRobert O'Callahan <robert@ocallahan.org>
Thu, 19 Aug 2010 21:35:08 +1200
changeset 50873 5a3b5dbd2929769d338e97eef8903591e21f999f
parent 50872 3ec65c47a51a24a353b8c3b08f0209046732dd66
child 50874 91427ac7438e0441de66dec9b603d7cbc63561e1
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjoshmoz, blocking
bugs588664
milestone2.0b5pre
Bug 588664. Cache DPI in nsCocoaWindow. r=joshmoz,a=blocking
widget/src/cocoa/nsChildView.mm
widget/src/cocoa/nsCocoaWindow.h
widget/src/cocoa/nsCocoaWindow.mm
--- a/widget/src/cocoa/nsChildView.mm
+++ b/widget/src/cocoa/nsChildView.mm
@@ -964,32 +964,21 @@ nsChildView::GetParent()
 {
   return mParentWidget;
 }
 
 float
 nsChildView::GetDPI()
 {
   NSWindow* window = [mView window];
-  NSScreen* screen = [window screen];
-  if (!screen)
-    return 96.0f;
-
-  CGDirectDisplayID displayID =
-    [[[screen deviceDescription] objectForKey:@"NSScreenNumber"] intValue];
-  CGFloat heightMM = CGDisplayScreenSize(displayID).height;
-  size_t heightPx = CGDisplayPixelsHigh(displayID);
-  CGFloat scaleFactor = [window userSpaceScaleFactor];
-
-  // Currently we don't do our own scaling to take account
-  // of userSpaceScaleFactor, so every "pixel" we draw is actually
-  // userSpaceScaleFactor screen pixels. So divide the screen height
-  // by userSpaceScaleFactor to get the number of "device pixels"
-  // available.
-  return (heightPx / scaleFactor) / (heightMM / MM_PER_INCH_FLOAT);
+  if (window && [window isKindOfClass:[BaseWindow class]]) {
+    return [(BaseWindow*)window getDPI];
+  }
+
+  return 96.0;
 }
 
 LayerManager*
 nsChildView::GetLayerManager()
 {
   nsCocoaWindow* window = GetXULWindowWidget();
   if (window && window->GetAcceleratedRendering() != mUseAcceleratedRendering) {
     mLayerManager = NULL;
--- a/widget/src/cocoa/nsCocoaWindow.h
+++ b/widget/src/cocoa/nsCocoaWindow.h
@@ -71,27 +71,33 @@ typedef struct _nsCocoaWindowList {
   // Data Storage
   NSMutableDictionary* mState;
   BOOL mDrawsIntoWindowFrame;
   NSColor* mActiveTitlebarColor;
   NSColor* mInactiveTitlebarColor;
 
   // Shadow
   BOOL mScheduledShadowInvalidation;
+
+  // DPI cache. Getting the physical screen size (CGDisplayScreenSize)
+  // is ridiculously slow, so we cache it in the toplevel window for all
+  // descendants to use.
+  float mDPI;
 }
 
 - (void)importState:(NSDictionary*)aState;
 - (NSMutableDictionary*)exportState;
 - (void)setDrawsContentsIntoWindowFrame:(BOOL)aState;
 - (BOOL)drawsContentsIntoWindowFrame;
 - (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive;
 - (NSColor*)titlebarColorForActiveWindow:(BOOL)aActive;
 
 - (void)deferredInvalidateShadow;
 - (void)invalidateShadow;
+- (float)getDPI;
 
 @end
 
 @interface NSWindow (Undocumented)
 
 // If a window has been explicitly removed from the "window cache" (to
 // deactivate it), it's sometimes necessary to "reset" it to reactivate it
 // (and put it back in the "window cache").  One way to do this, which Apple
--- a/widget/src/cocoa/nsCocoaWindow.mm
+++ b/widget/src/cocoa/nsCocoaWindow.mm
@@ -1932,26 +1932,53 @@ void nsCocoaWindow::SetPopupWindowLevel(
   if (mToplevelActiveState) {
     [self sendFocusEvent:NS_DEACTIVATE];
     mToplevelActiveState = PR_FALSE;
   }
 }
 
 @end
 
+static float
+GetDPI(NSWindow* aWindow)
+{
+  NSScreen* screen = [aWindow screen];
+  if (!screen)
+    return 96.0f;
+
+  CGDirectDisplayID displayID =
+    [[[screen deviceDescription] objectForKey:@"NSScreenNumber"] intValue];
+  CGFloat heightMM = ::CGDisplayScreenSize(displayID).height;
+  size_t heightPx = ::CGDisplayPixelsHigh(displayID);
+  CGFloat scaleFactor = [aWindow userSpaceScaleFactor];
+  if (scaleFactor < 0.01 || heightMM < 1 || heightPx < 1) {
+    // Something extremely bogus is going on
+    return 96.0f;
+  }
+
+  // Currently we don't do our own scaling to take account
+  // of userSpaceScaleFactor, so every "pixel" we draw is actually
+  // userSpaceScaleFactor screen pixels. So divide the screen height
+  // by userSpaceScaleFactor to get the number of "device pixels"
+  // available.
+  return (heightPx / scaleFactor) / (heightMM / MM_PER_INCH_FLOAT);
+}
+
 @implementation BaseWindow
 
 - (id)initWithContentRect:(NSRect)aContentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)aBufferingType defer:(BOOL)aFlag
 {
   [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag];
   mState = nil;
   mDrawsIntoWindowFrame = NO;
   mActiveTitlebarColor = nil;
   mInactiveTitlebarColor = nil;
   mScheduledShadowInvalidation = NO;
+  mDPI = GetDPI(self);
+
   return self;
 }
 
 - (void)dealloc
 {
   [mActiveTitlebarColor release];
   [mInactiveTitlebarColor release];
   [super dealloc];
@@ -2029,16 +2056,21 @@ static const NSString* kStateShowsToolba
 }
 
 - (void)invalidateShadow
 {
   [super invalidateShadow];
   mScheduledShadowInvalidation = NO;
 }
 
+- (float)getDPI
+{
+  return mDPI;
+}
+
 - (void) doCommandBySelector:(SEL)aSelector
 {
   // We override this so that it won't beep if it can't act.
   // We want to control the beeping for missing or disabled
   // commands ourselves.
   [self tryToPerform:aSelector with:nil];
 }