bug 794038 pt 2.0 - respond to changes to backing-store resolution when a window moves between HiDPI and non-HiDPI displays. r=smichaud

This commit is contained in:
Jonathan Kew 2012-10-16 20:41:20 +01:00
Родитель 1d9d7aca0e
Коммит 171fa34718
10 изменённых файлов: 147 добавлений и 6 удалений

Просмотреть файл

@ -5007,6 +5007,13 @@ NS_IMETHODIMP
nsDocShell::GetPositionAndSize(int32_t * x, int32_t * y, int32_t * cx,
int32_t * cy)
{
if (mParentWidget) {
// ensure size is up-to-date if window has changed resolution
nsIntRect r;
mParentWidget->GetClientBounds(r);
SetPositionAndSize(mBounds.x, mBounds.y, r.width, r.height, false);
}
// We should really consider just getting this information from
// our window instead of duplicating the storage and code...
if (cx || cy) {

Просмотреть файл

@ -1353,6 +1353,7 @@ public:
virtual void WindowSizeMoveDone() = 0;
virtual void SysColorChanged() = 0;
virtual void ThemeChanged() = 0;
virtual void BackingScaleFactorChanged() = 0;
nscoord MaxLineBoxWidth() {
return mMaxLineBoxWidth;

Просмотреть файл

@ -1604,6 +1604,45 @@ nsPresContext::SysColorChangedInternal()
RebuildAllStyleData(nsChangeHint(0));
}
void
nsPresContext::UIResolutionChanged()
{
if (!mPendingUIResolutionChanged) {
nsCOMPtr<nsIRunnable> ev =
NS_NewRunnableMethod(this, &nsPresContext::UIResolutionChangedInternal);
if (NS_SUCCEEDED(NS_DispatchToCurrentThread(ev))) {
mPendingUIResolutionChanged = true;
}
}
}
/*static*/ bool
nsPresContext::UIResolutionChangedSubdocumentCallback(nsIDocument* aDocument,
void* aData)
{
nsIPresShell* shell = aDocument->GetShell();
if (shell) {
nsPresContext* pc = shell->GetPresContext();
if (pc) {
pc->UIResolutionChangedInternal();
}
}
return true;
}
void
nsPresContext::UIResolutionChangedInternal()
{
mPendingUIResolutionChanged = false;
if (mDeviceContext->CheckDPIChange()) {
AppUnitsPerDevPixelChanged();
}
mDocument->EnumerateSubDocuments(UIResolutionChangedSubdocumentCallback,
nullptr);
}
void
nsPresContext::RebuildAllStyleData(nsChangeHint aExtraHint)
{

Просмотреть файл

@ -722,6 +722,13 @@ public:
*/
NS_HIDDEN_(void) ThemeChanged();
/*
* Notify the pres context that the resolution of the user interface has
* changed. This happens if a window is moved between HiDPI and non-HiDPI
* displays, so that the ratio of points to device pixels changes.
*/
NS_HIDDEN_(void) UIResolutionChanged();
/*
* Notify the pres context that a system color has changed
*/
@ -930,6 +937,10 @@ protected:
friend class nsRunnableMethod<nsPresContext>;
NS_HIDDEN_(void) ThemeChangedInternal();
NS_HIDDEN_(void) SysColorChangedInternal();
NS_HIDDEN_(void) UIResolutionChangedInternal();
static NS_HIDDEN_(bool)
UIResolutionChangedSubdocumentCallback(nsIDocument* aDocument, void* aData);
NS_HIDDEN_(void) SetImgAnimations(nsIContent *aParent, uint16_t aMode);
NS_HIDDEN_(void) SetSMILAnimations(nsIDocument *aDoc, uint16_t aNewMode,
@ -1165,6 +1176,7 @@ protected:
unsigned mPrefScrollbarSide : 2;
unsigned mPendingSysColorChanged : 1;
unsigned mPendingThemeChanged : 1;
unsigned mPendingUIResolutionChanged : 1;
unsigned mPendingMediaFeatureValuesChanged : 1;
unsigned mPrefChangePendingNeedsReflow : 1;
unsigned mMayHaveFixedBackgroundFrames : 1;

Просмотреть файл

@ -697,6 +697,7 @@ protected:
virtual void WindowSizeMoveDone();
virtual void SysColorChanged() { mPresContext->SysColorChanged(); }
virtual void ThemeChanged() { mPresContext->ThemeChanged(); }
virtual void BackingScaleFactorChanged() { mPresContext->UIResolutionChanged(); }
#ifdef DEBUG
// The reflow root under which we're currently reflowing. Null when

Просмотреть файл

@ -195,8 +195,8 @@ pref("media.video-queue.default-size", 10);
// 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);
// >= 2 : hidpi supported even with mixed backingScaleFactors (somewhat broken)
pref("gfx.hidpi.enabled", 2);
#endif
// 0 = Off, 1 = Full, 2 = Tagged Images Only.

Просмотреть файл

@ -396,6 +396,10 @@ public:
// pixels" and the Cocoa "points" coordinate system.
CGFloat BackingScaleFactor();
// Call if the window's backing scale factor changes - i.e., it is moved
// between HiDPI and non-HiDPI screens
void BackingScaleFactorChanged();
virtual double GetDefaultScale();
NS_IMETHOD Invalidate(const nsIntRect &aRect);

Просмотреть файл

@ -765,6 +765,29 @@ nsChildView::BackingScaleFactor()
return mBackingScaleFactor;
}
void
nsChildView::BackingScaleFactorChanged()
{
CGFloat newScale = nsCocoaUtils::GetBackingScaleFactor(mView);
// ignore notification if it hasn't really changed (or maybe we have
// disabled HiDPI mode via prefs)
if (mBackingScaleFactor == newScale) {
return;
}
mBackingScaleFactor = newScale;
if (!mWidgetListener || mWidgetListener->GetXULWindow()) {
return;
}
nsIPresShell* presShell = mWidgetListener->GetPresShell();
if (presShell) {
presShell->BackingScaleFactorChanged();
}
}
NS_IMETHODIMP nsChildView::ConstrainPosition(bool aAllowSlop,
int32_t *aX, int32_t *aY)
{
@ -2347,6 +2370,17 @@ NSEvent* gLastDragMouseDownEvent = nil;
return nsCocoaUtils::HiDPIEnabled() ? YES : NO;
}
- (void)viewDidChangeBackingProperties
{
[super viewDidChangeBackingProperties];
if (mGeckoChild) {
// actually, it could be the color space that's changed,
// but we can't tell the difference here except by retrieving
// the backing scale factor and comparing to the old value
mGeckoChild->BackingScaleFactorChanged();
}
}
// The display system has told us that a portion of our view is dirty. Tell
// gecko to paint it
- (void)drawRect:(NSRect)aRect

Просмотреть файл

@ -243,6 +243,7 @@ public:
NS_IMETHOD SetCursor(imgIContainer* aCursor, uint32_t aHotspotX, uint32_t aHotspotY);
CGFloat BackingScaleFactor();
void BackingScaleFactorChanged();
virtual double GetDefaultScale();
NS_IMETHOD SetTitle(const nsAString& aTitle);

Просмотреть файл

@ -30,6 +30,7 @@
#include "nsCocoaFeatures.h"
#include "nsIScreenManager.h"
#include "nsIWidgetListener.h"
#include "nsIPresShell.h"
#include "gfxPlatform.h"
#include "qcms.h"
@ -425,6 +426,10 @@ nsresult nsCocoaWindow::CreateNativeWindow(const NSRect &aRect,
mWindow = [[windowClass alloc] initWithContentRect:contentRect styleMask:features
backing:NSBackingStoreBuffered defer:YES];
// setup our notification delegate. Note that setDelegate: does NOT retain.
mDelegate = [[WindowDelegate alloc] initWithGeckoWindow:this];
[mWindow setDelegate:mDelegate];
// Make sure that the content rect we gave has been honored.
NSRect wantedFrame = [mWindow frameRectForContentRect:contentRect];
if (!NSEqualRects([mWindow frame], wantedFrame)) {
@ -445,10 +450,6 @@ nsresult nsCocoaWindow::CreateNativeWindow(const NSRect &aRect,
[mWindow setContentMinSize:NSMakeSize(60, 60)];
[mWindow disableCursorRects];
// setup our notification delegate. Note that setDelegate: does NOT retain.
mDelegate = [[WindowDelegate alloc] initWithGeckoWindow:this];
[mWindow setDelegate:mDelegate];
[[WindowDataMap sharedWindowDataMap] ensureDataForWindow:mWindow];
mWindowMadeHere = true;
@ -1415,6 +1416,29 @@ nsCocoaWindow::BackingScaleFactor()
return mBackingScaleFactor;
}
void
nsCocoaWindow::BackingScaleFactorChanged()
{
CGFloat newScale = nsCocoaUtils::GetBackingScaleFactor(mWindow);
// ignore notification if it hasn't really changed (or maybe we have
// disabled HiDPI mode via prefs)
if (mBackingScaleFactor == newScale) {
return;
}
mBackingScaleFactor = newScale;
if (!mWidgetListener || mWidgetListener->GetXULWindow()) {
return;
}
nsIPresShell* presShell = mWidgetListener->GetPresShell();
if (presShell) {
presShell->BackingScaleFactorChanged();
}
}
NS_IMETHODIMP nsCocoaWindow::SetCursor(nsCursor aCursor)
{
if (mPopupContentView)
@ -2240,6 +2264,24 @@ bool nsCocoaWindow::ShouldFocusPlugin()
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (void)windowDidChangeBackingProperties:(NSNotification *)aNotification
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
NSWindow *window = (NSWindow *)[aNotification object];
if ([window respondsToSelector:@selector(backingScaleFactor)]) {
CGFloat oldFactor =
[[[aNotification userInfo]
objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue];
if ([window backingScaleFactor] != oldFactor) {
mGeckoWindow->BackingScaleFactorChanged();
}
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
- (nsCocoaWindow*)geckoWidget
{
return mGeckoWindow;