зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to mozilla-central. a=merge
This commit is contained in:
Коммит
7ebb432ccd
|
@ -38,7 +38,10 @@ tasks:
|
|||
$if: 'tasks_for == "action"'
|
||||
then:
|
||||
name: "Action: ${action.title}"
|
||||
description: '${action.description}'
|
||||
description: |
|
||||
${action.description}
|
||||
|
||||
Action triggered by clientID `${clientId}`
|
||||
else:
|
||||
name: "Decision Task for cron job ${cron.job_name}"
|
||||
description: 'Created by a [cron task](https://tools.taskcluster.net/tasks/${cron.task_id})'
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
|
||||
#include "ErrorHandler.h"
|
||||
|
||||
#if defined(MOZ_LAUNCHER_PROCESS)
|
||||
#include "mozilla/LauncherRegistryInfo.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#endif // defined(MOZ_LAUNCHER_PROCESS)
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -15,8 +17,10 @@ void HandleLauncherError(const LauncherError& aError) {
|
|||
// This is a placeholder error handler. We'll add telemetry and a fallback
|
||||
// error log in future revisions.
|
||||
|
||||
#if defined(MOZ_LAUNCHER_PROCESS)
|
||||
LauncherRegistryInfo regInfo;
|
||||
Unused << regInfo.DisableDueToFailure();
|
||||
#endif // defined(MOZ_LAUNCHER_PROCESS)
|
||||
|
||||
WindowsError::UniqueString msg = aError.mError.AsString();
|
||||
if (!msg) {
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/DynamicallyLinkedFunctionPtr.h"
|
||||
#include "mozilla/LauncherRegistryInfo.h"
|
||||
#include "mozilla/LauncherResult.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/SafeMode.h"
|
||||
|
@ -32,6 +31,7 @@
|
|||
#include "ProcThreadAttributes.h"
|
||||
|
||||
#if defined(MOZ_LAUNCHER_PROCESS)
|
||||
#include "mozilla/LauncherRegistryInfo.h"
|
||||
#include "SameBinary.h"
|
||||
#endif // defined(MOZ_LAUNCHER_PROCESS)
|
||||
|
||||
|
@ -175,19 +175,20 @@ static bool DoLauncherProcessChecks(int& argc, wchar_t** argv) {
|
|||
namespace mozilla {
|
||||
|
||||
bool RunAsLauncherProcess(int& argc, wchar_t** argv) {
|
||||
LauncherRegistryInfo::ProcessType desiredType =
|
||||
DoLauncherProcessChecks(argc, argv)
|
||||
? LauncherRegistryInfo::ProcessType::Launcher
|
||||
: LauncherRegistryInfo::ProcessType::Browser;
|
||||
bool runAsLauncher = DoLauncherProcessChecks(argc, argv);
|
||||
|
||||
// If we're looking at browser, return fast when we're a child process.
|
||||
if (desiredType == LauncherRegistryInfo::ProcessType::Browser &&
|
||||
// If we're running as browser, return fast when we're a child process.
|
||||
if (!runAsLauncher &&
|
||||
mozilla::CheckArg(argc, argv, L"contentproc",
|
||||
static_cast<const wchar_t**>(nullptr),
|
||||
mozilla::CheckArgFlag::None) == mozilla::ARG_FOUND) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(MOZ_LAUNCHER_PROCESS)
|
||||
LauncherRegistryInfo::ProcessType desiredType =
|
||||
runAsLauncher ? LauncherRegistryInfo::ProcessType::Launcher
|
||||
: LauncherRegistryInfo::ProcessType::Browser;
|
||||
LauncherRegistryInfo regInfo;
|
||||
LauncherResult<LauncherRegistryInfo::ProcessType> runAsType =
|
||||
regInfo.Check(desiredType);
|
||||
|
@ -199,13 +200,17 @@ bool RunAsLauncherProcess(int& argc, wchar_t** argv) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (runAsType.unwrap() == LauncherRegistryInfo::ProcessType::Browser) {
|
||||
runAsLauncher =
|
||||
runAsType.unwrap() == LauncherRegistryInfo::ProcessType::Launcher;
|
||||
#endif // defined(MOZ_LAUNCHER_PROCESS)
|
||||
|
||||
if (!runAsLauncher) {
|
||||
// In this case, we will be proceeding to run as the browser.
|
||||
// We should check MOZ_DEBUG_BROWSER_* env vars.
|
||||
MaybeBreakForBrowserDebugging();
|
||||
}
|
||||
|
||||
return runAsType.unwrap() == LauncherRegistryInfo::ProcessType::Launcher;
|
||||
return runAsLauncher;
|
||||
}
|
||||
|
||||
int LauncherMain(int argc, wchar_t* argv[]) {
|
||||
|
|
|
@ -9,7 +9,6 @@ Library('winlauncher')
|
|||
FORCE_STATIC_LIB = True
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'/toolkit/xre/LauncherRegistryInfo.cpp',
|
||||
'DllBlocklistWin.cpp',
|
||||
'ErrorHandler.cpp',
|
||||
'LauncherProcessWin.cpp',
|
||||
|
@ -26,8 +25,12 @@ TEST_DIRS += [
|
|||
'test',
|
||||
]
|
||||
|
||||
for var in ('MOZ_APP_BASENAME', 'MOZ_APP_VENDOR'):
|
||||
DEFINES[var] = '"%s"' % CONFIG[var]
|
||||
if CONFIG['MOZ_LAUNCHER_PROCESS']:
|
||||
UNIFIED_SOURCES += [
|
||||
'/toolkit/xre/LauncherRegistryInfo.cpp',
|
||||
]
|
||||
for var in ('MOZ_APP_BASENAME', 'MOZ_APP_VENDOR'):
|
||||
DEFINES[var] = '"%s"' % CONFIG[var]
|
||||
|
||||
DisableStlWrapping()
|
||||
|
||||
|
|
|
@ -22,10 +22,6 @@ install:
|
|||
- npm config set spin false
|
||||
- npm install
|
||||
|
||||
before_script:
|
||||
- bash bin/download-firefox-travis.sh release-linux64-add-on-devel
|
||||
- export FIREFOX_BIN=./firefox/firefox
|
||||
|
||||
script:
|
||||
- npm test
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Copied and slightly modified from https://github.com/lidel/ipfs-firefox-addon/commit/d656832eec807ebae59543982dde96932ce5bb7c
|
||||
# Licensed under Creative Commons - CC0 1.0 Universal - https://github.com/lidel/ipfs-firefox-addon/blob/master/LICENSE
|
||||
BUILD_TYPE=${1:-$FIREFOX_RELEASE}
|
||||
echo "Looking up latest URL for $BUILD_TYPE"
|
||||
BUILD_ROOT="/pub/firefox/tinderbox-builds/mozilla-${BUILD_TYPE}/"
|
||||
ROOT="https://archive.mozilla.org"
|
||||
LATEST=$(curl -s "$ROOT$BUILD_ROOT" | grep $BUILD_TYPE | grep -Po '<a href=".+">\K[[:digit:]]+' | sort -n | tail -1)
|
||||
echo "Latest build located at $ROOT$BUILD_ROOT$LATEST"
|
||||
FILE=$(curl -s "$ROOT$BUILD_ROOT$LATEST/" | grep '.tar.' | grep -Po '<a href="\K[^"]*')
|
||||
echo "URL: $ROOT$FILE"
|
||||
wget -O "firefox-${BUILD_TYPE}.tar.bz2" "$ROOT$FILE" && tar xf "firefox-${BUILD_TYPE}.tar.bz2"
|
|
@ -49,7 +49,6 @@ for (const type of [
|
|||
"DISCOVERY_STREAM_SPOCS_UPDATE",
|
||||
"DOWNLOAD_CHANGED",
|
||||
"FILL_SEARCH_TERM",
|
||||
"FOCUS_SEARCH",
|
||||
"HANDOFF_SEARCH_TO_AWESOMEBAR",
|
||||
"HIDE_SEARCH",
|
||||
"INIT",
|
||||
|
|
|
@ -59,7 +59,7 @@ const INITIAL_STATE = {
|
|||
spocs: {
|
||||
spocs_endpoint: "",
|
||||
lastUpdated: null,
|
||||
data: [],
|
||||
data: {}, // {spocs: []}
|
||||
},
|
||||
},
|
||||
Search: {
|
||||
|
@ -491,10 +491,8 @@ function Search(prevState = INITIAL_STATE.Search, action) {
|
|||
switch (action.type) {
|
||||
case at.HIDE_SEARCH:
|
||||
return Object.assign({...prevState, hide: true});
|
||||
case at.FOCUS_SEARCH:
|
||||
return Object.assign({...prevState, focus: true});
|
||||
case at.SHOW_SEARCH:
|
||||
return Object.assign({...prevState, hide: false, focus: false});
|
||||
return Object.assign({...prevState, hide: false});
|
||||
default:
|
||||
return prevState;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
z-index: 2100;
|
||||
|
||||
.ReturnToAMOText {
|
||||
color: $grey-90-80;
|
||||
color: $grey-90;
|
||||
line-height: 32px;
|
||||
font-size: 23px;
|
||||
width: 100%;
|
||||
|
@ -23,19 +23,19 @@
|
|||
}
|
||||
|
||||
h2 {
|
||||
color: $grey-60-60;
|
||||
color: $grey-60;
|
||||
font-weight: 100;
|
||||
margin: 0 0 22px;
|
||||
margin: 0 0 36px;
|
||||
font-size: 36px;
|
||||
line-height: 48px;
|
||||
letter-spacing: 1.2px;
|
||||
}
|
||||
|
||||
p {
|
||||
color: $grey-90-50;
|
||||
color: $grey-60;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
margin-bottom: 4px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.puffy {
|
||||
|
@ -95,17 +95,18 @@
|
|||
}
|
||||
|
||||
.ReturnToAMOContainer {
|
||||
width: 835px;
|
||||
width: 960px;
|
||||
background: $white;
|
||||
box-shadow: 0 1px 15px 0 $black-30;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
padding: 38px 96px 28px 48px;
|
||||
padding: 64px 64px 72px;
|
||||
}
|
||||
|
||||
.ReturnToAMOAddonContents {
|
||||
width: 400px;
|
||||
margin-top: 42px;
|
||||
width: 560px;
|
||||
margin-top: 32px;
|
||||
margin-inline-end: 24px;
|
||||
}
|
||||
|
||||
.ReturnToAMOIcon {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
font-size: 14px;
|
||||
padding-left: $sidebar-width;
|
||||
display: flex;
|
||||
color: var(--newtab-text-primary-color);
|
||||
|
||||
.sidebar {
|
||||
inset-inline-start: 0;
|
||||
|
@ -23,9 +24,10 @@
|
|||
li a {
|
||||
padding: 10px 34px;
|
||||
display: block;
|
||||
color: var(--lwt-sidebar-text-color);
|
||||
|
||||
&:hover {
|
||||
background: $grey-20;
|
||||
background: var(--newtab-textbox-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +51,7 @@
|
|||
}
|
||||
|
||||
.sourceLabel {
|
||||
background: $grey-20;
|
||||
background: var(--newtab-textbox-background-color);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
|
||||
|
@ -136,6 +138,7 @@
|
|||
display: flex;
|
||||
background: $yellow-50;
|
||||
border-radius: 3px;
|
||||
color: $grey-90;
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
|
|
|
@ -2,11 +2,23 @@ import {CardGrid} from "content-src/components/DiscoveryStreamComponents/CardGri
|
|||
import {connect} from "react-redux";
|
||||
import {Hero} from "content-src/components/DiscoveryStreamComponents/Hero/Hero";
|
||||
import {HorizontalRule} from "content-src/components/DiscoveryStreamComponents/HorizontalRule/HorizontalRule";
|
||||
import {ImpressionStats} from "content-src/components/DiscoveryStreamImpressionStats/ImpressionStats";
|
||||
import {List} from "content-src/components/DiscoveryStreamComponents/List/List";
|
||||
import React from "react";
|
||||
import {SectionTitle} from "content-src/components/DiscoveryStreamComponents/SectionTitle/SectionTitle";
|
||||
import {selectLayoutRender} from "content-src/lib/selectLayoutRender";
|
||||
import {TopSites} from "content-src/components/DiscoveryStreamComponents/TopSites/TopSites";
|
||||
|
||||
// According to the Pocket API endpoint specs, `component.properties.items` is a required property with following values:
|
||||
// - Lists 1-5 items
|
||||
// - Hero 1-5 items
|
||||
// - CardGrid 1-8 items
|
||||
// To enforce that, we define various maximium items for individual components as an extra check.
|
||||
// Note that these values are subject to the future changes of the specs.
|
||||
const MAX_ROWS_HERO = 5;
|
||||
// const MAX_ROWS_LISTS = 5;
|
||||
// const MAX_ROWS_CARDGRID = 8;
|
||||
|
||||
export class _DiscoveryStreamBase extends React.PureComponent {
|
||||
renderComponent(component) {
|
||||
switch (component.type) {
|
||||
|
@ -15,27 +27,45 @@ export class _DiscoveryStreamBase extends React.PureComponent {
|
|||
case "SectionTitle":
|
||||
return (<SectionTitle />);
|
||||
case "CardGrid":
|
||||
return (<CardGrid feed={component.feed} />);
|
||||
case "Hero":
|
||||
return (<Hero
|
||||
title={component.header.title}
|
||||
return (<CardGrid
|
||||
title={component.header && component.header.title}
|
||||
data={component.data}
|
||||
feed={component.feed}
|
||||
style={component.properties.style}
|
||||
type={component.type}
|
||||
dispatch={this.props.dispatch}
|
||||
items={component.properties.items} />);
|
||||
case "Hero":
|
||||
const items = Math.min(MAX_ROWS_HERO,
|
||||
component.properties.items || (component.data ? component.data.recommendations.length : 0));
|
||||
const rows = component.data ? component.data.recommendations.slice(0, items) : [];
|
||||
return (
|
||||
<ImpressionStats rows={rows} dispatch={this.props.dispatch} source={component.type}>
|
||||
<Hero
|
||||
title={component.header && component.header.title}
|
||||
data={component.data}
|
||||
style={component.properties.style}
|
||||
type={component.type}
|
||||
dispatch={this.props.dispatch}
|
||||
items={items} />
|
||||
</ImpressionStats>
|
||||
);
|
||||
case "HorizontalRule":
|
||||
return (<HorizontalRule />);
|
||||
case "List":
|
||||
return (<List feed={component.feed} />);
|
||||
return (<List
|
||||
feed={component.feed}
|
||||
header={component.header} />);
|
||||
default:
|
||||
return (<div>{component.type}</div>);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {layout} = this.props.DiscoveryStream;
|
||||
const {layoutRender} = this.props.DiscoveryStream;
|
||||
return (
|
||||
<div className="discovery-stream ds-layout">
|
||||
{layout.map((row, rowIndex) => (
|
||||
{layoutRender.map((row, rowIndex) => (
|
||||
<div key={`row-${rowIndex}`} className={`ds-column ds-column-${row.width}`}>
|
||||
{row.components.map((component, componentIndex) => (
|
||||
<div key={`component-${componentIndex}`}>
|
||||
|
@ -49,4 +79,13 @@ export class _DiscoveryStreamBase extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
export const DiscoveryStreamBase = connect(state => ({DiscoveryStream: state.DiscoveryStream}))(_DiscoveryStreamBase);
|
||||
function transform(state) {
|
||||
return {
|
||||
DiscoveryStream: {
|
||||
...state.DiscoveryStream,
|
||||
layoutRender: selectLayoutRender(state),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const DiscoveryStreamBase = connect(transform)(_DiscoveryStreamBase);
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
|
||||
.outer-wrapper a {
|
||||
color: $grey-90;
|
||||
}
|
||||
|
||||
.discovery-stream.ds-layout {
|
||||
$columns: 12;
|
||||
display: grid;
|
||||
grid-template-columns: repeat($columns, 1fr);
|
||||
grid-column-gap: 48px;
|
||||
grid-row-gap: 10px;
|
||||
width: 936px;
|
||||
margin: 0 auto;
|
||||
|
||||
@while $columns > 0 {
|
||||
.ds-column-#{$columns} {
|
||||
|
|
|
@ -1,15 +1,40 @@
|
|||
import {connect} from "react-redux";
|
||||
import {DSCard} from "../DSCard/DSCard.jsx";
|
||||
import React from "react";
|
||||
|
||||
export class _CardGrid extends React.PureComponent {
|
||||
export class CardGrid extends React.PureComponent {
|
||||
render() {
|
||||
// const feed = this.props.DiscoveryStream.feeds[this.props.feed.url];
|
||||
const {data} = this.props;
|
||||
|
||||
// Handle a render before feed has been fetched by displaying nothing
|
||||
if (!data) {
|
||||
return (
|
||||
<div />
|
||||
);
|
||||
}
|
||||
|
||||
let cards = data.recommendations.slice(0, this.props.items).map((rec, index) => (
|
||||
<DSCard
|
||||
key={`dscard-${index}`}
|
||||
image_src={rec.image_src}
|
||||
title={rec.title}
|
||||
excerpt={rec.title}
|
||||
url={rec.url}
|
||||
id={rec.id}
|
||||
index={index}
|
||||
type={this.props.type}
|
||||
dispatch={this.props.dispatch}
|
||||
source={rec.domain} />
|
||||
));
|
||||
|
||||
return (
|
||||
<div>
|
||||
Card Grid
|
||||
<div className="ds-card-grid">
|
||||
{cards}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const CardGrid = connect(state => ({DiscoveryStream: state.DiscoveryStream}))(_CardGrid);
|
||||
CardGrid.defaultProps = {
|
||||
style: `border`,
|
||||
items: 4, // Number of stories to display
|
||||
};
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
.ds-card-grid {
|
||||
display: grid;
|
||||
|
||||
.ds-card {
|
||||
background: $white;
|
||||
box-shadow: 0 1px 4px $grey-10-10;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
// "2/3 width layout"
|
||||
.ds-column-5 &,
|
||||
.ds-column-6 &,
|
||||
.ds-column-7 &,
|
||||
.ds-column-8 & {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-gap: 24px;
|
||||
}
|
||||
|
||||
// "Full width layout"
|
||||
.ds-column-9 &,
|
||||
.dscolumn-10 &,
|
||||
.ds-column-11 &,
|
||||
.ds-column-12 & {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-gap: 24px;
|
||||
}
|
||||
}
|
|
@ -1,16 +1,36 @@
|
|||
import {actionCreators as ac} from "common/Actions.jsm";
|
||||
import React from "react";
|
||||
|
||||
export class DSCard extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onLinkClick = this.onLinkClick.bind(this);
|
||||
}
|
||||
|
||||
onLinkClick(event) {
|
||||
this.props.dispatch(ac.UserEvent({
|
||||
event: "CLICK",
|
||||
source: this.props.type.toUpperCase(),
|
||||
action_position: this.props.index,
|
||||
}));
|
||||
|
||||
this.props.dispatch(ac.ImpressionStats({
|
||||
source: this.props.type.toUpperCase(),
|
||||
click: 0,
|
||||
tiles: [{id: this.props.id, pos: this.props.index}],
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<a href={this.props.url} className="ds-card">
|
||||
<a href={this.props.url} className="ds-card" onClick={this.onLinkClick}>
|
||||
<div className="img-wrapper">
|
||||
<div className="img" style={{backgroundImage: `url(${this.props.image_src}`}} />
|
||||
</div>
|
||||
<div className="meta">
|
||||
<header>{this.props.title}</header>
|
||||
<p>{this.props.excerpt}</p>
|
||||
<p>{this.props.source}</p>
|
||||
<header className="title">{this.props.title}</header>
|
||||
<p className="excerpt">{this.props.excerpt}</p>
|
||||
<p className="source">{this.props.source}</p>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
// Type sizes
|
||||
$header-font-size: 17;
|
||||
$header-line-height: 24;
|
||||
$excerpt-font-size: 13;
|
||||
$excerpt-line-height: 20;
|
||||
|
||||
.ds-card {
|
||||
border: 5px solid transparent;
|
||||
|
||||
|
@ -11,7 +17,6 @@
|
|||
width: 100%;
|
||||
border: 0.5px solid $black-10;
|
||||
border-radius: 4px;
|
||||
margin: 0 0 12px;
|
||||
}
|
||||
|
||||
.img {
|
||||
|
@ -23,11 +28,21 @@
|
|||
|
||||
.meta {
|
||||
padding: 16px;
|
||||
|
||||
.title {
|
||||
// show only 2 lines of copy
|
||||
@include limit-visibile-lines(2, $header-line-height, $header-font-size);
|
||||
}
|
||||
|
||||
.excerpt {
|
||||
// show only 4 lines of copy
|
||||
@include limit-visibile-lines(4, $excerpt-line-height, $excerpt-font-size);
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
line-height: 24px;
|
||||
font-size: 17px;
|
||||
line-height: $header-line-height * 1px;
|
||||
font-size: $header-font-size * 1px;
|
||||
color: $grey-90;
|
||||
|
||||
&:hover {
|
||||
|
@ -40,8 +55,8 @@
|
|||
}
|
||||
|
||||
p {
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
font-size: $excerpt-font-size * 1px;
|
||||
line-height: $excerpt-line-height * 1px;
|
||||
color: $grey-50;
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
|
|
@ -1,27 +1,52 @@
|
|||
import {connect} from "react-redux";
|
||||
import {actionCreators as ac} from "common/Actions.jsm";
|
||||
import {DSCard} from "../DSCard/DSCard.jsx";
|
||||
import React from "react";
|
||||
|
||||
export class _Hero extends React.PureComponent {
|
||||
export class Hero extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onLinkClick = this.onLinkClick.bind(this);
|
||||
}
|
||||
|
||||
onLinkClick(event) {
|
||||
this.props.dispatch(ac.UserEvent({
|
||||
event: "CLICK",
|
||||
source: this.props.type.toUpperCase(),
|
||||
action_position: 0,
|
||||
}));
|
||||
|
||||
this.props.dispatch(ac.ImpressionStats({
|
||||
source: this.props.type.toUpperCase(),
|
||||
click: 0,
|
||||
tiles: [{id: this.heroRec.id, pos: 0}],
|
||||
}));
|
||||
}
|
||||
|
||||
render() {
|
||||
const feed = this.props.DiscoveryStream.feeds[this.props.feed.url];
|
||||
const {data} = this.props;
|
||||
|
||||
// Handle a render before feed has been fetched by displaying nothing
|
||||
if (!feed) {
|
||||
if (!data || !data.recommendations) {
|
||||
return (
|
||||
<div />
|
||||
);
|
||||
}
|
||||
|
||||
let [heroRec, ...otherRecs] = feed.data.recommendations;
|
||||
let [heroRec, ...otherRecs] = data.recommendations.slice(0, this.props.items);
|
||||
this.heroRec = heroRec;
|
||||
let truncateText = (text, cap) => `${text.substring(0, cap)}${text.length > cap ? `...` : ``}`;
|
||||
|
||||
let cards = otherRecs.slice(1, this.props.items).map((rec, index) => (
|
||||
// Note that `{index + 1}` is necessary below for telemetry since we treat heroRec as index 0.
|
||||
let cards = otherRecs.map((rec, index) => (
|
||||
<DSCard
|
||||
key={`dscard-${index}`}
|
||||
image_src={rec.image_src}
|
||||
title={truncateText(rec.title, 44)}
|
||||
url={rec.url}
|
||||
id={rec.id}
|
||||
index={index + 1}
|
||||
type={this.props.type}
|
||||
dispatch={this.props.dispatch}
|
||||
source={truncateText(`TODO: SOURCE`, 22)} />
|
||||
));
|
||||
|
||||
|
@ -29,7 +54,7 @@ export class _Hero extends React.PureComponent {
|
|||
<div>
|
||||
<div className="ds-header">{this.props.title}</div>
|
||||
<div className={`ds-hero ds-hero-${this.props.style}`}>
|
||||
<a href={heroRec.url} className="wrapper">
|
||||
<a href={heroRec.url} className="wrapper" onClick={this.onLinkClick}>
|
||||
<div className="img-wrapper">
|
||||
<div className="img" style={{backgroundImage: `url(${heroRec.image_src})`}} />
|
||||
</div>
|
||||
|
@ -48,9 +73,8 @@ export class _Hero extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
_Hero.defaultProps = {
|
||||
Hero.defaultProps = {
|
||||
data: {},
|
||||
style: `border`,
|
||||
items: 1, // Number of stories to display
|
||||
};
|
||||
|
||||
export const Hero = connect(state => ({DiscoveryStream: state.DiscoveryStream}))(_Hero);
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.img-wrapper {
|
||||
margin: 0 0 12px;
|
||||
}
|
||||
|
||||
// "1/3 width layout" (aka "Mobile First")
|
||||
.wrapper {
|
||||
color: $grey-50;
|
||||
|
|
|
@ -1,15 +1,60 @@
|
|||
import {connect} from "react-redux";
|
||||
import React from "react";
|
||||
|
||||
export class _List extends React.PureComponent {
|
||||
render() {
|
||||
// const feed = this.props.DiscoveryStream.feeds[this.props.feed.url];
|
||||
return (
|
||||
<div className="ds-list">
|
||||
List
|
||||
</div>
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @note exported for testing only
|
||||
*/
|
||||
export function ListItem(props) {
|
||||
// TODO performance: get feeds to send appropriately sized images rather
|
||||
// than waiting longer and scaling down on client?
|
||||
return (
|
||||
<li className="ds-list-item">
|
||||
<a className="ds-list-item-link" href={props.url}>
|
||||
<div className="ds-list-item-text">
|
||||
<div className="ds-list-item-title">
|
||||
<b>
|
||||
{props.title}
|
||||
</b>
|
||||
</div>
|
||||
<div className="ds-list-item-info">
|
||||
{`${props.domain} · TODO:Topic`}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<img className="ds-list-image" src={props.image_src} />
|
||||
</a>
|
||||
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @note exported for testing only
|
||||
*/
|
||||
export function _List(props) {
|
||||
const feed = props.DiscoveryStream.feeds[props.feed.url];
|
||||
|
||||
if (!feed || !feed.data || !feed.data.recommendations) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const recs = feed.data.recommendations;
|
||||
|
||||
let recMarkup = recs.slice(0, props.items).map((rec, index) => (
|
||||
<ListItem {...rec} key={`ds-list-item-$index`} />)
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3 className="ds-list-title">{props.header && props.header.title}</h3>
|
||||
<hr className="ds-list-border" />
|
||||
<ul className="ds-list">{recMarkup}</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
_List.defaultProps = {
|
||||
items: 6, // Number of stories to display. TODO: get from endpoint
|
||||
};
|
||||
|
||||
export const List = connect(state => ({DiscoveryStream: state.DiscoveryStream}))(_List);
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
.ds-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-row-gap: 10px;
|
||||
grid-column-gap: 24px;
|
||||
|
||||
// reset some stuff from <ul>. Should maybe be hoisted when we have better
|
||||
// regression detection?
|
||||
padding-inline-start: 0;
|
||||
}
|
||||
|
||||
.ds-list-item {
|
||||
// XXX see if we really want absolute units, maybe hoist somewhere central?
|
||||
line-height: 20px;
|
||||
font-size: 13px;
|
||||
|
||||
// reset some stuff from <li>. Should maybe be hoisted when we have better
|
||||
// regression detection?
|
||||
display: block;
|
||||
text-align: start;
|
||||
|
||||
.ds-list-item-link {
|
||||
mix-blend-mode: normal;
|
||||
|
||||
padding-bottom: 16px;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.ds-list-item-info {
|
||||
color: $grey-50;
|
||||
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ds-list-item-title {
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.ds-list-item-text {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ds-list-image {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
object-fit: cover;
|
||||
|
||||
border: 0.5px solid $black-12;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
|
@ -10,5 +10,92 @@
|
|||
.section-top-bar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.top-site-outer {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.top-sites-list {
|
||||
margin: 0 -12px;
|
||||
}
|
||||
}
|
||||
|
||||
// Only show 6 cards for 2/3 and 1/3
|
||||
// XXX hide-for-narrow is wrapping a previous functionality, can do better.
|
||||
.hide-for-narrow {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Only show 8 cards for the full row.
|
||||
// XXX hide-for-narrow is wrapping a previous functionality, can do better.
|
||||
.ds-column-9,
|
||||
.ds-column-10,
|
||||
.ds-column-11,
|
||||
.ds-column-12 {
|
||||
.ds-top-sites {
|
||||
.hide-for-narrow {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Size overrides for topsites in the 2/3 view.
|
||||
.ds-column-5,
|
||||
.ds-column-6,
|
||||
.ds-column-7,
|
||||
.ds-column-8 {
|
||||
.ds-top-sites {
|
||||
|
||||
.top-site-outer {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
.top-sites-list {
|
||||
margin: 0 -10px;
|
||||
}
|
||||
|
||||
.top-site-inner {
|
||||
--leftPanelIconWidth: 84.67px;
|
||||
|
||||
.tile {
|
||||
width: var(--leftPanelIconWidth);
|
||||
height: var(--leftPanelIconWidth);
|
||||
}
|
||||
|
||||
.title {
|
||||
width: var(--leftPanelIconWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Size overrides for topsites in the 1/3 view.
|
||||
.ds-column-1,
|
||||
.ds-column-2,
|
||||
.ds-column-3,
|
||||
.ds-column-4 {
|
||||
.ds-top-sites {
|
||||
|
||||
.top-site-outer {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.top-sites-list {
|
||||
margin: 0 -8px;
|
||||
}
|
||||
|
||||
.top-site-inner {
|
||||
--rightPanelIconWidth: 82.67px;
|
||||
|
||||
.tile {
|
||||
width: var(--rightPanelIconWidth);
|
||||
height: var(--rightPanelIconWidth);
|
||||
}
|
||||
|
||||
.title {
|
||||
width: var(--rightPanelIconWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
import {actionCreators as ac} from "common/Actions.jsm";
|
||||
import React from "react";
|
||||
|
||||
const VISIBLE = "visible";
|
||||
const VISIBILITY_CHANGE_EVENT = "visibilitychange";
|
||||
|
||||
export class ImpressionStats extends React.PureComponent {
|
||||
// This checks if the given cards are the same as those in the last impression ping.
|
||||
// If so, it should not send the same impression ping again.
|
||||
_needsImpressionStats(cards) {
|
||||
if (!this.impressionCardGuids || (this.impressionCardGuids.length !== cards.length)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (let i = 0; i < cards.length; i++) {
|
||||
if (cards[i].id !== this.impressionCardGuids[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_dispatchImpressionStats() {
|
||||
const {props} = this;
|
||||
const cards = props.rows;
|
||||
|
||||
if (this._needsImpressionStats(cards)) {
|
||||
props.dispatch(ac.ImpressionStats({
|
||||
source: props.source.toUpperCase(),
|
||||
tiles: cards.map(link => ({id: link.id})),
|
||||
}));
|
||||
this.impressionCardGuids = cards.map(link => link.id);
|
||||
}
|
||||
}
|
||||
|
||||
// This sends an event when a user sees a set of new content. If content
|
||||
// changes while the page is hidden (i.e. preloaded or on a hidden tab),
|
||||
// only send the event if the page becomes visible again.
|
||||
sendImpressionStatsOrAddListener() {
|
||||
const {props} = this;
|
||||
|
||||
if (!props.dispatch) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.document.visibilityState === VISIBLE) {
|
||||
this._dispatchImpressionStats();
|
||||
} else {
|
||||
// We should only ever send the latest impression stats ping, so remove any
|
||||
// older listeners.
|
||||
if (this._onVisibilityChange) {
|
||||
props.document.removeEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange);
|
||||
}
|
||||
|
||||
this._onVisibilityChange = () => {
|
||||
if (props.document.visibilityState === VISIBLE) {
|
||||
this._dispatchImpressionStats();
|
||||
props.document.removeEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange);
|
||||
}
|
||||
};
|
||||
props.document.addEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.rows.length) {
|
||||
this.sendImpressionStatsOrAddListener();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (this.props.rows.length && this.props.rows !== prevProps.rows) {
|
||||
this.sendImpressionStatsOrAddListener();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this._onVisibilityChange) {
|
||||
this.props.document.removeEventListener(VISIBILITY_CHANGE_EVENT, this._onVisibilityChange);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
ImpressionStats.defaultProps = {
|
||||
document: global.document,
|
||||
rows: [],
|
||||
source: "",
|
||||
};
|
|
@ -29,29 +29,35 @@ export class _Search extends React.PureComponent {
|
|||
window.gContentSearchController.search(event);
|
||||
}
|
||||
|
||||
doSearchHandoff(text) {
|
||||
this.props.dispatch(ac.OnlyToMain({type: at.HANDOFF_SEARCH_TO_AWESOMEBAR, data: {text}}));
|
||||
this.props.dispatch(ac.UserEvent({event: "SEARCH_HANDOFF"}));
|
||||
if (text) {
|
||||
// We don't hide the in-content search if there is no text (user hit <Enter>)
|
||||
this.props.dispatch({type: at.HIDE_SEARCH});
|
||||
}
|
||||
}
|
||||
|
||||
onSearchHandoffClick(event) {
|
||||
// When search hand-off is enabled, we render a big button that is styled to
|
||||
// look like a search textbox. If the button is clicked with the mouse, we style
|
||||
// the button as if it was a focused search box and show a fake cursor but
|
||||
// really focus the awesomebar without the focus styles.
|
||||
// look like a search textbox. If the button is clicked with the mouse, we
|
||||
// focus it. If the user types, transfer focus to awesomebar.
|
||||
// If the button is clicked from the keyboard, we focus the awesomebar normally.
|
||||
// This is to minimize confusion with users navigating with the keyboard and
|
||||
// users using assistive technologoy.
|
||||
event.preventDefault();
|
||||
const isKeyboardClick = event.clientX === 0 && event.clientY === 0;
|
||||
const hiddenFocus = !isKeyboardClick;
|
||||
this.props.dispatch(ac.OnlyToMain({type: at.HANDOFF_SEARCH_TO_AWESOMEBAR, data: {hiddenFocus}}));
|
||||
this.props.dispatch({type: at.FOCUS_SEARCH});
|
||||
|
||||
// TODO: Send a telemetry ping. BUG 1514732
|
||||
if (isKeyboardClick) {
|
||||
this.doSearchHandoff();
|
||||
} else {
|
||||
this._searchHandoffButton.focus();
|
||||
}
|
||||
}
|
||||
|
||||
onSearchHandoffKeyDown(event) {
|
||||
if (event.key.length === 1 && !event.altKey && !event.ctrlKey && !event.metaKey) {
|
||||
// We only care about key strokes that will produce a character.
|
||||
const text = event.key;
|
||||
this.props.dispatch(ac.OnlyToMain({type: at.HANDOFF_SEARCH_TO_AWESOMEBAR, data: {text}}));
|
||||
|
||||
// TODO: Send a telemetry ping. BUG 1514732
|
||||
this.doSearchHandoff(event.key);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,10 +69,7 @@ export class _Search extends React.PureComponent {
|
|||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
const text = event.clipboardData.getData("Text");
|
||||
this.props.dispatch(ac.OnlyToMain({type: at.HANDOFF_SEARCH_TO_AWESOMEBAR, data: {text}}));
|
||||
|
||||
// TODO: Send a telemetry ping. BUG 1514732
|
||||
this.doSearchHandoff(event.clipboardData.getData("Text"));
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
|
@ -127,7 +130,6 @@ export class _Search extends React.PureComponent {
|
|||
const wrapperClassName = [
|
||||
"search-wrapper",
|
||||
this.props.hide && "search-hidden",
|
||||
this.props.focus && "search-active",
|
||||
].filter(v => v).join(" ");
|
||||
|
||||
return (<div className={wrapperClassName}>
|
||||
|
|
|
@ -160,8 +160,7 @@ $glyph-forward: url('chrome://browser/skin/forward.svg');
|
|||
box-shadow: $shadow-secondary, 0 0 0 1px $black-25;
|
||||
}
|
||||
|
||||
&:focus,
|
||||
.search-active & {
|
||||
&:focus {
|
||||
border: $input-border-active;
|
||||
box-shadow: var(--newtab-textbox-focus-boxshadow);
|
||||
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import {createSelector} from "reselect";
|
||||
|
||||
function calculateSpocs(component, spocs) {
|
||||
let spocIndex = 0;
|
||||
return component.spocs.positions.map(position => {
|
||||
const rickRoll = Math.random();
|
||||
if (spocs.data.spocs[spocIndex] && rickRoll <= component.spocs.probability) {
|
||||
return {
|
||||
...position,
|
||||
result: spocs.data.spocs[spocIndex++],
|
||||
};
|
||||
}
|
||||
return position;
|
||||
});
|
||||
}
|
||||
|
||||
export const selectLayoutRender = createSelector(
|
||||
// Selects layout, feeds, spocs so that we only recompute if
|
||||
// any of these values change.
|
||||
[
|
||||
state => state.DiscoveryStream.layout,
|
||||
state => state.DiscoveryStream.feeds,
|
||||
state => state.DiscoveryStream.spocs,
|
||||
],
|
||||
|
||||
// Adds data to each component from feeds. This function only re-runs if one of the inputs change.
|
||||
// TODO: calculate spocs
|
||||
function layoutRender(layout, feeds, spocs) {
|
||||
return layout.map(row => ({
|
||||
...row,
|
||||
|
||||
// Loops through all the components and adds a .data property
|
||||
// containing data from feeds
|
||||
components: row.components.map(component => {
|
||||
if (!component.feed || !feeds[component.feed.url]) {
|
||||
return component;
|
||||
}
|
||||
|
||||
// Calculate if we should display a spoc or not.
|
||||
if (component.spocs && spocs.data.spocs && spocs.data.spocs.length) {
|
||||
component.spocs = {
|
||||
...component.spocs,
|
||||
positions: calculateSpocs(component, spocs),
|
||||
};
|
||||
}
|
||||
|
||||
return {...component, data: feeds[component.feed.url].data};
|
||||
}),
|
||||
}));
|
||||
}
|
||||
);
|
|
@ -2,6 +2,7 @@
|
|||
@import './variables';
|
||||
@import './theme';
|
||||
@import './icons';
|
||||
@import './mixins';
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// Note: lineHeight and fontSize should be unitless but can be derived from pixel values
|
||||
@mixin limit-visibile-lines($line-count, $line-height, $font-size) {
|
||||
max-height: 1em * $line-count * $line-height / $font-size;
|
||||
overflow: hidden;
|
||||
}
|
|
@ -45,6 +45,7 @@ $grey-90-90: rgba($grey-90, 0.9);
|
|||
$black: #000;
|
||||
$black-5: rgba($black, 0.05);
|
||||
$black-10: rgba($black, 0.1);
|
||||
$black-12: rgba($black, 0.12);
|
||||
$black-15: rgba($black, 0.15);
|
||||
$black-20: rgba($black, 0.2);
|
||||
$black-25: rgba($black, 0.25);
|
||||
|
|
|
@ -1066,12 +1066,10 @@ main {
|
|||
background-position-x: right 12px; }
|
||||
.search-handoff-button:hover {
|
||||
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.25); }
|
||||
.search-handoff-button:focus,
|
||||
.search-active .search-handoff-button {
|
||||
.search-handoff-button:focus {
|
||||
border: 1px solid var(--newtab-textbox-focus-color);
|
||||
box-shadow: var(--newtab-textbox-focus-boxshadow); }
|
||||
.search-handoff-button:focus .fake-caret,
|
||||
.search-active .search-handoff-button .fake-caret {
|
||||
.search-handoff-button:focus .fake-caret {
|
||||
display: block; }
|
||||
.search-hidden .search-handoff-button {
|
||||
opacity: 0;
|
||||
|
@ -1631,7 +1629,8 @@ main {
|
|||
margin: 0 auto;
|
||||
font-size: 14px;
|
||||
padding-left: 240px;
|
||||
display: flex; }
|
||||
display: flex;
|
||||
color: var(--newtab-text-primary-color); }
|
||||
.asrouter-admin .sidebar {
|
||||
inset-inline-start: 0;
|
||||
position: fixed;
|
||||
|
@ -1643,9 +1642,10 @@ main {
|
|||
list-style: none; }
|
||||
.asrouter-admin .sidebar li a {
|
||||
padding: 10px 34px;
|
||||
display: block; }
|
||||
display: block;
|
||||
color: var(--lwt-sidebar-text-color); }
|
||||
.asrouter-admin .sidebar li a:hover {
|
||||
background: #EDEDF0; }
|
||||
background: var(--newtab-textbox-background-color); }
|
||||
.asrouter-admin h1 {
|
||||
font-weight: 200;
|
||||
font-size: 32px; }
|
||||
|
@ -1658,7 +1658,7 @@ main {
|
|||
border-collapse: collapse;
|
||||
width: 100%; }
|
||||
.asrouter-admin .sourceLabel {
|
||||
background: #EDEDF0;
|
||||
background: var(--newtab-textbox-background-color);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px; }
|
||||
.asrouter-admin .sourceLabel.isDisabled {
|
||||
|
@ -1706,7 +1706,8 @@ main {
|
|||
padding: 10px;
|
||||
display: flex;
|
||||
background: #FFE900;
|
||||
border-radius: 3px; }
|
||||
border-radius: 3px;
|
||||
color: #0C0C0D; }
|
||||
.asrouter-admin .helpLink a {
|
||||
text-decoration: underline; }
|
||||
.asrouter-admin .dsEnabled {
|
||||
|
@ -1764,11 +1765,16 @@ main {
|
|||
.more-recommendations:dir(rtl)::after {
|
||||
transform: scaleX(-1); }
|
||||
|
||||
.outer-wrapper a {
|
||||
color: #0C0C0D; }
|
||||
|
||||
.discovery-stream.ds-layout {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
grid-column-gap: 48px;
|
||||
grid-row-gap: 10px; }
|
||||
grid-row-gap: 10px;
|
||||
width: 936px;
|
||||
margin: 0 auto; }
|
||||
.discovery-stream.ds-layout .ds-column-12 {
|
||||
grid-column-start: auto;
|
||||
grid-column-end: span 12; }
|
||||
|
@ -1809,6 +1815,26 @@ main {
|
|||
display: grid;
|
||||
grid-row-gap: 10px; }
|
||||
|
||||
.ds-card-grid {
|
||||
display: grid; }
|
||||
.ds-card-grid .ds-card {
|
||||
background: #FFF;
|
||||
box-shadow: 0 1px 4px rgba(249, 249, 250, 0.1);
|
||||
border-radius: 4px;
|
||||
margin-bottom: 24px; }
|
||||
.ds-column-5 .ds-card-grid,
|
||||
.ds-column-6 .ds-card-grid,
|
||||
.ds-column-7 .ds-card-grid,
|
||||
.ds-column-8 .ds-card-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-gap: 24px; }
|
||||
.ds-column-9 .ds-card-grid,
|
||||
.dscolumn-10 .ds-card-grid,
|
||||
.ds-column-11 .ds-card-grid,
|
||||
.ds-column-12 .ds-card-grid {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-gap: 24px; }
|
||||
|
||||
.ds-header {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
|
@ -1829,6 +1855,9 @@ main {
|
|||
.ds-hero .ds-card .meta {
|
||||
padding: 0; }
|
||||
|
||||
.ds-hero .img-wrapper {
|
||||
margin: 0 0 12px; }
|
||||
|
||||
.ds-hero .wrapper {
|
||||
color: #737373;
|
||||
margin: 18px 0;
|
||||
|
@ -1918,6 +1947,42 @@ main {
|
|||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-column-gap: 24px; }
|
||||
|
||||
.ds-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-row-gap: 10px;
|
||||
grid-column-gap: 24px;
|
||||
padding-inline-start: 0; }
|
||||
|
||||
.ds-list-item {
|
||||
line-height: 20px;
|
||||
font-size: 13px;
|
||||
display: block;
|
||||
text-align: start; }
|
||||
.ds-list-item .ds-list-item-link {
|
||||
mix-blend-mode: normal;
|
||||
padding-bottom: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between; }
|
||||
.ds-list-item .ds-list-item-info {
|
||||
color: #737373;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; }
|
||||
.ds-list-item .ds-list-item-title {
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 8px; }
|
||||
.ds-list-item .ds-list-item-text {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column; }
|
||||
.ds-list-item .ds-list-image {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
object-fit: cover;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.12);
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px; }
|
||||
|
||||
.ds-section-title ul {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
@ -1944,6 +2009,77 @@ main {
|
|||
padding: 0; }
|
||||
.ds-top-sites .top-sites .section-top-bar {
|
||||
display: none; }
|
||||
.ds-top-sites .top-sites .top-site-outer {
|
||||
padding: 0 12px; }
|
||||
.ds-top-sites .top-sites .top-sites-list {
|
||||
margin: 0 -12px; }
|
||||
|
||||
.ds-top-sites .hide-for-narrow {
|
||||
display: none; }
|
||||
|
||||
.ds-column-9 .ds-top-sites .hide-for-narrow,
|
||||
.ds-column-10 .ds-top-sites .hide-for-narrow,
|
||||
.ds-column-11 .ds-top-sites .hide-for-narrow,
|
||||
.ds-column-12 .ds-top-sites .hide-for-narrow {
|
||||
display: inline-block; }
|
||||
|
||||
.ds-column-5 .ds-top-sites .top-site-outer,
|
||||
.ds-column-6 .ds-top-sites .top-site-outer,
|
||||
.ds-column-7 .ds-top-sites .top-site-outer,
|
||||
.ds-column-8 .ds-top-sites .top-site-outer {
|
||||
padding: 0 10px; }
|
||||
|
||||
.ds-column-5 .ds-top-sites .top-sites-list,
|
||||
.ds-column-6 .ds-top-sites .top-sites-list,
|
||||
.ds-column-7 .ds-top-sites .top-sites-list,
|
||||
.ds-column-8 .ds-top-sites .top-sites-list {
|
||||
margin: 0 -10px; }
|
||||
|
||||
.ds-column-5 .ds-top-sites .top-site-inner,
|
||||
.ds-column-6 .ds-top-sites .top-site-inner,
|
||||
.ds-column-7 .ds-top-sites .top-site-inner,
|
||||
.ds-column-8 .ds-top-sites .top-site-inner {
|
||||
--leftPanelIconWidth: 84.67px; }
|
||||
.ds-column-5 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-6 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-7 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-8 .ds-top-sites .top-site-inner .tile {
|
||||
width: var(--leftPanelIconWidth);
|
||||
height: var(--leftPanelIconWidth); }
|
||||
.ds-column-5 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-6 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-7 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-8 .ds-top-sites .top-site-inner .title {
|
||||
width: var(--leftPanelIconWidth); }
|
||||
|
||||
.ds-column-1 .ds-top-sites .top-site-outer,
|
||||
.ds-column-2 .ds-top-sites .top-site-outer,
|
||||
.ds-column-3 .ds-top-sites .top-site-outer,
|
||||
.ds-column-4 .ds-top-sites .top-site-outer {
|
||||
padding: 0 8px; }
|
||||
|
||||
.ds-column-1 .ds-top-sites .top-sites-list,
|
||||
.ds-column-2 .ds-top-sites .top-sites-list,
|
||||
.ds-column-3 .ds-top-sites .top-sites-list,
|
||||
.ds-column-4 .ds-top-sites .top-sites-list {
|
||||
margin: 0 -8px; }
|
||||
|
||||
.ds-column-1 .ds-top-sites .top-site-inner,
|
||||
.ds-column-2 .ds-top-sites .top-site-inner,
|
||||
.ds-column-3 .ds-top-sites .top-site-inner,
|
||||
.ds-column-4 .ds-top-sites .top-site-inner {
|
||||
--rightPanelIconWidth: 82.67px; }
|
||||
.ds-column-1 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-2 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-3 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-4 .ds-top-sites .top-site-inner .tile {
|
||||
width: var(--rightPanelIconWidth);
|
||||
height: var(--rightPanelIconWidth); }
|
||||
.ds-column-1 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-2 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-3 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-4 .ds-top-sites .top-site-inner .title {
|
||||
width: var(--rightPanelIconWidth); }
|
||||
|
||||
.ds-card {
|
||||
border: 5px solid transparent; }
|
||||
|
@ -1954,8 +2090,7 @@ main {
|
|||
.ds-card .img-wrapper {
|
||||
width: 100%;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
margin: 0 0 12px; }
|
||||
border-radius: 4px; }
|
||||
.ds-card .img {
|
||||
height: 0;
|
||||
padding-top: 50%;
|
||||
|
@ -1963,6 +2098,12 @@ main {
|
|||
background-size: cover; }
|
||||
.ds-card .meta {
|
||||
padding: 16px; }
|
||||
.ds-card .meta .title {
|
||||
max-height: 2.82353em;
|
||||
overflow: hidden; }
|
||||
.ds-card .meta .excerpt {
|
||||
max-height: 6.15385em;
|
||||
overflow: hidden; }
|
||||
.ds-card header {
|
||||
line-height: 24px;
|
||||
font-size: 17px;
|
||||
|
@ -2187,7 +2328,7 @@ main {
|
|||
z-index: 2100; }
|
||||
.ReturnToAMOOverlay .ReturnToAMOText,
|
||||
.amo + body.hide-main .ReturnToAMOText {
|
||||
color: rgba(12, 12, 13, 0.8);
|
||||
color: #0C0C0D;
|
||||
line-height: 32px;
|
||||
font-size: 23px;
|
||||
width: 100%; }
|
||||
|
@ -2197,18 +2338,18 @@ main {
|
|||
margin-inline-end: 6px; }
|
||||
.ReturnToAMOOverlay h2,
|
||||
.amo + body.hide-main h2 {
|
||||
color: rgba(74, 74, 79, 0.6);
|
||||
color: #4A4A4F;
|
||||
font-weight: 100;
|
||||
margin: 0 0 22px;
|
||||
margin: 0 0 36px;
|
||||
font-size: 36px;
|
||||
line-height: 48px;
|
||||
letter-spacing: 1.2px; }
|
||||
.ReturnToAMOOverlay p,
|
||||
.amo + body.hide-main p {
|
||||
color: rgba(12, 12, 13, 0.5);
|
||||
color: #4A4A4F;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
margin-bottom: 4px; }
|
||||
margin-bottom: 16px; }
|
||||
.ReturnToAMOOverlay .puffy,
|
||||
.amo + body.hide-main .puffy {
|
||||
border-radius: 4px;
|
||||
|
@ -2256,16 +2397,17 @@ main {
|
|||
margin-top: 20px; }
|
||||
.ReturnToAMOOverlay .ReturnToAMOContainer,
|
||||
.amo + body.hide-main .ReturnToAMOContainer {
|
||||
width: 835px;
|
||||
width: 960px;
|
||||
background: #FFF;
|
||||
box-shadow: 0 1px 15px 0 rgba(0, 0, 0, 0.3);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
padding: 38px 96px 28px 48px; }
|
||||
padding: 64px 64px 72px; }
|
||||
.ReturnToAMOOverlay .ReturnToAMOAddonContents,
|
||||
.amo + body.hide-main .ReturnToAMOAddonContents {
|
||||
width: 400px;
|
||||
margin-top: 42px; }
|
||||
width: 560px;
|
||||
margin-top: 32px;
|
||||
margin-inline-end: 24px; }
|
||||
.ReturnToAMOOverlay .ReturnToAMOIcon,
|
||||
.amo + body.hide-main .ReturnToAMOIcon {
|
||||
width: 292px;
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1069,12 +1069,10 @@ main {
|
|||
background-position-x: right 12px; }
|
||||
.search-handoff-button:hover {
|
||||
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.25); }
|
||||
.search-handoff-button:focus,
|
||||
.search-active .search-handoff-button {
|
||||
.search-handoff-button:focus {
|
||||
border: 1px solid var(--newtab-textbox-focus-color);
|
||||
box-shadow: var(--newtab-textbox-focus-boxshadow); }
|
||||
.search-handoff-button:focus .fake-caret,
|
||||
.search-active .search-handoff-button .fake-caret {
|
||||
.search-handoff-button:focus .fake-caret {
|
||||
display: block; }
|
||||
.search-hidden .search-handoff-button {
|
||||
opacity: 0;
|
||||
|
@ -1634,7 +1632,8 @@ main {
|
|||
margin: 0 auto;
|
||||
font-size: 14px;
|
||||
padding-left: 240px;
|
||||
display: flex; }
|
||||
display: flex;
|
||||
color: var(--newtab-text-primary-color); }
|
||||
.asrouter-admin .sidebar {
|
||||
inset-inline-start: 0;
|
||||
position: fixed;
|
||||
|
@ -1646,9 +1645,10 @@ main {
|
|||
list-style: none; }
|
||||
.asrouter-admin .sidebar li a {
|
||||
padding: 10px 34px;
|
||||
display: block; }
|
||||
display: block;
|
||||
color: var(--lwt-sidebar-text-color); }
|
||||
.asrouter-admin .sidebar li a:hover {
|
||||
background: #EDEDF0; }
|
||||
background: var(--newtab-textbox-background-color); }
|
||||
.asrouter-admin h1 {
|
||||
font-weight: 200;
|
||||
font-size: 32px; }
|
||||
|
@ -1661,7 +1661,7 @@ main {
|
|||
border-collapse: collapse;
|
||||
width: 100%; }
|
||||
.asrouter-admin .sourceLabel {
|
||||
background: #EDEDF0;
|
||||
background: var(--newtab-textbox-background-color);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px; }
|
||||
.asrouter-admin .sourceLabel.isDisabled {
|
||||
|
@ -1709,7 +1709,8 @@ main {
|
|||
padding: 10px;
|
||||
display: flex;
|
||||
background: #FFE900;
|
||||
border-radius: 3px; }
|
||||
border-radius: 3px;
|
||||
color: #0C0C0D; }
|
||||
.asrouter-admin .helpLink a {
|
||||
text-decoration: underline; }
|
||||
.asrouter-admin .dsEnabled {
|
||||
|
@ -1767,11 +1768,16 @@ main {
|
|||
.more-recommendations:dir(rtl)::after {
|
||||
transform: scaleX(-1); }
|
||||
|
||||
.outer-wrapper a {
|
||||
color: #0C0C0D; }
|
||||
|
||||
.discovery-stream.ds-layout {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
grid-column-gap: 48px;
|
||||
grid-row-gap: 10px; }
|
||||
grid-row-gap: 10px;
|
||||
width: 936px;
|
||||
margin: 0 auto; }
|
||||
.discovery-stream.ds-layout .ds-column-12 {
|
||||
grid-column-start: auto;
|
||||
grid-column-end: span 12; }
|
||||
|
@ -1812,6 +1818,26 @@ main {
|
|||
display: grid;
|
||||
grid-row-gap: 10px; }
|
||||
|
||||
.ds-card-grid {
|
||||
display: grid; }
|
||||
.ds-card-grid .ds-card {
|
||||
background: #FFF;
|
||||
box-shadow: 0 1px 4px rgba(249, 249, 250, 0.1);
|
||||
border-radius: 4px;
|
||||
margin-bottom: 24px; }
|
||||
.ds-column-5 .ds-card-grid,
|
||||
.ds-column-6 .ds-card-grid,
|
||||
.ds-column-7 .ds-card-grid,
|
||||
.ds-column-8 .ds-card-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-gap: 24px; }
|
||||
.ds-column-9 .ds-card-grid,
|
||||
.dscolumn-10 .ds-card-grid,
|
||||
.ds-column-11 .ds-card-grid,
|
||||
.ds-column-12 .ds-card-grid {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-gap: 24px; }
|
||||
|
||||
.ds-header {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
|
@ -1832,6 +1858,9 @@ main {
|
|||
.ds-hero .ds-card .meta {
|
||||
padding: 0; }
|
||||
|
||||
.ds-hero .img-wrapper {
|
||||
margin: 0 0 12px; }
|
||||
|
||||
.ds-hero .wrapper {
|
||||
color: #737373;
|
||||
margin: 18px 0;
|
||||
|
@ -1921,6 +1950,42 @@ main {
|
|||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-column-gap: 24px; }
|
||||
|
||||
.ds-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-row-gap: 10px;
|
||||
grid-column-gap: 24px;
|
||||
padding-inline-start: 0; }
|
||||
|
||||
.ds-list-item {
|
||||
line-height: 20px;
|
||||
font-size: 13px;
|
||||
display: block;
|
||||
text-align: start; }
|
||||
.ds-list-item .ds-list-item-link {
|
||||
mix-blend-mode: normal;
|
||||
padding-bottom: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between; }
|
||||
.ds-list-item .ds-list-item-info {
|
||||
color: #737373;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; }
|
||||
.ds-list-item .ds-list-item-title {
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 8px; }
|
||||
.ds-list-item .ds-list-item-text {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column; }
|
||||
.ds-list-item .ds-list-image {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
object-fit: cover;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.12);
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px; }
|
||||
|
||||
.ds-section-title ul {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
@ -1947,6 +2012,77 @@ main {
|
|||
padding: 0; }
|
||||
.ds-top-sites .top-sites .section-top-bar {
|
||||
display: none; }
|
||||
.ds-top-sites .top-sites .top-site-outer {
|
||||
padding: 0 12px; }
|
||||
.ds-top-sites .top-sites .top-sites-list {
|
||||
margin: 0 -12px; }
|
||||
|
||||
.ds-top-sites .hide-for-narrow {
|
||||
display: none; }
|
||||
|
||||
.ds-column-9 .ds-top-sites .hide-for-narrow,
|
||||
.ds-column-10 .ds-top-sites .hide-for-narrow,
|
||||
.ds-column-11 .ds-top-sites .hide-for-narrow,
|
||||
.ds-column-12 .ds-top-sites .hide-for-narrow {
|
||||
display: inline-block; }
|
||||
|
||||
.ds-column-5 .ds-top-sites .top-site-outer,
|
||||
.ds-column-6 .ds-top-sites .top-site-outer,
|
||||
.ds-column-7 .ds-top-sites .top-site-outer,
|
||||
.ds-column-8 .ds-top-sites .top-site-outer {
|
||||
padding: 0 10px; }
|
||||
|
||||
.ds-column-5 .ds-top-sites .top-sites-list,
|
||||
.ds-column-6 .ds-top-sites .top-sites-list,
|
||||
.ds-column-7 .ds-top-sites .top-sites-list,
|
||||
.ds-column-8 .ds-top-sites .top-sites-list {
|
||||
margin: 0 -10px; }
|
||||
|
||||
.ds-column-5 .ds-top-sites .top-site-inner,
|
||||
.ds-column-6 .ds-top-sites .top-site-inner,
|
||||
.ds-column-7 .ds-top-sites .top-site-inner,
|
||||
.ds-column-8 .ds-top-sites .top-site-inner {
|
||||
--leftPanelIconWidth: 84.67px; }
|
||||
.ds-column-5 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-6 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-7 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-8 .ds-top-sites .top-site-inner .tile {
|
||||
width: var(--leftPanelIconWidth);
|
||||
height: var(--leftPanelIconWidth); }
|
||||
.ds-column-5 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-6 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-7 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-8 .ds-top-sites .top-site-inner .title {
|
||||
width: var(--leftPanelIconWidth); }
|
||||
|
||||
.ds-column-1 .ds-top-sites .top-site-outer,
|
||||
.ds-column-2 .ds-top-sites .top-site-outer,
|
||||
.ds-column-3 .ds-top-sites .top-site-outer,
|
||||
.ds-column-4 .ds-top-sites .top-site-outer {
|
||||
padding: 0 8px; }
|
||||
|
||||
.ds-column-1 .ds-top-sites .top-sites-list,
|
||||
.ds-column-2 .ds-top-sites .top-sites-list,
|
||||
.ds-column-3 .ds-top-sites .top-sites-list,
|
||||
.ds-column-4 .ds-top-sites .top-sites-list {
|
||||
margin: 0 -8px; }
|
||||
|
||||
.ds-column-1 .ds-top-sites .top-site-inner,
|
||||
.ds-column-2 .ds-top-sites .top-site-inner,
|
||||
.ds-column-3 .ds-top-sites .top-site-inner,
|
||||
.ds-column-4 .ds-top-sites .top-site-inner {
|
||||
--rightPanelIconWidth: 82.67px; }
|
||||
.ds-column-1 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-2 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-3 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-4 .ds-top-sites .top-site-inner .tile {
|
||||
width: var(--rightPanelIconWidth);
|
||||
height: var(--rightPanelIconWidth); }
|
||||
.ds-column-1 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-2 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-3 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-4 .ds-top-sites .top-site-inner .title {
|
||||
width: var(--rightPanelIconWidth); }
|
||||
|
||||
.ds-card {
|
||||
border: 5px solid transparent; }
|
||||
|
@ -1957,8 +2093,7 @@ main {
|
|||
.ds-card .img-wrapper {
|
||||
width: 100%;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
margin: 0 0 12px; }
|
||||
border-radius: 4px; }
|
||||
.ds-card .img {
|
||||
height: 0;
|
||||
padding-top: 50%;
|
||||
|
@ -1966,6 +2101,12 @@ main {
|
|||
background-size: cover; }
|
||||
.ds-card .meta {
|
||||
padding: 16px; }
|
||||
.ds-card .meta .title {
|
||||
max-height: 2.82353em;
|
||||
overflow: hidden; }
|
||||
.ds-card .meta .excerpt {
|
||||
max-height: 6.15385em;
|
||||
overflow: hidden; }
|
||||
.ds-card header {
|
||||
line-height: 24px;
|
||||
font-size: 17px;
|
||||
|
@ -2190,7 +2331,7 @@ main {
|
|||
z-index: 2100; }
|
||||
.ReturnToAMOOverlay .ReturnToAMOText,
|
||||
.amo + body.hide-main .ReturnToAMOText {
|
||||
color: rgba(12, 12, 13, 0.8);
|
||||
color: #0C0C0D;
|
||||
line-height: 32px;
|
||||
font-size: 23px;
|
||||
width: 100%; }
|
||||
|
@ -2200,18 +2341,18 @@ main {
|
|||
margin-inline-end: 6px; }
|
||||
.ReturnToAMOOverlay h2,
|
||||
.amo + body.hide-main h2 {
|
||||
color: rgba(74, 74, 79, 0.6);
|
||||
color: #4A4A4F;
|
||||
font-weight: 100;
|
||||
margin: 0 0 22px;
|
||||
margin: 0 0 36px;
|
||||
font-size: 36px;
|
||||
line-height: 48px;
|
||||
letter-spacing: 1.2px; }
|
||||
.ReturnToAMOOverlay p,
|
||||
.amo + body.hide-main p {
|
||||
color: rgba(12, 12, 13, 0.5);
|
||||
color: #4A4A4F;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
margin-bottom: 4px; }
|
||||
margin-bottom: 16px; }
|
||||
.ReturnToAMOOverlay .puffy,
|
||||
.amo + body.hide-main .puffy {
|
||||
border-radius: 4px;
|
||||
|
@ -2259,16 +2400,17 @@ main {
|
|||
margin-top: 20px; }
|
||||
.ReturnToAMOOverlay .ReturnToAMOContainer,
|
||||
.amo + body.hide-main .ReturnToAMOContainer {
|
||||
width: 835px;
|
||||
width: 960px;
|
||||
background: #FFF;
|
||||
box-shadow: 0 1px 15px 0 rgba(0, 0, 0, 0.3);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
padding: 38px 96px 28px 48px; }
|
||||
padding: 64px 64px 72px; }
|
||||
.ReturnToAMOOverlay .ReturnToAMOAddonContents,
|
||||
.amo + body.hide-main .ReturnToAMOAddonContents {
|
||||
width: 400px;
|
||||
margin-top: 42px; }
|
||||
width: 560px;
|
||||
margin-top: 32px;
|
||||
margin-inline-end: 24px; }
|
||||
.ReturnToAMOOverlay .ReturnToAMOIcon,
|
||||
.amo + body.hide-main .ReturnToAMOIcon {
|
||||
width: 292px;
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1066,12 +1066,10 @@ main {
|
|||
background-position-x: right 12px; }
|
||||
.search-handoff-button:hover {
|
||||
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.25); }
|
||||
.search-handoff-button:focus,
|
||||
.search-active .search-handoff-button {
|
||||
.search-handoff-button:focus {
|
||||
border: 1px solid var(--newtab-textbox-focus-color);
|
||||
box-shadow: var(--newtab-textbox-focus-boxshadow); }
|
||||
.search-handoff-button:focus .fake-caret,
|
||||
.search-active .search-handoff-button .fake-caret {
|
||||
.search-handoff-button:focus .fake-caret {
|
||||
display: block; }
|
||||
.search-hidden .search-handoff-button {
|
||||
opacity: 0;
|
||||
|
@ -1631,7 +1629,8 @@ main {
|
|||
margin: 0 auto;
|
||||
font-size: 14px;
|
||||
padding-left: 240px;
|
||||
display: flex; }
|
||||
display: flex;
|
||||
color: var(--newtab-text-primary-color); }
|
||||
.asrouter-admin .sidebar {
|
||||
inset-inline-start: 0;
|
||||
position: fixed;
|
||||
|
@ -1643,9 +1642,10 @@ main {
|
|||
list-style: none; }
|
||||
.asrouter-admin .sidebar li a {
|
||||
padding: 10px 34px;
|
||||
display: block; }
|
||||
display: block;
|
||||
color: var(--lwt-sidebar-text-color); }
|
||||
.asrouter-admin .sidebar li a:hover {
|
||||
background: #EDEDF0; }
|
||||
background: var(--newtab-textbox-background-color); }
|
||||
.asrouter-admin h1 {
|
||||
font-weight: 200;
|
||||
font-size: 32px; }
|
||||
|
@ -1658,7 +1658,7 @@ main {
|
|||
border-collapse: collapse;
|
||||
width: 100%; }
|
||||
.asrouter-admin .sourceLabel {
|
||||
background: #EDEDF0;
|
||||
background: var(--newtab-textbox-background-color);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px; }
|
||||
.asrouter-admin .sourceLabel.isDisabled {
|
||||
|
@ -1706,7 +1706,8 @@ main {
|
|||
padding: 10px;
|
||||
display: flex;
|
||||
background: #FFE900;
|
||||
border-radius: 3px; }
|
||||
border-radius: 3px;
|
||||
color: #0C0C0D; }
|
||||
.asrouter-admin .helpLink a {
|
||||
text-decoration: underline; }
|
||||
.asrouter-admin .dsEnabled {
|
||||
|
@ -1764,11 +1765,16 @@ main {
|
|||
.more-recommendations:dir(rtl)::after {
|
||||
transform: scaleX(-1); }
|
||||
|
||||
.outer-wrapper a {
|
||||
color: #0C0C0D; }
|
||||
|
||||
.discovery-stream.ds-layout {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(12, 1fr);
|
||||
grid-column-gap: 48px;
|
||||
grid-row-gap: 10px; }
|
||||
grid-row-gap: 10px;
|
||||
width: 936px;
|
||||
margin: 0 auto; }
|
||||
.discovery-stream.ds-layout .ds-column-12 {
|
||||
grid-column-start: auto;
|
||||
grid-column-end: span 12; }
|
||||
|
@ -1809,6 +1815,26 @@ main {
|
|||
display: grid;
|
||||
grid-row-gap: 10px; }
|
||||
|
||||
.ds-card-grid {
|
||||
display: grid; }
|
||||
.ds-card-grid .ds-card {
|
||||
background: #FFF;
|
||||
box-shadow: 0 1px 4px rgba(249, 249, 250, 0.1);
|
||||
border-radius: 4px;
|
||||
margin-bottom: 24px; }
|
||||
.ds-column-5 .ds-card-grid,
|
||||
.ds-column-6 .ds-card-grid,
|
||||
.ds-column-7 .ds-card-grid,
|
||||
.ds-column-8 .ds-card-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-gap: 24px; }
|
||||
.ds-column-9 .ds-card-grid,
|
||||
.dscolumn-10 .ds-card-grid,
|
||||
.ds-column-11 .ds-card-grid,
|
||||
.ds-column-12 .ds-card-grid {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-gap: 24px; }
|
||||
|
||||
.ds-header {
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
|
@ -1829,6 +1855,9 @@ main {
|
|||
.ds-hero .ds-card .meta {
|
||||
padding: 0; }
|
||||
|
||||
.ds-hero .img-wrapper {
|
||||
margin: 0 0 12px; }
|
||||
|
||||
.ds-hero .wrapper {
|
||||
color: #737373;
|
||||
margin: 18px 0;
|
||||
|
@ -1918,6 +1947,42 @@ main {
|
|||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-column-gap: 24px; }
|
||||
|
||||
.ds-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-row-gap: 10px;
|
||||
grid-column-gap: 24px;
|
||||
padding-inline-start: 0; }
|
||||
|
||||
.ds-list-item {
|
||||
line-height: 20px;
|
||||
font-size: 13px;
|
||||
display: block;
|
||||
text-align: start; }
|
||||
.ds-list-item .ds-list-item-link {
|
||||
mix-blend-mode: normal;
|
||||
padding-bottom: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between; }
|
||||
.ds-list-item .ds-list-item-info {
|
||||
color: #737373;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; }
|
||||
.ds-list-item .ds-list-item-title {
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 8px; }
|
||||
.ds-list-item .ds-list-item-text {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column; }
|
||||
.ds-list-item .ds-list-image {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
object-fit: cover;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.12);
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px; }
|
||||
|
||||
.ds-section-title ul {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
@ -1944,6 +2009,77 @@ main {
|
|||
padding: 0; }
|
||||
.ds-top-sites .top-sites .section-top-bar {
|
||||
display: none; }
|
||||
.ds-top-sites .top-sites .top-site-outer {
|
||||
padding: 0 12px; }
|
||||
.ds-top-sites .top-sites .top-sites-list {
|
||||
margin: 0 -12px; }
|
||||
|
||||
.ds-top-sites .hide-for-narrow {
|
||||
display: none; }
|
||||
|
||||
.ds-column-9 .ds-top-sites .hide-for-narrow,
|
||||
.ds-column-10 .ds-top-sites .hide-for-narrow,
|
||||
.ds-column-11 .ds-top-sites .hide-for-narrow,
|
||||
.ds-column-12 .ds-top-sites .hide-for-narrow {
|
||||
display: inline-block; }
|
||||
|
||||
.ds-column-5 .ds-top-sites .top-site-outer,
|
||||
.ds-column-6 .ds-top-sites .top-site-outer,
|
||||
.ds-column-7 .ds-top-sites .top-site-outer,
|
||||
.ds-column-8 .ds-top-sites .top-site-outer {
|
||||
padding: 0 10px; }
|
||||
|
||||
.ds-column-5 .ds-top-sites .top-sites-list,
|
||||
.ds-column-6 .ds-top-sites .top-sites-list,
|
||||
.ds-column-7 .ds-top-sites .top-sites-list,
|
||||
.ds-column-8 .ds-top-sites .top-sites-list {
|
||||
margin: 0 -10px; }
|
||||
|
||||
.ds-column-5 .ds-top-sites .top-site-inner,
|
||||
.ds-column-6 .ds-top-sites .top-site-inner,
|
||||
.ds-column-7 .ds-top-sites .top-site-inner,
|
||||
.ds-column-8 .ds-top-sites .top-site-inner {
|
||||
--leftPanelIconWidth: 84.67px; }
|
||||
.ds-column-5 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-6 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-7 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-8 .ds-top-sites .top-site-inner .tile {
|
||||
width: var(--leftPanelIconWidth);
|
||||
height: var(--leftPanelIconWidth); }
|
||||
.ds-column-5 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-6 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-7 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-8 .ds-top-sites .top-site-inner .title {
|
||||
width: var(--leftPanelIconWidth); }
|
||||
|
||||
.ds-column-1 .ds-top-sites .top-site-outer,
|
||||
.ds-column-2 .ds-top-sites .top-site-outer,
|
||||
.ds-column-3 .ds-top-sites .top-site-outer,
|
||||
.ds-column-4 .ds-top-sites .top-site-outer {
|
||||
padding: 0 8px; }
|
||||
|
||||
.ds-column-1 .ds-top-sites .top-sites-list,
|
||||
.ds-column-2 .ds-top-sites .top-sites-list,
|
||||
.ds-column-3 .ds-top-sites .top-sites-list,
|
||||
.ds-column-4 .ds-top-sites .top-sites-list {
|
||||
margin: 0 -8px; }
|
||||
|
||||
.ds-column-1 .ds-top-sites .top-site-inner,
|
||||
.ds-column-2 .ds-top-sites .top-site-inner,
|
||||
.ds-column-3 .ds-top-sites .top-site-inner,
|
||||
.ds-column-4 .ds-top-sites .top-site-inner {
|
||||
--rightPanelIconWidth: 82.67px; }
|
||||
.ds-column-1 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-2 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-3 .ds-top-sites .top-site-inner .tile,
|
||||
.ds-column-4 .ds-top-sites .top-site-inner .tile {
|
||||
width: var(--rightPanelIconWidth);
|
||||
height: var(--rightPanelIconWidth); }
|
||||
.ds-column-1 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-2 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-3 .ds-top-sites .top-site-inner .title,
|
||||
.ds-column-4 .ds-top-sites .top-site-inner .title {
|
||||
width: var(--rightPanelIconWidth); }
|
||||
|
||||
.ds-card {
|
||||
border: 5px solid transparent; }
|
||||
|
@ -1954,8 +2090,7 @@ main {
|
|||
.ds-card .img-wrapper {
|
||||
width: 100%;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
margin: 0 0 12px; }
|
||||
border-radius: 4px; }
|
||||
.ds-card .img {
|
||||
height: 0;
|
||||
padding-top: 50%;
|
||||
|
@ -1963,6 +2098,12 @@ main {
|
|||
background-size: cover; }
|
||||
.ds-card .meta {
|
||||
padding: 16px; }
|
||||
.ds-card .meta .title {
|
||||
max-height: 2.82353em;
|
||||
overflow: hidden; }
|
||||
.ds-card .meta .excerpt {
|
||||
max-height: 6.15385em;
|
||||
overflow: hidden; }
|
||||
.ds-card header {
|
||||
line-height: 24px;
|
||||
font-size: 17px;
|
||||
|
@ -2187,7 +2328,7 @@ main {
|
|||
z-index: 2100; }
|
||||
.ReturnToAMOOverlay .ReturnToAMOText,
|
||||
.amo + body.hide-main .ReturnToAMOText {
|
||||
color: rgba(12, 12, 13, 0.8);
|
||||
color: #0C0C0D;
|
||||
line-height: 32px;
|
||||
font-size: 23px;
|
||||
width: 100%; }
|
||||
|
@ -2197,18 +2338,18 @@ main {
|
|||
margin-inline-end: 6px; }
|
||||
.ReturnToAMOOverlay h2,
|
||||
.amo + body.hide-main h2 {
|
||||
color: rgba(74, 74, 79, 0.6);
|
||||
color: #4A4A4F;
|
||||
font-weight: 100;
|
||||
margin: 0 0 22px;
|
||||
margin: 0 0 36px;
|
||||
font-size: 36px;
|
||||
line-height: 48px;
|
||||
letter-spacing: 1.2px; }
|
||||
.ReturnToAMOOverlay p,
|
||||
.amo + body.hide-main p {
|
||||
color: rgba(12, 12, 13, 0.5);
|
||||
color: #4A4A4F;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
margin-bottom: 4px; }
|
||||
margin-bottom: 16px; }
|
||||
.ReturnToAMOOverlay .puffy,
|
||||
.amo + body.hide-main .puffy {
|
||||
border-radius: 4px;
|
||||
|
@ -2256,16 +2397,17 @@ main {
|
|||
margin-top: 20px; }
|
||||
.ReturnToAMOOverlay .ReturnToAMOContainer,
|
||||
.amo + body.hide-main .ReturnToAMOContainer {
|
||||
width: 835px;
|
||||
width: 960px;
|
||||
background: #FFF;
|
||||
box-shadow: 0 1px 15px 0 rgba(0, 0, 0, 0.3);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
padding: 38px 96px 28px 48px; }
|
||||
padding: 64px 64px 72px; }
|
||||
.ReturnToAMOOverlay .ReturnToAMOAddonContents,
|
||||
.amo + body.hide-main .ReturnToAMOAddonContents {
|
||||
width: 400px;
|
||||
margin-top: 42px; }
|
||||
width: 560px;
|
||||
margin-top: 32px;
|
||||
margin-inline-end: 24px; }
|
||||
.ReturnToAMOOverlay .ReturnToAMOIcon,
|
||||
.amo + body.hide-main .ReturnToAMOIcon {
|
||||
width: 292px;
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -66,7 +66,7 @@ A user event ping includes some basic metadata (tab id, addon version, etc.) as
|
|||
```js
|
||||
{
|
||||
// This indicates the type of interaction
|
||||
"event": ["CLICK", "SEARCH", "BLOCK", "DELETE", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "BOOKMARK_DELETE", "BOOKMARK_ADD", "OPEN_NEWTAB_PREFS", "CLOSE_NEWTAB_PREFS"],
|
||||
"event": ["CLICK", "SEARCH", "BLOCK", "DELETE", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "BOOKMARK_DELETE", "BOOKMARK_ADD", "OPEN_NEWTAB_PREFS", "CLOSE_NEWTAB_PREFS", "SEARCH_HANDOFF"],
|
||||
|
||||
// Optional field indicating the UI component type
|
||||
"source": "TOP_SITES",
|
||||
|
@ -106,6 +106,23 @@ A user event ping includes some basic metadata (tab id, addon version, etc.) as
|
|||
}
|
||||
```
|
||||
|
||||
#### Performing a search handoff
|
||||
|
||||
```js
|
||||
{
|
||||
"event": "SEARCH_HANDOFF",
|
||||
|
||||
// Basic metadata
|
||||
"action": "activity_stream_event",
|
||||
"page": ["about:newtab" | "about:home" | "about:welcome" | "unknown"],
|
||||
"client_id": "26288a14-5cc4-d14f-ae0a-bb01ef45be9c",
|
||||
"session_id": "005deed0-e3e4-4c02-a041-17405fd703f6",
|
||||
"addon_version": "20180710100040",
|
||||
"locale": "en-US",
|
||||
"user_prefs": 7
|
||||
}
|
||||
```
|
||||
|
||||
#### Clicking a top site item
|
||||
|
||||
```js
|
||||
|
|
|
@ -10,6 +10,8 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
AddonManager: "resource://gre/modules/AddonManager.jsm",
|
||||
UITour: "resource:///modules/UITour.jsm",
|
||||
FxAccounts: "resource://gre/modules/FxAccounts.jsm",
|
||||
AppConstants: "resource://gre/modules/AppConstants.jsm",
|
||||
OS: "resource://gre/modules/osfile.jsm",
|
||||
});
|
||||
const {ASRouterActions: ra, actionTypes: at, actionCreators: ac} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm", {});
|
||||
const {CFRMessageProvider} = ChromeUtils.import("resource://activity-stream/lib/CFRMessageProvider.jsm", {});
|
||||
|
@ -948,24 +950,49 @@ class _ASRouter {
|
|||
}
|
||||
}
|
||||
|
||||
// Windows specific calls to write attribution data
|
||||
// Used by `forceAttribution` to set required targeting attributes for
|
||||
// RTAMO messages. This should only be called from within about:newtab#asrouter
|
||||
/* istanbul ignore next */
|
||||
async _writeAttributionFile(data) {
|
||||
let appDir = Services.dirsvc.get("LocalAppData", Ci.nsIFile);
|
||||
let file = appDir.clone();
|
||||
file.append(Services.appinfo.vendor || "mozilla");
|
||||
file.append(AppConstants.MOZ_APP_NAME);
|
||||
|
||||
await OS.File.makeDir(file.path,
|
||||
{from: appDir.path, ignoreExisting: true});
|
||||
|
||||
file.append("postSigningData");
|
||||
await OS.File.writeAtomic(file.path, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* forceAttribution - this function should only be called from within about:newtab#asrouter.
|
||||
* It forces the browser attribution to be set to something specified in asrouter admin
|
||||
* tools, and reloads the providers in order to get messages that are dependant on this
|
||||
* attribution data (see Return to AMO flow in bug 1475354 for example). Note - only works with OSX
|
||||
* attribution data (see Return to AMO flow in bug 1475354 for example). Note - OSX and Windows only
|
||||
* @param {data} Object an object containing the attribtion data that came from asrouter admin page
|
||||
*/
|
||||
/* istanbul ignore next */
|
||||
async forceAttribution(data) {
|
||||
// Extract the parameters from data that will make up the referrer url
|
||||
const {source, campaign, content} = data;
|
||||
let appPath = Services.dirsvc.get("GreD", Ci.nsIFile).parent.parent.path;
|
||||
let attributionSvc = Cc["@mozilla.org/mac-attribution;1"]
|
||||
.getService(Ci.nsIMacAttributionService);
|
||||
if (AppConstants.platform === "win") {
|
||||
const attributionData = `source=${source}&campaign=${campaign}&content=${content}`;
|
||||
this._writeAttributionFile(encodeURIComponent(attributionData));
|
||||
} else if (AppConstants.platform === "macosx") {
|
||||
let appPath = Services.dirsvc.get("GreD", Ci.nsIFile).parent.parent.path;
|
||||
let attributionSvc = Cc["@mozilla.org/mac-attribution;1"]
|
||||
.getService(Ci.nsIMacAttributionService);
|
||||
|
||||
let referrer = `https://www.mozilla.org/anything/?utm_campaign=${campaign}&utm_source=${source}&utm_content=${encodeURIComponent(content)}`;
|
||||
let referrer = `https://www.mozilla.org/anything/?utm_campaign=${campaign}&utm_source=${source}&utm_content=${encodeURIComponent(content)}`;
|
||||
|
||||
// This sets the Attribution to be the referrer
|
||||
attributionSvc.setReferrerUrl(appPath, referrer, true);
|
||||
// This sets the Attribution to be the referrer
|
||||
attributionSvc.setReferrerUrl(appPath, referrer, true);
|
||||
}
|
||||
|
||||
// Clear cache call is only possible in a testing environment
|
||||
let env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
||||
env.set("XPCSHELL_TEST_PROFILE_DIR", "testing");
|
||||
|
||||
|
|
|
@ -286,41 +286,28 @@ class PlacesFeed {
|
|||
handoffSearchToAwesomebar({_target, data, meta}) {
|
||||
const urlBar = _target.browser.ownerGlobal.gURLBar;
|
||||
|
||||
if (!data.hiddenFocus && !data.text) {
|
||||
// Do a normal focus of awesomebar and reset the in content search (remove fake focus styles).
|
||||
if (!data.text) {
|
||||
// Do a normal focus of awesomebar.
|
||||
urlBar.focus();
|
||||
this.store.dispatch(ac.OnlyToOneContent({type: at.SHOW_SEARCH}, meta.fromTarget));
|
||||
// We are done here. return early.
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.text) {
|
||||
// Pass the provided text to the awesomebar.
|
||||
urlBar.search(data.text);
|
||||
this.store.dispatch(ac.OnlyToOneContent({type: at.HIDE_SEARCH}, meta.fromTarget));
|
||||
} else {
|
||||
// Focus the awesomebar without the style changes.
|
||||
urlBar.hiddenFocus();
|
||||
}
|
||||
// Pass the provided text to the awesomebar.
|
||||
urlBar.search(data.text);
|
||||
|
||||
const onKeydown = event => {
|
||||
// We only care about key strokes that will produce a character.
|
||||
if (event.key.length === 1 && !event.altKey && !event.ctrlKey && !event.metaKey) {
|
||||
// Once the user starts typing, we want to hide the in content search box
|
||||
// and show the focus styles on the awesomebar.
|
||||
this.store.dispatch(ac.OnlyToOneContent({type: at.HIDE_SEARCH}, meta.fromTarget));
|
||||
urlBar.removeHiddenFocus();
|
||||
urlBar.removeEventListener("keydown", onKeydown);
|
||||
}
|
||||
};
|
||||
const onDone = () => {
|
||||
// When done, let's cleanup everything.
|
||||
this.store.dispatch(ac.OnlyToOneContent({type: at.SHOW_SEARCH}, meta.fromTarget));
|
||||
urlBar.removeHiddenFocus();
|
||||
urlBar.removeEventListener("keydown", onKeydown);
|
||||
urlBar.removeEventListener("mousedown", onDone);
|
||||
urlBar.removeEventListener("blur", onDone);
|
||||
};
|
||||
const onKeydown = event => {
|
||||
// If the Esc button is pressed, we are done. Show in-content search and cleanup.
|
||||
if (event.key === "Escape") {
|
||||
onDone();
|
||||
}
|
||||
};
|
||||
urlBar.addEventListener("keydown", onKeydown);
|
||||
urlBar.addEventListener("mousedown", onDone);
|
||||
urlBar.addEventListener("blur", onDone);
|
||||
|
|
|
@ -126,7 +126,7 @@ topsites_form_edit_header=Wichtige Seite bearbeiten
|
|||
topsites_form_title_label=Titel
|
||||
topsites_form_title_placeholder=Name eingeben
|
||||
topsites_form_url_label=Adresse
|
||||
topsites_form_image_url_label=URL von benutzerdefinierter Grafik
|
||||
topsites_form_image_url_label=Adresse von benutzerdefinierter Grafik
|
||||
topsites_form_url_placeholder=Eine Adresse eingeben oder einfügen
|
||||
topsites_form_use_image_link=Eine benutzerdefinierte Grafik verwenden…
|
||||
# LOCALIZATION NOTE (topsites_form_*_button): These are verbs/actions.
|
||||
|
@ -134,8 +134,8 @@ topsites_form_preview_button=Vorschau
|
|||
topsites_form_add_button=Hinzufügen
|
||||
topsites_form_save_button=Speichern
|
||||
topsites_form_cancel_button=Abbrechen
|
||||
topsites_form_url_validation=Gültige URL erforderlich
|
||||
topsites_form_image_validation=Grafik konnte nicht geladen werden. Verwenden Sie eine andere URL.
|
||||
topsites_form_url_validation=Gültige Adresse erforderlich
|
||||
topsites_form_image_validation=Grafik konnte nicht geladen werden. Verwenden Sie eine andere Adresse.
|
||||
|
||||
# LOCALIZATION NOTE (pocket_read_more): This is shown at the bottom of the
|
||||
# trending stories section and precedes a list of links to popular topics.
|
||||
|
@ -144,7 +144,6 @@ pocket_read_more=Beliebte Themen:
|
|||
# end of the list of popular topic links.
|
||||
pocket_read_even_more=Weitere Nachrichten ansehen
|
||||
pocket_more_reccommendations=Mehr Empfehlungen
|
||||
pocket_learn_more=Weitere Informationen
|
||||
pocket_how_it_works=Wie es funktioniert
|
||||
pocket_cta_button=Pocket holen
|
||||
pocket_cta_text=Speichern Sie Ihre Lieblingstexte in Pocket und gewinnen Sie gedankenreiche Einblicke durch faszinierende Texte.
|
||||
|
|
|
@ -10159,6 +10159,11 @@
|
|||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||
"dev": true
|
||||
},
|
||||
"reselect": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz",
|
||||
"integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA=="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz",
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
"react-dom": "16.2.0",
|
||||
"react-intl": "2.4.0",
|
||||
"react-redux": "5.1.0",
|
||||
"redux": "4.0.1"
|
||||
"redux": "4.0.1",
|
||||
"reselect": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@octokit/rest": "15.17.0",
|
||||
|
|
|
@ -66,15 +66,15 @@ window.gActivityStreamStrings = {
|
|||
"topsites_form_title_label": "Titel",
|
||||
"topsites_form_title_placeholder": "Name eingeben",
|
||||
"topsites_form_url_label": "Adresse",
|
||||
"topsites_form_image_url_label": "URL von benutzerdefinierter Grafik",
|
||||
"topsites_form_image_url_label": "Adresse von benutzerdefinierter Grafik",
|
||||
"topsites_form_url_placeholder": "Eine Adresse eingeben oder einfügen",
|
||||
"topsites_form_use_image_link": "Eine benutzerdefinierte Grafik verwenden…",
|
||||
"topsites_form_preview_button": "Vorschau",
|
||||
"topsites_form_add_button": "Hinzufügen",
|
||||
"topsites_form_save_button": "Speichern",
|
||||
"topsites_form_cancel_button": "Abbrechen",
|
||||
"topsites_form_url_validation": "Gültige URL erforderlich",
|
||||
"topsites_form_image_validation": "Grafik konnte nicht geladen werden. Verwenden Sie eine andere URL.",
|
||||
"topsites_form_url_validation": "Gültige Adresse erforderlich",
|
||||
"topsites_form_image_validation": "Grafik konnte nicht geladen werden. Verwenden Sie eine andere Adresse.",
|
||||
"pocket_read_more": "Beliebte Themen:",
|
||||
"pocket_read_even_more": "Weitere Nachrichten ansehen",
|
||||
"pocket_more_reccommendations": "Mehr Empfehlungen",
|
||||
|
@ -110,6 +110,5 @@ window.gActivityStreamStrings = {
|
|||
"firstrun_privacy_notice": "Datenschutzhinweis",
|
||||
"firstrun_continue_to_login": "Weiter",
|
||||
"firstrun_skip_login": "Diesen Schritt überspringen",
|
||||
"context_menu_title": "Menü öffnen",
|
||||
"pocket_learn_more": "Weitere Informationen"
|
||||
"context_menu_title": "Menü öffnen"
|
||||
};
|
||||
|
|
|
@ -77,7 +77,7 @@ window.gActivityStreamPrerenderedState = {
|
|||
"spocs": {
|
||||
"spocs_endpoint": "",
|
||||
"lastUpdated": null,
|
||||
"data": []
|
||||
"data": {}
|
||||
}
|
||||
},
|
||||
"Search": {
|
||||
|
|
|
@ -70,6 +70,7 @@ export const UserEventAction = Joi.object().keys({
|
|||
event: Joi.valid([
|
||||
"CLICK",
|
||||
"SEARCH",
|
||||
"SEARCH_HANDOFF",
|
||||
"BLOCK",
|
||||
"DELETE",
|
||||
"DELETE_CONFIRM",
|
||||
|
|
|
@ -698,13 +698,8 @@ describe("Reducers", () => {
|
|||
const nextState = Search(undefined, {type: "HIDE_SEARCH"});
|
||||
assert.propertyVal(nextState, "hide", true);
|
||||
});
|
||||
it("should set focus to true on FOCUS_SEARCH", () => {
|
||||
const nextState = Search(undefined, {type: "FOCUS_SEARCH"});
|
||||
assert.propertyVal(nextState, "focus", true);
|
||||
});
|
||||
it("should set focus and hide to false on SHOW_SEARCH", () => {
|
||||
const nextState = Search(undefined, {type: "SHOW_SEARCH"});
|
||||
assert.propertyVal(nextState, "focus", false);
|
||||
assert.propertyVal(nextState, "hide", false);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
import {actionTypes as at} from "common/Actions.jsm";
|
||||
import {ImpressionStats} from "content-src/components/DiscoveryStreamImpressionStats/ImpressionStats";
|
||||
import React from "react";
|
||||
import {shallow} from "enzyme";
|
||||
|
||||
const SOURCE = "TEST_SOURCE";
|
||||
|
||||
describe("<ImpressionStats>", () => {
|
||||
const DEFAULT_PROPS = {
|
||||
rows: [{id: 1}, {id: 2}, {id: 3}],
|
||||
source: SOURCE,
|
||||
document: {
|
||||
visibilityState: "visible",
|
||||
addEventListener: sinon.stub(),
|
||||
removeEventListener: sinon.stub(),
|
||||
},
|
||||
};
|
||||
|
||||
const InnerEl = () => (<div>Inner Element</div>);
|
||||
|
||||
function renderImpressionStats(props = {}) {
|
||||
return shallow(<ImpressionStats {...DEFAULT_PROPS} {...props}>
|
||||
<InnerEl />
|
||||
</ImpressionStats>);
|
||||
}
|
||||
|
||||
it("should render props.children", () => {
|
||||
const wrapper = renderImpressionStats();
|
||||
assert.ok(wrapper.contains(<InnerEl />));
|
||||
});
|
||||
it("should send impression with the right stats when the page loads", () => {
|
||||
const dispatch = sinon.spy();
|
||||
const props = {dispatch};
|
||||
renderImpressionStats(props);
|
||||
|
||||
assert.calledOnce(dispatch);
|
||||
|
||||
const [action] = dispatch.firstCall.args;
|
||||
assert.equal(action.type, at.TELEMETRY_IMPRESSION_STATS);
|
||||
assert.equal(action.data.source, SOURCE);
|
||||
assert.deepEqual(action.data.tiles, [{id: 1}, {id: 2}, {id: 3}]);
|
||||
});
|
||||
it("should send 1 impression when the page becomes visibile after loading", () => {
|
||||
const props = {
|
||||
document: {
|
||||
visibilityState: "hidden",
|
||||
addEventListener: sinon.spy(),
|
||||
removeEventListener: sinon.spy(),
|
||||
},
|
||||
dispatch: sinon.spy(),
|
||||
};
|
||||
|
||||
renderImpressionStats(props);
|
||||
|
||||
// Was the event listener added?
|
||||
assert.calledWith(props.document.addEventListener, "visibilitychange");
|
||||
|
||||
// Make sure dispatch wasn't called yet
|
||||
assert.notCalled(props.dispatch);
|
||||
|
||||
// Simulate a visibilityChange event
|
||||
const [, listener] = props.document.addEventListener.firstCall.args;
|
||||
props.document.visibilityState = "visible";
|
||||
listener();
|
||||
|
||||
// Did we actually dispatch an event?
|
||||
assert.calledOnce(props.dispatch);
|
||||
assert.equal(props.dispatch.firstCall.args[0].type, at.TELEMETRY_IMPRESSION_STATS);
|
||||
|
||||
// Did we remove the event listener?
|
||||
assert.calledWith(props.document.removeEventListener, "visibilitychange", listener);
|
||||
});
|
||||
it("should remove visibility change listener when wrapper is removed", () => {
|
||||
const props = {
|
||||
dispatch: sinon.spy(),
|
||||
document: {
|
||||
visibilityState: "hidden",
|
||||
addEventListener: sinon.spy(),
|
||||
removeEventListener: sinon.spy(),
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = renderImpressionStats(props);
|
||||
assert.calledWith(props.document.addEventListener, "visibilitychange");
|
||||
const [, listener] = props.document.addEventListener.firstCall.args;
|
||||
|
||||
wrapper.unmount();
|
||||
assert.calledWith(props.document.removeEventListener, "visibilitychange", listener);
|
||||
});
|
||||
it("should send an impression if props are updated and props.rows are different", () => {
|
||||
const props = {dispatch: sinon.spy()};
|
||||
const wrapper = renderImpressionStats(props);
|
||||
props.dispatch.resetHistory();
|
||||
|
||||
// New rows
|
||||
wrapper.setProps({...DEFAULT_PROPS, ...{rows: [{id: 4}]}});
|
||||
|
||||
assert.calledOnce(props.dispatch);
|
||||
});
|
||||
it("should not send an impression if props are updated but IDs are the same", () => {
|
||||
const props = {dispatch: sinon.spy()};
|
||||
const wrapper = renderImpressionStats(props);
|
||||
props.dispatch.resetHistory();
|
||||
|
||||
wrapper.setProps(DEFAULT_PROPS);
|
||||
|
||||
assert.notCalled(props.dispatch);
|
||||
});
|
||||
it("should only send the latest impression on a visibility change", () => {
|
||||
const listeners = new Set();
|
||||
const props = {
|
||||
dispatch: sinon.spy(),
|
||||
document: {
|
||||
visibilityState: "hidden",
|
||||
addEventListener: (ev, cb) => listeners.add(cb),
|
||||
removeEventListener: (ev, cb) => listeners.delete(cb),
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = renderImpressionStats(props);
|
||||
|
||||
// Update twice
|
||||
wrapper.setProps({...props, ...{rows: [{id: 123}]}});
|
||||
wrapper.setProps({...props, ...{rows: [{id: 2432}]}});
|
||||
|
||||
assert.notCalled(props.dispatch);
|
||||
|
||||
// Simulate listeners getting called
|
||||
props.document.visibilityState = "visible";
|
||||
listeners.forEach(l => l());
|
||||
|
||||
// Make sure we only sent the latest event
|
||||
assert.calledOnce(props.dispatch);
|
||||
const [action] = props.dispatch.firstCall.args;
|
||||
assert.deepEqual(action.data.tiles, [{id: 2432}]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,85 @@
|
|||
import {_List as List, ListItem} from "content-src/components/DiscoveryStreamComponents/List/List";
|
||||
import {GlobalOverrider} from "test/unit/utils";
|
||||
import React from "react";
|
||||
import {shallow} from "enzyme";
|
||||
|
||||
describe("<List> presentation component", () => {
|
||||
const ValidRecommendations = [{a: 1}, {a: 2}];
|
||||
const ValidListProps = {
|
||||
DiscoveryStream: {
|
||||
feeds: {
|
||||
fakeFeedUrl: {
|
||||
data: {
|
||||
recommendations: ValidRecommendations,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
feed: {
|
||||
url: "fakeFeedUrl",
|
||||
},
|
||||
header: {
|
||||
title: "fakeFeedTitle",
|
||||
},
|
||||
};
|
||||
|
||||
it("should return null if feed.data is falsy", () => {
|
||||
const ListProps = {
|
||||
DiscoveryStream: {feeds: {a: "stuff"}},
|
||||
feed: {url: "a"},
|
||||
};
|
||||
|
||||
const wrapper = shallow(<List {...ListProps} />);
|
||||
|
||||
assert.isNull(wrapper.getElement());
|
||||
});
|
||||
|
||||
it("should return something containing a <ul> if props are valid", () => {
|
||||
const wrapper = shallow(<List {...ValidListProps} />);
|
||||
|
||||
const list = wrapper.find("ul");
|
||||
assert.ok(wrapper.exists());
|
||||
assert.lengthOf(list, 1);
|
||||
});
|
||||
|
||||
it("should return the right number of ListItems if props are valid", () => {
|
||||
const wrapper = shallow(<List {...ValidListProps} />);
|
||||
|
||||
const listItem = wrapper.find(ListItem);
|
||||
assert.lengthOf(listItem, ValidRecommendations.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe("<ListItem> presentation component", () => {
|
||||
const ValidListItemProps = {
|
||||
url: "FAKE_URL",
|
||||
title: "FAKE_TITLE",
|
||||
domain: "example.com",
|
||||
image_src: "FAKE_IMAGE_SRC",
|
||||
};
|
||||
|
||||
let globals;
|
||||
|
||||
beforeEach(() => {
|
||||
globals = new GlobalOverrider();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
globals.sandbox.restore();
|
||||
});
|
||||
|
||||
it("should contain 'a.ds-list-item-link' with the props.url set", () => {
|
||||
const wrapper = shallow(<ListItem {...ValidListItemProps} />);
|
||||
|
||||
const anchors = wrapper.find(
|
||||
`a.ds-list-item-link[href="${ValidListItemProps.url}"]`);
|
||||
assert.lengthOf(anchors, 1);
|
||||
});
|
||||
|
||||
it("should include an img with a src of props.image_src", () => {
|
||||
const wrapper = shallow(<ListItem {...ValidListItemProps} />);
|
||||
|
||||
const anchors = wrapper.find(`img[src="${ValidListItemProps.image_src}"]`);
|
||||
assert.lengthOf(anchors, 1);
|
||||
});
|
||||
});
|
|
@ -80,37 +80,41 @@ describe("<Search>", () => {
|
|||
assert.ok(wrapper.exists());
|
||||
assert.equal(wrapper.find(".search-handoff-button").length, 1);
|
||||
});
|
||||
it("should hand-off search when button is clicked with mouse", () => {
|
||||
it("should focus search hand-off button when clicked with mouse", () => {
|
||||
const dispatch = sinon.spy();
|
||||
const wrapper = shallowWithIntl(<Search {...DEFAULT_PROPS} handoffEnabled={true} dispatch={dispatch} />);
|
||||
wrapper.find(".search-handoff-button").simulate("click", {clientX: 101, clientY: 102});
|
||||
assert.calledWith(dispatch, {
|
||||
data: {hiddenFocus: true},
|
||||
meta: {from: "ActivityStream:Content", skipLocal: true, to: "ActivityStream:Main"},
|
||||
type: "HANDOFF_SEARCH_TO_AWESOMEBAR",
|
||||
});
|
||||
assert.calledWith(dispatch, {type: "FOCUS_SEARCH"});
|
||||
wrapper.instance()._searchHandoffButton = {focus: sinon.spy()};
|
||||
wrapper.find(".search-handoff-button").simulate("click", {clientX: 101, clientY: 102, preventDefault: () => {}});
|
||||
assert.calledOnce(wrapper.instance()._searchHandoffButton.focus);
|
||||
});
|
||||
it("should hand-off search when button is clicked with keyboard", () => {
|
||||
const dispatch = sinon.spy();
|
||||
const wrapper = shallowWithIntl(<Search {...DEFAULT_PROPS} handoffEnabled={true} dispatch={dispatch} />);
|
||||
wrapper.find(".search-handoff-button").simulate("click", {clientX: 0, clientY: 0});
|
||||
wrapper.find(".search-handoff-button").simulate("click", {clientX: 0, clientY: 0, preventDefault: () => {}});
|
||||
assert.calledTwice(dispatch);
|
||||
assert.calledWith(dispatch, {
|
||||
data: {hiddenFocus: false},
|
||||
data: {text: undefined},
|
||||
meta: {from: "ActivityStream:Content", skipLocal: true, to: "ActivityStream:Main"},
|
||||
type: "HANDOFF_SEARCH_TO_AWESOMEBAR",
|
||||
});
|
||||
assert.calledWith(dispatch, {type: "FOCUS_SEARCH"});
|
||||
const [action] = dispatch.secondCall.args;
|
||||
assert.isUserEventAction(action);
|
||||
assert.propertyVal(action.data, "event", "SEARCH_HANDOFF");
|
||||
});
|
||||
it("should hand-off search when user types", () => {
|
||||
const dispatch = sinon.spy();
|
||||
const wrapper = shallowWithIntl(<Search {...DEFAULT_PROPS} handoffEnabled={true} dispatch={dispatch} />);
|
||||
wrapper.find(".search-handoff-button").simulate("keydown", {key: "f"});
|
||||
assert.calledThrice(dispatch);
|
||||
assert.calledWith(dispatch, {
|
||||
data: {text: "f"},
|
||||
meta: {from: "ActivityStream:Content", skipLocal: true, to: "ActivityStream:Main"},
|
||||
type: "HANDOFF_SEARCH_TO_AWESOMEBAR",
|
||||
});
|
||||
assert.calledWith(dispatch, {type: "HIDE_SEARCH"});
|
||||
const [action] = dispatch.secondCall.args;
|
||||
assert.isUserEventAction(action);
|
||||
assert.propertyVal(action.data, "event", "SEARCH_HANDOFF");
|
||||
});
|
||||
it("should NOT hand-off search when user types with with ctrl pressed", () => {
|
||||
const dispatch = sinon.spy();
|
||||
|
@ -140,11 +144,16 @@ describe("<Search>", () => {
|
|||
},
|
||||
preventDefault: () => {},
|
||||
});
|
||||
assert.calledThrice(dispatch);
|
||||
assert.calledWith(dispatch, {
|
||||
data: {text: "some copied text"},
|
||||
meta: {from: "ActivityStream:Content", skipLocal: true, to: "ActivityStream:Main"},
|
||||
type: "HANDOFF_SEARCH_TO_AWESOMEBAR",
|
||||
});
|
||||
assert.calledWith(dispatch, {type: "HIDE_SEARCH"});
|
||||
const [action] = dispatch.secondCall.args;
|
||||
assert.isUserEventAction(action);
|
||||
assert.propertyVal(action.data, "event", "SEARCH_HANDOFF");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
import {combineReducers, createStore} from "redux";
|
||||
import {actionTypes as at} from "common/Actions.jsm";
|
||||
import {GlobalOverrider} from "test/unit/utils";
|
||||
import {reducers} from "common/Reducers.jsm";
|
||||
import {selectLayoutRender} from "content-src/lib/selectLayoutRender";
|
||||
|
||||
const FAKE_LAYOUT = [{width: 3, components: [{type: "foo", feed: {url: "foo.com"}}]}];
|
||||
const FAKE_FEEDS = {"foo.com": {data: ["foo", "bar"]}};
|
||||
|
||||
describe("selectLayoutRender", () => {
|
||||
let store;
|
||||
let globals;
|
||||
|
||||
beforeEach(() => {
|
||||
globals = new GlobalOverrider();
|
||||
store = createStore(combineReducers(reducers));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
globals.restore();
|
||||
});
|
||||
|
||||
it("should return an empty array given initial state", () => {
|
||||
const result = selectLayoutRender(store.getState());
|
||||
assert.deepEqual(result, []);
|
||||
});
|
||||
|
||||
it("should add .data property from feeds to each compontent in .layout", () => {
|
||||
store.dispatch({type: at.DISCOVERY_STREAM_LAYOUT_UPDATE, data: {layout: FAKE_LAYOUT}});
|
||||
store.dispatch({type: at.DISCOVERY_STREAM_FEEDS_UPDATE, data: FAKE_FEEDS});
|
||||
|
||||
const result = selectLayoutRender(store.getState());
|
||||
|
||||
assert.lengthOf(result, 1);
|
||||
assert.propertyVal(result[0], "width", 3);
|
||||
assert.deepEqual(result[0].components[0], {type: "foo", feed: {url: "foo.com"}, data: ["foo", "bar"]});
|
||||
});
|
||||
|
||||
it("should return layout property without data if feed isn't available", () => {
|
||||
store.dispatch({type: at.DISCOVERY_STREAM_LAYOUT_UPDATE, data: {layout: FAKE_LAYOUT}});
|
||||
store.dispatch({type: at.DISCOVERY_STREAM_FEEDS_UPDATE, data: {}});
|
||||
|
||||
const result = selectLayoutRender(store.getState());
|
||||
|
||||
assert.lengthOf(result, 1);
|
||||
assert.propertyVal(result[0], "width", 3);
|
||||
assert.deepEqual(result[0].components[0], FAKE_LAYOUT[0].components[0]);
|
||||
});
|
||||
|
||||
it("should return spoc result for rolls below the probability", () => {
|
||||
const fakeSpocConfig = {positions: [{index: 0}, {index: 1}], probability: 0.5};
|
||||
const fakeLayout = [{width: 3, components: [{type: "foo", feed: {url: "foo.com"}, spocs: fakeSpocConfig}]}];
|
||||
const fakeSpocsData = {lastUpdated: 0, spocs: {spocs: ["foo", "bar"]}};
|
||||
|
||||
store.dispatch({type: at.DISCOVERY_STREAM_LAYOUT_UPDATE, data: {layout: fakeLayout}});
|
||||
store.dispatch({type: at.DISCOVERY_STREAM_FEEDS_UPDATE, data: FAKE_FEEDS});
|
||||
store.dispatch({type: at.DISCOVERY_STREAM_SPOCS_UPDATE, data: fakeSpocsData});
|
||||
globals.sandbox.stub(global.Math, "random").returns(0.1);
|
||||
|
||||
const result = selectLayoutRender(store.getState());
|
||||
|
||||
assert.lengthOf(result, 1);
|
||||
assert.deepEqual(result[0].components[0].spocs.positions[0], {index: 0, result: "foo"});
|
||||
assert.deepEqual(result[0].components[0].spocs.positions[1], {index: 1, result: "bar"});
|
||||
});
|
||||
|
||||
it("should not return spoc result for rolls above the probability", () => {
|
||||
const fakeSpocConfig = {positions: [{index: 0}, {index: 1}], probability: 0.5};
|
||||
const fakeLayout = [{width: 3, components: [{type: "foo", feed: {url: "foo.com"}, spocs: fakeSpocConfig}]}];
|
||||
const fakeSpocsData = {lastUpdated: 0, spocs: {spocs: ["foo", "bar"]}};
|
||||
|
||||
store.dispatch({type: at.DISCOVERY_STREAM_LAYOUT_UPDATE, data: {layout: fakeLayout}});
|
||||
store.dispatch({type: at.DISCOVERY_STREAM_FEEDS_UPDATE, data: FAKE_FEEDS});
|
||||
store.dispatch({type: at.DISCOVERY_STREAM_SPOCS_UPDATE, data: fakeSpocsData});
|
||||
globals.sandbox.stub(global.Math, "random").returns(0.6);
|
||||
|
||||
const result = selectLayoutRender(store.getState());
|
||||
|
||||
assert.lengthOf(result, 1);
|
||||
assert.deepEqual(result[0].components[0].spocs.positions[0], {index: 0});
|
||||
assert.deepEqual(result[0].components[0].spocs.positions[1], {index: 1});
|
||||
});
|
||||
});
|
|
@ -309,7 +309,7 @@ describe("PlacesFeed", () => {
|
|||
it("should call handoffSearchToAwesomebar on HANDOFF_SEARCH_TO_AWESOMEBAR", () => {
|
||||
const action = {
|
||||
type: at.HANDOFF_SEARCH_TO_AWESOMEBAR,
|
||||
data: {hiddenFocus: false},
|
||||
data: {text: "f"},
|
||||
meta: {fromTarget: {}},
|
||||
_target: {browser: {ownerGlobal: {gURLBar: {focus: () => {}}}}},
|
||||
};
|
||||
|
@ -336,77 +336,14 @@ describe("PlacesFeed", () => {
|
|||
};
|
||||
listeners = {};
|
||||
});
|
||||
it("should properly handle hiddenFocus=false", () => {
|
||||
it("should properly handle normal focus (no text passed in)", () => {
|
||||
feed.handoffSearchToAwesomebar({
|
||||
_target: {browser: {ownerGlobal: {gURLBar: fakeUrlBar}}},
|
||||
data: {hiddenFocus: false},
|
||||
data: {},
|
||||
meta: {fromTarget: {}},
|
||||
});
|
||||
assert.calledOnce(fakeUrlBar.focus);
|
||||
assert.notCalled(fakeUrlBar.hiddenFocus);
|
||||
assert.calledOnce(feed.store.dispatch);
|
||||
assert.calledWith(feed.store.dispatch, {
|
||||
meta: {
|
||||
from: "ActivityStream:Main",
|
||||
skipMain: true,
|
||||
to: "ActivityStream:Content",
|
||||
toTarget: {},
|
||||
},
|
||||
type: "SHOW_SEARCH",
|
||||
});
|
||||
});
|
||||
it("should properly handle hiddenFocus=true", () => {
|
||||
feed.handoffSearchToAwesomebar({
|
||||
_target: {browser: {ownerGlobal: {gURLBar: fakeUrlBar}}},
|
||||
data: {hiddenFocus: true},
|
||||
meta: {fromTarget: {}},
|
||||
});
|
||||
assert.calledOnce(fakeUrlBar.hiddenFocus);
|
||||
assert.notCalled(fakeUrlBar.focus);
|
||||
assert.notCalled(feed.store.dispatch);
|
||||
|
||||
// Now call keydown listener with "Ctrl".
|
||||
feed.store.dispatch.resetHistory();
|
||||
listeners.keydown({key: "Ctrl"});
|
||||
assert.notCalled(fakeUrlBar.removeHiddenFocus);
|
||||
assert.notCalled(feed.store.dispatch);
|
||||
|
||||
// Now call keydown listener with "Ctrl+f".
|
||||
feed.store.dispatch.resetHistory();
|
||||
listeners.keydown({key: "f", ctrlKey: true});
|
||||
assert.notCalled(fakeUrlBar.removeHiddenFocus);
|
||||
assert.notCalled(feed.store.dispatch);
|
||||
|
||||
// Now call keydown listener with "f".
|
||||
feed.store.dispatch.resetHistory();
|
||||
listeners.keydown({key: "f"});
|
||||
assert.calledOnce(fakeUrlBar.removeHiddenFocus);
|
||||
assert.calledOnce(feed.store.dispatch);
|
||||
assert.calledWith(feed.store.dispatch, {
|
||||
meta: {
|
||||
from: "ActivityStream:Main",
|
||||
skipMain: true,
|
||||
to: "ActivityStream:Content",
|
||||
toTarget: {},
|
||||
},
|
||||
type: "HIDE_SEARCH",
|
||||
});
|
||||
|
||||
// And then call blur listener.
|
||||
fakeUrlBar.removeHiddenFocus.resetHistory();
|
||||
feed.store.dispatch.resetHistory();
|
||||
listeners.blur();
|
||||
assert.calledOnce(fakeUrlBar.removeHiddenFocus);
|
||||
assert.calledOnce(feed.store.dispatch);
|
||||
assert.calledWith(feed.store.dispatch, {
|
||||
meta: {
|
||||
from: "ActivityStream:Main",
|
||||
skipMain: true,
|
||||
to: "ActivityStream:Content",
|
||||
toTarget: {},
|
||||
},
|
||||
type: "SHOW_SEARCH",
|
||||
});
|
||||
});
|
||||
it("should properly handle text data passed in", () => {
|
||||
feed.handoffSearchToAwesomebar({
|
||||
|
@ -416,8 +353,10 @@ describe("PlacesFeed", () => {
|
|||
});
|
||||
assert.calledOnce(fakeUrlBar.search);
|
||||
assert.calledWith(fakeUrlBar.search, "f");
|
||||
assert.notCalled(fakeUrlBar.hiddenFocus);
|
||||
assert.notCalled(fakeUrlBar.focus);
|
||||
|
||||
// Now call blur listener.
|
||||
listeners.blur();
|
||||
assert.calledOnce(feed.store.dispatch);
|
||||
assert.calledWith(feed.store.dispatch, {
|
||||
meta: {
|
||||
|
@ -426,7 +365,30 @@ describe("PlacesFeed", () => {
|
|||
to: "ActivityStream:Content",
|
||||
toTarget: {},
|
||||
},
|
||||
type: "HIDE_SEARCH",
|
||||
type: "SHOW_SEARCH",
|
||||
});
|
||||
});
|
||||
it("should SHOW_SEARCH on ESC keydown", () => {
|
||||
feed.handoffSearchToAwesomebar({
|
||||
_target: {browser: {ownerGlobal: {gURLBar: fakeUrlBar}}},
|
||||
data: {text: "f"},
|
||||
meta: {fromTarget: {}},
|
||||
});
|
||||
assert.calledOnce(fakeUrlBar.search);
|
||||
assert.calledWith(fakeUrlBar.search, "f");
|
||||
assert.notCalled(fakeUrlBar.focus);
|
||||
|
||||
// Now call ESC keydown.
|
||||
listeners.keydown({key: "Escape"});
|
||||
assert.calledOnce(feed.store.dispatch);
|
||||
assert.calledWith(feed.store.dispatch, {
|
||||
meta: {
|
||||
from: "ActivityStream:Main",
|
||||
skipMain: true,
|
||||
to: "ActivityStream:Content",
|
||||
toTarget: {},
|
||||
},
|
||||
type: "SHOW_SEARCH",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -110,7 +110,6 @@ endif
|
|||
# and Mac requires some extra care due to cross-compilation.
|
||||
MOZ_PACKAGER_MINIFY=1
|
||||
|
||||
include $(topsrcdir)/toolkit/mozapps/installer/signing.mk
|
||||
include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
|
||||
|
||||
ifeq (bundle, $(MOZ_FS_LAYOUT))
|
||||
|
|
|
@ -62,7 +62,7 @@ $(CONFIG_DIR)/setup.exe::
|
|||
--convert-utf8-utf16le \
|
||||
$(srcdir)/nsis/extensionsLocale.nsh $(CONFIG_DIR)/extensionsLocale.nsh
|
||||
|
||||
GARBARGE_DIRS += instgen
|
||||
GARBAGE_DIRS += instgen
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
include $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/makensis.mk
|
||||
|
|
|
@ -10,61 +10,42 @@ def moz_jemalloc4(value):
|
|||
die('MOZ_JEMALLOC4 is deprecated')
|
||||
|
||||
|
||||
option('--enable-jemalloc', env='MOZ_MEMORY',
|
||||
help='Replace memory allocator with jemalloc')
|
||||
@depends(target)
|
||||
def jemalloc_default(target):
|
||||
return target.kernel in ('Darwin', 'Linux', 'WINNT')
|
||||
|
||||
|
||||
@depends('--enable-jemalloc', target)
|
||||
def jemalloc(value, target):
|
||||
if value.origin != 'default':
|
||||
return bool(value) or None
|
||||
|
||||
if target.kernel in ('Darwin', 'Linux', 'WINNT'):
|
||||
return True
|
||||
js_option('--enable-jemalloc', env='MOZ_MEMORY', default=jemalloc_default,
|
||||
help='{Replace|Do not replace} memory allocator with jemalloc')
|
||||
|
||||
|
||||
set_config('MOZ_MEMORY', jemalloc)
|
||||
set_define('MOZ_MEMORY', jemalloc)
|
||||
add_old_configure_assignment('MOZ_MEMORY', jemalloc)
|
||||
set_config('MOZ_MEMORY', True, when='--enable-jemalloc')
|
||||
set_define('MOZ_MEMORY', True, when='--enable-jemalloc')
|
||||
add_old_configure_assignment('MOZ_MEMORY', True, when='--enable-jemalloc')
|
||||
|
||||
|
||||
# Because --enable-jemalloc doesn't use a default because of the dependency
|
||||
# on the target, we can't use a js_option for it to propagate to js/src
|
||||
# through the old-configure.
|
||||
@depends(jemalloc)
|
||||
def jemalloc_for_old_configure(jemalloc):
|
||||
return '--%s-jemalloc' % ('enable' if jemalloc else 'disable')
|
||||
|
||||
|
||||
add_old_configure_arg(jemalloc_for_old_configure)
|
||||
|
||||
|
||||
option('--enable-replace-malloc',
|
||||
help='Enable ability to dynamically replace the malloc implementation')
|
||||
|
||||
|
||||
@depends('--enable-replace-malloc', jemalloc, milestone, build_project)
|
||||
def replace_malloc(value, jemalloc, milestone, build_project):
|
||||
# Enable on central for the debugging opportunities it adds.
|
||||
if value and not jemalloc:
|
||||
die('--enable-replace-malloc requires --enable-jemalloc')
|
||||
if value.origin != 'default':
|
||||
return bool(value) or None
|
||||
@depends(milestone, build_project)
|
||||
def replace_malloc_default(milestone, build_project):
|
||||
if build_project == 'memory':
|
||||
return True
|
||||
if milestone.is_nightly and jemalloc and build_project != 'js':
|
||||
if milestone.is_nightly and build_project != 'js':
|
||||
return True
|
||||
|
||||
|
||||
set_config('MOZ_REPLACE_MALLOC', replace_malloc)
|
||||
set_define('MOZ_REPLACE_MALLOC', replace_malloc)
|
||||
js_option('--enable-replace-malloc', default=replace_malloc_default,
|
||||
when='--enable-jemalloc',
|
||||
help='{Enable|Disable} ability to dynamically replace the malloc implementation')
|
||||
|
||||
|
||||
@depends(replace_malloc, build_project)
|
||||
def replace_malloc_static(replace_malloc, build_project):
|
||||
set_config('MOZ_REPLACE_MALLOC', True, when='--enable-replace-malloc')
|
||||
set_define('MOZ_REPLACE_MALLOC', True, when='--enable-replace-malloc')
|
||||
|
||||
|
||||
@depends(build_project, when='--enable-replace-malloc')
|
||||
def replace_malloc_static(build_project):
|
||||
# Default to statically linking replace-malloc libraries that can be
|
||||
# statically linked, except when building with --enable-project=memory.
|
||||
if replace_malloc and build_project != 'memory':
|
||||
if build_project != 'memory':
|
||||
return True
|
||||
|
||||
|
||||
|
|
|
@ -309,3 +309,19 @@ def win64_cargo_linker_config(linker, env):
|
|||
|
||||
|
||||
set_config('WIN64_CARGO_LINKER_CONFIG', win64_cargo_linker_config)
|
||||
|
||||
|
||||
@depends(target, c_compiler, rustc)
|
||||
@imports('os')
|
||||
def rustc_natvis_ldflags(target, compiler_info, rustc):
|
||||
if target.kernel == 'WINNT' and compiler_info.type in ('msvc', 'clang-cl'):
|
||||
sysroot = check_cmd_output(rustc, '--print', 'sysroot').strip()
|
||||
etc = os.path.join(sysroot, 'lib/rustlib/etc')
|
||||
ldflags = []
|
||||
for f in os.listdir(etc):
|
||||
if f.endswith('.natvis'):
|
||||
ldflags.append('-NATVIS:' + normsep(os.path.join(etc, f)))
|
||||
return ldflags
|
||||
|
||||
|
||||
set_config('RUSTC_NATVIS_LDFLAGS', rustc_natvis_ldflags)
|
||||
|
|
|
@ -79,9 +79,9 @@ BrowserElementWebNavigation.prototype = {
|
|||
postData: postData ? readInputStreamToString(postData) : null,
|
||||
headers: headers ? readInputStreamToString(headers) : null,
|
||||
baseURI: baseURI ? baseURI.spec : null,
|
||||
triggeringPrincipal: triggeringPrincipal
|
||||
? Utils.serializePrincipal(triggeringPrincipal)
|
||||
: Services.scriptSecurityManager.createNullPrincipal({}),
|
||||
triggeringPrincipal: Utils.serializePrincipal(
|
||||
triggeringPrincipal ||
|
||||
Services.scriptSecurityManager.createNullPrincipal({})),
|
||||
requestTime: telemetry.msSystemNow(),
|
||||
});
|
||||
},
|
||||
|
|
|
@ -115,11 +115,11 @@ const mozilla::Module::CIDEntry kDocShellCIDs[] = {
|
|||
{ &kNS_ABOUT_REDIRECTOR_MODULE_CID, false, nullptr, nsAboutRedirector::Create },
|
||||
{ &kNS_URI_LOADER_CID, false, nullptr, nsURILoaderConstructor },
|
||||
{ &kNS_DOCUMENTLOADER_SERVICE_CID, false, nullptr, nsDocLoaderConstructor },
|
||||
{ &kNS_EXTERNALHELPERAPPSERVICE_CID, false, nullptr, nsOSHelperAppServiceConstructor },
|
||||
{ &kNS_EXTERNALHELPERAPPSERVICE_CID, false, nullptr, nsOSHelperAppServiceConstructor, mozilla::Module::ALLOW_IN_SOCKET_PROCESS },
|
||||
{ &kNS_OSPERMISSIONREQUEST_CID, false, nullptr, nsOSPermissionRequestConstructor },
|
||||
{ &kNS_CONTENTHANDLERSERVICE_CID, false, nullptr, ContentHandlerServiceConstructor,
|
||||
mozilla::Module::CONTENT_PROCESS_ONLY },
|
||||
{ &kNS_EXTERNALPROTOCOLHANDLER_CID, false, nullptr, nsExternalProtocolHandlerConstructor },
|
||||
{ &kNS_EXTERNALPROTOCOLHANDLER_CID, false, nullptr, nsExternalProtocolHandlerConstructor, mozilla::Module::ALLOW_IN_SOCKET_PROCESS },
|
||||
{ &kNS_PREFETCHSERVICE_CID, false, nullptr, nsPrefetchServiceConstructor },
|
||||
{ &kNS_OFFLINECACHEUPDATESERVICE_CID, false, nullptr, nsOfflineCacheUpdateServiceConstructor },
|
||||
{ &kNS_LOCALHANDLERAPP_CID, false, nullptr, PlatformLocalHandlerApp_tConstructor },
|
||||
|
@ -171,9 +171,9 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
|
|||
{ NS_DOCUMENTLOADER_SERVICE_CONTRACTID, &kNS_DOCUMENTLOADER_SERVICE_CID },
|
||||
{ NS_HANDLERSERVICE_CONTRACTID, &kNS_CONTENTHANDLERSERVICE_CID, mozilla::Module::CONTENT_PROCESS_ONLY },
|
||||
{ NS_EXTERNALHELPERAPPSERVICE_CONTRACTID, &kNS_EXTERNALHELPERAPPSERVICE_CID },
|
||||
{ NS_EXTERNALPROTOCOLSERVICE_CONTRACTID, &kNS_EXTERNALHELPERAPPSERVICE_CID },
|
||||
{ NS_EXTERNALPROTOCOLSERVICE_CONTRACTID, &kNS_EXTERNALHELPERAPPSERVICE_CID, mozilla::Module::ALLOW_IN_SOCKET_PROCESS },
|
||||
{ NS_MIMESERVICE_CONTRACTID, &kNS_EXTERNALHELPERAPPSERVICE_CID },
|
||||
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default", &kNS_EXTERNALPROTOCOLHANDLER_CID },
|
||||
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default", &kNS_EXTERNALPROTOCOLHANDLER_CID, mozilla::Module::ALLOW_IN_SOCKET_PROCESS },
|
||||
{ NS_PREFETCHSERVICE_CONTRACTID, &kNS_PREFETCHSERVICE_CID },
|
||||
{ NS_OFFLINECACHEUPDATESERVICE_CONTRACTID, &kNS_OFFLINECACHEUPDATESERVICE_CID },
|
||||
{ NS_LOCALHANDLERAPP_CONTRACTID, &kNS_LOCALHANDLERAPP_CID },
|
||||
|
@ -195,6 +195,7 @@ static const mozilla::Module kDocShellModule = {mozilla::Module::kVersion,
|
|||
nullptr,
|
||||
nullptr,
|
||||
Initialize,
|
||||
Shutdown};
|
||||
Shutdown,
|
||||
mozilla::Module::ALLOW_IN_SOCKET_PROCESS};
|
||||
|
||||
NSMODULE_DEFN(docshell_provider) = &kDocShellModule;
|
||||
|
|
|
@ -1834,9 +1834,11 @@ waitForAllPaints(() => {
|
|||
await ensureElementRemoval(div);
|
||||
});
|
||||
|
||||
// Tests that transform animations are not able to run on the compositor due
|
||||
// to layout restrictions (e.g. animations on a large size frame) doesn't
|
||||
// flush layout at all.
|
||||
// Tests that transform animations on a large size frame doesn't flush layout at all.
|
||||
//
|
||||
// With WebRender, the large size frame could run on compositor.
|
||||
// Without WebRender, the large size frame is not able to run on the compositor
|
||||
// due to layout restrictions.
|
||||
add_task(async function flush_layout_for_transform_animations() {
|
||||
// Set layout.animation.prerender.partial to disallow transform animations
|
||||
// on large frames to be sent to the compositor.
|
||||
|
@ -1850,11 +1852,17 @@ waitForAllPaints(() => {
|
|||
easing: 'step-end' });
|
||||
|
||||
const FLUSH_LAYOUT = SpecialPowers.DOMWindowUtils.FLUSH_LAYOUT;
|
||||
const isWebRender =
|
||||
SpecialPowers.DOMWindowUtils.layerManagerType == 'WebRender';
|
||||
ok(SpecialPowers.DOMWindowUtils.needsFlush(FLUSH_LAYOUT),
|
||||
'Flush layout is needed for the appended div');
|
||||
await waitForAnimationReadyToRestyle(animation);
|
||||
|
||||
ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
|
||||
if (isWebRender) {
|
||||
ok(SpecialPowers.wrap(animation).isRunningOnCompositor);
|
||||
} else {
|
||||
ok(!SpecialPowers.wrap(animation).isRunningOnCompositor);
|
||||
}
|
||||
ok(!SpecialPowers.DOMWindowUtils.needsFlush(FLUSH_LAYOUT),
|
||||
'No further flush layout needed');
|
||||
|
||||
|
|
|
@ -1323,7 +1323,6 @@ Document::Document(const char* aContentType)
|
|||
mNotifiedPageForUseCounter(0),
|
||||
mUserHasInteracted(false),
|
||||
mHasUserInteractionTimerScheduled(false),
|
||||
mUserGestureActivated(false),
|
||||
mStackRefCnt(0),
|
||||
mUpdateNestLevel(0),
|
||||
mViewportType(Unknown),
|
||||
|
@ -11717,13 +11716,14 @@ void Document::MaybeNotifyAutoplayBlocked() {
|
|||
}
|
||||
|
||||
void Document::ClearUserGestureActivation() {
|
||||
Document* doc = this;
|
||||
while (doc) {
|
||||
MOZ_LOG(gUserInteractionPRLog, LogLevel::Debug,
|
||||
("Reset user activation flag for document %p.", this));
|
||||
doc->mUserGestureActivated = false;
|
||||
doc = doc->GetSameTypeParentDocument();
|
||||
if (!HasBeenUserGestureActivated()) {
|
||||
return;
|
||||
}
|
||||
RefPtr<BrowsingContext> bc = GetBrowsingContext();
|
||||
if (!bc) {
|
||||
return;
|
||||
}
|
||||
bc->NotifyResetUserGestureActivation();
|
||||
}
|
||||
|
||||
void Document::SetDocTreeHadAudibleMedia() {
|
||||
|
|
|
@ -4250,13 +4250,6 @@ class Document : public nsINode,
|
|||
// timer is scheduled.
|
||||
bool mHasUserInteractionTimerScheduled;
|
||||
|
||||
// Whether the user has interacted with the document via a restricted
|
||||
// set of gestures which are likely to be interaction with the document,
|
||||
// and not events that are fired as a byproduct of the user interacting
|
||||
// with the browser (events for like scrolling the page, keyboard short
|
||||
// cuts, etc).
|
||||
bool mUserGestureActivated;
|
||||
|
||||
mozilla::TimeStamp mPageUnloadingEventTimeStamp;
|
||||
|
||||
RefPtr<mozilla::dom::DocGroup> mDocGroup;
|
||||
|
|
|
@ -3195,8 +3195,7 @@ mozilla::ipc::IPCResult ContentChild::RecvGetFilesResponse(
|
|||
}
|
||||
|
||||
PURLClassifierChild* ContentChild::AllocPURLClassifierChild(
|
||||
const Principal& aPrincipal, const bool& aUseTrackingProtection,
|
||||
bool* aSuccess) {
|
||||
const Principal& aPrincipal, bool* aSuccess) {
|
||||
*aSuccess = true;
|
||||
return new URLClassifierChild();
|
||||
}
|
||||
|
|
|
@ -637,8 +637,7 @@ class ContentChild final : public PContentChild,
|
|||
|
||||
// PURLClassifierChild
|
||||
virtual PURLClassifierChild* AllocPURLClassifierChild(
|
||||
const Principal& aPrincipal, const bool& aUseTrackingProtection,
|
||||
bool* aSuccess) override;
|
||||
const Principal& aPrincipal, bool* aSuccess) override;
|
||||
virtual bool DeallocPURLClassifierChild(PURLClassifierChild* aActor) override;
|
||||
|
||||
// PURLClassifierLocalChild
|
||||
|
|
|
@ -5341,8 +5341,7 @@ mozilla::ipc::IPCResult ContentParent::RecvRecordDiscardedData(
|
|||
// PURLClassifierParent
|
||||
|
||||
PURLClassifierParent* ContentParent::AllocPURLClassifierParent(
|
||||
const Principal& aPrincipal, const bool& aUseTrackingProtection,
|
||||
bool* aSuccess) {
|
||||
const Principal& aPrincipal, bool* aSuccess) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
*aSuccess = true;
|
||||
|
@ -5351,8 +5350,7 @@ PURLClassifierParent* ContentParent::AllocPURLClassifierParent(
|
|||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvPURLClassifierConstructor(
|
||||
PURLClassifierParent* aActor, const Principal& aPrincipal,
|
||||
const bool& aUseTrackingProtection, bool* aSuccess) {
|
||||
PURLClassifierParent* aActor, const Principal& aPrincipal, bool* aSuccess) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aActor);
|
||||
*aSuccess = false;
|
||||
|
@ -5363,7 +5361,7 @@ mozilla::ipc::IPCResult ContentParent::RecvPURLClassifierConstructor(
|
|||
actor->ClassificationFailed();
|
||||
return IPC_OK();
|
||||
}
|
||||
return actor->StartClassify(principal, aUseTrackingProtection, aSuccess);
|
||||
return actor->StartClassify(principal, aSuccess);
|
||||
}
|
||||
|
||||
bool ContentParent::DeallocPURLClassifierParent(PURLClassifierParent* aActor) {
|
||||
|
|
|
@ -558,11 +558,10 @@ class ContentParent final : public PContentParent,
|
|||
|
||||
// PURLClassifierParent.
|
||||
virtual PURLClassifierParent* AllocPURLClassifierParent(
|
||||
const Principal& aPrincipal, const bool& aUseTrackingProtection,
|
||||
bool* aSuccess) override;
|
||||
const Principal& aPrincipal, bool* aSuccess) override;
|
||||
virtual mozilla::ipc::IPCResult RecvPURLClassifierConstructor(
|
||||
PURLClassifierParent* aActor, const Principal& aPrincipal,
|
||||
const bool& aUseTrackingProtection, bool* aSuccess) override;
|
||||
bool* aSuccess) override;
|
||||
|
||||
// PURLClassifierLocalParent.
|
||||
virtual PURLClassifierLocalParent* AllocPURLClassifierLocalParent(
|
||||
|
|
|
@ -816,7 +816,7 @@ parent:
|
|||
|
||||
async CreateAudioIPCConnection() returns (FileDescriptor fd);
|
||||
|
||||
sync PURLClassifier(Principal principal, bool useTrackingProtection)
|
||||
sync PURLClassifier(Principal principal)
|
||||
returns (bool success);
|
||||
|
||||
async PURLClassifierLocal(URIParams uri, IPCURLClassifierFeature[] features);
|
||||
|
|
|
@ -18,7 +18,7 @@ using namespace mozilla::dom;
|
|||
NS_IMPL_ISUPPORTS(URLClassifierParent, nsIURIClassifierCallback)
|
||||
|
||||
mozilla::ipc::IPCResult URLClassifierParent::StartClassify(
|
||||
nsIPrincipal* aPrincipal, bool aUseTrackingProtection, bool* aSuccess) {
|
||||
nsIPrincipal* aPrincipal, bool* aSuccess) {
|
||||
*aSuccess = false;
|
||||
nsresult rv = NS_OK;
|
||||
// Note that in safe mode, the URL classifier service isn't available, so we
|
||||
|
@ -26,8 +26,7 @@ mozilla::ipc::IPCResult URLClassifierParent::StartClassify(
|
|||
nsCOMPtr<nsIURIClassifier> uriClassifier =
|
||||
do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = uriClassifier->Classify(aPrincipal, nullptr, aUseTrackingProtection,
|
||||
this, aSuccess);
|
||||
rv = uriClassifier->Classify(aPrincipal, nullptr, this, aSuccess);
|
||||
}
|
||||
if (NS_FAILED(rv) || !*aSuccess) {
|
||||
// We treat the case where we fail to classify and the case where the
|
||||
|
|
|
@ -24,7 +24,6 @@ class URLClassifierParent : public nsIURIClassifierCallback,
|
|||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
mozilla::ipc::IPCResult StartClassify(nsIPrincipal* aPrincipal,
|
||||
bool aUseTrackingProtection,
|
||||
bool* aSuccess);
|
||||
|
||||
// nsIURIClassifierCallback.
|
||||
|
|
|
@ -403,8 +403,8 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
|
|||
wr::ToRoundedLayoutRect(aPipeline->mScBounds),
|
||||
wr::WrStackingContextClip::None(), nullptr, &opacity,
|
||||
aPipeline->mScTransform.IsIdentity() ? nullptr : &aPipeline->mScTransform,
|
||||
wr::TransformStyle::Flat, nullptr, aPipeline->mMixBlendMode,
|
||||
nsTArray<wr::FilterOp>(), true,
|
||||
wr::TransformStyle::Flat, wr::ReferenceFrameKind::Transform,
|
||||
aPipeline->mMixBlendMode, nsTArray<wr::FilterOp>(), true,
|
||||
// This is fine to do unconditionally because we only push images here.
|
||||
wr::RasterSpace::Screen());
|
||||
|
||||
|
|
|
@ -27,7 +27,8 @@ StackingContextHelper::StackingContextHelper(
|
|||
wr::DisplayListBuilder& aBuilder, const nsTArray<wr::FilterOp>& aFilters,
|
||||
const LayoutDeviceRect& aBounds, const gfx::Matrix4x4* aBoundTransform,
|
||||
const wr::WrAnimationProperty* aAnimation, const float* aOpacityPtr,
|
||||
const gfx::Matrix4x4* aTransformPtr, const gfx::Matrix4x4* aPerspectivePtr,
|
||||
const gfx::Matrix4x4* aTransformPtr,
|
||||
wr::ReferenceFrameKind aReferenceFrameKind,
|
||||
const gfx::CompositionOp& aMixBlendMode, bool aBackfaceVisible,
|
||||
bool aIsPreserve3D,
|
||||
const Maybe<nsDisplayTransform*>& aDeferredTransformItem,
|
||||
|
@ -41,7 +42,8 @@ StackingContextHelper::StackingContextHelper(
|
|||
// transformed items
|
||||
gfx::Matrix transform2d;
|
||||
if (aBoundTransform && aBoundTransform->CanDraw2D(&transform2d) &&
|
||||
!aPerspectivePtr && !aParentSC.mIsPreserve3D) {
|
||||
aReferenceFrameKind != wr::ReferenceFrameKind::Perspective &&
|
||||
!aParentSC.mIsPreserve3D) {
|
||||
mInheritedTransform = transform2d * aParentSC.mInheritedTransform;
|
||||
|
||||
int32_t apd = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
|
@ -70,7 +72,7 @@ StackingContextHelper::StackingContextHelper(
|
|||
mReferenceFrameId = mBuilder->PushStackingContext(
|
||||
wr::ToLayoutRect(aBounds), aClip, aAnimation, aOpacityPtr, aTransformPtr,
|
||||
aIsPreserve3D ? wr::TransformStyle::Preserve3D : wr::TransformStyle::Flat,
|
||||
aPerspectivePtr, wr::ToMixBlendMode(aMixBlendMode), aFilters,
|
||||
aReferenceFrameKind, wr::ToMixBlendMode(aMixBlendMode), aFilters,
|
||||
aBackfaceVisible, rasterSpace);
|
||||
|
||||
if (mReferenceFrameId) {
|
||||
|
|
|
@ -37,7 +37,7 @@ class MOZ_RAII StackingContextHelper {
|
|||
const wr::WrAnimationProperty* aAnimation = nullptr,
|
||||
const float* aOpacityPtr = nullptr,
|
||||
const gfx::Matrix4x4* aTransformPtr = nullptr,
|
||||
const gfx::Matrix4x4* aPerspectivePtr = nullptr,
|
||||
const wr::ReferenceFrameKind = wr::ReferenceFrameKind::Transform,
|
||||
const gfx::CompositionOp& aMixBlendMode = gfx::CompositionOp::OP_OVER,
|
||||
bool aBackfaceVisible = true, bool aIsPreserve3D = false,
|
||||
const Maybe<nsDisplayTransform*>& aDeferredTransformItem = Nothing(),
|
||||
|
|
|
@ -685,12 +685,12 @@ static void FinishAsyncMemoryReport() {
|
|||
// clang-format off
|
||||
// (For some reason, clang-format gets the second macro right, but totally mangles the first).
|
||||
#define REPORT_INTERNER(id) \
|
||||
helper.Report(aReport.interning.id##_interner, \
|
||||
helper.Report(aReport.interning.interners.id, \
|
||||
"interning/" #id "/interners");
|
||||
// clang-format on
|
||||
|
||||
#define REPORT_DATA_STORE(id) \
|
||||
helper.Report(aReport.interning.id##_data_store, \
|
||||
helper.Report(aReport.interning.data_stores.id, \
|
||||
"interning/" #id "/data-stores");
|
||||
|
||||
NS_IMPL_ISUPPORTS(WebRenderMemoryReporter, nsIMemoryReporter)
|
||||
|
|
|
@ -39,7 +39,7 @@ static StaticRefPtr<RenderThread> sRenderThread;
|
|||
|
||||
RenderThread::RenderThread(base::Thread* aThread)
|
||||
: mThread(aThread),
|
||||
mFrameCountMapLock("RenderThread.mFrameCountMapLock"),
|
||||
mWindowInfos("RenderThread.mWindowInfos"),
|
||||
mRenderTextureMapLock("RenderThread.mRenderTextureMapLock"),
|
||||
mHasShutdown(false),
|
||||
mHandlingDeviceReset(false) {}
|
||||
|
@ -180,8 +180,7 @@ void RenderThread::AddRenderer(wr::WindowId aWindowId,
|
|||
|
||||
mRenderers[aWindowId] = std::move(aRenderer);
|
||||
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
mWindowInfos.emplace(AsUint64(aWindowId), new WindowInfo());
|
||||
mWindowInfos.Lock()->emplace(AsUint64(aWindowId), new WindowInfo());
|
||||
}
|
||||
|
||||
void RenderThread::RemoveRenderer(wr::WindowId aWindowId) {
|
||||
|
@ -197,11 +196,11 @@ void RenderThread::RemoveRenderer(wr::WindowId aWindowId) {
|
|||
mHandlingDeviceReset = false;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
auto it = mWindowInfos.find(AsUint64(aWindowId));
|
||||
MOZ_ASSERT(it != mWindowInfos.end());
|
||||
auto windows = mWindowInfos.Lock();
|
||||
auto it = windows->find(AsUint64(aWindowId));
|
||||
MOZ_ASSERT(it != windows->end());
|
||||
WindowInfo* toDelete = it->second;
|
||||
mWindowInfos.erase(it);
|
||||
windows->erase(it);
|
||||
delete toDelete;
|
||||
}
|
||||
|
||||
|
@ -248,9 +247,9 @@ void RenderThread::HandleFrame(wr::WindowId aWindowId, bool aRender) {
|
|||
|
||||
bool hadSlowFrame;
|
||||
{ // scope lock
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
auto it = mWindowInfos.find(AsUint64(aWindowId));
|
||||
MOZ_ASSERT(it != mWindowInfos.end());
|
||||
auto windows = mWindowInfos.Lock();
|
||||
auto it = windows->find(AsUint64(aWindowId));
|
||||
MOZ_ASSERT(it != windows->end());
|
||||
WindowInfo* info = it->second;
|
||||
MOZ_ASSERT(info->mPendingCount > 0);
|
||||
startTime = info->mStartTimes.front();
|
||||
|
@ -432,9 +431,9 @@ bool RenderThread::TooManyPendingFrames(wr::WindowId aWindowId) {
|
|||
// Too many pending frames if pending frames exit more than maxFrameCount
|
||||
// or if RenderBackend is still processing a frame.
|
||||
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
auto it = mWindowInfos.find(AsUint64(aWindowId));
|
||||
if (it == mWindowInfos.end()) {
|
||||
auto windows = mWindowInfos.Lock();
|
||||
auto it = windows->find(AsUint64(aWindowId));
|
||||
if (it == windows->end()) {
|
||||
MOZ_ASSERT(false);
|
||||
return true;
|
||||
}
|
||||
|
@ -448,9 +447,9 @@ bool RenderThread::TooManyPendingFrames(wr::WindowId aWindowId) {
|
|||
}
|
||||
|
||||
bool RenderThread::IsDestroyed(wr::WindowId aWindowId) {
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
auto it = mWindowInfos.find(AsUint64(aWindowId));
|
||||
if (it == mWindowInfos.end()) {
|
||||
auto windows = mWindowInfos.Lock();
|
||||
auto it = windows->find(AsUint64(aWindowId));
|
||||
if (it == windows->end()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -458,9 +457,9 @@ bool RenderThread::IsDestroyed(wr::WindowId aWindowId) {
|
|||
}
|
||||
|
||||
void RenderThread::SetDestroyed(wr::WindowId aWindowId) {
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
auto it = mWindowInfos.find(AsUint64(aWindowId));
|
||||
if (it == mWindowInfos.end()) {
|
||||
auto windows = mWindowInfos.Lock();
|
||||
auto it = windows->find(AsUint64(aWindowId));
|
||||
if (it == windows->end()) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
@ -470,9 +469,9 @@ void RenderThread::SetDestroyed(wr::WindowId aWindowId) {
|
|||
void RenderThread::IncPendingFrameCount(wr::WindowId aWindowId,
|
||||
const VsyncId& aStartId,
|
||||
const TimeStamp& aStartTime) {
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
auto it = mWindowInfos.find(AsUint64(aWindowId));
|
||||
if (it == mWindowInfos.end()) {
|
||||
auto windows = mWindowInfos.Lock();
|
||||
auto it = windows->find(AsUint64(aWindowId));
|
||||
if (it == windows->end()) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
@ -482,9 +481,9 @@ void RenderThread::IncPendingFrameCount(wr::WindowId aWindowId,
|
|||
}
|
||||
|
||||
void RenderThread::DecPendingFrameCount(wr::WindowId aWindowId) {
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
auto it = mWindowInfos.find(AsUint64(aWindowId));
|
||||
if (it == mWindowInfos.end()) {
|
||||
auto windows = mWindowInfos.Lock();
|
||||
auto it = windows->find(AsUint64(aWindowId));
|
||||
if (it == windows->end()) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
@ -506,9 +505,9 @@ void RenderThread::DecPendingFrameCount(wr::WindowId aWindowId) {
|
|||
}
|
||||
|
||||
void RenderThread::IncRenderingFrameCount(wr::WindowId aWindowId) {
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
auto it = mWindowInfos.find(AsUint64(aWindowId));
|
||||
if (it == mWindowInfos.end()) {
|
||||
auto windows = mWindowInfos.Lock();
|
||||
auto it = windows->find(AsUint64(aWindowId));
|
||||
if (it == windows->end()) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
@ -516,9 +515,9 @@ void RenderThread::IncRenderingFrameCount(wr::WindowId aWindowId) {
|
|||
}
|
||||
|
||||
void RenderThread::FrameRenderingComplete(wr::WindowId aWindowId) {
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
auto it = mWindowInfos.find(AsUint64(aWindowId));
|
||||
if (it == mWindowInfos.end()) {
|
||||
auto windows = mWindowInfos.Lock();
|
||||
auto it = windows->find(AsUint64(aWindowId));
|
||||
if (it == windows->end()) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
@ -541,9 +540,9 @@ void RenderThread::FrameRenderingComplete(wr::WindowId aWindowId) {
|
|||
}
|
||||
|
||||
void RenderThread::NotifySlowFrame(wr::WindowId aWindowId) {
|
||||
MutexAutoLock lock(mFrameCountMapLock);
|
||||
auto it = mWindowInfos.find(AsUint64(aWindowId));
|
||||
if (it == mWindowInfos.end()) {
|
||||
auto windows = mWindowInfos.Lock();
|
||||
auto it = windows->find(AsUint64(aWindowId));
|
||||
if (it == windows->end()) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/DataMutex.h"
|
||||
#include "mozilla/webrender/webrender_ffi.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
|
@ -272,8 +272,7 @@ class RenderThread final {
|
|||
bool mHadSlowFrame = false;
|
||||
};
|
||||
|
||||
Mutex mFrameCountMapLock;
|
||||
std::unordered_map<uint64_t, WindowInfo*> mWindowInfos;
|
||||
DataMutex<std::unordered_map<uint64_t, WindowInfo*>> mWindowInfos;
|
||||
|
||||
Mutex mRenderTextureMapLock;
|
||||
std::unordered_map<uint64_t, RefPtr<RenderTextureHost>> mRenderTextures;
|
||||
|
|
|
@ -676,7 +676,7 @@ Maybe<wr::WrSpatialId> DisplayListBuilder::PushStackingContext(
|
|||
const wr::LayoutRect& aBounds, const wr::WrStackingContextClip& aClip,
|
||||
const WrAnimationProperty* aAnimation, const float* aOpacity,
|
||||
const gfx::Matrix4x4* aTransform, wr::TransformStyle aTransformStyle,
|
||||
const gfx::Matrix4x4* aPerspective, const wr::MixBlendMode& aMixBlendMode,
|
||||
const wr::ReferenceFrameKind aReferenceFrameKind, const wr::MixBlendMode& aMixBlendMode,
|
||||
const nsTArray<wr::FilterOp>& aFilters, bool aIsBackfaceVisible,
|
||||
const wr::RasterSpace& aRasterSpace) {
|
||||
MOZ_ASSERT(mClipChainLeaf.isNothing(),
|
||||
|
@ -687,20 +687,13 @@ Maybe<wr::WrSpatialId> DisplayListBuilder::PushStackingContext(
|
|||
matrix = ToLayoutTransform(*aTransform);
|
||||
}
|
||||
const wr::LayoutTransform* maybeTransform = aTransform ? &matrix : nullptr;
|
||||
wr::LayoutTransform perspective;
|
||||
if (aPerspective) {
|
||||
perspective = ToLayoutTransform(*aPerspective);
|
||||
}
|
||||
|
||||
const wr::LayoutTransform* maybePerspective =
|
||||
aPerspective ? &perspective : nullptr;
|
||||
WRDL_LOG("PushStackingContext b=%s t=%s\n", mWrState,
|
||||
Stringify(aBounds).c_str(),
|
||||
aTransform ? Stringify(*aTransform).c_str() : "none");
|
||||
|
||||
auto spatialId = wr_dp_push_stacking_context(
|
||||
mWrState, aBounds, mCurrentSpaceAndClipChain.space, &aClip, aAnimation,
|
||||
aOpacity, maybeTransform, aTransformStyle, maybePerspective,
|
||||
aOpacity, maybeTransform, aTransformStyle, aReferenceFrameKind,
|
||||
aMixBlendMode, aFilters.Elements(), aFilters.Length(), aIsBackfaceVisible,
|
||||
aRasterSpace);
|
||||
|
||||
|
|
|
@ -333,7 +333,7 @@ class DisplayListBuilder {
|
|||
const wr::LayoutRect& aBounds, const wr::WrStackingContextClip& aClip,
|
||||
const wr::WrAnimationProperty* aAnimation, const float* aOpacity,
|
||||
const gfx::Matrix4x4* aTransform, wr::TransformStyle aTransformStyle,
|
||||
const gfx::Matrix4x4* aPerspective, const wr::MixBlendMode& aMixBlendMode,
|
||||
const wr::ReferenceFrameKind, const wr::MixBlendMode& aMixBlendMode,
|
||||
const nsTArray<wr::FilterOp>& aFilters, bool aIsBackfaceVisible,
|
||||
const wr::RasterSpace& aRasterSpace);
|
||||
void PopStackingContext(bool aIsReferenceFrame);
|
||||
|
|
|
@ -1904,7 +1904,7 @@ pub extern "C" fn wr_dp_push_stacking_context(
|
|||
opacity: *const f32,
|
||||
transform: *const LayoutTransform,
|
||||
transform_style: TransformStyle,
|
||||
perspective: *const LayoutTransform,
|
||||
reference_frame_kind: ReferenceFrameKind,
|
||||
mix_blend_mode: MixBlendMode,
|
||||
filters: *const FilterOp,
|
||||
filter_count: usize,
|
||||
|
@ -1955,28 +1955,21 @@ pub extern "C" fn wr_dp_push_stacking_context(
|
|||
}
|
||||
}
|
||||
|
||||
let perspective_ref = unsafe { perspective.as_ref() };
|
||||
let perspective = match perspective_ref {
|
||||
Some(perspective) => Some(perspective.clone()),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let mut wr_spatial_id = spatial_id.to_webrender(state.pipeline_id);
|
||||
let wr_clip_id = clip.to_webrender(state.pipeline_id);
|
||||
|
||||
let is_reference_frame = transform_binding.is_some() || perspective.is_some();
|
||||
// Note: 0 has special meaning in WR land, standing for ROOT_REFERENCE_FRAME.
|
||||
// However, it is never returned by `push_reference_frame`, and we need to return
|
||||
// an option here across FFI, so we take that 0 value for the None semantics.
|
||||
// This is resolved into proper `Maybe<WrSpatialId>` inside `WebRenderAPI::PushStackingContext`.
|
||||
let mut result = WrSpatialId { id: 0 };
|
||||
if is_reference_frame {
|
||||
if let Some(transform_binding) = transform_binding {
|
||||
wr_spatial_id = state.frame_builder.dl_builder.push_reference_frame(
|
||||
&bounds,
|
||||
wr_spatial_id,
|
||||
transform_style,
|
||||
transform_binding,
|
||||
perspective,
|
||||
reference_frame_kind,
|
||||
);
|
||||
|
||||
bounds.origin = LayoutPoint::zero();
|
||||
|
|
|
@ -54,15 +54,13 @@ namespace mozilla {
|
|||
namespace wr {
|
||||
|
||||
// Because this struct is macro-generated on the Rust side, cbindgen can't see
|
||||
// it for some reason. Work around that by re-declaring it here.
|
||||
#define DECLARE_MEMBERS(id) \
|
||||
uintptr_t id##_interner; \
|
||||
uintptr_t id##_data_store;
|
||||
struct InterningMemoryReport {
|
||||
WEBRENDER_FOR_EACH_INTERNER(DECLARE_MEMBERS)
|
||||
// it. Work around that by re-declaring it here.
|
||||
#define DECLARE_MEMBER(id) uintptr_t id;
|
||||
struct InternerSubReport {
|
||||
WEBRENDER_FOR_EACH_INTERNER(DECLARE_MEMBER)
|
||||
};
|
||||
|
||||
#undef DECLARE_MEMBERS
|
||||
#undef DECLARE_MEMBER
|
||||
|
||||
struct FontInstanceFlags {
|
||||
uint32_t bits;
|
||||
|
|
|
@ -59,8 +59,8 @@ impl App {
|
|||
&LayoutRect::new(bounds.origin, LayoutSize::zero()),
|
||||
SpatialId::root_scroll_node(pipeline_id),
|
||||
TransformStyle::Flat,
|
||||
Some(PropertyBinding::Binding(property_key, LayoutTransform::identity())),
|
||||
None,
|
||||
PropertyBinding::Binding(property_key, LayoutTransform::identity()),
|
||||
ReferenceFrameKind::Transform,
|
||||
);
|
||||
|
||||
builder.push_stacking_context(
|
||||
|
|
|
@ -66,8 +66,8 @@ impl Example for App {
|
|||
&sub_bounds,
|
||||
space_and_clip.spatial_id,
|
||||
TransformStyle::Flat,
|
||||
Some(PropertyBinding::Binding(PropertyBindingKey::new(42), LayoutTransform::identity())),
|
||||
None,
|
||||
PropertyBinding::Binding(PropertyBindingKey::new(42), LayoutTransform::identity()),
|
||||
ReferenceFrameKind::Transform,
|
||||
);
|
||||
|
||||
// And this is for the root pipeline
|
||||
|
|
|
@ -19,7 +19,7 @@ use prim_store::{DeferredResolve, EdgeAaSegmentMask, PrimitiveInstanceKind, Prim
|
|||
use prim_store::{VisibleGradientTile, PrimitiveInstance, PrimitiveOpacity, SegmentInstanceIndex};
|
||||
use prim_store::{BrushSegment, ClipMaskKind, ClipTaskIndex};
|
||||
use prim_store::image::ImageSource;
|
||||
use render_backend::FrameResources;
|
||||
use render_backend::DataStores;
|
||||
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskTree, TileBlit};
|
||||
use renderer::{BlendMode, ImageBufferKind, ShaderColorMode};
|
||||
use renderer::BLOCKS_PER_UV_RECT;
|
||||
|
@ -614,7 +614,7 @@ impl AlphaBatchBuilder {
|
|||
render_tasks,
|
||||
).unwrap_or(OPAQUE_TASK_ADDRESS);
|
||||
|
||||
let prim_common_data = &ctx.resources.as_common_data(&prim_instance);
|
||||
let prim_common_data = &ctx.data_stores.as_common_data(&prim_instance);
|
||||
let prim_rect = LayoutRect::new(
|
||||
prim_instance.prim_origin,
|
||||
prim_common_data.prim_size,
|
||||
|
@ -622,7 +622,7 @@ impl AlphaBatchBuilder {
|
|||
|
||||
match prim_instance.kind {
|
||||
PrimitiveInstanceKind::Clear { data_handle } => {
|
||||
let prim_data = &ctx.resources.prim_data_store[data_handle];
|
||||
let prim_data = &ctx.data_stores.prim[data_handle];
|
||||
let prim_cache_address = gpu_cache.get_address(&prim_data.gpu_cache_handle);
|
||||
|
||||
// TODO(gw): We can abstract some of the common code below into
|
||||
|
@ -667,7 +667,7 @@ impl AlphaBatchBuilder {
|
|||
);
|
||||
}
|
||||
PrimitiveInstanceKind::NormalBorder { data_handle, ref cache_handles, .. } => {
|
||||
let prim_data = &ctx.resources.normal_border_data_store[data_handle];
|
||||
let prim_data = &ctx.data_stores.normal_border[data_handle];
|
||||
let common_data = &prim_data.common;
|
||||
let prim_cache_address = gpu_cache.get_address(&common_data.gpu_cache_handle);
|
||||
let cache_handles = &ctx.scratch.border_cache_handles[*cache_handles];
|
||||
|
@ -747,7 +747,7 @@ impl AlphaBatchBuilder {
|
|||
|
||||
// The GPU cache data is stored in the template and reused across
|
||||
// frames and display lists.
|
||||
let prim_data = &ctx.resources.text_run_data_store[data_handle];
|
||||
let prim_data = &ctx.data_stores.text_run[data_handle];
|
||||
let glyph_fetch_buffer = &mut self.glyph_fetch_buffer;
|
||||
let alpha_batch_list = &mut self.batch_lists.last_mut().unwrap().alpha_batch_list;
|
||||
let prim_cache_address = gpu_cache.get_address(&prim_data.gpu_cache_handle);
|
||||
|
@ -854,7 +854,7 @@ impl AlphaBatchBuilder {
|
|||
PrimitiveInstanceKind::LineDecoration { data_handle, ref cache_handle, .. } => {
|
||||
// The GPU cache data is stored in the template and reused across
|
||||
// frames and display lists.
|
||||
let common_data = &ctx.resources.line_decoration_data_store[data_handle].common;
|
||||
let common_data = &ctx.data_stores.line_decoration[data_handle].common;
|
||||
let prim_cache_address = gpu_cache.get_address(&common_data.gpu_cache_handle);
|
||||
|
||||
let (batch_kind, textures, prim_user_data, segment_user_data) = match cache_handle {
|
||||
|
@ -1488,7 +1488,7 @@ impl AlphaBatchBuilder {
|
|||
}
|
||||
}
|
||||
PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
|
||||
let prim_data = &ctx.resources.image_border_data_store[data_handle];
|
||||
let prim_data = &ctx.data_stores.image_border[data_handle];
|
||||
let common_data = &prim_data.common;
|
||||
let border_data = &prim_data.kind;
|
||||
|
||||
|
@ -1557,7 +1557,7 @@ impl AlphaBatchBuilder {
|
|||
);
|
||||
}
|
||||
PrimitiveInstanceKind::Rectangle { data_handle, segment_instance_index, opacity_binding_index, .. } => {
|
||||
let prim_data = &ctx.resources.prim_data_store[data_handle];
|
||||
let prim_data = &ctx.data_stores.prim[data_handle];
|
||||
let specified_blend_mode = BlendMode::PremultipliedAlpha;
|
||||
let opacity_binding = ctx.prim_store.get_opacity_binding(opacity_binding_index);
|
||||
|
||||
|
@ -1620,7 +1620,7 @@ impl AlphaBatchBuilder {
|
|||
);
|
||||
}
|
||||
PrimitiveInstanceKind::YuvImage { data_handle, segment_instance_index, .. } => {
|
||||
let yuv_image_data = &ctx.resources.yuv_image_data_store[data_handle].kind;
|
||||
let yuv_image_data = &ctx.data_stores.yuv_image[data_handle].kind;
|
||||
let mut textures = BatchTextures::no_texture();
|
||||
let mut uv_rect_addresses = [0; 3];
|
||||
|
||||
|
@ -1728,8 +1728,8 @@ impl AlphaBatchBuilder {
|
|||
);
|
||||
}
|
||||
PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
|
||||
let image_data = &ctx.resources.image_data_store[data_handle].kind;
|
||||
let common_data = &ctx.resources.image_data_store[data_handle].common;
|
||||
let image_data = &ctx.data_stores.image[data_handle].kind;
|
||||
let common_data = &ctx.data_stores.image[data_handle].common;
|
||||
let image_instance = &ctx.prim_store.images[image_instance_index];
|
||||
let opacity_binding = ctx.prim_store.get_opacity_binding(image_instance.opacity_binding_index);
|
||||
let specified_blend_mode = match image_data.alpha_type {
|
||||
|
@ -1867,7 +1867,7 @@ impl AlphaBatchBuilder {
|
|||
}
|
||||
}
|
||||
PrimitiveInstanceKind::LinearGradient { data_handle, ref visible_tiles_range, .. } => {
|
||||
let prim_data = &ctx.resources.linear_grad_data_store[data_handle];
|
||||
let prim_data = &ctx.data_stores.linear_grad[data_handle];
|
||||
let specified_blend_mode = BlendMode::PremultipliedAlpha;
|
||||
|
||||
let mut prim_header = PrimitiveHeader {
|
||||
|
@ -1948,7 +1948,7 @@ impl AlphaBatchBuilder {
|
|||
}
|
||||
}
|
||||
PrimitiveInstanceKind::RadialGradient { data_handle, ref visible_tiles_range, .. } => {
|
||||
let prim_data = &ctx.resources.radial_grad_data_store[data_handle];
|
||||
let prim_data = &ctx.data_stores.radial_grad[data_handle];
|
||||
let specified_blend_mode = BlendMode::PremultipliedAlpha;
|
||||
|
||||
let mut prim_header = PrimitiveHeader {
|
||||
|
@ -2359,17 +2359,17 @@ impl BrushBatchParameters {
|
|||
impl PrimitiveInstance {
|
||||
pub fn is_cacheable(
|
||||
&self,
|
||||
resources: &FrameResources,
|
||||
data_stores: &DataStores,
|
||||
resource_cache: &ResourceCache,
|
||||
) -> bool {
|
||||
let image_key = match self.kind {
|
||||
PrimitiveInstanceKind::Image { data_handle, .. } => {
|
||||
let image_data = &resources.image_data_store[data_handle].kind;
|
||||
let image_data = &data_stores.image[data_handle].kind;
|
||||
image_data.key
|
||||
}
|
||||
PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
|
||||
let yuv_image_data =
|
||||
&resources.yuv_image_data_store[data_handle].kind;
|
||||
&data_stores.yuv_image[data_handle].kind;
|
||||
yuv_image_data.yuv_key[0]
|
||||
}
|
||||
PrimitiveInstanceKind::Picture { .. } |
|
||||
|
|
|
@ -104,15 +104,9 @@ use util::{extract_inner_rect_safe, project_rect, ScaleOffset};
|
|||
*/
|
||||
|
||||
// Type definitions for interning clip nodes.
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
|
||||
pub struct ClipDataMarker;
|
||||
|
||||
pub type ClipDataStore = intern::DataStore<ClipItemKey, ClipNode, ClipDataMarker>;
|
||||
pub type ClipDataHandle = intern::Handle<ClipDataMarker>;
|
||||
pub type ClipDataUpdateList = intern::UpdateList<ClipItemKey>;
|
||||
pub type ClipDataInterner = intern::Interner<ClipItemKey, (), ClipDataMarker>;
|
||||
pub use intern_types::clip::Store as ClipDataStore;
|
||||
use intern_types::clip::Handle as ClipDataHandle;
|
||||
|
||||
// Result of comparing a clip node instance against a local rect.
|
||||
#[derive(Debug)]
|
||||
|
@ -1034,7 +1028,7 @@ impl ClipItem {
|
|||
// reduce the size of a primitive region. This is typically
|
||||
// used to eliminate redundant clips, and reduce the size of
|
||||
// any clip mask that eventually gets drawn.
|
||||
fn get_local_clip_rect(&self, local_pos: LayoutPoint) -> Option<LayoutRect> {
|
||||
pub fn get_local_clip_rect(&self, local_pos: LayoutPoint) -> Option<LayoutRect> {
|
||||
let size = match *self {
|
||||
ClipItem::Rectangle(size, ClipMode::Clip) => Some(size),
|
||||
ClipItem::Rectangle(_, ClipMode::ClipOut) => None,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
use api::{ExternalScrollId, LayoutPoint, LayoutRect, LayoutVector2D};
|
||||
use api::{ExternalScrollId, LayoutPoint, LayoutRect, LayoutVector2D, ReferenceFrameKind};
|
||||
use api::{PipelineId, ScrollClamping, ScrollNodeState, ScrollLocation, ScrollSensitivity};
|
||||
use api::{LayoutSize, LayoutTransform, PropertyBinding, TransformStyle, WorldPoint};
|
||||
use gpu_types::TransformPalette;
|
||||
|
@ -352,8 +352,8 @@ impl ClipScrollTree {
|
|||
&mut self,
|
||||
parent_index: Option<SpatialNodeIndex>,
|
||||
transform_style: TransformStyle,
|
||||
source_transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
source_perspective: Option<LayoutTransform>,
|
||||
source_transform: PropertyBinding<LayoutTransform>,
|
||||
kind: ReferenceFrameKind,
|
||||
origin_in_parent_reference_frame: LayoutVector2D,
|
||||
pipeline_id: PipelineId,
|
||||
) -> SpatialNodeIndex {
|
||||
|
@ -361,7 +361,7 @@ impl ClipScrollTree {
|
|||
parent_index,
|
||||
transform_style,
|
||||
source_transform,
|
||||
source_perspective,
|
||||
kind,
|
||||
origin_in_parent_reference_frame,
|
||||
pipeline_id,
|
||||
);
|
||||
|
@ -456,10 +456,6 @@ impl ClipScrollTree {
|
|||
|
||||
match node.node_type {
|
||||
SpatialNodeType::ReferenceFrame(ref info) => {
|
||||
if !info.source_perspective.is_identity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
match info.source_transform {
|
||||
PropertyBinding::Value(transform) => {
|
||||
if transform != LayoutTransform::identity() {
|
||||
|
@ -508,8 +504,8 @@ fn add_reference_frame(
|
|||
cst.add_reference_frame(
|
||||
parent,
|
||||
TransformStyle::Preserve3D,
|
||||
Some(PropertyBinding::Value(transform)),
|
||||
None,
|
||||
PropertyBinding::Value(transform),
|
||||
ReferenceFrameKind::Perspective,
|
||||
origin_in_parent_reference_frame,
|
||||
PipelineId::dummy(),
|
||||
)
|
||||
|
|
|
@ -9,7 +9,7 @@ use api::{FilterOp, FontInstanceKey, GlyphInstance, GlyphOptions, RasterSpace, G
|
|||
use api::{IframeDisplayItem, ImageKey, ImageRendering, ItemRange, LayoutPoint, ColorDepth};
|
||||
use api::{LayoutPrimitiveInfo, LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D};
|
||||
use api::{LineOrientation, LineStyle, NinePatchBorderSource, PipelineId};
|
||||
use api::{PropertyBinding, ReferenceFrame, ScrollFrameDisplayItem, ScrollSensitivity};
|
||||
use api::{PropertyBinding, ReferenceFrame, ReferenceFrameKind, ScrollFrameDisplayItem, ScrollSensitivity};
|
||||
use api::{Shadow, SpaceAndClipInfo, SpatialId, SpecificDisplayItem, StackingContext, StickyFrameDisplayItem, TexelRect};
|
||||
use api::{ClipMode, TransformStyle, YuvColorSpace, YuvData};
|
||||
use app_units::Au;
|
||||
|
@ -35,7 +35,7 @@ use prim_store::text_run::TextRun;
|
|||
use render_backend::{DocumentView};
|
||||
use resource_cache::{FontInstanceMap, ImageRequest};
|
||||
use scene::{Scene, ScenePipeline, StackingContextHelpers};
|
||||
use scene_builder::{DocumentResources, InternerMut};
|
||||
use scene_builder::{InternerMut, Interners};
|
||||
use spatial_node::{StickyFrameInfo, ScrollFrameKind, SpatialNodeType};
|
||||
use std::{f32, mem, usize};
|
||||
use std::collections::vec_deque::VecDeque;
|
||||
|
@ -139,9 +139,8 @@ pub struct DisplayListFlattener<'a> {
|
|||
/// order to determine the default font.
|
||||
pub config: FrameBuilderConfig,
|
||||
|
||||
/// Reference to the document resources, which contains
|
||||
/// shared (interned) data between display lists.
|
||||
resources: &'a mut DocumentResources,
|
||||
/// Reference to the set of data that is interned across display lists.
|
||||
interners: &'a mut Interners,
|
||||
|
||||
/// The root picture index for this flattener. This is the picture
|
||||
/// to start the culling phase from.
|
||||
|
@ -157,7 +156,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
output_pipelines: &FastHashSet<PipelineId>,
|
||||
frame_builder_config: &FrameBuilderConfig,
|
||||
new_scene: &mut Scene,
|
||||
resources: &mut DocumentResources,
|
||||
interners: &mut Interners,
|
||||
prim_store_stats: &PrimitiveStoreStats,
|
||||
) -> FrameBuilder {
|
||||
// We checked that the root pipeline is available on the render backend.
|
||||
|
@ -181,7 +180,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
pipeline_clip_chain_stack: vec![ClipChainId::NONE],
|
||||
prim_store: PrimitiveStore::new(&prim_store_stats),
|
||||
clip_store: ClipStore::new(),
|
||||
resources,
|
||||
interners,
|
||||
root_pic_index: PictureIndex(0),
|
||||
};
|
||||
|
||||
|
@ -326,7 +325,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
let prim_list = PrimitiveList::new(
|
||||
remaining_prims,
|
||||
&self.resources,
|
||||
&self.interners,
|
||||
);
|
||||
|
||||
// Now, create a picture with tile caching enabled that will hold all
|
||||
|
@ -339,8 +338,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
},
|
||||
);
|
||||
|
||||
let pic_data_handle = self.resources
|
||||
.picture_interner
|
||||
let pic_data_handle = self.interners
|
||||
.picture
|
||||
.intern(&pic_key, || {
|
||||
PrimitiveSceneData {
|
||||
prim_size: LayoutSize::zero(),
|
||||
|
@ -598,7 +597,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
pipeline_id,
|
||||
reference_frame.transform_style,
|
||||
reference_frame.transform,
|
||||
reference_frame.perspective,
|
||||
reference_frame.kind,
|
||||
reference_frame_relative_offset + origin.to_vector(),
|
||||
);
|
||||
|
||||
|
@ -690,8 +689,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
Some(spatial_node_index),
|
||||
iframe_pipeline_id,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
None,
|
||||
PropertyBinding::Value(LayoutTransform::identity()),
|
||||
ReferenceFrameKind::Transform,
|
||||
origin,
|
||||
);
|
||||
|
||||
|
@ -1028,8 +1027,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
for (local_pos, item) in clip_items {
|
||||
// Intern this clip item, and store the handle
|
||||
// in the clip chain node.
|
||||
let handle = self.resources
|
||||
.clip_interner
|
||||
let handle = self.interners
|
||||
.clip
|
||||
.intern(&item, || ());
|
||||
|
||||
clip_chain_id = self.clip_store.add_clip_chain_node(
|
||||
|
@ -1059,12 +1058,12 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
where
|
||||
P: Internable<InternData=PrimitiveSceneData>,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
DocumentResources: InternerMut<P>,
|
||||
Interners: InternerMut<P>,
|
||||
{
|
||||
// Build a primitive key.
|
||||
let prim_key = prim.build_key(info);
|
||||
|
||||
let interner = self.resources.interner_mut();
|
||||
let interner = self.interners.interner_mut();
|
||||
let prim_data_handle =
|
||||
interner
|
||||
.intern(&prim_key, || {
|
||||
|
@ -1134,7 +1133,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
where
|
||||
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
DocumentResources: InternerMut<P>,
|
||||
Interners: InternerMut<P>,
|
||||
{
|
||||
if prim.is_visible() {
|
||||
let clip_chain_id = self.build_clip_chain(
|
||||
|
@ -1161,7 +1160,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
where
|
||||
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
DocumentResources: InternerMut<P>,
|
||||
Interners: InternerMut<P>,
|
||||
ShadowItem: From<PendingPrimitive<P>>
|
||||
{
|
||||
// If a shadow context is not active, then add the primitive
|
||||
|
@ -1191,7 +1190,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
where
|
||||
P: Internable<InternData = PrimitiveSceneData>,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
DocumentResources: InternerMut<P>,
|
||||
Interners: InternerMut<P>,
|
||||
{
|
||||
let prim_instance = self.create_primitive(
|
||||
info,
|
||||
|
@ -1238,7 +1237,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// so that the relative order between them and our current SC is preserved.
|
||||
let extra_instance = sc.cut_flat_item_sequence(
|
||||
&mut self.prim_store,
|
||||
&mut self.resources,
|
||||
&mut self.interners,
|
||||
&self.clip_store,
|
||||
);
|
||||
(sc.is_3d(), extra_instance)
|
||||
|
@ -1386,7 +1385,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
stacking_context.requested_raster_space,
|
||||
PrimitiveList::new(
|
||||
stacking_context.primitives,
|
||||
&self.resources,
|
||||
&self.interners,
|
||||
),
|
||||
stacking_context.spatial_node_index,
|
||||
max_clip,
|
||||
|
@ -1405,7 +1404,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
stacking_context.is_backface_visible,
|
||||
stacking_context.clip_chain_id,
|
||||
stacking_context.spatial_node_index,
|
||||
&mut self.resources,
|
||||
&mut self.interners,
|
||||
);
|
||||
|
||||
if cur_instance.is_chased() {
|
||||
|
@ -1433,7 +1432,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
stacking_context.requested_raster_space,
|
||||
PrimitiveList::new(
|
||||
prims,
|
||||
&self.resources,
|
||||
&self.interners,
|
||||
),
|
||||
stacking_context.spatial_node_index,
|
||||
max_clip,
|
||||
|
@ -1448,7 +1447,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
stacking_context.is_backface_visible,
|
||||
stacking_context.clip_chain_id,
|
||||
stacking_context.spatial_node_index,
|
||||
&mut self.resources,
|
||||
&mut self.interners,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1468,7 +1467,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
stacking_context.requested_raster_space,
|
||||
PrimitiveList::new(
|
||||
vec![cur_instance.clone()],
|
||||
&self.resources,
|
||||
&self.interners,
|
||||
),
|
||||
stacking_context.spatial_node_index,
|
||||
max_clip,
|
||||
|
@ -1484,7 +1483,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
stacking_context.is_backface_visible,
|
||||
stacking_context.clip_chain_id,
|
||||
stacking_context.spatial_node_index,
|
||||
&mut self.resources,
|
||||
&mut self.interners,
|
||||
);
|
||||
|
||||
if cur_instance.is_chased() {
|
||||
|
@ -1511,7 +1510,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
stacking_context.requested_raster_space,
|
||||
PrimitiveList::new(
|
||||
vec![cur_instance.clone()],
|
||||
&self.resources,
|
||||
&self.interners,
|
||||
),
|
||||
stacking_context.spatial_node_index,
|
||||
max_clip,
|
||||
|
@ -1527,7 +1526,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
stacking_context.is_backface_visible,
|
||||
stacking_context.clip_chain_id,
|
||||
stacking_context.spatial_node_index,
|
||||
&mut self.resources,
|
||||
&mut self.interners,
|
||||
);
|
||||
|
||||
if cur_instance.is_chased() {
|
||||
|
@ -1584,15 +1583,15 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
parent_index: Option<SpatialNodeIndex>,
|
||||
pipeline_id: PipelineId,
|
||||
transform_style: TransformStyle,
|
||||
source_transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
source_perspective: Option<LayoutTransform>,
|
||||
source_transform: PropertyBinding<LayoutTransform>,
|
||||
kind: ReferenceFrameKind,
|
||||
origin_in_parent_reference_frame: LayoutVector2D,
|
||||
) -> SpatialNodeIndex {
|
||||
let index = self.clip_scroll_tree.add_reference_frame(
|
||||
parent_index,
|
||||
transform_style,
|
||||
source_transform,
|
||||
source_perspective,
|
||||
kind,
|
||||
origin_in_parent_reference_frame,
|
||||
pipeline_id,
|
||||
);
|
||||
|
@ -1619,8 +1618,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
None,
|
||||
pipeline_id,
|
||||
TransformStyle::Flat,
|
||||
None,
|
||||
None,
|
||||
PropertyBinding::Value(LayoutTransform::identity()),
|
||||
ReferenceFrameKind::Transform,
|
||||
LayoutVector2D::zero(),
|
||||
);
|
||||
|
||||
|
@ -1662,8 +1661,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
// Build the clip sources from the supplied region.
|
||||
let handle = self
|
||||
.resources
|
||||
.clip_interner
|
||||
.interners
|
||||
.clip
|
||||
.intern(&ClipItemKey::rectangle(clip_region.main.size, ClipMode::Clip), || ());
|
||||
|
||||
parent_clip_chain_index = self
|
||||
|
@ -1678,8 +1677,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
if let Some(ref image_mask) = clip_region.image_mask {
|
||||
let handle = self
|
||||
.resources
|
||||
.clip_interner
|
||||
.interners
|
||||
.clip
|
||||
.intern(&ClipItemKey::image_mask(image_mask), || ());
|
||||
|
||||
parent_clip_chain_index = self
|
||||
|
@ -1695,8 +1694,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
for region in clip_region.complex_clips {
|
||||
let handle = self
|
||||
.resources
|
||||
.clip_interner
|
||||
.interners
|
||||
.clip
|
||||
.intern(&ClipItemKey::rounded_rect(region.rect.size, region.radii, region.mode), || ());
|
||||
|
||||
parent_clip_chain_index = self
|
||||
|
@ -1847,7 +1846,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
raster_space,
|
||||
PrimitiveList::new(
|
||||
prims,
|
||||
&self.resources,
|
||||
&self.interners,
|
||||
),
|
||||
pending_shadow.clip_and_scroll.spatial_node_index,
|
||||
max_clip,
|
||||
|
@ -1862,8 +1861,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
Picture { composite_mode_key },
|
||||
);
|
||||
|
||||
let shadow_prim_data_handle = self.resources
|
||||
.picture_interner
|
||||
let shadow_prim_data_handle = self.interners
|
||||
.picture
|
||||
.intern(&shadow_pic_key, || {
|
||||
PrimitiveSceneData {
|
||||
prim_size: LayoutSize::zero(),
|
||||
|
@ -1919,7 +1918,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
where
|
||||
P: Internable<InternData=PrimitiveSceneData> + CreateShadow,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
DocumentResources: InternerMut<P>,
|
||||
Interners: InternerMut<P>,
|
||||
{
|
||||
// Offset the local rect and clip rect by the shadow offset.
|
||||
let mut info = pending_primitive.info.clone();
|
||||
|
@ -1944,7 +1943,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
where
|
||||
P: Internable<InternData = PrimitiveSceneData> + IsVisible,
|
||||
P::Source: AsInstanceKind<Handle<P::Marker>> + InternDebug,
|
||||
DocumentResources: InternerMut<P>,
|
||||
Interners: InternerMut<P>,
|
||||
{
|
||||
// For a normal primitive, if it has alpha > 0, then we add this
|
||||
// as a normal primitive to the parent picture.
|
||||
|
@ -2594,7 +2593,7 @@ impl FlattenedStackingContext {
|
|||
pub fn cut_flat_item_sequence(
|
||||
&mut self,
|
||||
prim_store: &mut PrimitiveStore,
|
||||
resources: &mut DocumentResources,
|
||||
interners: &mut Interners,
|
||||
clip_store: &ClipStore,
|
||||
) -> Option<PrimitiveInstance> {
|
||||
if !self.is_3d() || self.primitives.is_empty() {
|
||||
|
@ -2619,7 +2618,7 @@ impl FlattenedStackingContext {
|
|||
self.requested_raster_space,
|
||||
PrimitiveList::new(
|
||||
mem::replace(&mut self.primitives, Vec::new()),
|
||||
resources,
|
||||
interners,
|
||||
),
|
||||
self.spatial_node_index,
|
||||
LayoutRect::max_rect(),
|
||||
|
@ -2634,7 +2633,7 @@ impl FlattenedStackingContext {
|
|||
self.is_backface_visible,
|
||||
self.clip_chain_id,
|
||||
self.spatial_node_index,
|
||||
resources,
|
||||
interners,
|
||||
);
|
||||
|
||||
Some(prim_instance)
|
||||
|
@ -2702,7 +2701,7 @@ fn create_prim_instance(
|
|||
is_backface_visible: bool,
|
||||
clip_chain_id: ClipChainId,
|
||||
spatial_node_index: SpatialNodeIndex,
|
||||
resources: &mut DocumentResources,
|
||||
interners: &mut Interners,
|
||||
) -> PrimitiveInstance {
|
||||
let pic_key = PictureKey::new(
|
||||
is_backface_visible,
|
||||
|
@ -2710,8 +2709,8 @@ fn create_prim_instance(
|
|||
Picture { composite_mode_key },
|
||||
);
|
||||
|
||||
let data_handle = resources
|
||||
.picture_interner
|
||||
let data_handle = interners
|
||||
.picture
|
||||
.intern(&pic_key, || {
|
||||
PrimitiveSceneData {
|
||||
prim_size: LayoutSize::zero(),
|
||||
|
|
|
@ -18,7 +18,7 @@ use prim_store::{PrimitiveStore, SpaceMapper, PictureIndex, PrimitiveDebugId, Pr
|
|||
#[cfg(feature = "replay")]
|
||||
use prim_store::{PrimitiveStoreStats};
|
||||
use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
|
||||
use render_backend::{FrameResources, FrameStamp};
|
||||
use render_backend::{DataStores, FrameStamp};
|
||||
use render_task::{RenderTask, RenderTaskId, RenderTaskLocation, RenderTaskTree};
|
||||
use resource_cache::{ResourceCache};
|
||||
use scene::{ScenePipeline, SceneProperties};
|
||||
|
@ -86,7 +86,7 @@ pub struct FrameVisibilityState<'a> {
|
|||
pub scratch: &'a mut PrimitiveScratchBuffer,
|
||||
pub tile_cache: Option<TileCache>,
|
||||
pub retained_tiles: &'a mut RetainedTiles,
|
||||
pub resources: &'a mut FrameResources,
|
||||
pub data_stores: &'a mut DataStores,
|
||||
}
|
||||
|
||||
pub struct FrameBuildingContext<'a> {
|
||||
|
@ -244,7 +244,7 @@ impl FrameBuilder {
|
|||
device_pixel_scale: DevicePixelScale,
|
||||
scene_properties: &SceneProperties,
|
||||
transform_palette: &mut TransformPalette,
|
||||
resources: &mut FrameResources,
|
||||
data_stores: &mut DataStores,
|
||||
surfaces: &mut Vec<SurfaceInfo>,
|
||||
scratch: &mut PrimitiveScratchBuffer,
|
||||
debug_flags: DebugFlags,
|
||||
|
@ -305,7 +305,7 @@ impl FrameBuilder {
|
|||
&mut pic_update_state,
|
||||
&frame_context,
|
||||
gpu_cache,
|
||||
resources,
|
||||
data_stores,
|
||||
&self.clip_store,
|
||||
);
|
||||
|
||||
|
@ -326,7 +326,7 @@ impl FrameBuilder {
|
|||
scratch,
|
||||
tile_cache: None,
|
||||
retained_tiles: &mut retained_tiles,
|
||||
resources,
|
||||
data_stores,
|
||||
};
|
||||
|
||||
self.prim_store.update_visibility(
|
||||
|
@ -369,7 +369,7 @@ impl FrameBuilder {
|
|||
&mut pic_state,
|
||||
&frame_context,
|
||||
&mut frame_state,
|
||||
resources,
|
||||
data_stores,
|
||||
scratch,
|
||||
);
|
||||
|
||||
|
@ -417,7 +417,7 @@ impl FrameBuilder {
|
|||
texture_cache_profile: &mut TextureCacheProfileCounters,
|
||||
gpu_cache_profile: &mut GpuCacheProfileCounters,
|
||||
scene_properties: &SceneProperties,
|
||||
resources: &mut FrameResources,
|
||||
data_stores: &mut DataStores,
|
||||
scratch: &mut PrimitiveScratchBuffer,
|
||||
debug_flags: DebugFlags,
|
||||
) -> Frame {
|
||||
|
@ -458,7 +458,7 @@ impl FrameBuilder {
|
|||
device_pixel_scale,
|
||||
scene_properties,
|
||||
&mut transform_palette,
|
||||
resources,
|
||||
data_stores,
|
||||
&mut surfaces,
|
||||
scratch,
|
||||
debug_flags,
|
||||
|
@ -512,7 +512,7 @@ impl FrameBuilder {
|
|||
resource_cache,
|
||||
use_dual_source_blending,
|
||||
clip_scroll_tree,
|
||||
resources,
|
||||
data_stores,
|
||||
surfaces: &surfaces,
|
||||
scratch,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/* 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/. */
|
||||
|
||||
macro_rules! common {
|
||||
() => (
|
||||
use ::intern;
|
||||
#[allow(unused_imports)]
|
||||
use ::prim_store::PrimitiveSceneData;
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
|
||||
pub struct Marker;
|
||||
pub type Handle = intern::Handle<Marker>;
|
||||
)
|
||||
}
|
||||
|
||||
pub mod clip {
|
||||
common!();
|
||||
use ::clip::{ClipItemKey, ClipNode};
|
||||
pub type Store = intern::DataStore<ClipItemKey, ClipNode, Marker>;
|
||||
pub type UpdateList = intern::UpdateList<ClipItemKey>;
|
||||
pub type Interner = intern::Interner<ClipItemKey, (), Marker>;
|
||||
}
|
||||
|
||||
pub mod prim {
|
||||
common!();
|
||||
use ::prim_store::{PrimitiveKey, PrimitiveTemplate};
|
||||
pub type Store = intern::DataStore<PrimitiveKey, PrimitiveTemplate, Marker>;
|
||||
pub type UpdateList = intern::UpdateList<PrimitiveKey>;
|
||||
pub type Interner = intern::Interner<PrimitiveKey, PrimitiveSceneData, Marker>;
|
||||
}
|
||||
|
||||
pub mod normal_border {
|
||||
common!();
|
||||
use ::prim_store::borders::{NormalBorderKey, NormalBorderTemplate};
|
||||
pub type Store = intern::DataStore<NormalBorderKey, NormalBorderTemplate, Marker>;
|
||||
pub type UpdateList = intern::UpdateList<NormalBorderKey>;
|
||||
pub type Interner = intern::Interner<NormalBorderKey, PrimitiveSceneData, Marker>;
|
||||
}
|
||||
|
||||
pub mod image_border {
|
||||
common!();
|
||||
use ::prim_store::borders::{ImageBorderKey, ImageBorderTemplate};
|
||||
pub type Store = intern::DataStore<ImageBorderKey, ImageBorderTemplate, Marker>;
|
||||
pub type UpdateList = intern::UpdateList<ImageBorderKey>;
|
||||
pub type Interner = intern::Interner<ImageBorderKey, PrimitiveSceneData, Marker>;
|
||||
}
|
||||
|
||||
pub mod image {
|
||||
common!();
|
||||
use ::prim_store::image::{ImageKey, ImageTemplate};
|
||||
pub type Store = intern::DataStore<ImageKey, ImageTemplate, Marker>;
|
||||
pub type UpdateList = intern::UpdateList<ImageKey>;
|
||||
pub type Interner = intern::Interner<ImageKey, PrimitiveSceneData, Marker>;
|
||||
}
|
||||
|
||||
pub mod yuv_image {
|
||||
common!();
|
||||
use ::prim_store::image::{YuvImageKey, YuvImageTemplate};
|
||||
pub type Store = intern::DataStore<YuvImageKey, YuvImageTemplate, Marker>;
|
||||
pub type UpdateList = intern::UpdateList<YuvImageKey>;
|
||||
pub type Interner = intern::Interner<YuvImageKey, PrimitiveSceneData, Marker>;
|
||||
}
|
||||
|
||||
pub mod line_decoration {
|
||||
use ::prim_store::line_dec::{LineDecorationKey, LineDecorationTemplate};
|
||||
common!();
|
||||
pub type Store = intern::DataStore<LineDecorationKey, LineDecorationTemplate, Marker>;
|
||||
pub type UpdateList = intern::UpdateList<LineDecorationKey>;
|
||||
pub type Interner = intern::Interner<LineDecorationKey, PrimitiveSceneData, Marker>;
|
||||
}
|
||||
|
||||
pub mod linear_grad {
|
||||
common!();
|
||||
use ::prim_store::gradient::{LinearGradientKey, LinearGradientTemplate};
|
||||
pub type Store = intern::DataStore<LinearGradientKey, LinearGradientTemplate, Marker>;
|
||||
pub type UpdateList = intern::UpdateList<LinearGradientKey>;
|
||||
pub type Interner = intern::Interner<LinearGradientKey, PrimitiveSceneData, Marker>;
|
||||
}
|
||||
|
||||
pub mod radial_grad {
|
||||
common!();
|
||||
use ::prim_store::gradient::{RadialGradientKey, RadialGradientTemplate};
|
||||
pub type Store = intern::DataStore<RadialGradientKey, RadialGradientTemplate, Marker>;
|
||||
pub type UpdateList = intern::UpdateList<RadialGradientKey>;
|
||||
pub type Interner = intern::Interner<RadialGradientKey, PrimitiveSceneData, Marker>;
|
||||
}
|
||||
|
||||
pub mod picture {
|
||||
common!();
|
||||
use ::prim_store::picture::{PictureKey, PictureTemplate};
|
||||
pub type Store = intern::DataStore<PictureKey, PictureTemplate, Marker>;
|
||||
pub type UpdateList = intern::UpdateList<PictureKey>;
|
||||
pub type Interner = intern::Interner<PictureKey, PrimitiveSceneData, Marker>;
|
||||
}
|
||||
|
||||
pub mod text_run {
|
||||
common!();
|
||||
use ::prim_store::text_run::{TextRunKey, TextRunTemplate};
|
||||
pub type Store = intern::DataStore<TextRunKey, TextRunTemplate, Marker>;
|
||||
pub type UpdateList = intern::UpdateList<TextRunKey>;
|
||||
pub type Interner = intern::Interner<TextRunKey, PrimitiveSceneData, Marker>;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -100,6 +100,7 @@ mod gpu_types;
|
|||
mod hit_test;
|
||||
mod image;
|
||||
mod intern;
|
||||
mod intern_types;
|
||||
mod internal_types;
|
||||
mod picture;
|
||||
mod prim_store;
|
||||
|
|
|
@ -16,7 +16,7 @@ use debug_colors;
|
|||
use device::TextureFilter;
|
||||
use euclid::{TypedScale, vec3, TypedRect, TypedPoint2D, TypedSize2D};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use frame_builder::FrameVisibilityContext;
|
||||
use frame_builder::{FrameVisibilityContext, FrameVisibilityState};
|
||||
use intern::ItemUid;
|
||||
use internal_types::{FastHashMap, FastHashSet, PlaneSplitter};
|
||||
use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState, PictureContext};
|
||||
|
@ -27,12 +27,12 @@ use prim_store::{PictureIndex, PrimitiveInstance, SpaceMapper, VisibleFace, Prim
|
|||
use prim_store::{get_raster_rects, PrimitiveScratchBuffer, VectorKey, PointKey};
|
||||
use prim_store::{OpacityBindingStorage, ImageInstanceStorage, OpacityBindingIndex, RectangleKey};
|
||||
use print_tree::PrintTreePrinter;
|
||||
use render_backend::FrameResources;
|
||||
use render_backend::DataStores;
|
||||
use render_task::{ClearMode, RenderTask, RenderTaskCacheEntryHandle, TileBlit};
|
||||
use render_task::{RenderTaskCacheKey, RenderTaskCacheKeyKind, RenderTaskId, RenderTaskLocation};
|
||||
use resource_cache::ResourceCache;
|
||||
use scene::{FilterOpHelpers, SceneProperties};
|
||||
use scene_builder::DocumentResources;
|
||||
use scene_builder::Interners;
|
||||
use smallvec::SmallVec;
|
||||
use surface::{SurfaceDescriptor};
|
||||
use std::{mem, u16};
|
||||
|
@ -315,12 +315,26 @@ impl TileDescriptor {
|
|||
/// as last frame. This doesn't check validity of the
|
||||
/// tile based on the currently valid regions.
|
||||
fn is_same_content(&self) -> bool {
|
||||
self.image_keys.is_valid() &&
|
||||
self.opacity_bindings.is_valid() &&
|
||||
self.clip_uids.is_valid() &&
|
||||
self.clip_vertices.is_valid() &&
|
||||
self.prims.is_valid() &&
|
||||
self.transforms.is_valid()
|
||||
if !self.image_keys.is_valid() {
|
||||
return false;
|
||||
}
|
||||
if !self.opacity_bindings.is_valid() {
|
||||
return false;
|
||||
}
|
||||
if !self.clip_uids.is_valid() {
|
||||
return false;
|
||||
}
|
||||
if !self.clip_vertices.is_valid() {
|
||||
return false;
|
||||
}
|
||||
if !self.prims.is_valid() {
|
||||
return false;
|
||||
}
|
||||
if !self.transforms.is_valid() {
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,6 +385,9 @@ pub struct TileCache {
|
|||
/// scroll bars in gecko, when the content overflows under the
|
||||
/// scroll bar).
|
||||
world_bounding_rect: WorldRect,
|
||||
/// World space clip rect of the root clipping node. Every primitive
|
||||
/// has this as the root of the clip chain attached to the primitive.
|
||||
root_clip_rect: WorldRect,
|
||||
/// List of reference primitive information used for
|
||||
/// correlating the position between display lists.
|
||||
reference_prims: ReferencePrimitiveList,
|
||||
|
@ -497,6 +514,7 @@ impl TileCache {
|
|||
scroll_offset: None,
|
||||
pending_blits: Vec::new(),
|
||||
world_bounding_rect: WorldRect::zero(),
|
||||
root_clip_rect: WorldRect::max_rect(),
|
||||
reference_prims,
|
||||
root_clip_chain_id,
|
||||
}
|
||||
|
@ -529,8 +547,7 @@ impl TileCache {
|
|||
&mut self,
|
||||
pic_rect: LayoutRect,
|
||||
frame_context: &FrameVisibilityContext,
|
||||
resource_cache: &ResourceCache,
|
||||
retained_tiles: &mut RetainedTiles,
|
||||
frame_state: &mut FrameVisibilityState,
|
||||
) {
|
||||
// Work out the scroll offset to apply to the world reference point.
|
||||
let scroll_transform = frame_context.clip_scroll_tree.get_relative_transform(
|
||||
|
@ -548,11 +565,11 @@ impl TileCache {
|
|||
self.scroll_offset = Some(scroll_offset);
|
||||
|
||||
// Pull any retained tiles from the previous scene.
|
||||
let world_offset = if retained_tiles.tiles.is_empty() {
|
||||
let world_offset = if frame_state.retained_tiles.tiles.is_empty() {
|
||||
None
|
||||
} else {
|
||||
assert!(self.tiles.is_empty());
|
||||
self.tiles = mem::replace(&mut retained_tiles.tiles, Vec::new());
|
||||
self.tiles = mem::replace(&mut frame_state.retained_tiles.tiles, Vec::new());
|
||||
|
||||
// Get the positions of the reference primitives for this
|
||||
// new display list.
|
||||
|
@ -565,7 +582,7 @@ impl TileCache {
|
|||
|
||||
// Attempt to correlate them to work out which offset to apply.
|
||||
correlate_prim_maps(
|
||||
&retained_tiles.ref_prims,
|
||||
&frame_state.retained_tiles.ref_prims,
|
||||
&new_prim_map,
|
||||
)
|
||||
}.unwrap_or(WorldVector2D::zero());
|
||||
|
@ -735,6 +752,28 @@ impl TileCache {
|
|||
// detect this and skip the dependency update on scroll frames.
|
||||
self.needs_update = true;
|
||||
self.world_bounding_rect = WorldRect::zero();
|
||||
self.root_clip_rect = WorldRect::max_rect();
|
||||
|
||||
// Calculate the world space of the root clip node, that every primitive has
|
||||
// at the root of its clip chain (this is enforced by the per-pipeline-root
|
||||
// clip node added implicitly during display list flattening). Doing it once
|
||||
// here saves doing it for every primitive during update_prim_dependencies.
|
||||
let root_clip_chain_node = &frame_state
|
||||
.clip_store
|
||||
.clip_chain_nodes[self.root_clip_chain_id.0 as usize];
|
||||
let root_clip_node = &frame_state
|
||||
.data_stores
|
||||
.clip[root_clip_chain_node.handle];
|
||||
if let Some(clip_rect) = root_clip_node.item.get_local_clip_rect(root_clip_chain_node.local_pos) {
|
||||
self.map_local_to_world.set_target_spatial_node(
|
||||
root_clip_chain_node.spatial_node_index,
|
||||
frame_context.clip_scroll_tree,
|
||||
);
|
||||
|
||||
if let Some(world_clip_rect) = self.map_local_to_world.map(&clip_rect) {
|
||||
self.root_clip_rect = world_clip_rect;
|
||||
}
|
||||
}
|
||||
|
||||
// Do tile invalidation for any dependencies that we know now.
|
||||
for tile in &mut self.tiles {
|
||||
|
@ -743,7 +782,7 @@ impl TileCache {
|
|||
|
||||
// Content has changed if any images have changed
|
||||
for image_key in tile.descriptor.image_keys.items() {
|
||||
if resource_cache.is_image_dirty(*image_key) {
|
||||
if frame_state.resource_cache.is_image_dirty(*image_key) {
|
||||
tile.is_same_content = false;
|
||||
break;
|
||||
}
|
||||
|
@ -776,7 +815,7 @@ impl TileCache {
|
|||
&mut self,
|
||||
prim_instance: &PrimitiveInstance,
|
||||
clip_scroll_tree: &ClipScrollTree,
|
||||
resources: &FrameResources,
|
||||
data_stores: &DataStores,
|
||||
clip_chain_nodes: &[ClipChainNode],
|
||||
pictures: &[PicturePrimitive],
|
||||
resource_cache: &ResourceCache,
|
||||
|
@ -792,7 +831,7 @@ impl TileCache {
|
|||
clip_scroll_tree,
|
||||
);
|
||||
|
||||
let prim_data = &resources.as_common_data(&prim_instance);
|
||||
let prim_data = &data_stores.as_common_data(&prim_instance);
|
||||
|
||||
let prim_rect = match prim_instance.kind {
|
||||
PrimitiveInstanceKind::Picture { pic_index, .. } => {
|
||||
|
@ -838,7 +877,7 @@ impl TileCache {
|
|||
|
||||
// Some primitives can not be cached (e.g. external video images)
|
||||
let is_cacheable = prim_instance.is_cacheable(
|
||||
&resources,
|
||||
&data_stores,
|
||||
resource_cache,
|
||||
);
|
||||
|
||||
|
@ -874,7 +913,7 @@ impl TileCache {
|
|||
true
|
||||
}
|
||||
PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
|
||||
let image_data = &resources.image_data_store[data_handle].kind;
|
||||
let image_data = &data_stores.image[data_handle].kind;
|
||||
let image_instance = &image_instances[image_instance_index];
|
||||
let opacity_binding_index = image_instance.opacity_binding_index;
|
||||
|
||||
|
@ -889,7 +928,7 @@ impl TileCache {
|
|||
true
|
||||
}
|
||||
PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
|
||||
let yuv_image_data = &resources.yuv_image_data_store[data_handle].kind;
|
||||
let yuv_image_data = &data_stores.yuv_image[data_handle].kind;
|
||||
image_keys.extend_from_slice(&yuv_image_data.yuv_key);
|
||||
true
|
||||
}
|
||||
|
@ -915,7 +954,7 @@ impl TileCache {
|
|||
let mut current_clip_chain_id = prim_instance.clip_chain_id;
|
||||
while current_clip_chain_id != ClipChainId::NONE {
|
||||
let clip_chain_node = &clip_chain_nodes[current_clip_chain_id.0 as usize];
|
||||
let clip_node = &resources.clip_data_store[clip_chain_node.handle];
|
||||
let clip_node = &data_stores.clip[clip_chain_node.handle];
|
||||
|
||||
// We can skip the root clip node - it will be taken care of by the
|
||||
// world bounding rect calculated for the cache.
|
||||
|
@ -941,12 +980,7 @@ impl TileCache {
|
|||
size,
|
||||
);
|
||||
|
||||
// If the clip rect is in the same spatial node, it can be handled by the
|
||||
// local clip rect.
|
||||
if clip_chain_node.spatial_node_index == prim_instance.spatial_node_index {
|
||||
culling_rect = culling_rect.intersection(&local_clip_rect).unwrap_or(LayoutRect::zero());
|
||||
false
|
||||
} else if clip_spatial_node.coordinate_system_id == CoordinateSystemId(0) {
|
||||
if clip_spatial_node.coordinate_system_id == CoordinateSystemId(0) {
|
||||
// Clips that are not in the root coordinate system are not axis-aligned,
|
||||
// so we need to treat them as normal style clips with vertices.
|
||||
match self.map_local_to_world.map(&local_clip_rect) {
|
||||
|
@ -959,10 +993,16 @@ impl TileCache {
|
|||
.intersection(&clip_world_rect)
|
||||
.unwrap_or(WorldRect::zero());
|
||||
|
||||
world_clips.push((
|
||||
clip_world_rect.into(),
|
||||
clip_chain_node.spatial_node_index,
|
||||
));
|
||||
// If the clip rect is in the same spatial node, it can be handled by the
|
||||
// local clip rect.
|
||||
if clip_chain_node.spatial_node_index == prim_instance.spatial_node_index {
|
||||
culling_rect = culling_rect.intersection(&local_clip_rect).unwrap_or(LayoutRect::zero());
|
||||
} else {
|
||||
world_clips.push((
|
||||
clip_world_rect.into(),
|
||||
clip_chain_node.spatial_node_index,
|
||||
));
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
@ -984,7 +1024,12 @@ impl TileCache {
|
|||
|
||||
if add_to_clip_deps {
|
||||
clip_chain_uids.push(clip_chain_node.handle.uid());
|
||||
clip_spatial_nodes.insert(clip_chain_node.spatial_node_index);
|
||||
|
||||
// If the clip has the same spatial node, the relative transform
|
||||
// will always be the same, so there's no need to depend on it.
|
||||
if clip_chain_node.spatial_node_index != self.spatial_node_index {
|
||||
clip_spatial_nodes.insert(clip_chain_node.spatial_node_index);
|
||||
}
|
||||
|
||||
let local_clip_rect = LayoutRect::new(
|
||||
clip_chain_node.local_pos,
|
||||
|
@ -999,7 +1044,11 @@ impl TileCache {
|
|||
}
|
||||
|
||||
if include_clip_rect {
|
||||
self.world_bounding_rect = self.world_bounding_rect.union(&world_clip_rect);
|
||||
// Intersect the calculated prim bounds with the root clip rect, to save
|
||||
// having to process and transform the root clip rect in every primitive.
|
||||
if let Some(clipped_world_rect) = world_clip_rect.intersection(&self.root_clip_rect) {
|
||||
self.world_bounding_rect = self.world_bounding_rect.union(&clipped_world_rect);
|
||||
}
|
||||
}
|
||||
|
||||
self.map_local_to_world.set_target_spatial_node(
|
||||
|
@ -1062,7 +1111,12 @@ impl TileCache {
|
|||
tile.descriptor.clip_vertices.push(clip_vertex.into());
|
||||
}
|
||||
|
||||
tile.transforms.insert(prim_instance.spatial_node_index);
|
||||
// If the primitive has the same spatial node, the relative transform
|
||||
// will always be the same, so there's no need to depend on it.
|
||||
if prim_instance.spatial_node_index != self.spatial_node_index {
|
||||
tile.transforms.insert(prim_instance.spatial_node_index);
|
||||
}
|
||||
|
||||
for spatial_node_index in &clip_spatial_nodes {
|
||||
tile.transforms.insert(*spatial_node_index);
|
||||
}
|
||||
|
@ -1193,7 +1247,7 @@ impl TileCache {
|
|||
_scratch.push_debug_string(
|
||||
label_pos,
|
||||
debug_colors::RED,
|
||||
format!("{:?} {:?}", tile.id, tile.handle),
|
||||
format!("{:?} {:?} {:?}", tile.id, tile.handle, tile.world_rect),
|
||||
);
|
||||
label_pos.y += 20.0;
|
||||
_scratch.push_debug_string(
|
||||
|
@ -1207,6 +1261,16 @@ impl TileCache {
|
|||
// Add the tile rect to the dirty rect.
|
||||
dirty_world_rect = dirty_world_rect.union(&visible_rect);
|
||||
|
||||
#[cfg(feature = "debug_renderer")]
|
||||
{
|
||||
if frame_context.debug_flags.contains(DebugFlags::PICTURE_CACHING_DBG) {
|
||||
_scratch.push_debug_rect(
|
||||
visible_rect * frame_context.device_pixel_scale,
|
||||
debug_colors::RED,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Only cache tiles that have had the same content for at least two
|
||||
// frames. This skips caching on pages / benchmarks that are changing
|
||||
// every frame, which is wasteful.
|
||||
|
@ -1258,16 +1322,6 @@ impl TileCache {
|
|||
} else {
|
||||
let dirty_device_rect = dirty_world_rect * frame_context.device_pixel_scale;
|
||||
|
||||
#[cfg(feature = "debug_renderer")]
|
||||
{
|
||||
if frame_context.debug_flags.contains(DebugFlags::PICTURE_CACHING_DBG) {
|
||||
_scratch.push_debug_rect(
|
||||
dirty_device_rect,
|
||||
debug_colors::RED,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Some(DirtyRegion {
|
||||
dirty_world_rect,
|
||||
dirty_device_rect: dirty_device_rect.round().to_i32(),
|
||||
|
@ -1580,7 +1634,7 @@ impl PrimitiveList {
|
|||
/// significantly faster.
|
||||
pub fn new(
|
||||
mut prim_instances: Vec<PrimitiveInstance>,
|
||||
resources: &DocumentResources
|
||||
interners: &Interners
|
||||
) -> Self {
|
||||
let mut pictures = SmallVec::new();
|
||||
let mut clusters_map = FastHashMap::default();
|
||||
|
@ -1604,34 +1658,34 @@ impl PrimitiveList {
|
|||
let prim_data = match prim_instance.kind {
|
||||
PrimitiveInstanceKind::Rectangle { data_handle, .. } |
|
||||
PrimitiveInstanceKind::Clear { data_handle, .. } => {
|
||||
&resources.prim_interner[data_handle]
|
||||
&interners.prim[data_handle]
|
||||
}
|
||||
PrimitiveInstanceKind::Image { data_handle, .. } => {
|
||||
&resources.image_interner[data_handle]
|
||||
&interners.image[data_handle]
|
||||
}
|
||||
PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
|
||||
&resources.image_border_interner[data_handle]
|
||||
&interners.image_border[data_handle]
|
||||
}
|
||||
PrimitiveInstanceKind::LineDecoration { data_handle, .. } => {
|
||||
&resources.line_decoration_interner[data_handle]
|
||||
&interners.line_decoration[data_handle]
|
||||
}
|
||||
PrimitiveInstanceKind::LinearGradient { data_handle, .. } => {
|
||||
&resources.linear_grad_interner[data_handle]
|
||||
&interners.linear_grad[data_handle]
|
||||
}
|
||||
PrimitiveInstanceKind::NormalBorder { data_handle, .. } => {
|
||||
&resources.normal_border_interner[data_handle]
|
||||
&interners.normal_border[data_handle]
|
||||
}
|
||||
PrimitiveInstanceKind::Picture { data_handle, .. } => {
|
||||
&resources.picture_interner[data_handle]
|
||||
&interners.picture[data_handle]
|
||||
}
|
||||
PrimitiveInstanceKind::RadialGradient { data_handle, ..} => {
|
||||
&resources.radial_grad_interner[data_handle]
|
||||
&interners.radial_grad[data_handle]
|
||||
}
|
||||
PrimitiveInstanceKind::TextRun { data_handle, .. } => {
|
||||
&resources.text_run_interner[data_handle]
|
||||
&interners.text_run[data_handle]
|
||||
}
|
||||
PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
|
||||
&resources.yuv_image_interner[data_handle]
|
||||
&interners.yuv_image[data_handle]
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
|
|||
use frame_builder::{FrameBuildingState};
|
||||
use gpu_cache::GpuDataRequest;
|
||||
use intern;
|
||||
use intern_types;
|
||||
use prim_store::{
|
||||
BorderSegmentInfo, BrushSegment, NinePatchDescriptor, PrimKey,
|
||||
PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
|
||||
|
@ -158,18 +159,10 @@ impl From<NormalBorderKey> for NormalBorderTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
|
||||
pub struct NormalBorderDataMarker;
|
||||
|
||||
pub type NormalBorderDataStore = intern::DataStore<NormalBorderKey, NormalBorderTemplate, NormalBorderDataMarker>;
|
||||
pub type NormalBorderDataHandle = intern::Handle<NormalBorderDataMarker>;
|
||||
pub type NormalBorderDataUpdateList = intern::UpdateList<NormalBorderKey>;
|
||||
pub type NormalBorderDataInterner = intern::Interner<NormalBorderKey, PrimitiveSceneData, NormalBorderDataMarker>;
|
||||
pub use intern_types::normal_border::Handle as NormalBorderDataHandle;
|
||||
|
||||
impl intern::Internable for NormalBorderPrim {
|
||||
type Marker = NormalBorderDataMarker;
|
||||
type Marker = intern_types::normal_border::Marker;
|
||||
type Source = NormalBorderKey;
|
||||
type StoreData = NormalBorderTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
|
@ -335,18 +328,10 @@ impl From<ImageBorderKey> for ImageBorderTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
|
||||
pub struct ImageBorderDataMarker;
|
||||
|
||||
pub type ImageBorderDataStore = intern::DataStore<ImageBorderKey, ImageBorderTemplate, ImageBorderDataMarker>;
|
||||
pub type ImageBorderDataHandle = intern::Handle<ImageBorderDataMarker>;
|
||||
pub type ImageBorderDataUpdateList = intern::UpdateList<ImageBorderKey>;
|
||||
pub type ImageBorderDataInterner = intern::Interner<ImageBorderKey, PrimitiveSceneData, ImageBorderDataMarker>;
|
||||
pub use intern_types::image_border::Handle as ImageBorderDataHandle;
|
||||
|
||||
impl intern::Internable for ImageBorder {
|
||||
type Marker = ImageBorderDataMarker;
|
||||
type Marker = intern_types::image_border::Marker;
|
||||
type Source = ImageBorderKey;
|
||||
type StoreData = ImageBorderTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
|
|
|
@ -9,7 +9,8 @@ use api::{
|
|||
use display_list_flattener::{AsInstanceKind, IsVisible};
|
||||
use frame_builder::FrameBuildingState;
|
||||
use gpu_cache::{GpuCacheHandle, GpuDataRequest};
|
||||
use intern::{DataStore, Handle, Internable, InternDebug, Interner, UpdateList};
|
||||
use intern::{Internable, InternDebug};
|
||||
use intern_types;
|
||||
use prim_store::{BrushSegment, GradientTileRange};
|
||||
use prim_store::{PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData};
|
||||
use prim_store::{PrimKeyCommonData, PrimTemplateCommonData, PrimitiveStore};
|
||||
|
@ -225,15 +226,7 @@ impl LinearGradientTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
|
||||
pub struct LinearGradientDataMarker;
|
||||
|
||||
pub type LinearGradientDataStore = DataStore<LinearGradientKey, LinearGradientTemplate, LinearGradientDataMarker>;
|
||||
pub type LinearGradientDataHandle = Handle<LinearGradientDataMarker>;
|
||||
pub type LinearGradientDataUpdateList = UpdateList<LinearGradientKey>;
|
||||
pub type LinearGradientDataInterner = Interner<LinearGradientKey, PrimitiveSceneData, LinearGradientDataMarker>;
|
||||
pub type LinearGradientDataHandle = intern_types::linear_grad::Handle;
|
||||
|
||||
pub struct LinearGradient {
|
||||
pub extend_mode: ExtendMode,
|
||||
|
@ -247,7 +240,7 @@ pub struct LinearGradient {
|
|||
}
|
||||
|
||||
impl Internable for LinearGradient {
|
||||
type Marker = LinearGradientDataMarker;
|
||||
type Marker = intern_types::linear_grad::Marker;
|
||||
type Source = LinearGradientKey;
|
||||
type StoreData = LinearGradientTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
|
@ -452,15 +445,7 @@ impl RadialGradientTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
|
||||
pub struct RadialGradientDataMarker;
|
||||
|
||||
pub type RadialGradientDataStore = DataStore<RadialGradientKey, RadialGradientTemplate, RadialGradientDataMarker>;
|
||||
pub type RadialGradientDataHandle = Handle<RadialGradientDataMarker>;
|
||||
pub type RadialGradientDataUpdateList = UpdateList<RadialGradientKey>;
|
||||
pub type RadialGradientDataInterner = Interner<RadialGradientKey, PrimitiveSceneData, RadialGradientDataMarker>;
|
||||
pub type RadialGradientDataHandle = intern_types::radial_grad::Handle;
|
||||
|
||||
pub struct RadialGradient {
|
||||
pub extend_mode: ExtendMode,
|
||||
|
@ -473,7 +458,7 @@ pub struct RadialGradient {
|
|||
}
|
||||
|
||||
impl Internable for RadialGradient {
|
||||
type Marker = RadialGradientDataMarker;
|
||||
type Marker = intern_types::radial_grad::Marker;
|
||||
type Source = RadialGradientKey;
|
||||
type StoreData = RadialGradientTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
|
|
|
@ -11,7 +11,8 @@ use api::ImageKey as ApiImageKey;
|
|||
use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
|
||||
use frame_builder::FrameBuildingState;
|
||||
use gpu_cache::{GpuCacheHandle, GpuDataRequest};
|
||||
use intern::{DataStore, Handle, Internable, Interner, InternDebug, UpdateList};
|
||||
use intern::{Internable, InternDebug};
|
||||
use intern_types;
|
||||
use prim_store::{
|
||||
EdgeAaSegmentMask, OpacityBindingIndex, PrimitiveInstanceKind,
|
||||
PrimitiveOpacity, PrimitiveSceneData, PrimKey, PrimKeyCommonData,
|
||||
|
@ -333,18 +334,10 @@ impl From<ImageKey> for ImageTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
|
||||
pub struct ImageDataMarker;
|
||||
|
||||
pub type ImageDataStore = DataStore<ImageKey, ImageTemplate, ImageDataMarker>;
|
||||
pub type ImageDataHandle = Handle<ImageDataMarker>;
|
||||
pub type ImageDataUpdateList = UpdateList<ImageKey>;
|
||||
pub type ImageDataInterner = Interner<ImageKey, PrimitiveSceneData, ImageDataMarker>;
|
||||
pub use intern_types::image::Handle as ImageDataHandle;
|
||||
|
||||
impl Internable for Image {
|
||||
type Marker = ImageDataMarker;
|
||||
type Marker = intern_types::image::Marker;
|
||||
type Source = ImageKey;
|
||||
type StoreData = ImageTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
|
@ -507,18 +500,10 @@ impl From<YuvImageKey> for YuvImageTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
|
||||
pub struct YuvImageDataMarker;
|
||||
|
||||
pub type YuvImageDataStore = DataStore<YuvImageKey, YuvImageTemplate, YuvImageDataMarker>;
|
||||
pub type YuvImageDataHandle = Handle<YuvImageDataMarker>;
|
||||
pub type YuvImageDataUpdateList = UpdateList<YuvImageKey>;
|
||||
pub type YuvImageDataInterner = Interner<YuvImageKey, PrimitiveSceneData, YuvImageDataMarker>;
|
||||
pub use intern_types::yuv_image::Handle as YuvImageDataHandle;
|
||||
|
||||
impl Internable for YuvImage {
|
||||
type Marker = YuvImageDataMarker;
|
||||
type Marker = intern_types::yuv_image::Marker;
|
||||
type Source = YuvImageKey;
|
||||
type StoreData = YuvImageTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
|
|
|
@ -11,6 +11,7 @@ use display_list_flattener::{AsInstanceKind, CreateShadow, IsVisible};
|
|||
use frame_builder::{FrameBuildingState};
|
||||
use gpu_cache::GpuDataRequest;
|
||||
use intern;
|
||||
use intern_types;
|
||||
use prim_store::{
|
||||
PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
|
||||
PrimitiveSceneData, PrimitiveStore,
|
||||
|
@ -133,18 +134,10 @@ impl From<LineDecorationKey> for LineDecorationTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
|
||||
pub struct LineDecorationDataMarker;
|
||||
|
||||
pub type LineDecorationDataStore = intern::DataStore<LineDecorationKey, LineDecorationTemplate, LineDecorationDataMarker>;
|
||||
pub type LineDecorationDataHandle = intern::Handle<LineDecorationDataMarker>;
|
||||
pub type LineDecorationDataUpdateList = intern::UpdateList<LineDecorationKey>;
|
||||
pub type LineDecorationDataInterner = intern::Interner<LineDecorationKey, PrimitiveSceneData, LineDecorationDataMarker>;
|
||||
pub use intern_types::line_decoration::Handle as LineDecorationDataHandle;
|
||||
|
||||
impl intern::Internable for LineDecoration {
|
||||
type Marker = LineDecorationDataMarker;
|
||||
type Marker = intern_types::line_decoration::Marker;
|
||||
type Source = LineDecorationKey;
|
||||
type StoreData = LineDecorationTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
|
|
|
@ -41,7 +41,7 @@ use prim_store::picture::PictureDataHandle;
|
|||
use prim_store::text_run::{TextRunDataHandle, TextRunPrimitive};
|
||||
#[cfg(debug_assertions)]
|
||||
use render_backend::{FrameId};
|
||||
use render_backend::FrameResources;
|
||||
use render_backend::DataStores;
|
||||
use render_task::{RenderTask, RenderTaskCacheKey, to_cache_size};
|
||||
use render_task::{RenderTaskCacheKeyKind, RenderTaskId, RenderTaskCacheEntryHandle};
|
||||
use renderer::{MAX_VERTEX_TEXTURE_WIDTH};
|
||||
|
@ -821,14 +821,8 @@ impl PrimitiveTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
// Type definitions for interning primitives.
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
|
||||
pub struct PrimitiveDataMarker;
|
||||
|
||||
impl intern::Internable for PrimitiveKeyKind {
|
||||
type Marker = PrimitiveDataMarker;
|
||||
type Marker = ::intern_types::prim::Marker;
|
||||
type Source = PrimitiveKey;
|
||||
type StoreData = PrimitiveTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
|
@ -845,10 +839,7 @@ impl intern::Internable for PrimitiveKeyKind {
|
|||
}
|
||||
}
|
||||
|
||||
pub type PrimitiveDataStore = intern::DataStore<PrimitiveKey, PrimitiveTemplate, PrimitiveDataMarker>;
|
||||
pub type PrimitiveDataHandle = intern::Handle<PrimitiveDataMarker>;
|
||||
pub type PrimitiveDataUpdateList = intern::UpdateList<PrimitiveKey>;
|
||||
pub type PrimitiveDataInterner = intern::Interner<PrimitiveKey, PrimitiveSceneData, PrimitiveDataMarker>;
|
||||
use intern_types::prim::Handle as PrimitiveDataHandle;
|
||||
|
||||
// Maintains a list of opacity bindings that have been collapsed into
|
||||
// the color of a single primitive. This is an important optimization
|
||||
|
@ -1737,7 +1728,7 @@ impl PrimitiveStore {
|
|||
state: &mut PictureUpdateState,
|
||||
frame_context: &FrameBuildingContext,
|
||||
gpu_cache: &mut GpuCache,
|
||||
resources: &FrameResources,
|
||||
data_stores: &DataStores,
|
||||
clip_store: &ClipStore,
|
||||
) {
|
||||
if let Some(children) = self.pictures[pic_index.0].pre_update(
|
||||
|
@ -1750,7 +1741,7 @@ impl PrimitiveStore {
|
|||
state,
|
||||
frame_context,
|
||||
gpu_cache,
|
||||
resources,
|
||||
data_stores,
|
||||
clip_store,
|
||||
);
|
||||
}
|
||||
|
@ -1791,8 +1782,7 @@ impl PrimitiveStore {
|
|||
tile_cache.pre_update(
|
||||
pic.local_rect,
|
||||
frame_context,
|
||||
frame_state.resource_cache,
|
||||
frame_state.retained_tiles,
|
||||
frame_state,
|
||||
);
|
||||
|
||||
frame_state.tile_cache = Some(tile_cache);
|
||||
|
@ -1878,7 +1868,7 @@ impl PrimitiveStore {
|
|||
(pic.raster_config.is_none(), pic.local_rect, clip_node_collector)
|
||||
}
|
||||
_ => {
|
||||
let prim_data = &frame_state.resources.as_common_data(&prim_instance);
|
||||
let prim_data = &frame_state.data_stores.as_common_data(&prim_instance);
|
||||
|
||||
let prim_rect = LayoutRect::new(
|
||||
prim_instance.prim_origin,
|
||||
|
@ -1944,14 +1934,14 @@ impl PrimitiveStore {
|
|||
frame_context.device_pixel_scale,
|
||||
&frame_context.screen_world_rect,
|
||||
clip_node_collector.as_ref(),
|
||||
&mut frame_state.resources.clip_data_store,
|
||||
&mut frame_state.data_stores.clip,
|
||||
);
|
||||
|
||||
if let Some(ref mut tile_cache) = frame_state.tile_cache {
|
||||
tile_cache.update_prim_dependencies(
|
||||
prim_instance,
|
||||
frame_context.clip_scroll_tree,
|
||||
frame_state.resources,
|
||||
frame_state.data_stores,
|
||||
&frame_state.clip_store.clip_chain_nodes,
|
||||
&self.pictures,
|
||||
frame_state.resource_cache,
|
||||
|
@ -2192,7 +2182,7 @@ impl PrimitiveStore {
|
|||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
plane_split_anchor: usize,
|
||||
resources: &mut FrameResources,
|
||||
data_stores: &mut DataStores,
|
||||
scratch: &mut PrimitiveScratchBuffer,
|
||||
) -> bool {
|
||||
// If we have dependencies, we need to prepare them first, in order
|
||||
|
@ -2251,7 +2241,7 @@ impl PrimitiveStore {
|
|||
&mut pic_state_for_children,
|
||||
frame_context,
|
||||
frame_state,
|
||||
resources,
|
||||
data_stores,
|
||||
scratch,
|
||||
);
|
||||
|
||||
|
@ -2283,7 +2273,7 @@ impl PrimitiveStore {
|
|||
frame_context,
|
||||
frame_state,
|
||||
self,
|
||||
resources,
|
||||
data_stores,
|
||||
scratch,
|
||||
);
|
||||
|
||||
|
@ -2298,7 +2288,7 @@ impl PrimitiveStore {
|
|||
}
|
||||
|
||||
pic_state.is_cacheable &= prim_instance.is_cacheable(
|
||||
&resources,
|
||||
&data_stores,
|
||||
frame_state.resource_cache,
|
||||
);
|
||||
|
||||
|
@ -2356,7 +2346,7 @@ impl PrimitiveStore {
|
|||
pic_context,
|
||||
frame_context,
|
||||
frame_state,
|
||||
resources,
|
||||
data_stores,
|
||||
scratch,
|
||||
);
|
||||
}
|
||||
|
@ -2372,7 +2362,7 @@ impl PrimitiveStore {
|
|||
pic_state: &mut PictureState,
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
resources: &mut FrameResources,
|
||||
data_stores: &mut DataStores,
|
||||
scratch: &mut PrimitiveScratchBuffer,
|
||||
) {
|
||||
for (plane_split_anchor, prim_instance) in prim_list.prim_instances.iter_mut().enumerate() {
|
||||
|
@ -2424,7 +2414,7 @@ impl PrimitiveStore {
|
|||
frame_context,
|
||||
frame_state,
|
||||
plane_split_anchor,
|
||||
resources,
|
||||
data_stores,
|
||||
scratch,
|
||||
) {
|
||||
frame_state.profile_counters.visible_primitives.inc();
|
||||
|
@ -2442,14 +2432,14 @@ impl PrimitiveStore {
|
|||
pic_context: &PictureContext,
|
||||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
resources: &mut FrameResources,
|
||||
data_stores: &mut DataStores,
|
||||
scratch: &mut PrimitiveScratchBuffer,
|
||||
) {
|
||||
let is_chased = prim_instance.is_chased();
|
||||
|
||||
match &mut prim_instance.kind {
|
||||
PrimitiveInstanceKind::LineDecoration { data_handle, ref mut cache_handle, .. } => {
|
||||
let prim_data = &mut resources.line_decoration_data_store[*data_handle];
|
||||
let prim_data = &mut data_stores.line_decoration[*data_handle];
|
||||
let common_data = &mut prim_data.common;
|
||||
let line_dec_data = &mut prim_data.kind;
|
||||
|
||||
|
@ -2498,7 +2488,7 @@ impl PrimitiveStore {
|
|||
}
|
||||
}
|
||||
PrimitiveInstanceKind::TextRun { data_handle, run_index, .. } => {
|
||||
let prim_data = &mut resources.text_run_data_store[*data_handle];
|
||||
let prim_data = &mut data_stores.text_run[*data_handle];
|
||||
|
||||
// Update the template this instane references, which may refresh the GPU
|
||||
// cache with any shared template data.
|
||||
|
@ -2527,14 +2517,14 @@ impl PrimitiveStore {
|
|||
);
|
||||
}
|
||||
PrimitiveInstanceKind::Clear { data_handle, .. } => {
|
||||
let prim_data = &mut resources.prim_data_store[*data_handle];
|
||||
let prim_data = &mut data_stores.prim[*data_handle];
|
||||
|
||||
// Update the template this instane references, which may refresh the GPU
|
||||
// cache with any shared template data.
|
||||
prim_data.update(frame_state);
|
||||
}
|
||||
PrimitiveInstanceKind::NormalBorder { data_handle, ref mut cache_handles, .. } => {
|
||||
let prim_data = &mut resources.normal_border_data_store[*data_handle];
|
||||
let prim_data = &mut data_stores.normal_border[*data_handle];
|
||||
let common_data = &mut prim_data.common;
|
||||
let border_data = &mut prim_data.kind;
|
||||
|
||||
|
@ -2591,14 +2581,14 @@ impl PrimitiveStore {
|
|||
.extend(handles);
|
||||
}
|
||||
PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
|
||||
let prim_data = &mut resources.image_border_data_store[*data_handle];
|
||||
let prim_data = &mut data_stores.image_border[*data_handle];
|
||||
|
||||
// Update the template this instane references, which may refresh the GPU
|
||||
// cache with any shared template data.
|
||||
prim_data.kind.update(&mut prim_data.common, frame_state);
|
||||
}
|
||||
PrimitiveInstanceKind::Rectangle { data_handle, segment_instance_index, opacity_binding_index, .. } => {
|
||||
let prim_data = &mut resources.prim_data_store[*data_handle];
|
||||
let prim_data = &mut data_stores.prim[*data_handle];
|
||||
|
||||
// Update the template this instane references, which may refresh the GPU
|
||||
// cache with any shared template data.
|
||||
|
@ -2617,7 +2607,7 @@ impl PrimitiveStore {
|
|||
});
|
||||
}
|
||||
PrimitiveInstanceKind::YuvImage { data_handle, segment_instance_index, .. } => {
|
||||
let yuv_image_data = &mut resources.yuv_image_data_store[*data_handle];
|
||||
let yuv_image_data = &mut data_stores.yuv_image[*data_handle];
|
||||
|
||||
// Update the template this instane references, which may refresh the GPU
|
||||
// cache with any shared template data.
|
||||
|
@ -2628,7 +2618,7 @@ impl PrimitiveStore {
|
|||
});
|
||||
}
|
||||
PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
|
||||
let prim_data = &mut resources.image_data_store[*data_handle];
|
||||
let prim_data = &mut data_stores.image[*data_handle];
|
||||
let common_data = &mut prim_data.common;
|
||||
let image_data = &mut prim_data.kind;
|
||||
|
||||
|
@ -2742,7 +2732,7 @@ impl PrimitiveStore {
|
|||
});
|
||||
}
|
||||
PrimitiveInstanceKind::LinearGradient { data_handle, ref mut visible_tiles_range, .. } => {
|
||||
let prim_data = &mut resources.linear_grad_data_store[*data_handle];
|
||||
let prim_data = &mut data_stores.linear_grad[*data_handle];
|
||||
|
||||
// Update the template this instane references, which may refresh the GPU
|
||||
// cache with any shared template data.
|
||||
|
@ -2789,7 +2779,7 @@ impl PrimitiveStore {
|
|||
// for gradient primitives.
|
||||
}
|
||||
PrimitiveInstanceKind::RadialGradient { data_handle, ref mut visible_tiles_range, .. } => {
|
||||
let prim_data = &mut resources.radial_grad_data_store[*data_handle];
|
||||
let prim_data = &mut data_stores.radial_grad[*data_handle];
|
||||
|
||||
// Update the template this instane references, which may refresh the GPU
|
||||
// cache with any shared template data.
|
||||
|
@ -2972,7 +2962,7 @@ impl<'a> GpuDataRequest<'a> {
|
|||
clip_chain: &ClipChainInstance,
|
||||
segment_builder: &mut SegmentBuilder,
|
||||
clip_store: &ClipStore,
|
||||
resources: &FrameResources,
|
||||
data_stores: &DataStores,
|
||||
) -> bool {
|
||||
// If the brush is small, we generally want to skip building segments
|
||||
// and just draw it as a single primitive with clip mask. However,
|
||||
|
@ -2997,7 +2987,7 @@ impl<'a> GpuDataRequest<'a> {
|
|||
for i in 0 .. clip_chain.clips_range.count {
|
||||
let clip_instance = clip_store
|
||||
.get_instance_from_range(&clip_chain.clips_range, i);
|
||||
let clip_node = &resources.clip_data_store[clip_instance.handle];
|
||||
let clip_node = &data_stores.clip[clip_instance.handle];
|
||||
|
||||
// If this clip item is positioned by another positioning node, its relative position
|
||||
// could change during scrolling. This means that we would need to resegment. Instead
|
||||
|
@ -3102,11 +3092,11 @@ impl PrimitiveInstance {
|
|||
prim_clip_chain: &ClipChainInstance,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
prim_store: &mut PrimitiveStore,
|
||||
resources: &FrameResources,
|
||||
data_stores: &DataStores,
|
||||
segments_store: &mut SegmentStorage,
|
||||
segment_instances_store: &mut SegmentInstanceStorage,
|
||||
) {
|
||||
let prim_data = &resources.as_common_data(self);
|
||||
let prim_data = &data_stores.as_common_data(self);
|
||||
let prim_local_rect = LayoutRect::new(
|
||||
self.prim_origin,
|
||||
prim_data.prim_size,
|
||||
|
@ -3118,7 +3108,7 @@ impl PrimitiveInstance {
|
|||
segment_instance_index
|
||||
}
|
||||
PrimitiveInstanceKind::Image { data_handle, image_instance_index, .. } => {
|
||||
let image_data = &resources.image_data_store[data_handle].kind;
|
||||
let image_data = &data_stores.image[data_handle].kind;
|
||||
let image_instance = &mut prim_store.images[image_instance_index];
|
||||
// tiled images don't support segmentation
|
||||
if frame_state
|
||||
|
@ -3153,7 +3143,7 @@ impl PrimitiveInstance {
|
|||
prim_clip_chain,
|
||||
&mut frame_state.segment_builder,
|
||||
frame_state.clip_store,
|
||||
resources,
|
||||
data_stores,
|
||||
) {
|
||||
frame_state.segment_builder.build(|segment| {
|
||||
segments.push(
|
||||
|
@ -3193,7 +3183,7 @@ impl PrimitiveInstance {
|
|||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
prim_store: &PrimitiveStore,
|
||||
resources: &mut FrameResources,
|
||||
data_stores: &mut DataStores,
|
||||
segments_store: &mut SegmentStorage,
|
||||
segment_instances_store: &mut SegmentInstanceStorage,
|
||||
clip_mask_instances: &mut Vec<ClipMaskKind>,
|
||||
|
@ -3231,21 +3221,21 @@ impl PrimitiveInstance {
|
|||
&segments_store[segment_instance.segments_range]
|
||||
}
|
||||
PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
|
||||
let border_data = &resources.image_border_data_store[data_handle].kind;
|
||||
let border_data = &data_stores.image_border[data_handle].kind;
|
||||
|
||||
// TODO: This is quite messy - once we remove legacy primitives we
|
||||
// can change this to be a tuple match on (instance, template)
|
||||
border_data.brush_segments.as_slice()
|
||||
}
|
||||
PrimitiveInstanceKind::NormalBorder { data_handle, .. } => {
|
||||
let border_data = &resources.normal_border_data_store[data_handle].kind;
|
||||
let border_data = &data_stores.normal_border[data_handle].kind;
|
||||
|
||||
// TODO: This is quite messy - once we remove legacy primitives we
|
||||
// can change this to be a tuple match on (instance, template)
|
||||
border_data.brush_segments.as_slice()
|
||||
}
|
||||
PrimitiveInstanceKind::LinearGradient { data_handle, .. } => {
|
||||
let prim_data = &resources.linear_grad_data_store[data_handle];
|
||||
let prim_data = &data_stores.linear_grad[data_handle];
|
||||
|
||||
// TODO: This is quite messy - once we remove legacy primitives we
|
||||
// can change this to be a tuple match on (instance, template)
|
||||
|
@ -3256,7 +3246,7 @@ impl PrimitiveInstance {
|
|||
prim_data.brush_segments.as_slice()
|
||||
}
|
||||
PrimitiveInstanceKind::RadialGradient { data_handle, .. } => {
|
||||
let prim_data = &resources.radial_grad_data_store[data_handle];
|
||||
let prim_data = &data_stores.radial_grad[data_handle];
|
||||
|
||||
// TODO: This is quite messy - once we remove legacy primitives we
|
||||
// can change this to be a tuple match on (instance, template)
|
||||
|
@ -3292,7 +3282,7 @@ impl PrimitiveInstance {
|
|||
pic_state,
|
||||
frame_context,
|
||||
frame_state,
|
||||
&mut resources.clip_data_store,
|
||||
&mut data_stores.clip,
|
||||
);
|
||||
clip_mask_instances.push(clip_mask_kind);
|
||||
} else {
|
||||
|
@ -3318,7 +3308,7 @@ impl PrimitiveInstance {
|
|||
frame_context.device_pixel_scale,
|
||||
&pic_context.dirty_world_rect,
|
||||
None,
|
||||
&mut resources.clip_data_store,
|
||||
&mut data_stores.clip,
|
||||
);
|
||||
|
||||
let clip_mask_kind = segment.update_clip_task(
|
||||
|
@ -3329,7 +3319,7 @@ impl PrimitiveInstance {
|
|||
pic_state,
|
||||
frame_context,
|
||||
frame_state,
|
||||
&mut resources.clip_data_store,
|
||||
&mut data_stores.clip,
|
||||
);
|
||||
clip_mask_instances.push(clip_mask_kind);
|
||||
}
|
||||
|
@ -3347,7 +3337,7 @@ impl PrimitiveInstance {
|
|||
frame_context: &FrameBuildingContext,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
prim_store: &mut PrimitiveStore,
|
||||
resources: &mut FrameResources,
|
||||
data_stores: &mut DataStores,
|
||||
scratch: &mut PrimitiveScratchBuffer,
|
||||
) {
|
||||
let prim_info = &mut scratch.prim_info[self.visibility_info.0 as usize];
|
||||
|
@ -3360,7 +3350,7 @@ impl PrimitiveInstance {
|
|||
&prim_info.clip_chain,
|
||||
frame_state,
|
||||
prim_store,
|
||||
resources,
|
||||
data_stores,
|
||||
&mut scratch.segments,
|
||||
&mut scratch.segment_instances,
|
||||
);
|
||||
|
@ -3375,7 +3365,7 @@ impl PrimitiveInstance {
|
|||
frame_context,
|
||||
frame_state,
|
||||
prim_store,
|
||||
resources,
|
||||
data_stores,
|
||||
&mut scratch.segments,
|
||||
&mut scratch.segment_instances,
|
||||
&mut scratch.clip_mask_instances,
|
||||
|
@ -3402,7 +3392,7 @@ impl PrimitiveInstance {
|
|||
frame_state.gpu_cache,
|
||||
frame_state.resource_cache,
|
||||
frame_state.render_tasks,
|
||||
&mut resources.clip_data_store,
|
||||
&mut data_stores.clip,
|
||||
);
|
||||
|
||||
let clip_task_id = frame_state.render_tasks.add(clip_task);
|
||||
|
|
|
@ -8,7 +8,8 @@ use api::{
|
|||
};
|
||||
use app_units::Au;
|
||||
use display_list_flattener::{AsInstanceKind, IsVisible};
|
||||
use intern::{DataStore, Handle, Internable, Interner, InternDebug, UpdateList};
|
||||
use intern::{Internable, InternDebug};
|
||||
use intern_types;
|
||||
use picture::PictureCompositeMode;
|
||||
use prim_store::{
|
||||
PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
|
||||
|
@ -185,18 +186,10 @@ impl From<PictureKey> for PictureTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
|
||||
pub struct PictureDataMarker;
|
||||
|
||||
pub type PictureDataStore = DataStore<PictureKey, PictureTemplate, PictureDataMarker>;
|
||||
pub type PictureDataHandle = Handle<PictureDataMarker>;
|
||||
pub type PictureDataUpdateList = UpdateList<PictureKey>;
|
||||
pub type PictureDataInterner = Interner<PictureKey, PrimitiveSceneData, PictureDataMarker>;
|
||||
pub use intern_types::picture::Handle as PictureDataHandle;
|
||||
|
||||
impl Internable for Picture {
|
||||
type Marker = PictureDataMarker;
|
||||
type Marker = intern_types::picture::Marker;
|
||||
type Source = PictureKey;
|
||||
type StoreData = PictureTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
|
|
|
@ -10,6 +10,7 @@ use frame_builder::{FrameBuildingState, PictureContext};
|
|||
use glyph_rasterizer::{FontInstance, FontTransform, GlyphKey, FONT_SIZE_LIMIT};
|
||||
use gpu_cache::GpuCache;
|
||||
use intern;
|
||||
use intern_types;
|
||||
use prim_store::{PrimitiveOpacity, PrimitiveSceneData, PrimitiveScratchBuffer};
|
||||
use prim_store::{PrimitiveStore, PrimKeyCommonData, PrimTemplateCommonData, VectorKey};
|
||||
use render_task::{RenderTaskTree};
|
||||
|
@ -161,15 +162,7 @@ impl TextRunTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
|
||||
pub struct TextRunDataMarker;
|
||||
|
||||
pub type TextRunDataStore = intern::DataStore<TextRunKey, TextRunTemplate, TextRunDataMarker>;
|
||||
pub type TextRunDataHandle = intern::Handle<TextRunDataMarker>;
|
||||
pub type TextRunDataUpdateList = intern::UpdateList<TextRunKey>;
|
||||
pub type TextRunDataInterner = intern::Interner<TextRunKey, PrimitiveSceneData, TextRunDataMarker>;
|
||||
pub use intern_types::text_run::Handle as TextRunDataHandle;
|
||||
|
||||
pub struct TextRun {
|
||||
pub font: FontInstance,
|
||||
|
@ -179,7 +172,7 @@ pub struct TextRun {
|
|||
}
|
||||
|
||||
impl intern::Internable for TextRun {
|
||||
type Marker = TextRunDataMarker;
|
||||
type Marker = intern_types::text_run::Marker;
|
||||
type Source = TextRunKey;
|
||||
type StoreData = TextRunTemplate;
|
||||
type InternData = PrimitiveSceneData;
|
||||
|
|
|
@ -401,21 +401,39 @@ pub struct IpcProfileCounters {
|
|||
pub display_lists: ResourceProfileCounter,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InternProfileCounters {
|
||||
pub prims: ResourceProfileCounter,
|
||||
pub images: ResourceProfileCounter,
|
||||
pub image_borders: ResourceProfileCounter,
|
||||
pub line_decs: ResourceProfileCounter,
|
||||
pub linear_gradients: ResourceProfileCounter,
|
||||
pub normal_borders: ResourceProfileCounter,
|
||||
pub pictures: ResourceProfileCounter,
|
||||
pub radial_gradients: ResourceProfileCounter,
|
||||
pub text_runs: ResourceProfileCounter,
|
||||
pub yuv_images: ResourceProfileCounter,
|
||||
pub clips: ResourceProfileCounter,
|
||||
macro_rules! declare_intern_profile_counters {
|
||||
( $( $name: ident, )+ ) => {
|
||||
#[derive(Clone)]
|
||||
pub struct InternProfileCounters {
|
||||
$(
|
||||
pub $name: ResourceProfileCounter,
|
||||
)+
|
||||
}
|
||||
|
||||
impl InternProfileCounters {
|
||||
#[cfg(feature = "debug_renderer")]
|
||||
fn draw(
|
||||
&self,
|
||||
debug_renderer: &mut DebugRenderer,
|
||||
draw_state: &mut DrawState,
|
||||
) {
|
||||
Profiler::draw_counters(
|
||||
&[
|
||||
$(
|
||||
&self.$name,
|
||||
)+
|
||||
],
|
||||
debug_renderer,
|
||||
true,
|
||||
draw_state,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enumerate_interners!(declare_intern_profile_counters);
|
||||
|
||||
impl IpcProfileCounters {
|
||||
pub fn set(
|
||||
&mut self,
|
||||
|
@ -455,17 +473,17 @@ impl BackendProfileCounters {
|
|||
display_lists: ResourceProfileCounter::new("Display Lists Sent"),
|
||||
},
|
||||
intern: InternProfileCounters {
|
||||
prims: ResourceProfileCounter::new("Interned primitives"),
|
||||
images: ResourceProfileCounter::new("Interned images"),
|
||||
image_borders: ResourceProfileCounter::new("Interned image borders"),
|
||||
line_decs: ResourceProfileCounter::new("Interned line decorations"),
|
||||
linear_gradients: ResourceProfileCounter::new("Interned linear gradients"),
|
||||
normal_borders: ResourceProfileCounter::new("Interned normal borders"),
|
||||
pictures: ResourceProfileCounter::new("Interned pictures"),
|
||||
radial_gradients: ResourceProfileCounter::new("Interned radial gradients"),
|
||||
text_runs: ResourceProfileCounter::new("Interned text runs"),
|
||||
yuv_images: ResourceProfileCounter::new("Interned YUV images"),
|
||||
clips: ResourceProfileCounter::new("Interned clips"),
|
||||
prim: ResourceProfileCounter::new("Interned primitives"),
|
||||
image: ResourceProfileCounter::new("Interned images"),
|
||||
image_border: ResourceProfileCounter::new("Interned image borders"),
|
||||
line_decoration: ResourceProfileCounter::new("Interned line decorations"),
|
||||
linear_grad: ResourceProfileCounter::new("Interned linear gradients"),
|
||||
normal_border: ResourceProfileCounter::new("Interned normal borders"),
|
||||
picture: ResourceProfileCounter::new("Interned pictures"),
|
||||
radial_grad: ResourceProfileCounter::new("Interned radial gradients"),
|
||||
text_run: ResourceProfileCounter::new("Interned text runs"),
|
||||
yuv_image: ResourceProfileCounter::new("Interned YUV images"),
|
||||
clip: ResourceProfileCounter::new("Interned clips"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1111,24 +1129,7 @@ impl Profiler {
|
|||
&mut self.draw_state
|
||||
);
|
||||
|
||||
Profiler::draw_counters(
|
||||
&[
|
||||
&backend_profile.intern.clips,
|
||||
&backend_profile.intern.prims,
|
||||
&backend_profile.intern.images,
|
||||
&backend_profile.intern.image_borders,
|
||||
&backend_profile.intern.line_decs,
|
||||
&backend_profile.intern.linear_gradients,
|
||||
&backend_profile.intern.normal_borders,
|
||||
&backend_profile.intern.pictures,
|
||||
&backend_profile.intern.radial_gradients,
|
||||
&backend_profile.intern.text_runs,
|
||||
&backend_profile.intern.yuv_images,
|
||||
],
|
||||
debug_renderer,
|
||||
true,
|
||||
&mut self.draw_state
|
||||
);
|
||||
backend_profile.intern.draw(debug_renderer, &mut self.draw_state);
|
||||
|
||||
Profiler::draw_counters(
|
||||
&[
|
||||
|
|
|
@ -22,24 +22,18 @@ use api::channel::{MsgReceiver, MsgSender, Payload};
|
|||
use api::CaptureBits;
|
||||
#[cfg(feature = "replay")]
|
||||
use api::CapturedDocument;
|
||||
use clip::ClipDataStore;
|
||||
use clip_scroll_tree::{SpatialNodeIndex, ClipScrollTree};
|
||||
#[cfg(feature = "debugger")]
|
||||
use debug_server;
|
||||
use frame_builder::{FrameBuilder, FrameBuilderConfig};
|
||||
use gpu_cache::GpuCache;
|
||||
use hit_test::{HitTest, HitTester};
|
||||
use intern_types;
|
||||
use internal_types::{DebugOutput, FastHashMap, FastHashSet, RenderedDocument, ResultMsg};
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
use picture::RetainedTiles;
|
||||
use prim_store::{PrimitiveDataStore, PrimitiveScratchBuffer, PrimitiveInstance};
|
||||
use prim_store::{PrimitiveScratchBuffer, PrimitiveInstance};
|
||||
use prim_store::{PrimitiveInstanceKind, PrimTemplateCommonData};
|
||||
use prim_store::borders::{ImageBorderDataStore, NormalBorderDataStore};
|
||||
use prim_store::gradient::{LinearGradientDataStore, RadialGradientDataStore};
|
||||
use prim_store::image::{ImageDataStore, YuvImageDataStore};
|
||||
use prim_store::line_dec::LineDecorationDataStore;
|
||||
use prim_store::picture::PictureDataStore;
|
||||
use prim_store::text_run::TextRunDataStore;
|
||||
use profiler::{BackendProfileCounters, IpcProfileCounters, ResourceProfileCounters};
|
||||
use record::ApiRecordingReceiver;
|
||||
use renderer::{AsyncPropertySampler, PipelineInfo};
|
||||
|
@ -214,33 +208,46 @@ impl FrameStamp {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! declare_frame_resources {
|
||||
( $( { $x: ident, $y: ty, $datastore_ident: ident, $datastore_type: ty } )+ ) => {
|
||||
macro_rules! declare_data_stores {
|
||||
( $( $name: ident, )+ ) => {
|
||||
/// A collection of resources that are shared by clips, primitives
|
||||
/// between display lists.
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Default)]
|
||||
pub struct FrameResources {
|
||||
pub struct DataStores {
|
||||
$(
|
||||
pub $datastore_ident: $datastore_type,
|
||||
pub $name: intern_types::$name::Store,
|
||||
)+
|
||||
}
|
||||
|
||||
impl FrameResources {
|
||||
impl DataStores {
|
||||
/// Reports CPU heap usage.
|
||||
fn report_memory(&self, ops: &mut MallocSizeOfOps, r: &mut MemoryReport) {
|
||||
$(
|
||||
r.interning.$datastore_ident += self.$datastore_ident.size_of(ops);
|
||||
r.interning.data_stores.$name += self.$name.size_of(ops);
|
||||
)+
|
||||
}
|
||||
|
||||
fn apply_updates(
|
||||
&mut self,
|
||||
updates: InternerUpdates,
|
||||
profile_counters: &mut BackendProfileCounters,
|
||||
) {
|
||||
$(
|
||||
self.$name.apply_updates(
|
||||
updates.$name,
|
||||
&mut profile_counters.intern.$name,
|
||||
);
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enumerate_interners!(declare_frame_resources);
|
||||
enumerate_interners!(declare_data_stores);
|
||||
|
||||
impl FrameResources {
|
||||
impl DataStores {
|
||||
pub fn as_common_data(
|
||||
&self,
|
||||
prim_inst: &PrimitiveInstance
|
||||
|
@ -248,43 +255,43 @@ impl FrameResources {
|
|||
match prim_inst.kind {
|
||||
PrimitiveInstanceKind::Rectangle { data_handle, .. } |
|
||||
PrimitiveInstanceKind::Clear { data_handle, .. } => {
|
||||
let prim_data = &self.prim_data_store[data_handle];
|
||||
let prim_data = &self.prim[data_handle];
|
||||
&prim_data.common
|
||||
}
|
||||
PrimitiveInstanceKind::Image { data_handle, .. } => {
|
||||
let prim_data = &self.image_data_store[data_handle];
|
||||
let prim_data = &self.image[data_handle];
|
||||
&prim_data.common
|
||||
}
|
||||
PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
|
||||
let prim_data = &self.image_border_data_store[data_handle];
|
||||
let prim_data = &self.image_border[data_handle];
|
||||
&prim_data.common
|
||||
}
|
||||
PrimitiveInstanceKind::LineDecoration { data_handle, .. } => {
|
||||
let prim_data = &self.line_decoration_data_store[data_handle];
|
||||
let prim_data = &self.line_decoration[data_handle];
|
||||
&prim_data.common
|
||||
}
|
||||
PrimitiveInstanceKind::LinearGradient { data_handle, .. } => {
|
||||
let prim_data = &self.linear_grad_data_store[data_handle];
|
||||
let prim_data = &self.linear_grad[data_handle];
|
||||
&prim_data.common
|
||||
}
|
||||
PrimitiveInstanceKind::NormalBorder { data_handle, .. } => {
|
||||
let prim_data = &self.normal_border_data_store[data_handle];
|
||||
let prim_data = &self.normal_border[data_handle];
|
||||
&prim_data.common
|
||||
}
|
||||
PrimitiveInstanceKind::Picture { data_handle, .. } => {
|
||||
let prim_data = &self.picture_data_store[data_handle];
|
||||
let prim_data = &self.picture[data_handle];
|
||||
&prim_data.common
|
||||
}
|
||||
PrimitiveInstanceKind::RadialGradient { data_handle, .. } => {
|
||||
let prim_data = &self.radial_grad_data_store[data_handle];
|
||||
let prim_data = &self.radial_grad[data_handle];
|
||||
&prim_data.common
|
||||
}
|
||||
PrimitiveInstanceKind::TextRun { data_handle, .. } => {
|
||||
let prim_data = &self.text_run_data_store[data_handle];
|
||||
let prim_data = &self.text_run[data_handle];
|
||||
&prim_data.common
|
||||
}
|
||||
PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
|
||||
let prim_data = &self.yuv_image_data_store[data_handle];
|
||||
let prim_data = &self.yuv_image[data_handle];
|
||||
&prim_data.common
|
||||
}
|
||||
}
|
||||
|
@ -333,7 +340,7 @@ struct Document {
|
|||
// renderer.
|
||||
has_built_scene: bool,
|
||||
|
||||
resources: FrameResources,
|
||||
data_stores: DataStores,
|
||||
|
||||
/// Contains various vecs of data that is used only during frame building,
|
||||
/// where we want to recycle the memory each new display list, to avoid constantly
|
||||
|
@ -370,7 +377,7 @@ impl Document {
|
|||
hit_tester_is_valid: false,
|
||||
rendered_frame_is_valid: false,
|
||||
has_built_scene: false,
|
||||
resources: FrameResources::default(),
|
||||
data_stores: DataStores::default(),
|
||||
scratch: PrimitiveScratchBuffer::new(),
|
||||
}
|
||||
}
|
||||
|
@ -512,13 +519,13 @@ impl Document {
|
|||
&mut resource_profile.texture_cache,
|
||||
&mut resource_profile.gpu_cache,
|
||||
&self.dynamic_properties,
|
||||
&mut self.resources,
|
||||
&mut self.data_stores,
|
||||
&mut self.scratch,
|
||||
debug_flags,
|
||||
);
|
||||
self.hit_tester = Some(frame_builder.create_hit_tester(
|
||||
&self.clip_scroll_tree,
|
||||
&self.resources.clip_data_store,
|
||||
&self.data_stores.clip,
|
||||
));
|
||||
frame
|
||||
};
|
||||
|
@ -548,7 +555,7 @@ impl Document {
|
|||
|
||||
self.hit_tester = Some(frame_builder.create_hit_tester(
|
||||
&self.clip_scroll_tree,
|
||||
&self.resources.clip_data_store,
|
||||
&self.data_stores.clip,
|
||||
));
|
||||
self.hit_tester_is_valid = true;
|
||||
}
|
||||
|
@ -886,7 +893,7 @@ impl RenderBackend {
|
|||
self.update_document(
|
||||
txn.document_id,
|
||||
replace(&mut txn.resource_updates, Vec::new()),
|
||||
txn.doc_resource_updates.take(),
|
||||
txn.interner_updates.take(),
|
||||
replace(&mut txn.frame_ops, Vec::new()),
|
||||
replace(&mut txn.notifications, Vec::new()),
|
||||
txn.render_frame,
|
||||
|
@ -1270,7 +1277,7 @@ impl RenderBackend {
|
|||
&mut self,
|
||||
document_id: DocumentId,
|
||||
resource_updates: Vec<ResourceUpdate>,
|
||||
doc_resource_updates: Option<DocumentResourceUpdates>,
|
||||
interner_updates: Option<InternerUpdates>,
|
||||
mut frame_ops: Vec<FrameMsg>,
|
||||
mut notifications: Vec<NotificationRequest>,
|
||||
mut render_frame: bool,
|
||||
|
@ -1297,51 +1304,8 @@ impl RenderBackend {
|
|||
|
||||
// If there are any additions or removals of clip modes
|
||||
// during the scene build, apply them to the data store now.
|
||||
if let Some(updates) = doc_resource_updates {
|
||||
doc.resources.clip_data_store.apply_updates(
|
||||
updates.clip_updates,
|
||||
&mut profile_counters.intern.clips,
|
||||
);
|
||||
doc.resources.prim_data_store.apply_updates(
|
||||
updates.prim_updates,
|
||||
&mut profile_counters.intern.prims,
|
||||
);
|
||||
doc.resources.image_data_store.apply_updates(
|
||||
updates.image_updates,
|
||||
&mut profile_counters.intern.images,
|
||||
);
|
||||
doc.resources.image_border_data_store.apply_updates(
|
||||
updates.image_border_updates,
|
||||
&mut profile_counters.intern.image_borders,
|
||||
);
|
||||
doc.resources.line_decoration_data_store.apply_updates(
|
||||
updates.line_decoration_updates,
|
||||
&mut profile_counters.intern.line_decs,
|
||||
);
|
||||
doc.resources.linear_grad_data_store.apply_updates(
|
||||
updates.linear_grad_updates,
|
||||
&mut profile_counters.intern.linear_gradients,
|
||||
);
|
||||
doc.resources.normal_border_data_store.apply_updates(
|
||||
updates.normal_border_updates,
|
||||
&mut profile_counters.intern.normal_borders,
|
||||
);
|
||||
doc.resources.picture_data_store.apply_updates(
|
||||
updates.picture_updates,
|
||||
&mut profile_counters.intern.pictures,
|
||||
);
|
||||
doc.resources.radial_grad_data_store.apply_updates(
|
||||
updates.radial_grad_updates,
|
||||
&mut profile_counters.intern.radial_gradients,
|
||||
);
|
||||
doc.resources.text_run_data_store.apply_updates(
|
||||
updates.text_run_updates,
|
||||
&mut profile_counters.intern.text_runs,
|
||||
);
|
||||
doc.resources.yuv_image_data_store.apply_updates(
|
||||
updates.yuv_image_updates,
|
||||
&mut profile_counters.intern.yuv_images,
|
||||
);
|
||||
if let Some(updates) = interner_updates {
|
||||
doc.data_stores.apply_updates(updates, profile_counters);
|
||||
}
|
||||
|
||||
// TODO: this scroll variable doesn't necessarily mean we scrolled. It is only used
|
||||
|
@ -1564,7 +1528,7 @@ impl RenderBackend {
|
|||
}
|
||||
report.hit_testers += doc.hit_tester.size_of(ops);
|
||||
|
||||
doc.resources.report_memory(ops, &mut report)
|
||||
doc.data_stores.report_memory(ops, &mut report)
|
||||
}
|
||||
|
||||
report += self.resource_cache.report_memory(op);
|
||||
|
@ -1673,8 +1637,8 @@ impl RenderBackend {
|
|||
config.serialize_tree(&doc.clip_scroll_tree, file_name);
|
||||
}
|
||||
|
||||
let frame_resources_name = format!("frame-resources-{}-{}", (id.0).0, id.1);
|
||||
config.serialize(&doc.resources, frame_resources_name);
|
||||
let data_stores_name = format!("data-stores-{}-{}", (id.0).0, id.1);
|
||||
config.serialize(&doc.data_stores, data_stores_name);
|
||||
}
|
||||
|
||||
debug!("\tscene builder");
|
||||
|
@ -1758,13 +1722,13 @@ impl RenderBackend {
|
|||
let scene = CaptureConfig::deserialize::<Scene, _>(root, &scene_name)
|
||||
.expect(&format!("Unable to open {}.ron", scene_name));
|
||||
|
||||
let doc_resources_name = format!("doc-resources-{}-{}", (id.0).0, id.1);
|
||||
let doc_resources = CaptureConfig::deserialize::<DocumentResources, _>(root, &doc_resources_name)
|
||||
.expect(&format!("Unable to open {}.ron", doc_resources_name));
|
||||
let interners_name = format!("interners-{}-{}", (id.0).0, id.1);
|
||||
let interners = CaptureConfig::deserialize::<Interners, _>(root, &interners_name)
|
||||
.expect(&format!("Unable to open {}.ron", interners_name));
|
||||
|
||||
let frame_resources_name = format!("frame-resources-{}-{}", (id.0).0, id.1);
|
||||
let frame_resources = CaptureConfig::deserialize::<FrameResources, _>(root, &frame_resources_name)
|
||||
.expect(&format!("Unable to open {}.ron", frame_resources_name));
|
||||
let data_stores_name = format!("data-stores-{}-{}", (id.0).0, id.1);
|
||||
let data_stores = CaptureConfig::deserialize::<DataStores, _>(root, &data_stores_name)
|
||||
.expect(&format!("Unable to open {}.ron", data_stores_name));
|
||||
|
||||
let mut doc = Document {
|
||||
scene: scene.clone(),
|
||||
|
@ -1780,7 +1744,7 @@ impl RenderBackend {
|
|||
hit_tester_is_valid: false,
|
||||
rendered_frame_is_valid: false,
|
||||
has_built_scene: false,
|
||||
resources: frame_resources,
|
||||
data_stores,
|
||||
scratch: PrimitiveScratchBuffer::new(),
|
||||
};
|
||||
|
||||
|
@ -1819,7 +1783,7 @@ impl RenderBackend {
|
|||
output_pipelines: doc.output_pipelines.clone(),
|
||||
font_instances: self.resource_cache.get_font_instances(),
|
||||
build_frame,
|
||||
doc_resources,
|
||||
interners,
|
||||
});
|
||||
|
||||
self.documents.insert(id, doc);
|
||||
|
|
|
@ -4251,7 +4251,7 @@ impl Renderer {
|
|||
for item in items {
|
||||
match item {
|
||||
DebugItem::Rect { rect, color } => {
|
||||
let inner_color = color.scale_alpha(0.1).into();
|
||||
let inner_color = color.scale_alpha(0.5).into();
|
||||
let outer_color = (*color).into();
|
||||
|
||||
debug_renderer.add_quad(
|
||||
|
|
|
@ -10,31 +10,20 @@ use api::channel::MsgSender;
|
|||
#[cfg(feature = "capture")]
|
||||
use capture::CaptureConfig;
|
||||
use frame_builder::{FrameBuilderConfig, FrameBuilder};
|
||||
use clip::{ClipDataInterner, ClipDataUpdateList};
|
||||
use clip_scroll_tree::ClipScrollTree;
|
||||
use display_list_flattener::DisplayListFlattener;
|
||||
use intern::{Internable, Interner};
|
||||
use intern_types;
|
||||
use internal_types::{FastHashMap, FastHashSet};
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
use prim_store::{PrimitiveDataInterner, PrimitiveDataUpdateList, PrimitiveKeyKind};
|
||||
use prim_store::{PrimitiveKeyKind};
|
||||
use prim_store::PrimitiveStoreStats;
|
||||
use prim_store::borders::{
|
||||
ImageBorder, ImageBorderDataInterner, ImageBorderDataUpdateList,
|
||||
NormalBorderPrim, NormalBorderDataInterner, NormalBorderDataUpdateList
|
||||
};
|
||||
use prim_store::gradient::{
|
||||
LinearGradient, LinearGradientDataInterner, LinearGradientDataUpdateList,
|
||||
RadialGradient, RadialGradientDataInterner, RadialGradientDataUpdateList
|
||||
};
|
||||
use prim_store::image::{
|
||||
Image, ImageDataInterner, ImageDataUpdateList,
|
||||
YuvImage, YuvImageDataInterner, YuvImageDataUpdateList,
|
||||
};
|
||||
use prim_store::line_dec::{
|
||||
LineDecoration, LineDecorationDataInterner, LineDecorationDataUpdateList
|
||||
};
|
||||
use prim_store::picture::{PictureDataInterner, Picture, PictureDataUpdateList};
|
||||
use prim_store::text_run::{TextRunDataInterner, TextRun, TextRunDataUpdateList};
|
||||
use prim_store::borders::{ImageBorder, NormalBorderPrim};
|
||||
use prim_store::gradient::{LinearGradient, RadialGradient};
|
||||
use prim_store::image::{Image, YuvImage};
|
||||
use prim_store::line_dec::LineDecoration;
|
||||
use prim_store::picture::Picture;
|
||||
use prim_store::text_run::TextRun;
|
||||
use resource_cache::{AsyncBlobImageInfo, FontInstanceMap};
|
||||
use render_backend::DocumentView;
|
||||
use renderer::{PipelineInfo, SceneBuilderHooks};
|
||||
|
@ -46,20 +35,6 @@ use util::drain_filter;
|
|||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
pub struct DocumentResourceUpdates {
|
||||
pub clip_updates: ClipDataUpdateList,
|
||||
pub prim_updates: PrimitiveDataUpdateList,
|
||||
pub image_updates: ImageDataUpdateList,
|
||||
pub image_border_updates: ImageBorderDataUpdateList,
|
||||
pub line_decoration_updates: LineDecorationDataUpdateList,
|
||||
pub linear_grad_updates: LinearGradientDataUpdateList,
|
||||
pub normal_border_updates: NormalBorderDataUpdateList,
|
||||
pub picture_updates: PictureDataUpdateList,
|
||||
pub radial_grad_updates: RadialGradientDataUpdateList,
|
||||
pub text_run_updates: TextRunDataUpdateList,
|
||||
pub yuv_image_updates: YuvImageDataUpdateList,
|
||||
}
|
||||
|
||||
/// Represents the work associated to a transaction before scene building.
|
||||
pub struct Transaction {
|
||||
pub document_id: DocumentId,
|
||||
|
@ -117,7 +92,7 @@ pub struct BuiltTransaction {
|
|||
pub frame_ops: Vec<FrameMsg>,
|
||||
pub removed_pipelines: Vec<PipelineId>,
|
||||
pub notifications: Vec<NotificationRequest>,
|
||||
pub doc_resource_updates: Option<DocumentResourceUpdates>,
|
||||
pub interner_updates: Option<InternerUpdates>,
|
||||
pub scene_build_start_time: u64,
|
||||
pub scene_build_end_time: u64,
|
||||
pub render_frame: bool,
|
||||
|
@ -149,7 +124,7 @@ pub struct LoadScene {
|
|||
pub view: DocumentView,
|
||||
pub config: FrameBuilderConfig,
|
||||
pub build_frame: bool,
|
||||
pub doc_resources: DocumentResources,
|
||||
pub interners: Interners,
|
||||
}
|
||||
|
||||
pub struct BuiltScene {
|
||||
|
@ -194,8 +169,8 @@ pub enum SceneSwapResult {
|
|||
Aborted,
|
||||
}
|
||||
|
||||
macro_rules! declare_document_resources {
|
||||
( $( { $interner_ident: ident, $interner_type: ty, $x: ident, $y: ty } )+ ) => {
|
||||
macro_rules! declare_interners {
|
||||
( $( $name: ident, )+ ) => {
|
||||
/// This struct contains all items that can be shared between
|
||||
/// display lists. We want to intern and share the same clips,
|
||||
/// primitives and other things between display lists so that:
|
||||
|
@ -205,13 +180,19 @@ macro_rules! declare_document_resources {
|
|||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
#[derive(Default)]
|
||||
pub struct DocumentResources {
|
||||
pub struct Interners {
|
||||
$(
|
||||
pub $interner_ident: $interner_type,
|
||||
pub $name: intern_types::$name::Interner,
|
||||
)+
|
||||
}
|
||||
|
||||
impl DocumentResources {
|
||||
pub struct InternerUpdates {
|
||||
$(
|
||||
pub $name: intern_types::$name::UpdateList,
|
||||
)+
|
||||
}
|
||||
|
||||
impl Interners {
|
||||
/// Reports CPU heap memory used by the interners.
|
||||
fn report_memory(
|
||||
&self,
|
||||
|
@ -219,24 +200,32 @@ macro_rules! declare_document_resources {
|
|||
r: &mut MemoryReport,
|
||||
) {
|
||||
$(
|
||||
r.interning.$interner_ident += self.$interner_ident.size_of(ops);
|
||||
r.interning.interners.$name += self.$name.size_of(ops);
|
||||
)+
|
||||
}
|
||||
|
||||
fn end_frame_and_get_pending_updates(&mut self) -> InternerUpdates {
|
||||
InternerUpdates {
|
||||
$(
|
||||
$name: self.$name.end_frame_and_get_pending_updates(),
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enumerate_interners!(declare_document_resources);
|
||||
enumerate_interners!(declare_interners);
|
||||
|
||||
// Access to `DocumentResources` interners by `Internable`
|
||||
// Access to `Interners` interners by `Internable`
|
||||
pub trait InternerMut<I: Internable>
|
||||
{
|
||||
fn interner_mut(&mut self) -> &mut Interner<I::Source, I::InternData, I::Marker>;
|
||||
}
|
||||
|
||||
macro_rules! impl_internet_mut {
|
||||
macro_rules! impl_interner_mut {
|
||||
($($ty:ident: $mem:ident,)*) => {
|
||||
$(impl InternerMut<$ty> for DocumentResources {
|
||||
$(impl InternerMut<$ty> for Interners {
|
||||
fn interner_mut(&mut self) -> &mut Interner<
|
||||
<$ty as Internable>::Source,
|
||||
<$ty as Internable>::InternData,
|
||||
|
@ -248,17 +237,17 @@ macro_rules! impl_internet_mut {
|
|||
}
|
||||
}
|
||||
|
||||
impl_internet_mut! {
|
||||
Image: image_interner,
|
||||
ImageBorder: image_border_interner,
|
||||
LineDecoration: line_decoration_interner,
|
||||
LinearGradient: linear_grad_interner,
|
||||
NormalBorderPrim: normal_border_interner,
|
||||
Picture: picture_interner,
|
||||
PrimitiveKeyKind: prim_interner,
|
||||
RadialGradient: radial_grad_interner,
|
||||
TextRun: text_run_interner,
|
||||
YuvImage: yuv_image_interner,
|
||||
impl_interner_mut! {
|
||||
Image: image,
|
||||
ImageBorder: image_border,
|
||||
LineDecoration: line_decoration,
|
||||
LinearGradient: linear_grad,
|
||||
NormalBorderPrim: normal_border,
|
||||
Picture: picture,
|
||||
PrimitiveKeyKind: prim,
|
||||
RadialGradient: radial_grad,
|
||||
TextRun: text_run,
|
||||
YuvImage: yuv_image,
|
||||
}
|
||||
|
||||
// A document in the scene builder contains the current scene,
|
||||
|
@ -267,7 +256,7 @@ impl_internet_mut! {
|
|||
// display lists.
|
||||
struct Document {
|
||||
scene: Scene,
|
||||
resources: DocumentResources,
|
||||
interners: Interners,
|
||||
prim_store_stats: PrimitiveStoreStats,
|
||||
}
|
||||
|
||||
|
@ -275,7 +264,7 @@ impl Document {
|
|||
fn new(scene: Scene) -> Self {
|
||||
Document {
|
||||
scene,
|
||||
resources: DocumentResources::default(),
|
||||
interners: Interners::default(),
|
||||
prim_store_stats: PrimitiveStoreStats::empty(),
|
||||
}
|
||||
}
|
||||
|
@ -395,8 +384,8 @@ impl SceneBuilder {
|
|||
#[cfg(feature = "capture")]
|
||||
fn save_scene(&mut self, config: CaptureConfig) {
|
||||
for (id, doc) in &self.documents {
|
||||
let doc_resources_name = format!("doc-resources-{}-{}", (id.0).0, id.1);
|
||||
config.serialize(&doc.resources, doc_resources_name);
|
||||
let interners_name = format!("interners-{}-{}", (id.0).0, id.1);
|
||||
config.serialize(&doc.interners, interners_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,7 +397,7 @@ impl SceneBuilder {
|
|||
let scene_build_start_time = precise_time_ns();
|
||||
|
||||
let mut built_scene = None;
|
||||
let mut doc_resource_updates = None;
|
||||
let mut interner_updates = None;
|
||||
|
||||
if item.scene.has_root_pipeline() {
|
||||
let mut clip_scroll_tree = ClipScrollTree::new();
|
||||
|
@ -422,81 +411,12 @@ impl SceneBuilder {
|
|||
&item.output_pipelines,
|
||||
&self.config,
|
||||
&mut new_scene,
|
||||
&mut item.doc_resources,
|
||||
&mut item.interners,
|
||||
&PrimitiveStoreStats::empty(),
|
||||
);
|
||||
|
||||
// TODO(djg): Can we do better than this? Use a #[derive] to
|
||||
// write the code for us, or unify updates into one enum/list?
|
||||
let clip_updates = item
|
||||
.doc_resources
|
||||
.clip_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let prim_updates = item
|
||||
.doc_resources
|
||||
.prim_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let image_updates = item
|
||||
.doc_resources
|
||||
.image_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let image_border_updates = item
|
||||
.doc_resources
|
||||
.image_border_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let line_decoration_updates = item
|
||||
.doc_resources
|
||||
.line_decoration_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let linear_grad_updates = item
|
||||
.doc_resources
|
||||
.linear_grad_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let normal_border_updates = item
|
||||
.doc_resources
|
||||
.normal_border_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let picture_updates = item
|
||||
.doc_resources
|
||||
.picture_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let radial_grad_updates = item
|
||||
.doc_resources
|
||||
.radial_grad_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let text_run_updates = item
|
||||
.doc_resources
|
||||
.text_run_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let yuv_image_updates = item
|
||||
.doc_resources
|
||||
.yuv_image_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
doc_resource_updates = Some(
|
||||
DocumentResourceUpdates {
|
||||
clip_updates,
|
||||
prim_updates,
|
||||
image_updates,
|
||||
image_border_updates,
|
||||
line_decoration_updates,
|
||||
linear_grad_updates,
|
||||
normal_border_updates,
|
||||
picture_updates,
|
||||
radial_grad_updates,
|
||||
text_run_updates,
|
||||
yuv_image_updates,
|
||||
}
|
||||
interner_updates = Some(
|
||||
item.interners.end_frame_and_get_pending_updates()
|
||||
);
|
||||
|
||||
built_scene = Some(BuiltScene {
|
||||
|
@ -510,7 +430,7 @@ impl SceneBuilder {
|
|||
item.document_id,
|
||||
Document {
|
||||
scene: item.scene,
|
||||
resources: item.doc_resources,
|
||||
interners: item.interners,
|
||||
prim_store_stats: PrimitiveStoreStats::empty(),
|
||||
},
|
||||
);
|
||||
|
@ -528,7 +448,7 @@ impl SceneBuilder {
|
|||
notifications: Vec::new(),
|
||||
scene_build_start_time,
|
||||
scene_build_end_time: precise_time_ns(),
|
||||
doc_resource_updates,
|
||||
interner_updates,
|
||||
});
|
||||
|
||||
self.forward_built_transaction(txn);
|
||||
|
@ -572,7 +492,7 @@ impl SceneBuilder {
|
|||
}
|
||||
|
||||
let mut built_scene = None;
|
||||
let mut doc_resource_updates = None;
|
||||
let mut interner_updates = None;
|
||||
if scene.has_root_pipeline() {
|
||||
if let Some(request) = txn.request_scene_build.take() {
|
||||
let mut clip_scroll_tree = ClipScrollTree::new();
|
||||
|
@ -586,7 +506,7 @@ impl SceneBuilder {
|
|||
&request.output_pipelines,
|
||||
&self.config,
|
||||
&mut new_scene,
|
||||
&mut doc.resources,
|
||||
&mut doc.interners,
|
||||
&doc.prim_store_stats,
|
||||
);
|
||||
|
||||
|
@ -594,75 +514,8 @@ impl SceneBuilder {
|
|||
doc.prim_store_stats = frame_builder.prim_store.get_stats();
|
||||
|
||||
// Retrieve the list of updates from the clip interner.
|
||||
let clip_updates = doc
|
||||
.resources
|
||||
.clip_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let prim_updates = doc
|
||||
.resources
|
||||
.prim_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let image_updates = doc
|
||||
.resources
|
||||
.image_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let image_border_updates = doc
|
||||
.resources
|
||||
.image_border_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let line_decoration_updates = doc
|
||||
.resources
|
||||
.line_decoration_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let linear_grad_updates = doc
|
||||
.resources
|
||||
.linear_grad_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let normal_border_updates = doc
|
||||
.resources
|
||||
.normal_border_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let picture_updates = doc
|
||||
.resources
|
||||
.picture_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let radial_grad_updates = doc
|
||||
.resources
|
||||
.radial_grad_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let text_run_updates = doc
|
||||
.resources
|
||||
.text_run_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
let yuv_image_updates = doc
|
||||
.resources
|
||||
.yuv_image_interner
|
||||
.end_frame_and_get_pending_updates();
|
||||
|
||||
doc_resource_updates = Some(
|
||||
DocumentResourceUpdates {
|
||||
clip_updates,
|
||||
prim_updates,
|
||||
image_updates,
|
||||
image_border_updates,
|
||||
line_decoration_updates,
|
||||
linear_grad_updates,
|
||||
normal_border_updates,
|
||||
picture_updates,
|
||||
radial_grad_updates,
|
||||
text_run_updates,
|
||||
yuv_image_updates,
|
||||
}
|
||||
interner_updates = Some(
|
||||
doc.interners.end_frame_and_get_pending_updates()
|
||||
);
|
||||
|
||||
built_scene = Some(BuiltScene {
|
||||
|
@ -697,7 +550,7 @@ impl SceneBuilder {
|
|||
frame_ops: replace(&mut txn.frame_ops, Vec::new()),
|
||||
removed_pipelines: replace(&mut txn.removed_pipelines, Vec::new()),
|
||||
notifications: replace(&mut txn.notifications, Vec::new()),
|
||||
doc_resource_updates,
|
||||
interner_updates,
|
||||
scene_build_start_time,
|
||||
scene_build_end_time: precise_time_ns(),
|
||||
})
|
||||
|
@ -760,7 +613,7 @@ impl SceneBuilder {
|
|||
let ops = self.size_of_ops.as_mut().unwrap();
|
||||
let mut report = MemoryReport::default();
|
||||
for doc in self.documents.values() {
|
||||
doc.resources.report_memory(ops, &mut report);
|
||||
doc.interners.report_memory(ops, &mut report);
|
||||
}
|
||||
|
||||
report
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::{ExternalScrollId, LayoutPixel, LayoutPoint, LayoutRect, LayoutSize, LayoutTransform};
|
||||
use api::{LayoutVector2D, PipelineId, PropertyBinding, ScrollClamping, ScrollLocation};
|
||||
use api::{LayoutVector2D, PipelineId, PropertyBinding, ReferenceFrameKind, ScrollClamping, ScrollLocation};
|
||||
use api::{TransformStyle, ScrollSensitivity, StickyOffsetBounds};
|
||||
use clip_scroll_tree::{CoordinateSystem, CoordinateSystemId, SpatialNodeIndex, TransformUpdateState};
|
||||
use euclid::SideOffsets2D;
|
||||
|
@ -116,18 +116,15 @@ impl SpatialNode {
|
|||
pub fn new_reference_frame(
|
||||
parent_index: Option<SpatialNodeIndex>,
|
||||
transform_style: TransformStyle,
|
||||
source_transform: Option<PropertyBinding<LayoutTransform>>,
|
||||
source_perspective: Option<LayoutTransform>,
|
||||
source_transform: PropertyBinding<LayoutTransform>,
|
||||
kind: ReferenceFrameKind,
|
||||
origin_in_parent_reference_frame: LayoutVector2D,
|
||||
pipeline_id: PipelineId,
|
||||
) -> Self {
|
||||
let identity = LayoutTransform::identity();
|
||||
let source_perspective = source_perspective.map_or_else(
|
||||
LayoutFastTransform::identity, |perspective| perspective.into());
|
||||
let info = ReferenceFrameInfo {
|
||||
transform_style,
|
||||
source_transform: source_transform.unwrap_or(PropertyBinding::Value(identity)),
|
||||
source_perspective,
|
||||
source_transform,
|
||||
kind,
|
||||
origin_in_parent_reference_frame,
|
||||
invertible: true,
|
||||
};
|
||||
|
@ -142,7 +139,6 @@ impl SpatialNode {
|
|||
Self::new(pipeline_id, Some(parent_index), SpatialNodeType::StickyFrame(sticky_frame_info))
|
||||
}
|
||||
|
||||
|
||||
pub fn add_child(&mut self, child: SpatialNodeIndex) {
|
||||
self.children.push(child);
|
||||
}
|
||||
|
@ -257,17 +253,26 @@ impl SpatialNode {
|
|||
match self.node_type {
|
||||
SpatialNodeType::ReferenceFrame(ref mut info) => {
|
||||
// Resolve the transform against any property bindings.
|
||||
let source_transform = scene_properties.resolve_layout_transform(&info.source_transform);
|
||||
let source_transform = LayoutFastTransform::from(
|
||||
scene_properties.resolve_layout_transform(&info.source_transform)
|
||||
);
|
||||
|
||||
// Do a change-basis operation on the perspective matrix using
|
||||
// the scroll offset.
|
||||
let scrolled_perspective = info.source_perspective
|
||||
.pre_translate(&state.parent_accumulated_scroll_offset)
|
||||
.post_translate(-state.parent_accumulated_scroll_offset);
|
||||
let source_transform = match info.kind {
|
||||
ReferenceFrameKind::Perspective => {
|
||||
// Do a change-basis operation on the perspective matrix
|
||||
// using the scroll offset.
|
||||
source_transform
|
||||
.pre_translate(&state.parent_accumulated_scroll_offset)
|
||||
.post_translate(-state.parent_accumulated_scroll_offset)
|
||||
}
|
||||
ReferenceFrameKind::Transform => source_transform,
|
||||
};
|
||||
|
||||
let resolved_transform =
|
||||
LayoutFastTransform::with_vector(info.origin_in_parent_reference_frame)
|
||||
.pre_mul(&source_transform.into())
|
||||
.pre_mul(&scrolled_perspective);
|
||||
.pre_mul(&source_transform);
|
||||
|
||||
// The transformation for this viewport in world coordinates is the transformation for
|
||||
// our parent reference frame, plus any accumulated scrolling offsets from nodes
|
||||
|
@ -494,8 +499,8 @@ impl SpatialNode {
|
|||
state.parent_reference_frame_transform = self.world_viewport_transform;
|
||||
|
||||
let should_flatten =
|
||||
info.transform_style == TransformStyle::Flat &&
|
||||
info.source_perspective.is_identity();
|
||||
info.kind == ReferenceFrameKind::Transform &&
|
||||
info.transform_style == TransformStyle::Flat;
|
||||
|
||||
if should_flatten {
|
||||
state.parent_reference_frame_transform = state.parent_reference_frame_transform.project_to_2d();
|
||||
|
@ -661,7 +666,7 @@ pub struct ReferenceFrameInfo {
|
|||
/// frame.
|
||||
pub source_transform: PropertyBinding<LayoutTransform>,
|
||||
pub transform_style: TransformStyle,
|
||||
pub source_perspective: LayoutFastTransform,
|
||||
pub kind: ReferenceFrameKind,
|
||||
|
||||
/// The original, not including the transform and relative to the parent reference frame,
|
||||
/// origin of this reference frame. This is already rolled into the `transform' property, but
|
||||
|
|
|
@ -22,7 +22,7 @@ use pathfinder_partitioner::mesh::Mesh;
|
|||
use picture::SurfaceInfo;
|
||||
use prim_store::{PrimitiveStore, DeferredResolve, PrimitiveScratchBuffer};
|
||||
use profiler::FrameProfileCounters;
|
||||
use render_backend::{FrameId, FrameResources};
|
||||
use render_backend::{DataStores, FrameId};
|
||||
use render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind};
|
||||
use render_task::{BlurTask, ClearMode, GlyphTask, RenderTaskLocation, RenderTaskTree, ScalingTask};
|
||||
use resource_cache::ResourceCache;
|
||||
|
@ -55,7 +55,7 @@ pub struct RenderTargetContext<'a, 'rc> {
|
|||
pub resource_cache: &'rc mut ResourceCache,
|
||||
pub use_dual_source_blending: bool,
|
||||
pub clip_scroll_tree: &'a ClipScrollTree,
|
||||
pub resources: &'a FrameResources,
|
||||
pub data_stores: &'a DataStores,
|
||||
pub surfaces: &'a [SurfaceInfo],
|
||||
pub scratch: &'a PrimitiveScratchBuffer,
|
||||
}
|
||||
|
@ -658,7 +658,7 @@ impl RenderTarget for AlphaRenderTarget {
|
|||
clip_store,
|
||||
ctx.clip_scroll_tree,
|
||||
transforms,
|
||||
&ctx.resources.clip_data_store,
|
||||
&ctx.data_stores.clip,
|
||||
);
|
||||
}
|
||||
RenderTaskKind::ClipRegion(ref task) => {
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче