mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 819930 - Part 1: Implement an API for emulating CSS media types. r=dbaron
This commit is contained in:
parent
229a51dbe5
commit
3b2ae36916
@ -23,7 +23,7 @@ interface nsIMarkupDocumentViewer;
|
||||
|
||||
[ref] native nsIMarkupDocumentViewerTArray(nsTArray<nsCOMPtr<nsIMarkupDocumentViewer> >);
|
||||
|
||||
[scriptable, uuid(02d37b31-e654-4b74-9bc3-14dfe0020bb3)]
|
||||
[scriptable, uuid(23326580-e6ce-4ee1-94b8-f1d9424a9977)]
|
||||
interface nsIMarkupDocumentViewer : nsISupports
|
||||
{
|
||||
|
||||
@ -136,4 +136,17 @@ interface nsIMarkupDocumentViewer : nsISupports
|
||||
* in CSS pixels.
|
||||
*/
|
||||
void changeMaxLineBoxWidth(in int32_t maxLineBoxWidth);
|
||||
|
||||
/*
|
||||
* Render the document as if being viewed on a device with the specified
|
||||
* media type. This will cause a reflow.
|
||||
*
|
||||
* @param mediaType The media type to be emulated
|
||||
*/
|
||||
void emulateMedium(in AString aMediaType);
|
||||
|
||||
/*
|
||||
* Restore the viewer's natural media type
|
||||
*/
|
||||
void stopEmulatingMedium();
|
||||
};
|
||||
|
@ -2965,6 +2965,80 @@ nsDocumentViewer::GetAuthorStyleDisabled(bool* aStyleDisabled)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
ExtResourceEmulateMedium(nsIDocument* aDocument, void* aClosure)
|
||||
{
|
||||
nsIPresShell* shell = aDocument->GetShell();
|
||||
if (shell) {
|
||||
nsPresContext* ctxt = shell->GetPresContext();
|
||||
if (ctxt) {
|
||||
const nsAString* mediaType = static_cast<nsAString*>(aClosure);
|
||||
ctxt->EmulateMedium(*mediaType);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ChildEmulateMedium(nsIMarkupDocumentViewer* aChild, void* aClosure)
|
||||
{
|
||||
const nsAString* mediaType = static_cast<nsAString*>(aClosure);
|
||||
aChild->EmulateMedium(*mediaType);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocumentViewer::EmulateMedium(const nsAString& aMediaType)
|
||||
{
|
||||
if (mPresContext) {
|
||||
mPresContext->EmulateMedium(aMediaType);
|
||||
}
|
||||
CallChildren(ChildEmulateMedium, const_cast<nsAString*>(&aMediaType));
|
||||
|
||||
if (mDocument) {
|
||||
mDocument->EnumerateExternalResources(ExtResourceEmulateMedium,
|
||||
const_cast<nsAString*>(&aMediaType));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
ExtResourceStopEmulatingMedium(nsIDocument* aDocument, void* aClosure)
|
||||
{
|
||||
nsIPresShell* shell = aDocument->GetShell();
|
||||
if (shell) {
|
||||
nsPresContext* ctxt = shell->GetPresContext();
|
||||
if (ctxt) {
|
||||
ctxt->StopEmulatingMedium();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ChildStopEmulatingMedium(nsIMarkupDocumentViewer* aChild, void* aClosure)
|
||||
{
|
||||
aChild->StopEmulatingMedium();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocumentViewer::StopEmulatingMedium()
|
||||
{
|
||||
if (mPresContext) {
|
||||
mPresContext->StopEmulatingMedium();
|
||||
}
|
||||
CallChildren(ChildStopEmulatingMedium, nullptr);
|
||||
|
||||
if (mDocument) {
|
||||
mDocument->EnumerateExternalResources(ExtResourceStopEmulatingMedium,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocumentViewer::GetDefaultCharacterSet(nsACString& aDefaultCharacterSet)
|
||||
{
|
||||
|
@ -233,6 +233,7 @@ nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
|
||||
mMedium = nsGkAtoms::print;
|
||||
mPaginated = true;
|
||||
}
|
||||
mMediaEmulated = mMedium;
|
||||
|
||||
if (!IsDynamic()) {
|
||||
mImageAnimationMode = imgIContainer::kDontAnimMode;
|
||||
@ -1691,6 +1692,30 @@ nsPresContext::UIResolutionChangedInternal()
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::EmulateMedium(const nsAString& aMediaType)
|
||||
{
|
||||
nsIAtom* previousMedium = Medium();
|
||||
mIsEmulatingMedia = true;
|
||||
|
||||
nsAutoString mediaType;
|
||||
nsContentUtils::ASCIIToLower(aMediaType, mediaType);
|
||||
|
||||
mMediaEmulated = do_GetAtom(mediaType);
|
||||
if (mMediaEmulated != previousMedium && mShell) {
|
||||
MediaFeatureValuesChanged(eRebuildStyleIfNeeded, nsChangeHint(0));
|
||||
}
|
||||
}
|
||||
|
||||
void nsPresContext::StopEmulatingMedium()
|
||||
{
|
||||
nsIAtom* previousMedium = Medium();
|
||||
mIsEmulatingMedia = false;
|
||||
if (Medium() != previousMedium) {
|
||||
MediaFeatureValuesChanged(eRebuildStyleIfNeeded, nsChangeHint(0));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::RebuildAllStyleData(nsChangeHint aExtraHint)
|
||||
{
|
||||
|
@ -305,7 +305,22 @@ public:
|
||||
/**
|
||||
* Get medium of presentation
|
||||
*/
|
||||
nsIAtom* Medium() { return mMedium; }
|
||||
nsIAtom* Medium() {
|
||||
if (!mIsEmulatingMedia)
|
||||
return mMedium;
|
||||
return mMediaEmulated;
|
||||
}
|
||||
|
||||
/*
|
||||
* Render the document as if being viewed on a device with the specified
|
||||
* media type.
|
||||
*/
|
||||
void EmulateMedium(const nsAString& aMediaType);
|
||||
|
||||
/*
|
||||
* Restore the viewer's natural medium
|
||||
*/
|
||||
void StopEmulatingMedium();
|
||||
|
||||
void* AllocateFromShell(size_t aSize)
|
||||
{
|
||||
@ -1151,6 +1166,7 @@ protected:
|
||||
nsRefPtr<nsAnimationManager> mAnimationManager;
|
||||
nsIAtom* mMedium; // initialized by subclass ctors;
|
||||
// weak pointer to static atom
|
||||
nsCOMPtr<nsIAtom> mMediaEmulated;
|
||||
|
||||
nsILinkHandler* mLinkHandler; // [WEAK]
|
||||
|
||||
@ -1260,6 +1276,7 @@ protected:
|
||||
unsigned mPendingUIResolutionChanged : 1;
|
||||
unsigned mPendingMediaFeatureValuesChanged : 1;
|
||||
unsigned mPrefChangePendingNeedsReflow : 1;
|
||||
unsigned mIsEmulatingMedia : 1;
|
||||
// True if the requests in mInvalidateRequestsSinceLastPaint cover the
|
||||
// entire viewport
|
||||
unsigned mAllInvalidated : 1;
|
||||
|
@ -149,6 +149,7 @@ MOCHITEST_FILES = \
|
||||
test_bug851485.html \
|
||||
test_bug851445.html \
|
||||
bug851445_helper.html \
|
||||
test_emulateMedium.html \
|
||||
$(NULL)
|
||||
|
||||
ifeq (,$(filter gonk,$(MOZ_WIDGET_TOOLKIT)))
|
||||
|
141
layout/base/tests/test_emulateMedium.html
Normal file
141
layout/base/tests/test_emulateMedium.html
Normal file
@ -0,0 +1,141 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=819930
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 819930</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<style>
|
||||
@media braille {
|
||||
body {
|
||||
background-color: rgb(255, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@media embossed {
|
||||
body {
|
||||
background-color: rgb(210, 180, 140);
|
||||
}
|
||||
}
|
||||
|
||||
@media handheld {
|
||||
body {
|
||||
background-color: rgb(0, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
body {
|
||||
background-color: rgb(0, 255, 255);
|
||||
}
|
||||
}
|
||||
|
||||
@media projection {
|
||||
body {
|
||||
background-color: rgb(30, 144, 255);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen {
|
||||
body {
|
||||
background-color: green;
|
||||
}
|
||||
}
|
||||
|
||||
@media speech {
|
||||
body {
|
||||
background-color: rgb(192, 192, 192);
|
||||
}
|
||||
}
|
||||
|
||||
@media tty {
|
||||
body {
|
||||
background-color: rgb(255, 192, 203);
|
||||
}
|
||||
}
|
||||
|
||||
@media tv {
|
||||
body {
|
||||
background-color: rgb(75, 0, 130);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=819930">Mozilla Bug 819930</a>
|
||||
<p id="display"></p>
|
||||
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
let tests = [{name: 'braille', value: 'rgb(255, 255, 0)'},
|
||||
{name: 'embossed', value: 'rgb(210, 180, 140)'},
|
||||
{name: 'handheld', value: 'rgb(0, 255, 0)'},
|
||||
{name: 'print', value: 'rgb(0, 255, 255)'},
|
||||
{name: 'projection', value: 'rgb(30, 144, 255)'},
|
||||
{name: 'speech', value: 'rgb(192, 192, 192)'},
|
||||
{name: 'tty', value: 'rgb(255, 192, 203)'},
|
||||
{name: 'tv', value: 'rgb(75, 0, 130)'}];
|
||||
|
||||
let originalColor = 'rgb(0, 128, 0)';
|
||||
let body = document.body;
|
||||
|
||||
let getColor = function() {
|
||||
return window.getComputedStyle(body)
|
||||
.getPropertyValue('background-color');
|
||||
};
|
||||
|
||||
tests.forEach(function(test) {
|
||||
// Emulate the given media
|
||||
SpecialPowers.emulateMedium(window, test.name);
|
||||
is(getColor(), test.value, 'emulating ' + test.name + ' produced ' +
|
||||
'correct rendering');
|
||||
|
||||
// Do the @media screen rules get applied after ending the emulation?
|
||||
SpecialPowers.stopEmulatingMedium(window);
|
||||
is(getColor(), originalColor, 'Ending ' + test.name +
|
||||
' emulation restores style for original medium');
|
||||
|
||||
// CSS media types are case-insensitive; we should be too.
|
||||
SpecialPowers.emulateMedium(window, test.name.toUpperCase());
|
||||
is(getColor(), test.value,
|
||||
test.name + ' emulation is case-insensitive');
|
||||
SpecialPowers.stopEmulatingMedium(window);
|
||||
});
|
||||
|
||||
// Emulating screen should produce the same rendering as when there is
|
||||
// no emulation in effect
|
||||
SpecialPowers.emulateMedium(window, 'screen');
|
||||
is(getColor(), originalColor,
|
||||
'Emulating screen produces original rendering');
|
||||
SpecialPowers.stopEmulatingMedium(window);
|
||||
|
||||
// Screen should be case-insensitive too
|
||||
SpecialPowers.emulateMedium(window, 'SCREEN');
|
||||
is(getColor(), originalColor, 'screen emulation is case-insensitive');
|
||||
SpecialPowers.stopEmulatingMedium(window);
|
||||
|
||||
// An invalid parameter shouldn't fail. Given the CSS rules above,
|
||||
// an invalid parameter should result in a different rendering from any
|
||||
// produced thus far
|
||||
try {
|
||||
SpecialPowers.emulateMedium(window, 'clay');
|
||||
let invalid = getColor();
|
||||
tests.push({name: 'screen', value: 'green'});
|
||||
tests.forEach(function(test) {
|
||||
isnot(invalid, test.value, 'Emulating invalid type differs from ' +
|
||||
test.name);
|
||||
});
|
||||
} catch (e) {
|
||||
ok(false, 'Supplying invalid type to emulateMedium shouldn\'t throw');
|
||||
}
|
||||
|
||||
SpecialPowers.stopEmulatingMedium(window);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -1113,6 +1113,13 @@ SpecialPowersAPI.prototype = {
|
||||
this._getMUDV(window).textZoom = zoom;
|
||||
},
|
||||
|
||||
emulateMedium: function(window, mediaType) {
|
||||
this._getMUDV(window).emulateMedium(mediaType);
|
||||
},
|
||||
stopEmulatingMedium: function(window) {
|
||||
this._getMUDV(window).stopEmulatingMedium();
|
||||
},
|
||||
|
||||
createSystemXHR: function() {
|
||||
return this.wrap(Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest));
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user