Skip to content

Commit

Permalink
bug 674373 pt 6 - support HiDPI display in Cocoa widget code. r=roc,s…
Browse files Browse the repository at this point in the history
…michaud
  • Loading branch information
jfkthame committed Sep 29, 2012
1 parent b47d8df commit 23dd56b
Show file tree
Hide file tree
Showing 18 changed files with 580 additions and 166 deletions.
11 changes: 8 additions & 3 deletions browser/base/content/tabbrowser.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3577,12 +3577,17 @@
dt.mozCursor = "default";
// Create a canvas to which we capture the current tab.
// Until canvas is HiDPI-aware (bug 780362), we need to scale the desired
// canvas size (in CSS pixels) to the window's backing resolution in order
// to get a full-resolution drag image for use on HiDPI displays.
let windowUtils = window.getInterface(Ci.nsIDOMWindowUtils);
let scale = windowUtils.screenPixelsPerCSSPixel / windowUtils.fullZoom;
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas.mozOpaque = true;
canvas.width = 160;
canvas.height = 90;
canvas.width = 160 * scale;
canvas.height = 90 * scale;
PageThumbs.captureToCanvas(browser.contentWindow, canvas);
dt.setDragImage(canvas, -16, -16);
dt.setDragImage(canvas, -16 * scale, -16 * scale);
// _dragData.offsetX/Y give the coordinates that the mouse should be
// positioned relative to the corner of the new window created upon
Expand Down
8 changes: 4 additions & 4 deletions layout/style/test/test_media_queries.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

var iframe;

function getZoomRatio() {
function getScreenPixelsPerCSSPixel() {
return SpecialPowers.DOMWindowUtils.screenPixelsPerCSSPixel;
}

Expand Down Expand Up @@ -357,9 +357,9 @@
should_apply("not all and (max-device-aspect-ratio: " + low_dar_2 + ")");
expression_should_not_be_parseable("max-device-aspect-ratio");

var real_dpr = 1.0 * getZoomRatio();
var high_dpr = 1.1 * getZoomRatio();
var low_dpr = 0.9 * getZoomRatio();
var real_dpr = 1.0 * getScreenPixelsPerCSSPixel();
var high_dpr = 1.1 * getScreenPixelsPerCSSPixel();
var low_dpr = 0.9 * getScreenPixelsPerCSSPixel();
should_apply("all and (max--moz-device-pixel-ratio: " + real_dpr + ")");
should_apply("all and (min--moz-device-pixel-ratio: " + real_dpr + ")");
should_not_apply("not all and (max--moz-device-pixel-ratio: " + real_dpr + ")");
Expand Down
12 changes: 7 additions & 5 deletions layout/xul/base/src/nsMenuPopupFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,9 @@ class nsMenuPopupFrame : public nsBoxFrame, public nsMenuParent

void EnsureMenuItemIsVisible(nsMenuFrame* aMenuFrame);

// Move the popup to the screen coordinate (aLeft, aTop). If aUpdateAttrs
// is true, and the popup already has left or top attributes, then those
// attributes are updated to the new location.
// Move the popup to the screen coordinate (aLeft, aTop) in CSS pixels.
// If aUpdateAttrs is true, and the popup already has left or top attributes,
// then those attributes are updated to the new location.
// The frame may be destroyed by this method.
void MoveTo(int32_t aLeft, int32_t aTop, bool aUpdateAttrs);

Expand Down Expand Up @@ -302,6 +302,7 @@ class nsMenuPopupFrame : public nsBoxFrame, public nsMenuParent
nsIContent* GetAnchor() const { return mAnchorContent; }

// Return the screen coordinates of the popup, or (-1, -1) if anchored.
// This position is in CSS pixels.
nsIntPoint ScreenPosition() const { return nsIntPoint(mScreenXPos, mScreenYPos); }

NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
Expand Down Expand Up @@ -387,8 +388,9 @@ class nsMenuPopupFrame : public nsBoxFrame, public nsMenuParent
// would be before resizing. Computations are performed using this size.
nsSize mPrefSize;

// the position of the popup. The screen coordinates, if set to values other
// than -1, override mXPos and mYPos.
// The position of the popup, in CSS pixels.
// The screen coordinates, if set to values other than -1,
// override mXPos and mYPos.
int32_t mXPos;
int32_t mYPos;
int32_t mScreenXPos;
Expand Down
20 changes: 16 additions & 4 deletions layout/xul/base/src/nsXULPopupManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,11 @@ nsXULPopupManager::PopupMoved(nsIFrame* aFrame, nsIntPoint aPnt)
if (!menuPopupFrame)
return;

// Convert desired point to CSS pixels for comparison
nsPresContext* presContext = menuPopupFrame->PresContext();
aPnt.x = presContext->DevPixelsToIntCSSPixels(aPnt.x);
aPnt.y = presContext->DevPixelsToIntCSSPixels(aPnt.y);

// Don't do anything if the popup is already at the specified location. This
// prevents recursive calls when a popup is positioned.
nsIntPoint currentPnt = menuPopupFrame->ScreenPosition();
Expand Down Expand Up @@ -346,13 +351,20 @@ nsXULPopupManager::PopupResized(nsIFrame* aFrame, nsIntSize aSize)
nsPresContext* presContext = menuPopupFrame->PresContext();

nsSize currentSize = menuPopupFrame->GetSize();
if (aSize.width != presContext->AppUnitsToDevPixels(currentSize.width) ||
aSize.height != presContext->AppUnitsToDevPixels(currentSize.height)) {

// convert both current and new sizes to integer CSS pixels for comparison;
// we won't set attributes if there is only a sub-CSS-pixel discrepancy
nsIntSize currCSS(nsPresContext::AppUnitsToIntCSSPixels(currentSize.width),
nsPresContext::AppUnitsToIntCSSPixels(currentSize.height));
nsIntSize newCSS(presContext->DevPixelsToIntCSSPixels(aSize.width),
presContext->DevPixelsToIntCSSPixels(aSize.height));

if (newCSS.width != currCSS.width || newCSS.height != currCSS.height) {
// for resizes, we just set the width and height attributes
nsIContent* popup = menuPopupFrame->GetContent();
nsAutoString width, height;
width.AppendInt(aSize.width);
height.AppendInt(aSize.height);
width.AppendInt(newCSS.width);
height.AppendInt(newCSS.height);
popup->SetAttr(kNameSpaceID_None, nsGkAtoms::width, width, false);
popup->SetAttr(kNameSpaceID_None, nsGkAtoms::height, height, true);
}
Expand Down
12 changes: 9 additions & 3 deletions modules/libpref/src/init/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,14 @@ pref("media.autoplay.enabled", true);
// nsBuiltinDecoderReader's mVideoQueue.
pref("media.video-queue.default-size", 10);

#ifdef XP_MACOSX
// Whether to run in native HiDPI mode on machines with "Retina"/HiDPI display;
// <= 0 : hidpi mode disabled, display will just use pixel-based upscaling
// == 1 : hidpi supported if all screens share the same backingScaleFactor
// >= 2 : hidpi supported even with mixed backingScaleFactors (currently broken)
pref("gfx.hidpi.enabled", 1);
#endif

// 0 = Off, 1 = Full, 2 = Tagged Images Only.
// See eCMSMode in gfx/thebes/gfxPlatform.h
pref("gfx.color_management.mode", 2);
Expand Down Expand Up @@ -1588,9 +1596,7 @@ pref("layout.css.dpi", -1);
// automatically based on user settings for the platform (e.g., "UI scale factor"
// on Mac). A positive value is used as-is. This effectively controls the size
// of a CSS "px". This is only used for windows on the screen, not for printing.
// XXX the default value here should be 0, but before we can set it to 0,
// we have to get this feature working on all platforms.
pref("layout.css.devPixelsPerPx", "1.0");
pref("layout.css.devPixelsPerPx", "-1.0");

// Is support for the the @supports rule enabled?
pref("layout.css.supports-rule.enabled", true);
Expand Down
30 changes: 30 additions & 0 deletions widget/cocoa/nsChildView.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,16 @@ class nsChildView : public nsBaseWidget,
NS_IMETHOD SetFocus(bool aRaise);
NS_IMETHOD GetBounds(nsIntRect &aRect);

// Returns the "backing scale factor" of the view's window, which is the
// ratio of pixels in the window's backing store to Cocoa points. Prior to
// HiDPI support in OS X 10.7, this was always 1.0, but in HiDPI mode it
// will be 2.0 (and might potentially other values as screen resolutions
// evolve). This gives the relationship between what Gecko calls "device
// pixels" and the Cocoa "points" coordinate system.
CGFloat BackingScaleFactor();

virtual double GetDefaultScale();

NS_IMETHOD Invalidate(const nsIntRect &aRect);

virtual void* GetNativeData(uint32_t aDataType);
Expand Down Expand Up @@ -516,6 +526,20 @@ class nsChildView : public nsBaseWidget,
return mTextInputHandler;
}

// unit conversion convenience functions
nsIntPoint CocoaPointsToDevPixels(const NSPoint& aPt) {
return nsCocoaUtils::CocoaPointsToDevPixels(aPt, BackingScaleFactor());
}
nsIntRect CocoaPointsToDevPixels(const NSRect& aRect) {
return nsCocoaUtils::CocoaPointsToDevPixels(aRect, BackingScaleFactor());
}
CGFloat DevPixelsToCocoaPoints(int32_t aPixels) {
return nsCocoaUtils::DevPixelsToCocoaPoints(aPixels, BackingScaleFactor());
}
NSRect DevPixelsToCocoaPoints(const nsIntRect& aRect) {
return nsCocoaUtils::DevPixelsToCocoaPoints(aRect, BackingScaleFactor());
}

protected:

void ReportMoveEvent();
Expand Down Expand Up @@ -552,6 +576,12 @@ class nsChildView : public nsBaseWidget,
nsRefPtr<gfxASurface> mTempThebesSurface;
nsRefPtr<mozilla::gl::TextureImage> mResizerImage;

// Cached value of [mView backingScaleFactor], to avoid sending two obj-c
// messages (respondsToSelector, backingScaleFactor) every time we need to
// use it.
// ** We'll need to reinitialize this if the backing resolution changes. **
CGFloat mBackingScaleFactor;

bool mVisible;
bool mDrawing;
bool mPluginDrawing;
Expand Down
Loading

0 comments on commit 23dd56b

Please sign in to comment.