mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Merge mozilla-central to inbound. a=merge CLOSED TREE
This commit is contained in:
commit
9dda825205
@ -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;
|
||||
|
File diff suppressed because one or more lines are too long
@ -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;
|
||||
|
File diff suppressed because one or more lines are too long
@ -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;
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -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.
|
||||
|
5
browser/components/newtab/package-lock.json
generated
5
browser/components/newtab/package-lock.json
generated
@ -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;
|
||||
|
@ -3196,8 +3196,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,
|
||||
};
|
||||
|
107
gfx/wr/webrender/src/intern_types.rs
Normal file
107
gfx/wr/webrender/src/intern_types.rs
Normal file
@ -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) => {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user