Showing preview only (299K chars total). Download the full file or copy to clipboard to get everything.
Repository: fathyb/carbonyl
Branch: main
Commit: ab80a276b1bd
Files: 104
Total size: 274.8 KB
Directory structure:
gitextract_4jcv0hr0/
├── .cargo/
│ └── config.toml
├── .dockerignore
├── .github/
│ └── funding.yml
├── .gitignore
├── .gitmodules
├── .refloat/
│ └── config.js
├── Cargo.toml
├── Dockerfile
├── build.rs
├── changelog.md
├── chromium/
│ ├── .gclient
│ └── patches/
│ ├── chromium/
│ │ ├── 0001-Add-Carbonyl-library.patch
│ │ ├── 0002-Add-Carbonyl-service.patch
│ │ ├── 0003-Setup-shared-software-rendering-surface.patch
│ │ ├── 0004-Setup-browser-default-settings.patch
│ │ ├── 0005-Remove-some-debug-assertions.patch
│ │ ├── 0006-Setup-display-DPI.patch
│ │ ├── 0007-Disable-text-effects.patch
│ │ ├── 0008-Fix-text-layout.patch
│ │ ├── 0009-Bridge-browser-into-Carbonyl-library.patch
│ │ ├── 0010-Conditionally-enable-text-rendering.patch
│ │ ├── 0011-Rename-carbonyl-Renderer-to-carbonyl-Bridge.patch
│ │ ├── 0012-Create-separate-bridge-for-Blink.patch
│ │ ├── 0013-Refactor-rendering-bridge.patch
│ │ └── 0014-Move-Skia-text-rendering-control-to-bridge.patch
│ ├── skia/
│ │ ├── 0001-Disable-text-rendering.patch
│ │ └── 0002-Export-some-private-APIs.patch
│ └── webrtc/
│ └── 0001-Disable-GIO-on-Linux.patch
├── cliff.toml
├── license.md
├── package.json
├── readme.md
├── scripts/
│ ├── build.sh
│ ├── changelog.sh
│ ├── copy-binaries.sh
│ ├── docker-build.sh
│ ├── docker-push.sh
│ ├── env.sh
│ ├── gclient.sh
│ ├── gn.sh
│ ├── npm-package.mjs
│ ├── npm-package.sh
│ ├── npm-publish.sh
│ ├── patches.sh
│ ├── platform-triple.sh
│ ├── release.sh
│ ├── restore-mtime.sh
│ ├── run.sh
│ ├── runtime-hash.sh
│ ├── runtime-pull.sh
│ └── runtime-push.sh
└── src/
├── browser/
│ ├── BUILD.gn
│ ├── args.gn
│ ├── bridge.cc
│ ├── bridge.h
│ ├── bridge.rs
│ ├── carbonyl.mojom
│ ├── export.h
│ ├── host_display_client.cc
│ ├── host_display_client.h
│ ├── render_service_impl.cc
│ ├── render_service_impl.h
│ ├── renderer.cc
│ └── renderer.h
├── browser.rs
├── cli/
│ ├── cli.rs
│ ├── program.rs
│ └── usage.txt
├── cli.rs
├── gfx/
│ ├── color.rs
│ ├── point.rs
│ ├── rect.rs
│ ├── size.rs
│ └── vector.rs
├── gfx.rs
├── input/
│ ├── dcs/
│ │ ├── control_flow.rs
│ │ ├── parser.rs
│ │ ├── resource.rs
│ │ └── status.rs
│ ├── dcs.rs
│ ├── keyboard.rs
│ ├── listen.rs
│ ├── mouse.rs
│ ├── parser.rs
│ └── tty.rs
├── input.rs
├── lib.rs
├── output/
│ ├── cell.rs
│ ├── frame_sync.rs
│ ├── kd_tree.rs
│ ├── painter.rs
│ ├── quad.rs
│ ├── quantizer.rs
│ ├── render_thread.rs
│ ├── renderer.rs
│ ├── window.rs
│ └── xterm.rs
├── output.rs
├── ui/
│ └── navigation.rs
├── ui.rs
├── utils/
│ ├── four_bits.rs
│ ├── log.rs
│ └── try_block.rs
└── utils.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .cargo/config.toml
================================================
[build]
target-dir = "build"
================================================
FILE: .dockerignore
================================================
/build
!/build/browser
/chromium
================================================
FILE: .github/funding.yml
================================================
github: fathyb
================================================
FILE: .gitignore
================================================
.DS_Store
node_modules/
/.ccache
/.git_cache
/.vscode
/build
/chromium/*
!/chromium/.gclient
!/chromium/depot_tools
!/chromium/patches
/packages/*/build
================================================
FILE: .gitmodules
================================================
[submodule "chromium/depot_tools"]
path = chromium/depot_tools
url = https://chromium.googlesource.com/chromium/tools/depot_tools.git
================================================
FILE: .refloat/config.js
================================================
import { commit } from "refloat";
import docker from "github.com/refloat-plugins/docker";
import pkg from "../package.json";
const { version } = JSON.parse(pkg);
const triple = (platform, arch) => `${archs[arch]}-${platforms[platform]}`;
const lib = (platform, arch) =>
`build/${triple(platform, arch)}/release/libcarbonyl.${sharedLib[platform]}`;
const sharedLib = {
macos: "dylib",
linux: "so",
};
const platforms = {
macos: "apple-darwin",
linux: "unknown-linux-gnu",
};
const archs = {
arm64: "aarch64",
amd64: "x86_64",
};
export const jobs = ["macos", "linux"].flatMap((platform) => {
return [
{
name: `Build runtime (${platform})`,
agent: { tags: ["chromium-src", platform] },
steps: [
...["arm64", "amd64"].map((arch) => ({
import: { workspace: `core-${triple(platform, arch)}` },
})),
{
parallel: ["arm64", "amd64"].map((arch) => ({
name: `Fetch pre-built runtime for ${arch}`,
command: `
if scripts/runtime-pull.sh ${arch}; then
touch skip-build-${arch}
cp \\
${lib(platform, arch)} \\
build/pre-built/${triple(platform, arch)}
fi
`,
})),
},
{
name: "Fetch Chromium",
command: `
if [ -z "$CHROMIUM_ROOT" ]; then
echo "Chromium build environment not setup"
exit 2
fi
if [ ! -f skip-build-arm64 ] || [ ! -f skip-build-amd64 ]; then
cp chromium/.gclient "$CHROMIUM_ROOT"
scripts/gclient.sh sync
scripts/patches.sh apply
rm -rf "$CHROMIUM_ROOT/src/carbonyl"
mkdir "$CHROMIUM_ROOT/src/carbonyl"
ln -s "$(pwd)/src" "$CHROMIUM_ROOT/src/carbonyl/src"
ln -s "$(pwd)/build" "$CHROMIUM_ROOT/src/carbonyl/build"
fi
`,
},
{
parallel: ["arm64", "amd64"].map((arch) => {
const target =
platform === "linux" && arch === "amd64" ? "Default" : arch;
return {
serial: [
{
name: `Build Chromium (${arch})`,
command: `
if [ ! -f skip-build-${arch} ]; then
scripts/build.sh ${target} ${arch}
scripts/copy-binaries.sh ${target} ${arch}
fi
`,
env: {
MACOSX_DEPLOYMENT_TARGET: "10.13",
CARBONYL_SKIP_CARGO_BUILD: "true",
AR_AARCH64_UNKNOWN_LINUX_GNU: "aarch64-linux-gnu-ar",
CC_AARCH64_UNKNOWN_LINUX_GNU: "aarch64-linux-gnu-gcc",
CXX_AARCH64_UNKNOWN_LINUX_GNU: "aarch64-linux-gnu-g++",
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER:
"aarch64-linux-gnu-gcc",
AR_X86_64_UNKNOWN_LINUX_GNU: "x86_64-linux-gnu-ar",
CC_X86_64_UNKNOWN_LINUX_GNU: "x86_64-linux-gnu-gcc",
CXX_X86_64_UNKNOWN_LINUX_GNU: "x86_64-linux-gnu-g++",
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER:
"x86_64-linux-gnu-gcc",
},
},
{
parallel: [
{
name: `Push binaries to CDN (${arch})`,
command: `
if [ ! -f skip-build-${arch} ]; then
scripts/runtime-push.sh ${arch}
fi
`,
env: {
CDN_ACCESS_KEY_ID: { secret: true },
CDN_SECRET_ACCESS_KEY: { secret: true },
},
},
{
export: {
workspace: `runtime-${triple(platform, arch)}`,
path: `build/pre-built/${triple(platform, arch)}`,
},
},
],
},
],
};
}),
},
],
},
...["arm64", "amd64"].flatMap((arch) => {
const triple = `${archs[arch]}-${platforms[platform]}`;
const lib = `build/${triple}/release/libcarbonyl.${sharedLib[platform]}`;
return [
{
name: `Build core (${platform}/${arch})`,
docker:
platform === "linux"
? {
image: "fathyb/rust-cross",
cache: ["/usr/local/cargo/registry"],
}
: undefined,
agent: { tags: platform === "linux" ? ["docker"] : ["macos"] },
steps: [
{
name: "Install Rust toolchain",
command: `rustup target add ${triple}`,
},
{
name: "Build core library",
command: `cargo build --target ${triple} --release`,
env: { MACOSX_DEPLOYMENT_TARGET: "10.13" },
},
{
name: "Set core library install name",
command:
platform === "macos"
? `install_name_tool -id @executable_path/libcarbonyl.dylib ${lib}`
: "echo not necessary",
},
{
export: {
workspace: `core-${triple}`,
path: "build/*/release/*.{dylib,so,dll}",
},
},
],
},
{
name: `Package (${platform}/${arch})`,
docker: "fathyb/rust-cross",
agent: { tags: ["docker"] },
steps: [
{
import: { workspace: `runtime-${triple}` },
},
{
name: "Zip binaries",
command: `
mkdir build/zip
cp -r build/pre-built/${triple} build/zip/carbonyl-${version}
cd build/zip
zip -r package.zip carbonyl-${version}
`,
},
{
export: {
artifact: {
name: `carbonyl.${platform}-${arch}.zip`,
path: "build/zip/package.zip",
},
},
},
],
},
];
}),
];
});
if (commit.defaultBranch) {
jobs.push(
{
name: "Publish to Docker",
agent: { tags: ["carbonyl-publish"] },
docker: "fathyb/rust-cross",
steps: [
{
serial: ["arm64", "amd64"].map((arch) => ({
import: { workspace: `runtime-${triple("linux", arch)}` },
})),
},
{
parallel: ["arm64", "amd64"].map((arch) => ({
serial: [
{
name: `Build ${arch} image`,
command: `scripts/docker-build.sh ${arch}`,
},
],
})),
},
{
name: "Publish images to DockerHub",
command: "scripts/docker-push.sh next",
using: docker.login({
username: { secret: "DOCKER_PUBLISH_USERNAME" },
password: { secret: "DOCKER_PUBLISH_TOKEN" },
}),
},
],
},
{
name: "Publish to npm",
agent: { tags: ["carbonyl-publish"] },
docker: "node:18",
steps: [
...["macos", "linux"].flatMap((platform) =>
["arm64", "amd64"].map((arch) => ({
import: { workspace: `runtime-${triple(platform, arch)}` },
}))
),
{
name: "Package",
command: "scripts/npm-package.sh",
},
{
name: "Write npm token",
env: { CARBONYL_NPM_PUBLISH_TOKEN: { secret: true } },
command:
'echo "//registry.npmjs.org/:_authToken=${CARBONYL_NPM_PUBLISH_TOKEN}" > ~/.npmrc',
},
{
parallel: ["amd64", "arm64"].flatMap((arch) =>
["linux", "macos"].map((platform) => ({
name: `Publish ${platform}/${arch} package`,
command: "scripts/npm-publish.sh --tag next",
env: {
CARBONYL_PUBLISH_ARCH: arch,
CARBONYL_PUBLISH_PLATFORM: platform,
},
}))
),
},
{
name: "Publish main package",
command: "scripts/npm-publish.sh --tag next",
},
],
}
);
}
================================================
FILE: Cargo.toml
================================================
[package]
name = "carbonyl"
version = "0.0.3"
edition = "2021"
[dependencies]
libc = "0.2"
unicode-width = "0.1.10"
unicode-segmentation = "1.10.0"
chrono = "0.4.23"
[lib]
name = "carbonyl"
path = "src/lib.rs"
crate-type = ["cdylib"]
================================================
FILE: Dockerfile
================================================
FROM rust:1.67 AS cross-compile
RUN apt-get update && \
apt-get install -y \
zip g++-aarch64-linux-gnu g++-x86-64-linux-gnu libc6-dev-arm64-cross libc6-dev-amd64-cross && \
rustup target add aarch64-unknown-linux-gnu x86_64-unknown-linux-gnu && \
rustup toolchain install stable-aarch64-unknown-linux-gnu stable-x86_64-unknown-linux-gnu && \
rm -rf /var/lib/apt/lists/*
ENV AR_AARCH64_UNKNOWN_LINUX_GNU=aarch64-linux-gnu-ar
ENV CC_AARCH64_UNKNOWN_LINUX_GNU=aarch64-linux-gnu-gcc
ENV CXX_AARCH64_UNKNOWN_LINUX_GNU=aarch64-linux-gnu-g++
ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc
ENV AR_X86_64_UNKNOWN_LINUX_GNU=x86_64-linux-gnu-ar
ENV CC_X86_64_UNKNOWN_LINUX_GNU=x86_64-linux-gnu-gcc
ENV CXX_X86_64_UNKNOWN_LINUX_GNU=x86_64-linux-gnu-g++
ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=x86_64-linux-gnu-gcc
FROM debian:bullseye-slim
RUN groupadd -r carbonyl && \
useradd -r -g carbonyl carbonyl && \
mkdir -p /carbonyl/data && \
chown -R carbonyl:carbonyl /carbonyl && \
apt-get update && \
apt-get install -y libasound2 libexpat1 libfontconfig1 libnss3 && \
rm -rf /var/lib/apt/lists/*
USER carbonyl
VOLUME /carbonyl/data
ENV HOME=/carbonyl/data
COPY . /carbonyl
RUN /carbonyl/carbonyl --version
ENTRYPOINT ["/carbonyl/carbonyl", "--no-sandbox", "--disable-dev-shm-usage", "--user-data-dir=/carbonyl/data"]
================================================
FILE: build.rs
================================================
use std::path::PathBuf;
#[cfg(target_arch = "x86_64")]
fn link_sysroot() {
let sysroot_path = PathBuf::from("./chromium/src/build/linux/debian_bullseye_amd64-sysroot");
if sysroot_path.is_dir() {
println!("cargo:rustc-link-search=chromium/src/build/linux/debian_bullseye_amd64-sysroot/lib/x86_64-linux-gnu");
println!("cargo:rustc-link-search=chromium/src/build/linux/debian_bullseye_amd64-sysroot/usr/lib/x86_64-linux-gnu");
println!(
"cargo:rustc-link-arg=--sysroot=./chromium/src/build/linux/debian_bullseye_amd64-sysroot"
);
} else {
println!("cargo:warning={}", "x86_64 debian sysroot provided by chromium was not found!");
println!("cargo:warning={}", "carbonyl may fail to link against a proper libc!");
}
}
#[cfg(target_arch = "x86")]
fn link_sysroot() {
let sysroot_path = PathBuf::from("./chromium/src/build/linux/debian_bullseye_i386-sysroot");
if sysroot_path.is_dir() {
println!("cargo:rustc-link-search=chromium/src/build/linux/debian_bullseye_i386-sysroot/lib/i386-linux-gnu");
println!("cargo:rustc-link-search=chromium/src/build/linux/debian_bullseye_i386-sysroot/usr/lib/i386-linux-gnu");
println!(
"cargo:rustc-link-arg=--sysroot=./chromium/src/build/linux/debian_bullseye_i386-sysroot"
);
} else {
println!("cargo:warning={}", "x86 debian sysroot provided by chromium was not found!");
println!("cargo:warning={}", "carbonyl may fail to link against a proper libc!");
}
}
#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
fn link_sysroot() {
// Intentionally left blank.
}
fn main() {
link_sysroot();
}
================================================
FILE: changelog.md
================================================
# Changelog
All notable changes to this project will be documented in this file.
## [0.0.3] - 2023-02-18
### 🚀 Features
- Add `--help` and `--version` ([#105](https://github.com/fathyb/carbonyl/issues/105))
- Add logo and description to `--help` ([#106](https://github.com/fathyb/carbonyl/issues/106))
- Use Cmd instead of Alt for navigation shortcuts ([#109](https://github.com/fathyb/carbonyl/issues/109))
- Enable h.264 support ([#103](https://github.com/fathyb/carbonyl/issues/103))
- Introduce quadrant rendering ([#120](https://github.com/fathyb/carbonyl/issues/120))
### 🐛 Bug Fixes
- Fix arguments parsing ([#108](https://github.com/fathyb/carbonyl/issues/108))
- Fix missing module error on npm package ([#113](https://github.com/fathyb/carbonyl/issues/113))
- Enable threaded compositing with bitmap mode
- Fix idling CPU usage ([#126](https://github.com/fathyb/carbonyl/issues/126))
- Package proper library in binaries ([#127](https://github.com/fathyb/carbonyl/issues/127))
### 📖 Documentation
- Update download links
- Fix commit_preprocessors url ([#102](https://github.com/fathyb/carbonyl/issues/102))
- Add `--rm` to Docker example ([#101](https://github.com/fathyb/carbonyl/issues/101))
## [0.0.2] - 2023-02-09
### 🚀 Features
- Better true color detection
- Linux support
- Xterm title
- Hide stderr unless crash
- Add `--debug` to print stderr on exit ([#23](https://github.com/fathyb/carbonyl/issues/23))
- Add navigation UI ([#86](https://github.com/fathyb/carbonyl/issues/86))
- Handle terminal resize ([#87](https://github.com/fathyb/carbonyl/issues/87))
### 🐛 Bug Fixes
- Parser fixes
- Properly enter tab and return keys
- Fix some special characters ([#35](https://github.com/fathyb/carbonyl/issues/35))
- Improve terminal size detection ([#36](https://github.com/fathyb/carbonyl/issues/36))
- Allow working directories that contain spaces ([#63](https://github.com/fathyb/carbonyl/issues/63))
- Do not use tags for checkout ([#64](https://github.com/fathyb/carbonyl/issues/64))
- Do not checkout nacl ([#79](https://github.com/fathyb/carbonyl/issues/79))
- Wrap zip files in carbonyl folder ([#88](https://github.com/fathyb/carbonyl/issues/88))
- Fix WebGL support on Linux ([#90](https://github.com/fathyb/carbonyl/issues/90))
- Fix initial freeze on Docker ([#91](https://github.com/fathyb/carbonyl/issues/91))
### 📖 Documentation
- Upload demo videos
- Fix video layout
- Fix a typo ([#1](https://github.com/fathyb/carbonyl/issues/1))
- Fix a typo `ie.` -> `i.e.` ([#9](https://github.com/fathyb/carbonyl/issues/9))
- Fix build instructions ([#15](https://github.com/fathyb/carbonyl/issues/15))
- Add ascii logo
- Add comparisons ([#34](https://github.com/fathyb/carbonyl/issues/34))
- Add OS support ([#50](https://github.com/fathyb/carbonyl/issues/50))
- Add download link
- Fix linux download links
- Document shared library
- Fix a typo (`know` -> `known`) ([#71](https://github.com/fathyb/carbonyl/issues/71))
- Add license
### Build
- Various build system fixes ([#20](https://github.com/fathyb/carbonyl/issues/20))
================================================
FILE: chromium/.gclient
================================================
solutions = [
{
"name": "src",
"url": "https://chromium.googlesource.com/chromium/src.git@111.0.5511.1",
"managed": False,
"custom_deps": {},
"custom_vars": {
"use_rust": True,
"checkout_pgo_profiles": True,
"checkout_nacl": False,
}
},
]
================================================
FILE: chromium/patches/chromium/0001-Add-Carbonyl-library.patch
================================================
From 0ed9a390f25d73492ce1170ce229b95772fd458d Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Thu, 9 Feb 2023 03:20:50 +0100
Subject: [PATCH 01/14] Add Carbonyl library
---
carbonyl/build | 1 +
carbonyl/src | 1 +
headless/BUILD.gn | 15 ++++++++++++++-
3 files changed, 16 insertions(+), 1 deletion(-)
create mode 120000 carbonyl/build
create mode 120000 carbonyl/src
diff --git a/carbonyl/build b/carbonyl/build
new file mode 120000
index 0000000000000..44735d5866459
--- /dev/null
+++ b/carbonyl/build
@@ -0,0 +1 @@
+../../../build
\ No newline at end of file
diff --git a/carbonyl/src b/carbonyl/src
new file mode 120000
index 0000000000000..dabb0e15a991e
--- /dev/null
+++ b/carbonyl/src
@@ -0,0 +1 @@
+../../../src
\ No newline at end of file
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index bfae1e3290de0..8018111ed9898 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -453,6 +453,7 @@ component("headless_non_renderer") {
"//build:branding_buildflags",
"//build:branding_buildflags",
"//build:chromeos_buildflags",
+ "//carbonyl/src/browser:carbonyl",
"//components/cookie_config",
"//components/crash/core/common:common",
"//components/embedder_support",
@@ -993,13 +994,25 @@ static_library("headless_shell_lib") {
}
executable("headless_shell") {
+ if (is_mac && !use_lld) {
+ ldflags = [ "-Wl,-no_compact_unwind" ]
+ } else if (is_linux) {
+ ldflags = [
+ "-Wl,-rpath=\$ORIGIN/.",
+ "-Wl,-rpath-link=.",
+ ]
+ }
+
configs -= [ "//build/config/compiler:thinlto_optimize_default" ]
configs += [ "//build/config/compiler:thinlto_optimize_max" ]
sources = [ "app/headless_shell_main.cc" ]
defines = []
- deps = [ ":headless_shell_lib" ]
+ deps = [
+ ":headless_shell_lib",
+ "//carbonyl/src/browser:carbonyl",
+ ]
if (!headless_use_embedded_resources) {
data = [
================================================
FILE: chromium/patches/chromium/0002-Add-Carbonyl-service.patch
================================================
From 795b29828fd7ac95548c4dcab483cbc3b6c1d361 Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Thu, 9 Feb 2023 03:21:59 +0100
Subject: [PATCH 02/14] Add Carbonyl service
---
cc/trees/layer_tree_host.cc | 21 ++
cc/trees/layer_tree_host.h | 8 +
content/browser/browser_interface_binders.cc | 4 +
.../renderer_host/render_frame_host_impl.cc | 6 +
.../renderer_host/render_frame_host_impl.h | 7 +
content/renderer/render_frame_impl.cc | 288 ++++++++++++++++++
content/renderer/render_frame_impl.h | 8 +
.../blink/public/web/web_frame_widget.h | 7 +
.../blink/renderer/platform/fonts/font.cc | 63 +++-
9 files changed, 409 insertions(+), 3 deletions(-)
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 55295cc3f1e2f..20fa1030fb4e8 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -481,6 +481,24 @@ bool LayerTreeHost::MainFrameUpdatesAreDeferred() const {
bool LayerTreeHost::IsUsingLayerLists() const {
return settings_.use_layer_lists;
}
+
+void LayerTreeHost::StartTerminalRender() {
+ DCHECK(IsMainThread());
+
+ auto it = terminal_render_callbacks_.begin();
+
+ while (it != terminal_render_callbacks_.end()) {
+ auto& callback = *it->get();
+
+ if (callback) {
+ callback();
+
+ it++;
+ } else {
+ it = terminal_render_callbacks_.erase(it);
+ }
+ }
+}
void LayerTreeHost::CommitComplete(const CommitTimestamps& commit_timestamps) {
DCHECK(IsMainThread());
@@ -1648,6 +1666,9 @@ bool LayerTreeHost::PaintContent(const LayerList& update_layer_list) {
for (const auto& layer : update_layer_list) {
did_paint_content |= layer->Update();
}
+
+ StartTerminalRender();
+
return did_paint_content;
}
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index c26301594abc2..ed217c22359c4 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -167,6 +167,12 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
// Returns the process global unique identifier for this LayerTreeHost.
int GetId() const;
+ // Carbonyl
+ void StartTerminalRender();
+ void ObserveTerminalRender(std::shared_ptr<std::function<bool()>> callback) {
+ terminal_render_callbacks_.push_back(callback);
+ }
+
// The commit state for the frame being assembled by the compositor host.
const CommitState* pending_commit_state() const {
DCHECK(IsMainThread());
@@ -1086,6 +1092,8 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
bool syncing_deltas_for_test_ = false;
+ std::vector<std::shared_ptr<std::function<bool()>>> terminal_render_callbacks_;
+
base::WeakPtrFactory<LayerTreeHost> weak_ptr_factory_{this};
};
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
index 6e62b36a76799..e07dcb983698b 100644
--- a/content/browser/browser_interface_binders.cc
+++ b/content/browser/browser_interface_binders.cc
@@ -887,6 +887,10 @@ void PopulateFrameBinders(RenderFrameHostImpl* host, mojo::BinderMap* map) {
base::BindRepeating(&RenderFrameHostImpl::GetVirtualAuthenticatorManager,
base::Unretained(host)));
+ map->Add<carbonyl::mojom::CarbonylRenderService>(
+ base::BindRepeating(&RenderFrameHostImpl::GetCarbonylRenderService,
+ base::Unretained(host)));
+
map->Add<device::mojom::DevicePostureProvider>(
base::BindRepeating(&BindDevicePostureProvider));
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 8ba82589beb32..cc0ad634bcb4c 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -10731,6 +10731,12 @@ void RenderFrameHostImpl::BindTrustTokenQueryAnswerer(
std::move(receiver), ComputeTopFrameOrigin(GetLastCommittedOrigin()));
}
+void RenderFrameHostImpl::GetCarbonylRenderService(
+ mojo::PendingReceiver<carbonyl::mojom::CarbonylRenderService> receiver) {
+ carbonyl_render_service_ = std::make_unique<carbonyl::CarbonylRenderServiceImpl>(
+ std::move(receiver));
+}
+
void RenderFrameHostImpl::GetAudioContextManager(
mojo::PendingReceiver<blink::mojom::AudioContextManager> receiver) {
AudioContextManagerImpl::Create(this, std::move(receiver));
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index db16f07685acf..8c36cce0ec604 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -176,6 +176,8 @@
#include "media/mojo/mojom/remoting.mojom-forward.h"
#endif
+#include "carbonyl/src/browser/render_service_impl.h"
+
namespace blink {
class AssociatedInterfaceRegistry;
class DocumentPolicy;
@@ -1834,6 +1836,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Set the `frame_` for sending messages to the renderer process.
void SetMojomFrameRemote(mojo::PendingAssociatedRemote<mojom::Frame>);
+ void GetCarbonylRenderService(
+ mojo::PendingReceiver<carbonyl::mojom::CarbonylRenderService> receiver);
+
void GetAudioContextManager(
mojo::PendingReceiver<blink::mojom::AudioContextManager> receiver);
@@ -4720,6 +4725,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
// The observers watching our state changed event.
base::ObserverList<RenderFrameHostObserver> observers_;
+ std::unique_ptr<carbonyl::CarbonylRenderServiceImpl> carbonyl_render_service_;
+
// BrowserInterfaceBroker implementation through which this
// RenderFrameHostImpl exposes document-scoped Mojo services to the currently
// active document in the corresponding RenderFrame.
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 9e09c5342699e..97b61ffb954be 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -232,6 +232,7 @@
#include "third_party/blink/public/web/web_view.h"
#include "third_party/blink/public/web/web_widget.h"
#include "third_party/blink/public/web/web_window_features.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "ui/accessibility/ax_tree_update.h"
#include "ui/events/base_event_utils.h"
#include "url/origin.h"
@@ -255,6 +256,39 @@
#include "content/renderer/java/gin_java_bridge_dispatcher.h"
#endif
+// Carbonyl
+#include <stdlib.h>
+#include <iostream>
+#include "cc/paint/paint_recorder.h"
+#include "cc/paint/skia_paint_canvas.h"
+#include "cc/raster/playback_image_provider.h"
+#include "cc/tiles/software_image_decode_cache.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/render_frame_metadata_observer.h"
+#include "components/paint_preview/common/paint_preview_tracker.h"
+#include "third_party/blink/renderer/core/exported/web_view_impl.h"
+#include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h"
+#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/paint/paint_flags.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
+#include "third_party/skia/include/core/SkEncodedImageFormat.h"
+#include "third_party/skia/include/core/SkMesh.h"
+#include "third_party/skia/include/core/SkStream.h"
+#include "third_party/skia/include/core/SkSurface.h"
+#include "third_party/skia/include/core/SkVertices.h"
+#include "third_party/skia/include/docs/SkPDFDocument.h"
+#include "third_party/skia/include/svg/SkSVGCanvas.h"
+#include "third_party/skia/include/svg/SkSVGCanvas.h"
+#include "third_party/skia/include/utils/SkBase64.h"
+#include "third_party/skia/src/text/GlyphRun.h"
+#include "third_party/skia/src/core/SkClipStackDevice.h"
+#include "third_party/skia/src/core/SkDevice.h"
+#include "third_party/skia/src/core/SkFontPriv.h"
+#include "third_party/skia/src/utils/SkUTF.h"
+
using base::Time;
using blink::ContextMenuData;
using blink::WebContentDecryptionModule;
@@ -1912,8 +1946,229 @@ RenderFrameImpl::~RenderFrameImpl() {
base::trace_event::TraceLog::GetInstance()->RemoveProcessLabel(routing_id_);
g_routing_id_frame_map.Get().erase(routing_id_);
agent_scheduling_group_.RemoveRoute(routing_id_);
+
+ if (auto& callback = *render_callback_.get()) {
+ callback = nullptr;
+ }
}
+} // namespace content
+
+namespace carbonyl {
+class TextCaptureDevice: public SkClipStackDevice {
+public:
+ TextCaptureDevice(
+ const SkImageInfo& info,
+ const SkSurfaceProps& props
+ ):
+ SkClipStackDevice(info, props)
+ {
+ clear(SkRect::MakeWH(info.width(), info.height()));
+ }
+
+ void swap(std::vector<carbonyl::mojom::TextDataPtr>& data) {
+ data.swap(data_);
+ }
+
+ void clear() {
+ data_.clear();
+ }
+
+ void clear(const SkRect& rect) {
+ data_.push_back(
+ carbonyl::mojom::TextData::New(
+ std::string(),
+ gfx::SkRectToRectF(rect),
+ 0
+ )
+ );
+ }
+
+protected:
+ SkBaseDevice* onCreateDevice(const CreateInfo& info, const SkPaint*) override {
+ return new TextCaptureDevice(info.fInfo, SkSurfaceProps(0, info.fPixelGeometry));
+ }
+
+ void drawDevice(SkBaseDevice* baseDevice, const SkSamplingOptions&, const SkPaint& paint) override {
+ if(isUnsupportedPaint(paint)) {
+ return;
+ }
+
+ auto blendMode = paint.getBlendMode_or(SkBlendMode::kClear);
+
+ if (blendMode != SkBlendMode::kSrc && blendMode != SkBlendMode::kSrcOver) {
+ return;
+ }
+
+ auto* device = static_cast<TextCaptureDevice*>(baseDevice);
+ SkMatrix transform = device->getRelativeTransform(*this);
+
+ for (auto& data: device->data_) {
+ data_.push_back(
+ carbonyl::mojom::TextData::New(
+ data->contents,
+ gfx::SkRectToRectF(transform.mapRect(gfx::RectFToSkRect(data->bounds))),
+ data->color
+ )
+ );
+ }
+ }
+
+ void drawPaint(const SkPaint&) override {}
+ void drawOval(const SkRect&, const SkPaint&) override {}
+ void drawPoints(SkCanvas::PointMode, size_t, const SkPoint[], const SkPaint&) override {}
+ void drawImageRect(const SkImage*,
+ const SkRect*,
+ const SkRect& rect,
+ const SkSamplingOptions&,
+ const SkPaint&,
+ SkCanvas::SrcRectConstraint) override {
+ // clear(scale(rect));
+ }
+
+ void drawVertices(const SkVertices* vertices,
+ sk_sp<SkBlender>,
+ const SkPaint& paint,
+ bool = false) override {
+ drawRect(vertices->bounds(), paint);
+ }
+
+ void drawMesh(const SkMesh& mesh, sk_sp<SkBlender>, const SkPaint& paint) override {
+ drawRect(mesh.bounds(), paint);
+ }
+
+ void drawPath(const SkPath& path, const SkPaint& paint, bool = false) override {
+ drawRect(path.getBounds(), paint);
+ }
+
+ void drawRRect(const SkRRect& rect, const SkPaint& paint) override {
+ drawRect(rect.rect(), paint);
+ }
+
+ bool isUnsupportedPaint(const SkPaint& paint) {
+ return (
+ paint.getShader() ||
+ paint.getBlender() ||
+ paint.getPathEffect() ||
+ paint.getMaskFilter() ||
+ paint.getImageFilter() ||
+ paint.getColorFilter() ||
+ paint.getImageFilter()
+ );
+ }
+
+ void drawRect(const SkRect& rect, const SkPaint& paint) override {
+ if (
+ paint.getStyle() == SkPaint::Style::kFill_Style &&
+ paint.getAlphaf() == 1.0 &&
+ !isUnsupportedPaint(paint)
+ ) {
+ auto blendMode = paint.getBlendMode_or(SkBlendMode::kClear);
+
+ if (blendMode == SkBlendMode::kSrc || blendMode == SkBlendMode::kSrcOver) {
+ clear(scale(rect));
+ } else {
+ std::cerr << "Blending mode: " << SkBlendMode_Name(blendMode) << std::endl;
+ }
+ }
+ }
+
+ void onDrawGlyphRunList(SkCanvas*,
+ const sktext::GlyphRunList& glyphRunList,
+ const SkPaint&,
+ const SkPaint& paint) override {
+ auto position = scale(glyphRunList.origin());
+
+ for (auto& glyphRun : glyphRunList) {
+ auto runSize = glyphRun.runSize();
+ SkAutoSTArray<64, SkUnichar> unichars(runSize);
+ SkFontPriv::GlyphsToUnichars(glyphRun.font(), glyphRun.glyphsIDs().data(),
+ runSize, unichars.get());
+
+ auto base64_ptr = std::make_unique<char[]>(runSize + 1);
+ char* base64 = base64_ptr.get();
+
+ for (size_t i = 0; i < runSize; ++i) {
+ base64[i] = unichars[i];
+ }
+
+ base64[runSize] = '\0';
+
+ size_t size = 0;
+ auto error = SkBase64::Decode(base64, runSize, nullptr, &size);
+
+ if (error != SkBase64::kNoError) {
+ return;
+ }
+
+ auto utf8_ptr = std::make_unique<char[]>(size);
+ char* utf8 = utf8_ptr.get();
+
+ error = SkBase64::Decode(base64, runSize, utf8, &size);
+
+ if (error != SkBase64::kNoError) {
+ return;
+ }
+
+ data_.push_back(
+ carbonyl::mojom::TextData::New(
+ std::string(utf8, size),
+ gfx::RectF(position.x(), position.y(), 0, 0),
+ paint.getColor()
+ )
+ );
+ }
+ }
+
+private:
+ SkRect scale(const SkRect& rect) {
+ return localToDevice().mapRect(rect);
+ }
+ SkPoint scale(const SkPoint& point) {
+ return localToDevice().mapPoint(point);
+ }
+
+ std::vector<carbonyl::mojom::TextDataPtr> data_;
+};
+
+class RendererService {
+ public:
+ RendererService() = default;
+
+ SkCanvas* BeginPaint(int width, int height) {
+ if (width != width_ || height != height_ || !device_) {
+ width_ = width;
+ height_ = height;
+
+ device_ = sk_sp(
+ new TextCaptureDevice(
+ SkImageInfo::MakeUnknown(width, height),
+ SkSurfaceProps(0, kUnknown_SkPixelGeometry)
+ )
+ );
+ canvas_ = std::make_unique<SkCanvas>(device_);
+ }
+
+ device_->clear();
+
+ return canvas_.get();
+ }
+
+ void Swap(std::vector<carbonyl::mojom::TextDataPtr>& data) {
+ device_->swap(data);
+ }
+
+ private:
+ int width_ = 0;
+ int height_ = 0;
+ sk_sp<TextCaptureDevice> device_;
+ std::unique_ptr<SkCanvas> canvas_;
+};
+
+} // namespace carbonyl
+
+namespace content {
+
void RenderFrameImpl::Initialize(blink::WebFrame* parent) {
initialized_ = true;
is_main_frame_ = !parent;
@@ -1942,6 +2197,8 @@ void RenderFrameImpl::Initialize(blink::WebFrame* parent) {
factory.RegisterRemoteFactory(GetWebFrame()->GetLocalFrameToken(),
GetBrowserInterfaceBroker());
}
+
+ browser_interface_broker_proxy_.GetInterface(std::move(carbonyl_render_service_receiver_));
frame_request_blocker_ = blink::WebFrameRequestBlocker::Create();
@@ -1954,6 +2211,37 @@ void RenderFrameImpl::Initialize(blink::WebFrame* parent) {
agent_scheduling_group_.AddFrameRoute(
routing_id_, this,
GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch("carbonyl-b64-text")) {
+ setenv("carbonyl_b64_text", "true", 1);
+ }
+
+ auto* host = GetLocalRootWebFrameWidget()->LayerTreeHost();
+ auto renderer = std::make_shared<carbonyl::RendererService>();
+
+ render_callback_ = std::make_shared<std::function<bool()>>(
+ [=]() -> bool {
+ if (!IsMainFrame() || IsHidden()) {
+ return false;
+ }
+
+ size_t width = frame_->DocumentSize().width();
+ size_t height = frame_->VisibleContentRect().height();
+ auto* view = static_cast<blink::WebViewImpl*>(GetWebFrame()->View());
+ std::vector<carbonyl::mojom::TextDataPtr> data;
+
+ view->MainFrameImpl()->GetFrame()->View()->GetPaintRecord().Playback(
+ renderer->BeginPaint(width, height)
+ );
+
+ renderer->Swap(data);
+ carbonyl_render_service_->DrawText(std::move(data));
+
+ return true;
+ }
+ );
+
+ host->ObserveTerminalRender(render_callback_);
}
void RenderFrameImpl::GetInterface(
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 3b558293121ce..f996b74bfae7e 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -118,6 +118,8 @@
#include "content/common/pepper_plugin.mojom.h"
#endif
+#include "carbonyl/src/browser/carbonyl.mojom.h"
+
namespace blink {
namespace scheduler {
class WebAgentGroupScheduler;
@@ -1446,6 +1448,8 @@ class CONTENT_EXPORT RenderFrameImpl
std::unique_ptr<blink::WebURLLoaderFactoryForTest>
web_url_loader_factory_override_for_test_;
+ std::shared_ptr<std::function<bool()>> render_callback_;
+
// When the browser asks the renderer to commit a navigation, it should always
// result in a committed navigation reported via DidCommitProvisionalLoad().
// This is important because DidCommitProvisionalLoad() is responsible for
@@ -1522,6 +1526,10 @@ class CONTENT_EXPORT RenderFrameImpl
// false, but set to true by some tests.
bool send_content_state_immediately_ = false;
+ mojo::Remote<carbonyl::mojom::CarbonylRenderService> carbonyl_render_service_;
+ mojo::PendingReceiver<carbonyl::mojom::CarbonylRenderService> carbonyl_render_service_receiver_ =
+ carbonyl_render_service_.BindNewPipeAndPassReceiver();
+
base::WeakPtrFactory<RenderFrameImpl> weak_factory_{this};
};
diff --git a/third_party/blink/public/web/web_frame_widget.h b/third_party/blink/public/web/web_frame_widget.h
index 6264d513b398c..3988df585a159 100644
--- a/third_party/blink/public/web/web_frame_widget.h
+++ b/third_party/blink/public/web/web_frame_widget.h
@@ -53,6 +53,10 @@ struct ApplyViewportChangesArgs;
class LayerTreeHost;
} // namespace cc
+namespace content {
+class RenderFrameImpl;
+} // namespace content
+
namespace gfx {
class PointF;
class RectF;
@@ -227,6 +231,9 @@ class WebFrameWidget : public WebWidget {
// GPU benchmarking extension needs access to the LayerTreeHost
friend class GpuBenchmarkingContext;
+ // Allow RenderFrameImpl to access the LayerTreeHost for html2svg
+ friend class content::RenderFrameImpl;
+
// This private constructor and the class/friend declaration ensures that
// WebFrameWidgetImpl is the only concrete subclass that implements
// WebFrameWidget, so that it is safe to downcast to WebFrameWidgetImpl.
diff --git a/third_party/blink/renderer/platform/fonts/font.cc b/third_party/blink/renderer/platform/fonts/font.cc
index 089a11b156ade..dfdc79eacce3b 100644
--- a/third_party/blink/renderer/platform/fonts/font.cc
+++ b/third_party/blink/renderer/platform/fonts/font.cc
@@ -24,6 +24,8 @@
#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "base/base64.h"
+
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/fonts/character_range.h"
@@ -149,11 +151,17 @@ bool Font::operator==(const Font& other) const {
namespace {
+static const bool carbonyl_b64_text = true;
+
void DrawBlobs(cc::PaintCanvas* canvas,
const cc::PaintFlags& flags,
const ShapeResultBloberizer::BlobBuffer& blobs,
const gfx::PointF& point,
- cc::NodeId node_id = cc::kInvalidNodeId) {
+ cc::NodeId node_id = cc::kInvalidNodeId) {
+ if (carbonyl_b64_text) {
+ return;
+ }
+
for (const auto& blob_info : blobs) {
DCHECK(blob_info.blob);
cc::PaintCanvasAutoRestore auto_restore(canvas, false);
@@ -198,8 +206,7 @@ void DrawBlobs(cc::PaintCanvas* canvas,
}
}
if (node_id != cc::kInvalidNodeId) {
- canvas->drawTextBlob(blob_info.blob, point.x(), point.y(), node_id,
- flags);
+ canvas->drawTextBlob(blob_info.blob, point.x(), point.y(), node_id, flags);
} else {
canvas->drawTextBlob(blob_info.blob, point.x(), point.y(), flags);
}
@@ -230,6 +237,31 @@ void Font::DrawText(cc::PaintCanvas* canvas,
if (ShouldSkipDrawing())
return;
+ if (carbonyl_b64_text) {
+ auto string = StringView(
+ run_info.run.ToStringView(),
+ run_info.from,
+ run_info.to - run_info.from
+ ).ToString().Utf8();
+ auto base64 = base::Base64Encode(base::as_bytes(base::make_span(string)));
+
+ // Bypass HarfBuzz text shaping for the Carbonyl Skia back-end
+ auto blob = SkTextBlob::MakeFromString(
+ base64.c_str(),
+ PrimaryFont()->
+ PlatformData().
+ CreateSkFont(false, &font_description_)
+ );
+
+ if (node_id != cc::kInvalidNodeId) {
+ canvas->drawTextBlob(blob, point.x(), point.y(), node_id, flags);
+ } else {
+ canvas->drawTextBlob(blob, point.x(), point.y(), flags);
+ }
+
+ return;
+ }
+
CachingWordShaper word_shaper(*this);
ShapeResultBuffer buffer;
word_shaper.FillResultBuffer(run_info, &buffer);
@@ -253,6 +285,31 @@ void Font::DrawText(cc::PaintCanvas* canvas,
if (ShouldSkipDrawing())
return;
+ if (carbonyl_b64_text) {
+ auto string = StringView(
+ text_info.text,
+ text_info.from,
+ text_info.Length()
+ ).ToString().Utf8();
+ auto base64 = base::Base64Encode(base::as_bytes(base::make_span(string)));
+
+ // Bypass HarfBuzz text shaping for the Carbonyl Skia back-end
+ auto blob = SkTextBlob::MakeFromString(
+ base64.c_str(),
+ PrimaryFont()->
+ PlatformData().
+ CreateSkFont(false, &font_description_)
+ );
+
+ if (node_id != cc::kInvalidNodeId) {
+ canvas->drawTextBlob(blob, point.x(), point.y(), node_id, flags);
+ } else {
+ canvas->drawTextBlob(blob, point.x(), point.y(), flags);
+ }
+
+ return;
+ }
+
ShapeResultBloberizer::FillGlyphsNG bloberizer(
GetFontDescription(), device_scale_factor > 1.0f, text_info.text,
text_info.from, text_info.to, text_info.shape_result,
================================================
FILE: chromium/patches/chromium/0003-Setup-shared-software-rendering-surface.patch
================================================
From eea9662f4ba08a655057143d320e4e692fd92469 Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Thu, 9 Feb 2023 03:24:29 +0100
Subject: [PATCH 03/14] Setup shared software rendering surface
---
components/viz/host/host_display_client.cc | 4 +++-
components/viz/host/host_display_client.h | 6 ++++--
.../viz/host/layered_window_updater_impl.cc | 2 +-
.../viz/host/layered_window_updater_impl.h | 2 +-
.../output_surface_provider_impl.cc | 16 ++++++++++++++++
.../compositor/viz_process_transport_factory.cc | 4 +++-
.../mojom/compositing/display_private.mojom | 1 -
.../compositing/layered_window_updater.mojom | 2 +-
ui/compositor/compositor.h | 16 ++++++++++++++++
9 files changed, 45 insertions(+), 8 deletions(-)
diff --git a/components/viz/host/host_display_client.cc b/components/viz/host/host_display_client.cc
index 6d905b62e6258..bfb803829c73b 100644
--- a/components/viz/host/host_display_client.cc
+++ b/components/viz/host/host_display_client.cc
@@ -47,9 +47,9 @@ void HostDisplayClient::OnDisplayReceivedCALayerParams(
}
#endif
-#if BUILDFLAG(IS_WIN)
void HostDisplayClient::CreateLayeredWindowUpdater(
mojo::PendingReceiver<mojom::LayeredWindowUpdater> receiver) {
+#if BUILDFLAG(IS_WIN)
if (!NeedsToUseLayerWindow(widget_)) {
DLOG(ERROR) << "HWND shouldn't be using a layered window";
return;
@@ -57,7 +57,9 @@ void HostDisplayClient::CreateLayeredWindowUpdater(
layered_window_updater_ =
std::make_unique<LayeredWindowUpdaterImpl>(widget_, std::move(receiver));
+#endif
}
+#if BUILDFLAG(IS_WIN)
void HostDisplayClient::AddChildWindowToBrowser(
gpu::SurfaceHandle child_window) {
NOTREACHED();
diff --git a/components/viz/host/host_display_client.h b/components/viz/host/host_display_client.h
index 5eeaadec9773f..f3409f0eeda03 100644
--- a/components/viz/host/host_display_client.h
+++ b/components/viz/host/host_display_client.h
@@ -47,11 +47,13 @@ class VIZ_HOST_EXPORT HostDisplayClient : public mojom::DisplayClient {
#endif
#if BUILDFLAG(IS_WIN)
- void CreateLayeredWindowUpdater(
- mojo::PendingReceiver<mojom::LayeredWindowUpdater> receiver) override;
void AddChildWindowToBrowser(gpu::SurfaceHandle child_window) override;
#endif
+ protected:
+ void CreateLayeredWindowUpdater(
+ mojo::PendingReceiver<mojom::LayeredWindowUpdater> receiver) override;
+
// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/components/viz/host/layered_window_updater_impl.cc b/components/viz/host/layered_window_updater_impl.cc
index 271486b45dcc8..a62210d8ca3c8 100644
--- a/components/viz/host/layered_window_updater_impl.cc
+++ b/components/viz/host/layered_window_updater_impl.cc
@@ -44,7 +44,7 @@ void LayeredWindowUpdaterImpl::OnAllocatedSharedMemory(
// |region|'s handle will close when it goes out of scope.
}
-void LayeredWindowUpdaterImpl::Draw(DrawCallback draw_callback) {
+void LayeredWindowUpdaterImpl::Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) {
TRACE_EVENT0("viz", "LayeredWindowUpdaterImpl::Draw");
if (!canvas_) {
diff --git a/components/viz/host/layered_window_updater_impl.h b/components/viz/host/layered_window_updater_impl.h
index 8af69cac78b74..9f74e511c263d 100644
--- a/components/viz/host/layered_window_updater_impl.h
+++ b/components/viz/host/layered_window_updater_impl.h
@@ -38,7 +38,7 @@ class VIZ_HOST_EXPORT LayeredWindowUpdaterImpl
// mojom::LayeredWindowUpdater implementation.
void OnAllocatedSharedMemory(const gfx::Size& pixel_size,
base::UnsafeSharedMemoryRegion region) override;
- void Draw(DrawCallback draw_callback) override;
+ void Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) override;
private:
const HWND hwnd_;
diff --git a/components/viz/service/display_embedder/output_surface_provider_impl.cc b/components/viz/service/display_embedder/output_surface_provider_impl.cc
index d8f25c1435d4b..2929ebd3887c2 100644
--- a/components/viz/service/display_embedder/output_surface_provider_impl.cc
+++ b/components/viz/service/display_embedder/output_surface_provider_impl.cc
@@ -16,6 +16,7 @@
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
#include "build/chromeos_buildflags.h"
+#include "carbonyl/src/browser/software_output_device_proxy.h"
#include "cc/base/switches.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
@@ -29,6 +30,7 @@
#include "gpu/command_buffer/service/scheduler_sequence.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/ipc/common/surface_handle.h"
+#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
#include "ui/base/ui_base_switches.h"
#if BUILDFLAG(IS_WIN)
@@ -134,10 +136,24 @@ std::unique_ptr<OutputSurface> OutputSurfaceProviderImpl::CreateOutputSurface(
}
}
+namespace {
+ static const bool use_layered_window = true;
+}
+
std::unique_ptr<SoftwareOutputDevice>
OutputSurfaceProviderImpl::CreateSoftwareOutputDeviceForPlatform(
gpu::SurfaceHandle surface_handle,
mojom::DisplayClient* display_client) {
+// #if !BUILDFLAG(IS_APPLE)
+ if (use_layered_window) {
+ DCHECK(display_client);
+ mojo::PendingRemote<mojom::LayeredWindowUpdater> layered_window_updater;
+ display_client->CreateLayeredWindowUpdater(
+ layered_window_updater.InitWithNewPipeAndPassReceiver());
+ return std::make_unique<SoftwareOutputDeviceProxy>(
+ std::move(layered_window_updater));
+ }
+// #endif
if (headless_)
return std::make_unique<SoftwareOutputDevice>();
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc
index 3b44531f2618f..fae71c1c19a4f 100644
--- a/content/browser/compositor/viz_process_transport_factory.cc
+++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -53,6 +53,8 @@
#include "ui/gfx/win/rendering_window_manager.h"
#endif
+#include "carbonyl/src/browser/host_display_client.h"
+
namespace content {
namespace {
@@ -400,7 +402,7 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
root_params->display_private =
display_private.BindNewEndpointAndPassReceiver();
compositor_data.display_client =
- std::make_unique<HostDisplayClient>(compositor);
+ std::make_unique<carbonyl::HostDisplayClient>();
root_params->display_client =
compositor_data.display_client->GetBoundRemote(resize_task_runner_);
mojo::AssociatedRemote<viz::mojom::ExternalBeginFrameController>
diff --git a/services/viz/privileged/mojom/compositing/display_private.mojom b/services/viz/privileged/mojom/compositing/display_private.mojom
index 52f44a31de4a8..65b938d76e430 100644
--- a/services/viz/privileged/mojom/compositing/display_private.mojom
+++ b/services/viz/privileged/mojom/compositing/display_private.mojom
@@ -103,7 +103,6 @@ interface DisplayClient {
// Creates a LayeredWindowUpdater implementation to draw into a layered
// window.
- [EnableIf=is_win]
CreateLayeredWindowUpdater(pending_receiver<LayeredWindowUpdater> receiver);
// Sends the created child window to the browser process so that it can be
diff --git a/services/viz/privileged/mojom/compositing/layered_window_updater.mojom b/services/viz/privileged/mojom/compositing/layered_window_updater.mojom
index 2f462f0deb5fc..695869b83cefa 100644
--- a/services/viz/privileged/mojom/compositing/layered_window_updater.mojom
+++ b/services/viz/privileged/mojom/compositing/layered_window_updater.mojom
@@ -26,5 +26,5 @@ interface LayeredWindowUpdater {
// Draws to the HWND by copying pixels from shared memory. Callback must be
// called after draw operation is complete to signal shared memory can be
// modified.
- Draw() => ();
+ Draw(gfx.mojom.Rect damage_rect) => ();
};
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index 50cea82c6b477..f024e6013bfb9 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -87,6 +87,7 @@ class DisplayPrivate;
class ExternalBeginFrameController;
} // namespace mojom
class ContextProvider;
+class HostDisplayClient;
class HostFrameSinkManager;
class LocalSurfaceId;
class RasterContextProvider;
@@ -143,6 +144,16 @@ class COMPOSITOR_EXPORT ContextFactory {
virtual viz::HostFrameSinkManager* GetHostFrameSinkManager() = 0;
};
+class COMPOSITOR_EXPORT CompositorDelegate {
+ public:
+ virtual bool IsOffscreen() const = 0;
+ virtual std::unique_ptr<viz::HostDisplayClient> CreateHostDisplayClient(
+ ui::Compositor* compositor) = 0;
+
+ protected:
+ virtual ~CompositorDelegate() {}
+};
+
// Compositor object to take care of GPU painting.
// A Browser compositor object is responsible for generating the final
// displayable form of pixels comprising a single widget's contents. It draws an
@@ -186,6 +197,9 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver,
// Schedules a redraw of the layer tree associated with this compositor.
void ScheduleDraw();
+ CompositorDelegate* delegate() const { return delegate_; }
+ void SetDelegate(CompositorDelegate* delegate) { delegate_ = delegate; }
+
// Sets the root of the layer tree drawn by this Compositor. The root layer
// must have no parent. The compositor's root layer is reset if the root layer
// is destroyed. NULL can be passed to reset the root layer, in which case the
@@ -503,6 +517,8 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver,
std::unique_ptr<PendingBeginFrameArgs> pending_begin_frame_args_;
+ CompositorDelegate* delegate_ = nullptr;
+
// The root of the Layer tree drawn by this compositor.
raw_ptr<Layer> root_layer_ = nullptr;
================================================
FILE: chromium/patches/chromium/0004-Setup-browser-default-settings.patch
================================================
From c960c9b1f7ef3f16b27e4eaa4896e3563c88ea91 Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Thu, 9 Feb 2023 03:27:27 +0100
Subject: [PATCH 04/14] Setup browser default settings
---
headless/public/headless_browser.cc | 4 ++--
headless/public/headless_browser.h | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/headless/public/headless_browser.cc b/headless/public/headless_browser.cc
index b6c70ecb0fc23..c836a082d2e68 100644
--- a/headless/public/headless_browser.cc
+++ b/headless/public/headless_browser.cc
@@ -22,14 +22,14 @@ namespace headless {
namespace {
// Product name for building the default user agent string.
-const char kHeadlessProductName[] = "HeadlessChrome";
+const char kHeadlessProductName[] = "Google Chrome";
constexpr gfx::Size kDefaultWindowSize(800, 600);
constexpr gfx::FontRenderParams::Hinting kDefaultFontRenderHinting =
gfx::FontRenderParams::Hinting::HINTING_FULL;
std::string GetProductNameAndVersion() {
- return std::string(kHeadlessProductName) + "/" + PRODUCT_VERSION;
+ return std::string(kHeadlessProductName) + "/" + PRODUCT_VERSION + " (Carbonyl)";
}
} // namespace
diff --git a/headless/public/headless_browser.h b/headless/public/headless_browser.h
index 48efaa7d57ca2..afc0236147519 100644
--- a/headless/public/headless_browser.h
+++ b/headless/public/headless_browser.h
@@ -176,10 +176,10 @@ struct HEADLESS_EXPORT HeadlessBrowser::Options {
base::FilePath user_data_dir;
// Run a browser context in an incognito mode. Enabled by default.
- bool incognito_mode = true;
+ bool incognito_mode = false;
// If true, then all pop-ups and calls to window.open will fail.
- bool block_new_web_contents = false;
+ bool block_new_web_contents = true;
// Whether or not BeginFrames will be issued over DevTools protocol
// (experimental).
================================================
FILE: chromium/patches/chromium/0005-Remove-some-debug-assertions.patch
================================================
From 481ff19118891fe65e80b8be0e1f4498874d3b56 Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Thu, 9 Feb 2023 03:28:35 +0100
Subject: [PATCH 05/14] Remove some debug assertions
---
.../browser/web_contents/web_contents_impl.cc | 1 -
.../core/v8/script_promise_resolver.cc | 44 +++++++++----------
.../compositing/paint_artifact_compositor.cc | 2 -
.../platform/graphics/graphics_context.cc | 16 +++----
4 files changed, 30 insertions(+), 33 deletions(-)
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 74749758894a2..4eb891c32b474 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -5988,7 +5988,6 @@ void WebContentsImpl::DidNavigateMainFramePreCommit(
if (IsFullscreen())
ExitFullscreen(false);
- DCHECK(!IsFullscreen());
// Clean up keyboard lock state when navigating.
CancelKeyboardLock(keyboard_lock_widget_);
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
index c3176f4937c21..56d34529dedfa 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
@@ -58,28 +58,28 @@ ScriptPromiseResolver::ScriptPromiseResolver(
ScriptPromiseResolver::~ScriptPromiseResolver() = default;
void ScriptPromiseResolver::Dispose() {
-#if DCHECK_IS_ON()
- // This assertion fails if:
- // - promise() is called at least once and
- // - this resolver is destructed before it is resolved, rejected,
- // detached, the V8 isolate is terminated or the associated
- // ExecutionContext is stopped.
- const bool is_properly_detached =
- state_ == kDetached || !is_promise_called_ ||
- !GetScriptState()->ContextIsValid() || !GetExecutionContext() ||
- GetExecutionContext()->IsContextDestroyed();
- if (!is_properly_detached && !suppress_detach_check_) {
- // This is here to make it easier to track down which promise resolvers are
- // being abandoned. See https://crbug.com/873980.
- static crash_reporter::CrashKeyString<1024> trace_key(
- "scriptpromiseresolver-trace");
- crash_reporter::SetCrashKeyStringToStackTrace(&trace_key,
- create_stack_trace_);
- DCHECK(false)
- << "ScriptPromiseResolver was not properly detached; created at\n"
- << create_stack_trace_.ToString();
- }
-#endif
+// #if DCHECK_IS_ON()
+// // This assertion fails if:
+// // - promise() is called at least once and
+// // - this resolver is destructed before it is resolved, rejected,
+// // detached, the V8 isolate is terminated or the associated
+// // ExecutionContext is stopped.
+// const bool is_properly_detached =
+// state_ == kDetached || !is_promise_called_ ||
+// !GetScriptState()->ContextIsValid() || !GetExecutionContext() ||
+// GetExecutionContext()->IsContextDestroyed();
+// if (!is_properly_detached && !suppress_detach_check_) {
+// // This is here to make it easier to track down which promise resolvers are
+// // being abandoned. See https://crbug.com/873980.
+// static crash_reporter::CrashKeyString<1024> trace_key(
+// "scriptpromiseresolver-trace");
+// crash_reporter::SetCrashKeyStringToStackTrace(&trace_key,
+// create_stack_trace_);
+// DCHECK(false)
+// << "ScriptPromiseResolver was not properly detached; created at\n"
+// << create_stack_trace_.ToString();
+// }
+// #endif
deferred_resolve_task_.Cancel();
}
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index d3131a4e07ece..a9464abd86a69 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -196,7 +196,6 @@ bool NeedsFullUpdateAfterPaintingChunk(
// properties are changed, which would indicate a missing call to
// SetNeedsUpdate.
if (previous.properties != repainted.properties) {
- NOTREACHED();
return true;
}
@@ -253,7 +252,6 @@ bool NeedsFullUpdateAfterPaintingChunk(
// properties are changed, which would indicate a missing call to
// SetNeedsUpdate.
if (previous.properties != repainted.properties) {
- NOTREACHED();
return true;
}
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.cc b/third_party/blink/renderer/platform/graphics/graphics_context.cc
index 2518b71275670..3a1b8e6646c43 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_context.cc
+++ b/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -146,14 +146,14 @@ GraphicsContext::GraphicsContext(PaintController& paint_controller)
}
GraphicsContext::~GraphicsContext() {
-#if DCHECK_IS_ON()
- if (!disable_destruction_checks_) {
- DCHECK(!paint_state_index_);
- DCHECK(!paint_state_->SaveCount());
- DCHECK(!layer_count_);
- DCHECK(!SaveCount());
- }
-#endif
+// #if DCHECK_IS_ON()
+// if (!disable_destruction_checks_) {
+// DCHECK(!paint_state_index_);
+// DCHECK(!paint_state_->SaveCount());
+// DCHECK(!layer_count_);
+// DCHECK(!SaveCount());
+// }
+// #endif
}
void GraphicsContext::CopyConfigFrom(GraphicsContext& other) {
================================================
FILE: chromium/patches/chromium/0006-Setup-display-DPI.patch
================================================
From cc9c37adb3ad2613a114bd37e1fde43f83951d88 Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Sun, 12 Feb 2023 01:00:43 +0100
Subject: [PATCH 06/14] Setup display DPI
---
.../lib/browser/headless_browser_impl_aura.cc | 11 ++--
headless/lib/browser/headless_screen.cc | 5 +-
ui/display/display.cc | 52 ++++++++++---------
3 files changed, 35 insertions(+), 33 deletions(-)
diff --git a/headless/lib/browser/headless_browser_impl_aura.cc b/headless/lib/browser/headless_browser_impl_aura.cc
index 81261215c702f..508660db32151 100644
--- a/headless/lib/browser/headless_browser_impl_aura.cc
+++ b/headless/lib/browser/headless_browser_impl_aura.cc
@@ -19,6 +19,8 @@
#include "ui/events/devices/device_data_manager.h"
#include "ui/gfx/geometry/rect.h"
+#include "carbonyl/src/browser/bridge.h"
+
namespace headless {
void HeadlessBrowserImpl::PlatformInitialize() {
@@ -57,13 +59,8 @@ void HeadlessBrowserImpl::PlatformSetWebContentsBounds(
const gfx::Rect& bounds) {
// Browser's window bounds should contain all web contents, so that we're sure
// that we will actually produce visible damage when taking a screenshot.
- gfx::Rect old_host_bounds =
- web_contents->window_tree_host()->GetBoundsInPixels();
- gfx::Rect new_host_bounds(
- 0, 0, std::max(old_host_bounds.width(), bounds.x() + bounds.width()),
- std::max(old_host_bounds.height(), bounds.y() + bounds.height()));
- web_contents->window_tree_host()->SetBoundsInPixels(new_host_bounds);
- web_contents->window_tree_host()->window()->SetBounds(new_host_bounds);
+ web_contents->window_tree_host()->SetBoundsInPixels(ScaleToEnclosedRect(bounds, carbonyl::Renderer::GetDPI()));
+ web_contents->window_tree_host()->window()->SetBounds(bounds);
gfx::NativeView native_view = web_contents->web_contents()->GetNativeView();
native_view->SetBounds(bounds);
diff --git a/headless/lib/browser/headless_screen.cc b/headless/lib/browser/headless_screen.cc
index 28f1a65f6dce5..8bf00ef5e036a 100644
--- a/headless/lib/browser/headless_screen.cc
+++ b/headless/lib/browser/headless_screen.cc
@@ -13,6 +13,8 @@
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/native_widget_types.h"
+#include "carbonyl/src/browser/bridge.h"
+
namespace headless {
// static
@@ -49,7 +51,8 @@ display::Display HeadlessScreen::GetDisplayNearestWindow(
HeadlessScreen::HeadlessScreen(const gfx::Rect& screen_bounds) {
static int64_t synthesized_display_id = 2000;
display::Display display(synthesized_display_id++);
- display.SetScaleAndBounds(1.0f, screen_bounds);
+ float dpi = carbonyl::Renderer::GetDPI();
+ display.SetScaleAndBounds(dpi, ScaleToEnclosedRect(screen_bounds, dpi));
ProcessDisplayChanged(display, true /* is_primary */);
}
diff --git a/ui/display/display.cc b/ui/display/display.cc
index 466ef1fd1fe6e..1d71f3b4c9857 100644
--- a/ui/display/display.cc
+++ b/ui/display/display.cc
@@ -21,6 +21,8 @@
#include "ui/gfx/geometry/transform.h"
#include "ui/gfx/icc_profile.h"
+#include "carbonyl/src/browser/bridge.h"
+
namespace display {
namespace {
@@ -39,22 +41,22 @@ float g_forced_device_scale_factor = -1.0;
constexpr float kDisplaySizeAllowanceEpsilon = 0.01f;
bool HasForceDeviceScaleFactorImpl() {
- return base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kForceDeviceScaleFactor);
+ // return base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kForceDeviceScaleFactor);
+ return true;
}
float GetForcedDeviceScaleFactorImpl() {
- double scale_in_double = 1.0;
- if (HasForceDeviceScaleFactorImpl()) {
- std::string value =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kForceDeviceScaleFactor);
- if (!base::StringToDouble(value, &scale_in_double)) {
- LOG(ERROR) << "Failed to parse the default device scale factor:" << value;
- scale_in_double = 1.0;
- }
- }
- return static_cast<float>(scale_in_double);
+ // double scale_in_double = 1.0;
+ // if (HasForceDeviceScaleFactorImpl()) {
+ // std::string value =
+ // base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ // switches::kForceDeviceScaleFactor);
+ // if (!base::StringToDouble(value, &scale_in_double)) {
+ // LOG(ERROR) << "Failed to parse the default device scale factor:" << value;
+ // scale_in_double = 1.0;
+ // }
+ // }
+ return carbonyl::Bridge::GetCurrent()->GetDPI();
}
const char* ToRotationString(display::Display::Rotation rotation) {
@@ -97,11 +99,11 @@ void Display::ResetForceDeviceScaleFactorForTesting() {
// static
void Display::SetForceDeviceScaleFactor(double dsf) {
// Reset any previously set values and unset the flag.
- g_has_forced_device_scale_factor = -1;
- g_forced_device_scale_factor = -1.0;
+ // g_has_forced_device_scale_factor = -1;
+ // g_forced_device_scale_factor = -1.0;
- base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kForceDeviceScaleFactor, base::StringPrintf("%.2f", dsf));
+ // base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ // switches::kForceDeviceScaleFactor, base::StringPrintf("%.2f", dsf));
}
// static
@@ -273,15 +275,15 @@ void Display::SetScaleAndBounds(float device_scale_factor,
}
void Display::SetScale(float device_scale_factor) {
- if (!HasForceDeviceScaleFactor()) {
-#if BUILDFLAG(IS_APPLE)
- // Unless an explicit scale factor was provided for testing, ensure the
- // scale is integral.
- device_scale_factor = static_cast<int>(device_scale_factor);
-#endif
+// if (!HasForceDeviceScaleFactor()) {
+// #if BUILDFLAG(IS_APPLE)
+// // Unless an explicit scale factor was provided for testing, ensure the
+// // scale is integral.
+// device_scale_factor = static_cast<int>(device_scale_factor);
+// #endif
device_scale_factor_ = device_scale_factor;
- }
- device_scale_factor_ = std::max(0.5f, device_scale_factor_);
+ // }
+ // device_scale_factor_ = std::max(0.5f, device_scale_factor_);
}
void Display::SetSize(const gfx::Size& size_in_pixel) {
================================================
FILE: chromium/patches/chromium/0007-Disable-text-effects.patch
================================================
From 022ed4d808369659eab4e83cd677eb974215c58c Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Thu, 9 Feb 2023 03:31:17 +0100
Subject: [PATCH 07/14] Disable text effects
---
.../core/paint/ng/ng_text_painter_base.cc | 30 ++++++++--------
ui/gfx/render_text.cc | 34 +++++++++----------
2 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/third_party/blink/renderer/core/paint/ng/ng_text_painter_base.cc b/third_party/blink/renderer/core/paint/ng/ng_text_painter_base.cc
index 008d80040e719..c11da51d0e906 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_text_painter_base.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_text_painter_base.cc
@@ -123,21 +123,21 @@ void NGTextPainterBase::PaintUnderOrOverLineDecorations(
continue;
}
- if (decoration_info.HasUnderline() && decoration_info.FontData() &&
- EnumHasFlags(lines_to_paint, TextDecorationLine::kUnderline)) {
- decoration_info.SetUnderlineLineData(decoration_offset);
- PaintDecorationUnderOrOverLine(fragment_paint_info, context,
- decoration_info,
- TextDecorationLine::kUnderline, flags);
- }
-
- if (decoration_info.HasOverline() && decoration_info.FontData() &&
- EnumHasFlags(lines_to_paint, TextDecorationLine::kOverline)) {
- decoration_info.SetOverlineLineData(decoration_offset);
- PaintDecorationUnderOrOverLine(fragment_paint_info, context,
- decoration_info,
- TextDecorationLine::kOverline, flags);
- }
+ // if (decoration_info.HasUnderline() && decoration_info.FontData() &&
+ // EnumHasFlags(lines_to_paint, TextDecorationLine::kUnderline)) {
+ // decoration_info.SetUnderlineLineData(decoration_offset);
+ // PaintDecorationUnderOrOverLine(fragment_paint_info, context,
+ // decoration_info,
+ // TextDecorationLine::kUnderline, flags);
+ // }
+
+ // if (decoration_info.HasOverline() && decoration_info.FontData() &&
+ // EnumHasFlags(lines_to_paint, TextDecorationLine::kOverline)) {
+ // decoration_info.SetOverlineLineData(decoration_offset);
+ // PaintDecorationUnderOrOverLine(fragment_paint_info, context,
+ // decoration_info,
+ // TextDecorationLine::kOverline, flags);
+ // }
}
}
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 67fbf128ea158..a645ba61c8597 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -55,9 +55,9 @@ constexpr char16_t kEllipsisCodepoint = 0x2026;
// Fraction of the text size to raise the center of a strike-through line above
// the baseline.
-const SkScalar kStrikeThroughOffset = (SK_Scalar1 * 65 / 252);
+// const SkScalar kStrikeThroughOffset = (SK_Scalar1 * 65 / 252);
// Fraction of the text size to lower an underline below the baseline.
-const SkScalar kUnderlineOffset = (SK_Scalar1 / 9);
+// const SkScalar kUnderlineOffset = (SK_Scalar1 / 9);
// Float comparison needs epsilon to consider rounding errors in float
// arithmetic. Epsilon should be dependent on the context and here, we are
@@ -374,27 +374,27 @@ void SkiaTextRenderer::DrawUnderline(int x,
int y,
int width,
SkScalar thickness_factor) {
- SkScalar x_scalar = SkIntToScalar(x);
- const SkScalar text_size = font_.getSize();
- SkRect r = SkRect::MakeLTRB(
- x_scalar, y + text_size * kUnderlineOffset, x_scalar + width,
- y + (text_size *
- (kUnderlineOffset +
- (thickness_factor * RenderText::kLineThicknessFactor))));
- canvas_skia_->drawRect(r, flags_);
+ // SkScalar x_scalar = SkIntToScalar(x);
+ // const SkScalar text_size = font_.getSize();
+ // SkRect r = SkRect::MakeLTRB(
+ // x_scalar, y + text_size * kUnderlineOffset, x_scalar + width,
+ // y + (text_size *
+ // (kUnderlineOffset +
+ // (thickness_factor * RenderText::kLineThicknessFactor))));
+ // canvas_skia_->drawRect(r, flags_);
}
void SkiaTextRenderer::DrawStrike(int x,
int y,
int width,
SkScalar thickness_factor) {
- const SkScalar text_size = font_.getSize();
- const SkScalar height = text_size * thickness_factor;
- const SkScalar top = y - text_size * kStrikeThroughOffset - height / 2;
- SkScalar x_scalar = SkIntToScalar(x);
- const SkRect r =
- SkRect::MakeLTRB(x_scalar, top, x_scalar + width, top + height);
- canvas_skia_->drawRect(r, flags_);
+ // const SkScalar text_size = font_.getSize();
+ // const SkScalar height = text_size * thickness_factor;
+ // const SkScalar top = y - text_size * kStrikeThroughOffset - height / 2;
+ // SkScalar x_scalar = SkIntToScalar(x);
+ // const SkRect r =
+ // SkRect::MakeLTRB(x_scalar, top, x_scalar + width, top + height);
+ // canvas_skia_->drawRect(r, flags_);
}
StyleIterator::StyleIterator(const BreakList<SkColor>* colors,
================================================
FILE: chromium/patches/chromium/0008-Fix-text-layout.patch
================================================
From 7b1f72900f704ffecc48c66da7ccd6de205b88f7 Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Thu, 9 Feb 2023 03:32:14 +0100
Subject: [PATCH 08/14] Fix text layout
---
.../core/css/resolver/style_resolver.cc | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index 6207b72d17cb9..79cb8c85b697f 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -281,7 +281,9 @@ String ComputeBaseComputedStyleDiff(const ComputedStyle* base_computed_style,
return g_null_atom;
}
- return String("Field diff: ") + builder.ReleaseString();
+ // TODO(fathy): Carbonyl should properly set the computed style
+ // return String("Field diff: ") + builder.ReleaseString();
+ return g_null_atom;
}
#endif // DCHECK_IS_ON()
@@ -1039,6 +1041,19 @@ scoped_refptr<ComputedStyle> StyleResolver::ResolveStyle(
UseCounter::Count(GetDocument(), WebFeature::kHasGlyphRelativeUnits);
}
+ auto font = state.StyleBuilder().GetFontDescription();
+ FontFamily family;
+
+ family.SetFamily("monospace", FontFamily::Type::kGenericFamily);
+ font.SetFamily(family);
+ font.SetStretch(ExtraExpandedWidthValue());
+ font.SetKerning(FontDescription::kNoneKerning);
+ font.SetComputedSize(11.75 / 7.0);
+ font.SetGenericFamily(FontDescription::kMonospaceFamily);
+ font.SetIsAbsoluteSize(true);
+ state.StyleBuilder().SetFontDescription(font);
+ state.StyleBuilder().SetLineHeight(Length::Fixed(14.0 / 7.0));
+
state.LoadPendingResources();
// Now return the style.
================================================
FILE: chromium/patches/chromium/0009-Bridge-browser-into-Carbonyl-library.patch
================================================
From 792e123bb57b1b379b0367b2568302e2cb0dc3c9 Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Thu, 9 Feb 2023 03:32:30 +0100
Subject: [PATCH 09/14] Bridge browser into Carbonyl library
---
headless/app/headless_shell.cc | 33 +-
headless/app/headless_shell_main.cc | 5 +
headless/lib/browser/headless_browser_impl.cc | 406 +++++++++++++++++-
headless/lib/browser/headless_browser_impl.h | 16 +
.../lib/browser/headless_web_contents_impl.cc | 28 ++
.../lib/browser/headless_web_contents_impl.h | 2 +
6 files changed, 462 insertions(+), 28 deletions(-)
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc
index e08385b9cf740..5b51c22ae1da3 100644
--- a/headless/app/headless_shell.cc
+++ b/headless/app/headless_shell.cc
@@ -4,6 +4,8 @@
#include "headless/app/headless_shell.h"
+#include "carbonyl/src/browser/bridge.h"
+
#include <memory>
#include "base/base_switches.h"
@@ -90,6 +92,8 @@ void HeadlessShell::OnBrowserStart(HeadlessBrowser* browser) {
HeadlessBrowserContext::Builder context_builder =
browser_->CreateBrowserContextBuilder();
+ context_builder.SetWindowSize(carbonyl::Renderer::Main()->GetSize());
+
// Retrieve the locale set by InitApplicationLocale() in
// headless_content_main_delegate.cc in a way that is free of side-effects.
context_builder.SetAcceptLanguage(base::i18n::GetConfiguredLocale());
@@ -113,39 +117,14 @@ void HeadlessShell::OnBrowserStart(HeadlessBrowser* browser) {
GURL target_url = ConvertArgumentToURL(args.front());
- // If driven by a debugger just open the target page and
- // leave expecting the debugger will do what they need.
- if (IsRemoteDebuggingEnabled()) {
- HeadlessWebContents::Builder builder(
- browser_context_->CreateWebContentsBuilder());
- HeadlessWebContents* web_contents =
- builder.SetInitialURL(target_url).Build();
- if (!web_contents) {
- LOG(ERROR) << "Navigation to " << target_url << " failed.";
- ShutdownSoon();
- }
- return;
- }
-
- // Otherwise instantiate headless shell command handler that will
- // execute the commands against the target page.
-#if defined(HEADLESS_ENABLE_COMMANDS)
- GURL handler_url = HeadlessCommandHandler::GetHandlerUrl();
HeadlessWebContents::Builder builder(
browser_context_->CreateWebContentsBuilder());
HeadlessWebContents* web_contents =
- builder.SetInitialURL(handler_url).Build();
+ builder.SetInitialURL(target_url).Build();
if (!web_contents) {
- LOG(ERROR) << "Navigation to " << handler_url << " failed.";
+ LOG(ERROR) << "Navigation to " << target_url << " failed.";
ShutdownSoon();
- return;
}
-
- HeadlessCommandHandler::ProcessCommands(
- HeadlessWebContentsImpl::From(web_contents)->web_contents(),
- std::move(target_url),
- base::BindOnce(&HeadlessShell::ShutdownSoon, weak_factory_.GetWeakPtr()));
-#endif
}
void HeadlessShell::ShutdownSoon() {
diff --git a/headless/app/headless_shell_main.cc b/headless/app/headless_shell_main.cc
index 35736145f5caf..f9b8bac5c18a5 100644
--- a/headless/app/headless_shell_main.cc
+++ b/headless/app/headless_shell_main.cc
@@ -13,7 +13,12 @@
#include "sandbox/mac/seatbelt_exec.h"
#endif
+#include "base/at_exit.h"
+#include "carbonyl/src/browser/bridge.h"
+
int main(int argc, const char** argv) {
+ carbonyl_shell_main();
+
#if BUILDFLAG(IS_WIN)
sandbox::SandboxInterfaceInfo sandbox_info = {nullptr};
content::InitializeSandboxInfo(&sandbox_info);
diff --git a/headless/lib/browser/headless_browser_impl.cc b/headless/lib/browser/headless_browser_impl.cc
index 1a1223108be6d..fd45d215479ab 100644
--- a/headless/lib/browser/headless_browser_impl.cc
+++ b/headless/lib/browser/headless_browser_impl.cc
@@ -7,6 +7,8 @@
#include <string>
#include <utility>
#include <vector>
+#include <iostream>
+#include <signal.h>
#include "base/callback_helpers.h"
#include "base/command_line.h"
@@ -27,6 +29,23 @@
#include "services/network/public/cpp/network_switches.h"
#include "ui/events/devices/device_data_manager.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/web_contents.h"
+#include "carbonyl/src/browser/bridge.h"
+#include "third_party/blink/public/common/input/web_mouse_event.h"
+#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+namespace carbonyl {
+
+static unsigned int current_mouse_x = 0;
+static unsigned int current_mouse_y = 0;
+static headless::HeadlessBrowserImpl* browser = nullptr;
+
+}
+
namespace headless {
HeadlessBrowserImpl::HeadlessBrowserImpl(
@@ -38,7 +57,15 @@ HeadlessBrowserImpl::HeadlessBrowserImpl(
default_browser_context_(nullptr),
agent_host_(nullptr) {}
-HeadlessBrowserImpl::~HeadlessBrowserImpl() = default;
+HeadlessBrowserImpl::~HeadlessBrowserImpl() {
+ if (carbonyl::browser == this) {
+ carbonyl::browser = nullptr;
+ }
+
+ if (input_thread_.joinable()) {
+ input_thread_.join();
+ }
+}
HeadlessBrowserContext::Builder
HeadlessBrowserImpl::CreateBrowserContextBuilder() {
@@ -91,6 +118,307 @@ void HeadlessBrowserImpl::set_browser_main_parts(
browser_main_parts_ = browser_main_parts;
}
+void HeadlessBrowserImpl::Resize() {
+ auto size = carbonyl::Renderer::GetSize();
+ auto rect = gfx::Rect(0, 0, size.width(), size.height());
+
+ for (auto* ctx: GetAllBrowserContexts()) {
+ for (auto* contents: ctx->GetAllWebContents()) {
+ auto* impl = HeadlessWebContentsImpl::From(contents);
+
+ if (!impl) {
+ continue;
+ }
+
+ PlatformSetWebContentsBounds(impl, rect);
+ }
+ }
+
+ carbonyl::Renderer::Main()->Resize();
+}
+
+void HeadlessBrowserImpl::OnShutdownInput() {
+ Shutdown();
+}
+void HeadlessBrowserImpl::OnRefreshInput() {
+ for (auto* ctx: GetAllBrowserContexts()) {
+ for (auto* contents: ctx->GetAllWebContents()) {
+ auto* impl = HeadlessWebContentsImpl::From(contents);
+
+ if (!impl) {
+ continue;
+ }
+
+ auto& nav = impl->web_contents()->GetController();
+
+ nav.Reload(content::ReloadType::NORMAL, true);
+ }
+ }
+}
+
+void HeadlessBrowserImpl::OnGoToInput(const char* url_str) {
+ if (!carbonyl::browser) {
+ return;
+ }
+
+ auto ctxs = GetAllBrowserContexts();
+
+ if (ctxs.empty()) {
+ return;
+ }
+
+ auto url = GURL(std::string(url_str));
+
+ if (!url.is_valid() || url.spec().size() > url::kMaxURLChars) {
+ return;
+ }
+
+ auto* ctx = ctxs[0];
+ auto contents = ctx->GetAllWebContents();
+
+ if (contents.empty()) {
+ ctx->CreateWebContentsBuilder().SetInitialURL(url).Build();
+ } else {
+ HeadlessWebContentsImpl::From(contents[0])->OpenURL(url);
+ }
+}
+
+void HeadlessBrowserImpl::OnGoBackInput() {
+ for (auto* ctx: GetAllBrowserContexts()) {
+ for (auto* contents: ctx->GetAllWebContents()) {
+ auto* impl = HeadlessWebContentsImpl::From(contents);
+
+ if (!impl) {
+ continue;
+ }
+
+ auto& nav = impl->web_contents()->GetController();
+
+ if (nav.CanGoBack()) {
+ nav.GoBack();
+ }
+ }
+ }
+}
+void HeadlessBrowserImpl::OnGoForwardInput() {
+ for (auto* ctx: GetAllBrowserContexts()) {
+ for (auto* contents: ctx->GetAllWebContents()) {
+ auto* impl = HeadlessWebContentsImpl::From(contents);
+
+ if (!impl) {
+ continue;
+ }
+
+ auto& nav = impl->web_contents()->GetController();
+
+ if (nav.CanGoForward()) {
+ nav.GoForward();
+ }
+ }
+ }
+}
+
+void HeadlessBrowserImpl::OnScrollInput(int delta) {
+ blink::WebMouseWheelEvent event;
+
+ event.SetType(blink::WebInputEvent::Type::kMouseWheel);
+ event.SetTimeStamp(base::TimeTicks::Now());
+ event.SetPositionInWidget(carbonyl::current_mouse_x, carbonyl::current_mouse_y);
+ event.SetPositionInScreen(carbonyl::current_mouse_x, carbonyl::current_mouse_y);
+
+ event.delta_y = delta;
+ event.phase = blink::WebMouseWheelEvent::kPhaseBegan;
+ event.dispatch_type = blink::WebInputEvent::DispatchType::kBlocking;
+
+ for (auto* ctx: GetAllBrowserContexts()) {
+ for (auto* contents: ctx->GetAllWebContents()) {
+ auto* impl = HeadlessWebContentsImpl::From(contents);
+
+ if (!impl) {
+ continue;
+ }
+
+ auto *host = impl->web_contents()->GetRenderViewHost()->GetWidget();
+
+ if (!host) {
+ continue;
+ }
+
+ host->ForwardWheelEvent(event);
+ }
+ }
+
+ // Send a synthetic wheel event with phaseEnded to finish scrolling.
+ event.delta_y = 0;
+ event.phase = blink::WebMouseWheelEvent::kPhaseEnded;
+ event.dispatch_type = blink::WebInputEvent::DispatchType::kEventNonBlocking;
+ event.has_synthetic_phase = true;
+
+ for (auto* ctx: GetAllBrowserContexts()) {
+ for (auto* contents: ctx->GetAllWebContents()) {
+ auto* impl = HeadlessWebContentsImpl::From(contents);
+
+ if (!impl) {
+ continue;
+ }
+
+ auto *host = impl->web_contents()->GetRenderViewHost()->GetWidget();
+
+ if (!host) {
+ continue;
+ }
+
+ host->ForwardWheelEvent(event);
+ }
+ }
+}
+
+void HeadlessBrowserImpl::OnKeyPressInput(char key) {
+ bool raw = true;
+ content::NativeWebKeyboardEvent event(
+ blink::WebKeyboardEvent::Type::kRawKeyDown,
+ blink::WebInputEvent::kNoModifiers,
+ base::TimeTicks::Now());
+
+ // TODO(fathy): support IME
+ switch (key) {
+ case 0x11:
+ event.windows_key_code = ui::KeyboardCode::VKEY_UP;
+ break;
+ case 0x12:
+ event.windows_key_code = ui::KeyboardCode::VKEY_DOWN;
+ break;
+ case 0x13:
+ event.windows_key_code = ui::KeyboardCode::VKEY_RIGHT;
+ break;
+ case 0x14:
+ event.windows_key_code = ui::KeyboardCode::VKEY_LEFT;
+ break;
+ case 0x7f:
+ event.windows_key_code = ui::KeyboardCode::VKEY_BACK;
+ break;
+ default:
+ raw = false;
+
+ event.text[0] = key;
+ }
+
+ for (auto* ctx: GetAllBrowserContexts()) {
+ for (auto* contents: ctx->GetAllWebContents()) {
+ auto* impl = HeadlessWebContentsImpl::From(contents);
+
+ if (!impl) {
+ continue;
+ }
+
+ auto *host = impl->web_contents()->GetRenderViewHost()->GetWidget();
+
+ if (!host) {
+ continue;
+ }
+
+ event.SetType(
+ raw
+ ? blink::WebKeyboardEvent::Type::kRawKeyDown
+ : blink::WebKeyboardEvent::Type::kKeyDown
+ );
+ host->ForwardKeyboardEvent(event);
+
+ event.SetType(blink::WebKeyboardEvent::Type::kKeyUp);
+ host->ForwardKeyboardEvent(event);
+ }
+ }
+}
+
+void HeadlessBrowserImpl::OnMouseUpInput(unsigned int x, unsigned int y) {
+ for (auto* ctx: GetAllBrowserContexts()) {
+ for (auto* contents: ctx->GetAllWebContents()) {
+ auto* impl = HeadlessWebContentsImpl::From(contents);
+
+ if (!impl) {
+ continue;
+ }
+
+ auto *host = impl->web_contents()->GetRenderViewHost()->GetWidget();
+
+ if (!host) {
+ continue;
+ }
+
+ blink::WebMouseEvent event;
+
+ event.button = blink::WebMouseEvent::Button::kLeft;
+ event.click_count = 1;
+ event.SetType(blink::WebInputEvent::Type::kMouseUp);
+ event.SetTimeStamp(base::TimeTicks::Now());
+ event.SetPositionInWidget(x, y);
+ event.SetPositionInScreen(x, y);
+
+ host->ForwardMouseEvent(event);
+ }
+ }
+}
+
+void HeadlessBrowserImpl::OnMouseDownInput(unsigned int x, unsigned int y) {
+ for (auto* ctx: GetAllBrowserContexts()) {
+ for (auto* contents: ctx->GetAllWebContents()) {
+ auto* impl = HeadlessWebContentsImpl::From(contents);
+
+ if (!impl) {
+ continue;
+ }
+
+ auto *host = impl->web_contents()->GetRenderViewHost()->GetWidget();
+
+ if (!host) {
+ continue;
+ }
+
+ blink::WebMouseEvent event;
+
+ event.button = blink::WebMouseEvent::Button::kLeft;
+ event.click_count = 1;
+ event.SetType(blink::WebInputEvent::Type::kMouseDown);
+ event.SetTimeStamp(base::TimeTicks::Now());
+ event.SetPositionInWidget(x, y);
+ event.SetPositionInScreen(x, y);
+
+ host->ForwardMouseEvent(event);
+ }
+ }
+}
+
+void HeadlessBrowserImpl::OnMouseMoveInput(unsigned int x, unsigned int y) {
+ for (auto* ctx: GetAllBrowserContexts()) {
+ for (auto* contents: ctx->GetAllWebContents()) {
+ auto* impl = HeadlessWebContentsImpl::From(contents);
+
+ if (!impl) {
+ continue;
+ }
+
+ auto *host = impl->web_contents()->GetRenderViewHost()->GetWidget();
+
+ if (!host) {
+ continue;
+ }
+
+ blink::WebMouseEvent event;
+
+ carbonyl::current_mouse_x = x;
+ carbonyl::current_mouse_y = y;
+
+ event.click_count = 1;
+ event.SetType(blink::WebInputEvent::Type::kMouseMove);
+ event.SetTimeStamp(base::TimeTicks::Now());
+ event.SetPositionInWidget(x, y);
+ event.SetPositionInScreen(x, y);
+
+ host->ForwardMouseEvent(event);
+ }
+ }
+}
+
void HeadlessBrowserImpl::RunOnStartCallback() {
// We don't support the tethering domain on this agent host.
agent_host_ = content::DevToolsAgentHost::CreateForBrowser(
@@ -98,6 +426,82 @@ void HeadlessBrowserImpl::RunOnStartCallback() {
PlatformStart();
std::move(on_start_callback_).Run(this);
+
+ signal(SIGWINCH, [](int signal) {
+ if (carbonyl::browser) {
+ carbonyl::browser->Resize();
+ }
+ });
+
+ input_thread_ = std::thread([=]() {
+ carbonyl::browser = this;
+
+ carbonyl_bridge_browser_delegate delegate = {
+ .shutdown = []() {
+ if (carbonyl::browser) {
+ carbonyl::browser->OnShutdownInput();
+ }
+ },
+ .refresh = []() {
+ if (carbonyl::browser) {
+ carbonyl::browser->OnRefreshInput();
+ }
+ },
+ .go_to = [](const char* url) {
+ if (carbonyl::browser) {
+ carbonyl::browser->OnGoToInput(url);
+ }
+ },
+ .go_back = []() {
+ if (carbonyl::browser) {
+ carbonyl::browser->OnGoBackInput();
+ }
+ },
+ .go_forward = []() {
+ if (carbonyl::browser) {
+ carbonyl::browser->OnGoForwardInput();
+ }
+ },
+ .scroll = [](int delta) {
+ if (carbonyl::browser) {
+ carbonyl::browser->OnScrollInput(delta);
+ }
+ },
+ .key_press = [](char key) {
+ if (carbonyl::browser) {
+ carbonyl::browser->OnKeyPressInput(key);
+ }
+ },
+ .mouse_up = [](unsigned int x, unsigned int y) {
+ if (carbonyl::browser) {
+ carbonyl::browser->OnMouseUpInput(x, y);
+ }
+ },
+ .mouse_down = [](unsigned int x, unsigned int y) {
+ if (carbonyl::browser) {
+ carbonyl::browser->OnMouseDownInput(x, y);
+ }
+ },
+ .mouse_move = [](unsigned int x, unsigned int y) {
+ if (carbonyl::browser) {
+ carbonyl::browser->OnMouseMoveInput(x, y);
+ }
+ },
+ .post_task = [](void (*fn)(void*), void* data) {
+ if (carbonyl::browser) {
+ carbonyl::browser->BrowserMainThread()->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ fn,
+ data
+ )
+ );
+ }
+ }
+ };
+
+ carbonyl::Renderer::Main()->Listen(&delegate);
+ });
}
HeadlessBrowserContext* HeadlessBrowserImpl::CreateBrowserContext(
diff --git a/headless/lib/browser/headless_browser_impl.h b/headless/lib/browser/headless_browser_impl.h
index a2d531ab32ff5..963808352c0c4 100644
--- a/headless/lib/browser/headless_browser_impl.h
+++ b/headless/lib/browser/headless_browser_impl.h
@@ -11,6 +11,7 @@
#include <memory>
#include <string>
#include <vector>
+#include <thread>
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
@@ -121,9 +122,24 @@ class HEADLESS_EXPORT HeadlessBrowserImpl : public HeadlessBrowser,
policy::PolicyService* GetPolicyService();
#endif
+ void Resize();
+ void OnShutdownInput();
+ void OnRefreshInput();
+ void OnGoToInput(const char* url);
+ void OnGoBackInput();
+ void OnGoForwardInput();
+ void OnScrollInput(int delta);
+ void OnKeyPressInput(char key);
+ void OnMouseUpInput(unsigned int x, unsigned int y);
+ void OnMouseDownInput(unsigned int x, unsigned int y);
+ void OnMouseMoveInput(unsigned int x, unsigned int y);
+
bool did_shutdown() const { return did_shutdown_; }
protected:
+ // TODO: use base::TaskRunner
+ std::thread input_thread_;
+
#if BUILDFLAG(IS_MAC)
std::unique_ptr<display::ScopedNativeScreen> screen_;
#endif
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
index 010ff2c94287e..fad8c3fdd2bfe 100644
--- a/headless/lib/browser/headless_web_contents_impl.cc
+++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -8,6 +8,7 @@
#include <string>
#include <utility>
#include <vector>
+#include <iostream>
#include "base/bind.h"
#include "base/command_line.h"
@@ -21,10 +22,13 @@
#include "base/values.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
+#include "carbonyl/src/browser/bridge.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_termination_info.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -390,6 +394,30 @@ void HeadlessWebContentsImpl::RenderViewReady() {
devtools_target_ready_notification_sent_ = true;
}
+void HeadlessWebContentsImpl::TitleWasSet(content::NavigationEntry* entry) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ if (!web_contents() || !web_contents()->GetPrimaryMainFrame()->IsActive())
+ return;
+
+ carbonyl::Renderer::Main()->SetTitle(base::UTF16ToUTF8(entry->GetTitleForDisplay()));
+}
+
+void HeadlessWebContentsImpl::DidFinishNavigation(content::NavigationHandle* handle) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ if (!handle->IsInMainFrame() || !web_contents() || !web_contents()->GetPrimaryMainFrame()->IsActive())
+ return;
+
+ auto& nav = web_contents()->GetController();
+
+ carbonyl::Renderer::Main()->PushNav(
+ handle->GetURL().spec(),
+ nav.CanGoBack(),
+ nav.CanGoForward()
+ );
+}
+
int HeadlessWebContentsImpl::GetMainFrameRenderProcessId() const {
if (!web_contents() || !web_contents()->GetPrimaryMainFrame())
return -1;
diff --git a/headless/lib/browser/headless_web_contents_impl.h b/headless/lib/browser/headless_web_contents_impl.h
index b80147fd06be8..09773596aa5ce 100644
--- a/headless/lib/browser/headless_web_contents_impl.h
+++ b/headless/lib/browser/headless_web_contents_impl.h
@@ -91,6 +91,8 @@ class HEADLESS_EXPORT HeadlessWebContentsImpl
void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
void RenderViewReady() override;
+ void TitleWasSet(content::NavigationEntry* entry) override;
+ void DidFinishNavigation(content::NavigationHandle* navigation_handle) override;
content::WebContents* web_contents() const;
bool OpenURL(const GURL& url);
================================================
FILE: chromium/patches/chromium/0010-Conditionally-enable-text-rendering.patch
================================================
From bdc80f35a7113b7523c4d992edc9170db082deb0 Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Sun, 12 Feb 2023 00:55:33 +0100
Subject: [PATCH 10/14] Conditionally enable text rendering
---
content/renderer/render_frame_impl.cc | 3 ++-
.../core/css/resolver/style_resolver.cc | 26 +++++++++++--------
third_party/blink/renderer/platform/BUILD.gn | 1 +
.../blink/renderer/platform/fonts/font.cc | 10 +++----
4 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 97b61ffb954be..891efd6a9d796 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -259,6 +259,7 @@
// Carbonyl
#include <stdlib.h>
#include <iostream>
+#include "carbonyl/src/browser/bridge.h"
#include "cc/paint/paint_recorder.h"
#include "cc/paint/skia_paint_canvas.h"
#include "cc/raster/playback_image_provider.h"
@@ -2221,7 +2222,7 @@ void RenderFrameImpl::Initialize(blink::WebFrame* parent) {
render_callback_ = std::make_shared<std::function<bool()>>(
[=]() -> bool {
- if (!IsMainFrame() || IsHidden()) {
+ if (!IsMainFrame() || IsHidden() || carbonyl::Bridge::BitmapMode()) {
return false;
}
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index 79cb8c85b697f..7129982acf4a6 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -116,6 +116,8 @@
#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "carbonyl/src/browser/bridge.h"
+
namespace blink {
namespace {
@@ -1041,18 +1043,20 @@ scoped_refptr<ComputedStyle> StyleResolver::ResolveStyle(
UseCounter::Count(GetDocument(), WebFeature::kHasGlyphRelativeUnits);
}
- auto font = state.StyleBuilder().GetFontDescription();
- FontFamily family;
+ if (!carbonyl::Bridge::BitmapMode()) {
+ auto font = state.StyleBuilder().GetFontDescription();
+ FontFamily family;
- family.SetFamily("monospace", FontFamily::Type::kGenericFamily);
- font.SetFamily(family);
- font.SetStretch(ExtraExpandedWidthValue());
- font.SetKerning(FontDescription::kNoneKerning);
- font.SetComputedSize(11.75 / 7.0);
- font.SetGenericFamily(FontDescription::kMonospaceFamily);
- font.SetIsAbsoluteSize(true);
- state.StyleBuilder().SetFontDescription(font);
- state.StyleBuilder().SetLineHeight(Length::Fixed(14.0 / 7.0));
+ family.SetFamily("monospace", FontFamily::Type::kGenericFamily);
+ font.SetFamily(family);
+ font.SetStretch(ExtraExpandedWidthValue());
+ font.SetKerning(FontDescription::kNoneKerning);
+ font.SetComputedSize(13.25 / 4.0);
+ font.SetGenericFamily(FontDescription::kMonospaceFamily);
+ font.SetIsAbsoluteSize(true);
+ state.StyleBuilder().SetFontDescription(font);
+ state.StyleBuilder().SetLineHeight(Length::Fixed(16.0 / 4.0));
+ }
state.LoadPendingResources();
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index e7b1c1a52e4c9..63fc13e44b5ae 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1678,6 +1678,7 @@ component("platform") {
"//base/allocator:buildflags",
"//build:chromecast_buildflags",
"//build:chromeos_buildflags",
+ "//carbonyl/src/browser:carbonyl",
"//cc/ipc",
"//cc/mojo_embedder",
"//components/paint_preview/common",
diff --git a/third_party/blink/renderer/platform/fonts/font.cc b/third_party/blink/renderer/platform/fonts/font.cc
index dfdc79eacce3b..4625300729523 100644
--- a/third_party/blink/renderer/platform/fonts/font.cc
+++ b/third_party/blink/renderer/platform/fonts/font.cc
@@ -49,6 +49,8 @@
#include "third_party/skia/include/core/SkTextBlob.h"
#include "ui/gfx/geometry/rect_f.h"
+#include "carbonyl/src/browser/bridge.h"
+
namespace blink {
namespace {
@@ -151,14 +153,12 @@ bool Font::operator==(const Font& other) const {
namespace {
-static const bool carbonyl_b64_text = true;
-
void DrawBlobs(cc::PaintCanvas* canvas,
const cc::PaintFlags& flags,
const ShapeResultBloberizer::BlobBuffer& blobs,
const gfx::PointF& point,
cc::NodeId node_id = cc::kInvalidNodeId) {
- if (carbonyl_b64_text) {
+ if (!carbonyl::Bridge::BitmapMode()) {
return;
}
@@ -237,7 +237,7 @@ void Font::DrawText(cc::PaintCanvas* canvas,
if (ShouldSkipDrawing())
return;
- if (carbonyl_b64_text) {
+ if (!carbonyl::Bridge::BitmapMode()) {
auto string = StringView(
run_info.run.ToStringView(),
run_info.from,
@@ -285,7 +285,7 @@ void Font::DrawText(cc::PaintCanvas* canvas,
if (ShouldSkipDrawing())
return;
- if (carbonyl_b64_text) {
+ if (!carbonyl::Bridge::BitmapMode()) {
auto string = StringView(
text_info.text,
text_info.from,
================================================
FILE: chromium/patches/chromium/0011-Rename-carbonyl-Renderer-to-carbonyl-Bridge.patch
================================================
From fa52dbb68b7822ee4c01a697197e68ef1ab4a19c Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Sun, 12 Feb 2023 01:29:05 +0100
Subject: [PATCH 11/14] Rename carbonyl::Renderer to carbonyl::Bridge
---
headless/app/headless_shell.cc | 5 ++++-
headless/app/headless_shell_main.cc | 2 +-
headless/lib/browser/headless_browser_impl.cc | 8 ++++----
headless/lib/browser/headless_browser_impl_aura.cc | 2 +-
headless/lib/browser/headless_screen.cc | 2 +-
headless/lib/browser/headless_web_contents_impl.cc | 4 ++--
6 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc
index 5b51c22ae1da3..b6a52857e8f90 100644
--- a/headless/app/headless_shell.cc
+++ b/headless/app/headless_shell.cc
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
+#include "base/functional/callback.h"
#include "base/i18n/rtl.h"
#include "base/task/thread_pool.h"
#include "build/branding_buildflags.h"
@@ -92,7 +93,9 @@ void HeadlessShell::OnBrowserStart(HeadlessBrowser* browser) {
HeadlessBrowserContext::Builder context_builder =
browser_->CreateBrowserContextBuilder();
- context_builder.SetWindowSize(carbonyl::Renderer::Main()->GetSize());
+ carbonyl::Bridge::GetCurrent()->StartRenderer();
+
+ context_builder.SetWindowSize(carbonyl::Bridge::GetCurrent()->GetSize());
// Retrieve the locale set by InitApplicationLocale() in
// headless_content_main_delegate.cc in a way that is free of side-effects.
diff --git a/headless/app/headless_shell_main.cc b/headless/app/headless_shell_main.cc
index f9b8bac5c18a5..739df1ae1bd58 100644
--- a/headless/app/headless_shell_main.cc
+++ b/headless/app/headless_shell_main.cc
@@ -17,7 +17,7 @@
#include "carbonyl/src/browser/bridge.h"
int main(int argc, const char** argv) {
- carbonyl_shell_main();
+ carbonyl::Bridge::Main();
#if BUILDFLAG(IS_WIN)
sandbox::SandboxInterfaceInfo sandbox_info = {nullptr};
diff --git a/headless/lib/browser/headless_browser_impl.cc b/headless/lib/browser/headless_browser_impl.cc
index fd45d215479ab..1df3ffe72c93d 100644
--- a/headless/lib/browser/headless_browser_impl.cc
+++ b/headless/lib/browser/headless_browser_impl.cc
@@ -119,7 +119,7 @@ void HeadlessBrowserImpl::set_browser_main_parts(
}
void HeadlessBrowserImpl::Resize() {
- auto size = carbonyl::Renderer::GetSize();
+ auto size = carbonyl::Bridge::GetCurrent()->Resize();
auto rect = gfx::Rect(0, 0, size.width(), size.height());
for (auto* ctx: GetAllBrowserContexts()) {
@@ -134,7 +134,7 @@ void HeadlessBrowserImpl::Resize() {
}
}
- carbonyl::Renderer::Main()->Resize();
+ carbonyl::Bridge::GetCurrent()->Resize();
}
void HeadlessBrowserImpl::OnShutdownInput() {
@@ -279,7 +279,7 @@ void HeadlessBrowserImpl::OnKeyPressInput(char key) {
blink::WebKeyboardEvent::Type::kRawKeyDown,
blink::WebInputEvent::kNoModifiers,
base::TimeTicks::Now());
-
+
// TODO(fathy): support IME
switch (key) {
case 0x11:
@@ -500,7 +500,7 @@ void HeadlessBrowserImpl::RunOnStartCallback() {
}
};
- carbonyl::Renderer::Main()->Listen(&delegate);
+ carbonyl::Bridge::GetCurrent()->Listen(&delegate);
});
}
diff --git a/headless/lib/browser/headless_browser_impl_aura.cc b/headless/lib/browser/headless_browser_impl_aura.cc
index 508660db32151..80340d9f1b3b3 100644
--- a/headless/lib/browser/headless_browser_impl_aura.cc
+++ b/headless/lib/browser/headless_browser_impl_aura.cc
@@ -59,7 +59,7 @@ void HeadlessBrowserImpl::PlatformSetWebContentsBounds(
const gfx::Rect& bounds) {
// Browser's window bounds should contain all web contents, so that we're sure
// that we will actually produce visible damage when taking a screenshot.
- web_contents->window_tree_host()->SetBoundsInPixels(ScaleToEnclosedRect(bounds, carbonyl::Renderer::GetDPI()));
+ web_contents->window_tree_host()->SetBoundsInPixels(ScaleToEnclosedRect(bounds, carbonyl::Bridge::GetCurrent()->GetDPI()));
web_contents->window_tree_host()->window()->SetBounds(bounds);
gfx::NativeView native_view = web_contents->web_contents()->GetNativeView();
diff --git a/headless/lib/browser/headless_screen.cc b/headless/lib/browser/headless_screen.cc
index 8bf00ef5e036a..89c5ccc8d7759 100644
--- a/headless/lib/browser/headless_screen.cc
+++ b/headless/lib/browser/headless_screen.cc
@@ -51,7 +51,7 @@ display::Display HeadlessScreen::GetDisplayNearestWindow(
HeadlessScreen::HeadlessScreen(const gfx::Rect& screen_bounds) {
static int64_t synthesized_display_id = 2000;
display::Display display(synthesized_display_id++);
- float dpi = carbonyl::Renderer::GetDPI();
+ float dpi = carbonyl::Bridge::GetCurrent()->GetDPI();
display.SetScaleAndBounds(dpi, ScaleToEnclosedRect(screen_bounds, dpi));
ProcessDisplayChanged(display, true /* is_primary */);
}
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
index fad8c3fdd2bfe..a166a08f6ea15 100644
--- a/headless/lib/browser/headless_web_contents_impl.cc
+++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -400,7 +400,7 @@ void HeadlessWebContentsImpl::TitleWasSet(content::NavigationEntry* entry) {
if (!web_contents() || !web_contents()->GetPrimaryMainFrame()->IsActive())
return;
- carbonyl::Renderer::Main()->SetTitle(base::UTF16ToUTF8(entry->GetTitleForDisplay()));
+ carbonyl::Bridge::GetCurrent()->SetTitle(base::UTF16ToUTF8(entry->GetTitleForDisplay()));
}
void HeadlessWebContentsImpl::DidFinishNavigation(content::NavigationHandle* handle) {
@@ -411,7 +411,7 @@ void HeadlessWebContentsImpl::DidFinishNavigation(content::NavigationHandle* han
auto& nav = web_contents()->GetController();
- carbonyl::Renderer::Main()->PushNav(
+ carbonyl::Bridge::GetCurrent()->PushNav(
handle->GetURL().spec(),
nav.CanGoBack(),
nav.CanGoForward()
================================================
FILE: chromium/patches/chromium/0012-Create-separate-bridge-for-Blink.patch
================================================
From 6862e372717eff278470453e800dc693f33b873c Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Sun, 12 Feb 2023 02:20:32 +0100
Subject: [PATCH 12/14] Create separate bridge for Blink
---
.../blink/renderer/core/css/resolver/style_resolver.cc | 4 ++--
third_party/blink/renderer/platform/BUILD.gn | 2 +-
third_party/blink/renderer/platform/fonts/font.cc | 8 ++++----
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index 7129982acf4a6..cb116ee07c8f6 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -116,7 +116,7 @@
#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-#include "carbonyl/src/browser/bridge.h"
+#include "carbonyl/src/browser/blink.h"
namespace blink {
@@ -1043,7 +1043,7 @@ scoped_refptr<ComputedStyle> StyleResolver::ResolveStyle(
UseCounter::Count(GetDocument(), WebFeature::kHasGlyphRelativeUnits);
}
- if (!carbonyl::Bridge::BitmapMode()) {
+ if (!carbonyl::blink::BitmapMode()) {
auto font = state.StyleBuilder().GetFontDescription();
FontFamily family;
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 63fc13e44b5ae..ceb41d781acf6 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1678,7 +1678,7 @@ component("platform") {
"//base/allocator:buildflags",
"//build:chromecast_buildflags",
"//build:chromeos_buildflags",
- "//carbonyl/src/browser:carbonyl",
+ "//carbonyl/src/browser:blink",
"//cc/ipc",
"//cc/mojo_embedder",
"//components/paint_preview/common",
diff --git a/third_party/blink/renderer/platform/fonts/font.cc b/third_party/blink/renderer/platform/fonts/font.cc
index 4625300729523..3d1b463e9651c 100644
--- a/third_party/blink/renderer/platform/fonts/font.cc
+++ b/third_party/blink/renderer/platform/fonts/font.cc
@@ -49,7 +49,7 @@
#include "third_party/skia/include/core/SkTextBlob.h"
#include "ui/gfx/geometry/rect_f.h"
-#include "carbonyl/src/browser/bridge.h"
+#include "carbonyl/src/browser/blink.h"
namespace blink {
@@ -158,7 +158,7 @@ void DrawBlobs(cc::PaintCanvas* canvas,
const ShapeResultBloberizer::BlobBuffer& blobs,
const gfx::PointF& point,
cc::NodeId node_id = cc::kInvalidNodeId) {
- if (!carbonyl::Bridge::BitmapMode()) {
+ if (!carbonyl::blink::BitmapMode()) {
return;
}
@@ -237,7 +237,7 @@ void Font::DrawText(cc::PaintCanvas* canvas,
if (ShouldSkipDrawing())
return;
- if (!carbonyl::Bridge::BitmapMode()) {
+ if (!carbonyl::blink::BitmapMode()) {
auto string = StringView(
run_info.run.ToStringView(),
run_info.from,
@@ -285,7 +285,7 @@ void Font::DrawText(cc::PaintCanvas* canvas,
if (ShouldSkipDrawing())
return;
- if (!carbonyl::Bridge::BitmapMode()) {
+ if (!carbonyl::blink::BitmapMode()) {
auto string = StringView(
text_info.text,
text_info.from,
================================================
FILE: chromium/patches/chromium/0013-Refactor-rendering-bridge.patch
================================================
From 3b67b346ec26a47b50178124d715a8320f612d4d Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Mon, 13 Feb 2023 16:28:50 +0100
Subject: [PATCH 13/14] Refactor rendering bridge
---
components/viz/service/BUILD.gn | 3 +
.../output_surface_provider_impl.cc | 2 +-
.../software_output_device_proxy.cc | 155 ++++++++++++++++++
.../software_output_device_proxy.h | 91 ++++++++++
content/browser/BUILD.gn | 2 +
.../browser/web_contents/web_contents_impl.cc | 4 +-
.../browser/web_contents/web_contents_impl.h | 2 +-
content/public/browser/web_contents.h | 3 +
content/renderer/BUILD.gn | 3 +
content/renderer/render_frame_impl.cc | 5 +
headless/BUILD.gn | 10 +-
headless/app/headless_shell.cc | 6 +-
headless/app/headless_shell_main.cc | 4 +-
headless/lib/browser/headless_browser_impl.cc | 12 +-
.../lib/browser/headless_browser_impl_aura.cc | 2 +-
.../lib/browser/headless_browser_impl_mac.mm | 9 +-
.../headless_browser_main_parts_mac.mm | 9 +
headless/lib/browser/headless_screen.cc | 28 +++-
headless/lib/browser/headless_screen.h | 8 +-
.../lib/browser/headless_web_contents_impl.cc | 8 +-
printing/printing_context_mac.mm | 2 +
third_party/blink/renderer/core/BUILD.gn | 1 +
.../core/css/resolver/style_resolver.cc | 4 +-
third_party/blink/renderer/platform/BUILD.gn | 2 +-
.../blink/renderer/platform/fonts/font.cc | 8 +-
ui/display/BUILD.gn | 1 +
ui/display/display.cc | 51 +-----
27 files changed, 351 insertions(+), 84 deletions(-)
create mode 100644 components/viz/service/display_embedder/software_output_device_proxy.cc
create mode 100644 components/viz/service/display_embedder/software_output_device_proxy.h
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index fb793e98d5939..e1b4dfa4cd49f 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -139,6 +139,8 @@ viz_component("service") {
"display_embedder/skia_render_copy_results.h",
"display_embedder/software_output_surface.cc",
"display_embedder/software_output_surface.h",
+ "display_embedder/software_output_device_proxy.cc",
+ "display_embedder/software_output_device_proxy.h",
"display_embedder/vsync_parameter_listener.cc",
"display_embedder/vsync_parameter_listener.h",
"frame_sinks/begin_frame_tracker.cc",
@@ -229,6 +231,7 @@ viz_component("service") {
"//build:chromeos_buildflags",
"//cc/base",
"//cc/paint",
+ "//carbonyl/src/browser:viz",
"//components/crash/core/common:crash_key",
"//components/power_scheduler",
diff --git a/components/viz/service/display_embedder/output_surface_provider_impl.cc b/components/viz/service/display_embedder/output_surface_provider_impl.cc
index 2929ebd3887c2..cd6f81dfa8b1d 100644
--- a/components/viz/service/display_embedder/output_surface_provider_impl.cc
+++ b/components/viz/service/display_embedder/output_surface_provider_impl.cc
@@ -16,7 +16,6 @@
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
#include "build/chromeos_buildflags.h"
-#include "carbonyl/src/browser/software_output_device_proxy.h"
#include "cc/base/switches.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
@@ -24,6 +23,7 @@
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/display_embedder/skia_output_surface_dependency_impl.h"
#include "components/viz/service/display_embedder/skia_output_surface_impl.h"
+#include "components/viz/service/display_embedder/software_output_device_proxy.h"
#include "components/viz/service/display_embedder/software_output_surface.h"
#include "components/viz/service/gl/gpu_service_impl.h"
#include "gpu/command_buffer/client/shared_memory_limits.h"
diff --git a/components/viz/service/display_embedder/software_output_device_proxy.cc b/components/viz/service/display_embedder/software_output_device_proxy.cc
new file mode 100644
index 0000000000000..a61668050cf0e
--- /dev/null
+++ b/components/viz/service/display_embedder/software_output_device_proxy.cc
@@ -0,0 +1,155 @@
+#include "components/viz/service/display_embedder/software_output_device_proxy.h"
+
+#include "base/memory/unsafe_shared_memory_region.h"
+#include "base/threading/thread_checker.h"
+#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
+#include "components/viz/common/resources/resource_sizes.h"
+#include "components/viz/service/display_embedder/output_device_backing.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
+#include "skia/ext/platform_canvas.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "ui/gfx/skia_util.h"
+
+#if BUILDFLAG(IS_WIN)
+#include "skia/ext/skia_utils_win.h"
+#include "ui/gfx/gdi_util.h"
+#include "ui/gfx/win/hwnd_util.h"
+#else
+#include "mojo/public/cpp/base/shared_memory_utils.h"
+#endif
+
+namespace viz {
+
+SoftwareOutputDeviceBase::~SoftwareOutputDeviceBase() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(!in_paint_);
+}
+
+void SoftwareOutputDeviceBase::Resize(const gfx::Size& viewport_pixel_size,
+ float scale_factor) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(!in_paint_);
+
+ if (viewport_pixel_size_ == viewport_pixel_size)
+ return;
+
+ viewport_pixel_size_ = viewport_pixel_size;
+ ResizeDelegated();
+}
+
+SkCanvas* SoftwareOutputDeviceBase::BeginPaint(
+ const gfx::Rect& damage_rect) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(!in_paint_);
+
+ damage_rect_ = damage_rect;
+ in_paint_ = true;
+ return BeginPaintDelegated();
+}
+
+void SoftwareOutputDeviceBase::EndPaint() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(in_paint_);
+
+ in_paint_ = false;
+
+ gfx::Rect intersected_damage_rect = damage_rect_;
+ intersected_damage_rect.Intersect(gfx::Rect(viewport_pixel_size_));
+ if (intersected_damage_rect.IsEmpty())
+ return;
+
+ EndPaintDelegated(intersected_damage_rect);
+}
+
+SoftwareOutputDeviceProxy::~SoftwareOutputDeviceProxy() = default;
+
+SoftwareOutputDeviceProxy::SoftwareOutputDeviceProxy(
+ mojo::PendingRemote<mojom::LayeredWindowUpdater> layered_window_updater)
+ : layered_window_updater_(std::move(layered_window_updater)) {
+ DCHECK(layered_window_updater_.is_bound());
+}
+
+void SoftwareOutputDeviceProxy::OnSwapBuffers(
+ SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback,
+ gfx::FrameData data) {
+ DCHECK(swap_ack_callback_.is_null());
+
+ // We aren't waiting on DrawAck() and can immediately run the callback.
+ if (!waiting_on_draw_ack_) {
+ task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(std::move(swap_ack_callback), viewport_pixel_size_));
+ return;
+ }
+
+ swap_ack_callback_ = std::move(swap_ack_callback);
+}
+
+void SoftwareOutputDeviceProxy::ResizeDelegated() {
+ canvas_.reset();
+
+ size_t required_bytes;
+ if (!ResourceSizes::MaybeSizeInBytes(
+ viewport_pixel_size_, ResourceFormat::RGBA_8888, &required_bytes)) {
+ DLOG(ERROR) << "Invalid viewport size " << viewport_pixel_size_.ToString();
+ return;
+ }
+
+ base::UnsafeSharedMemoryRegion region =
+ base::UnsafeSharedMemoryRegion::Create(required_bytes);
+ if (!region.IsValid()) {
+ DLOG(ERROR) << "Failed to allocate " << required_bytes << " bytes";
+ return;
+ }
+
+ #if defined(WIN32)
+ canvas_ = skia::CreatePlatformCanvasWithSharedSection(
+ viewport_pixel_size_.width(), viewport_pixel_size_.height(), false,
+ region.GetPlatformHandle(), skia::CRASH_ON_FAILURE);
+ #else
+ shm_mapping_ = region.Map();
+ if (!shm_mapping_.IsValid()) {
+ DLOG(ERROR) << "Failed to map " << required_bytes << " bytes";
+ return;
+ }
+
+ canvas_ = skia::CreatePlatformCanvasWithPixels(
+ viewport_pixel_size_.width(), viewport_pixel_size_.height(), false,
+ static_cast<uint8_t*>(shm_mapping_.memory()), skia::CRASH_ON_FAILURE);
+ #endif
+
+ // Transfer region ownership to the browser process.
+ layered_window_updater_->OnAllocatedSharedMemory(viewport_pixel_size_,
+ std::move(region));
+}
+
+SkCanvas* SoftwareOutputDeviceProxy::BeginPaintDelegated() {
+ return canvas_.get();
+}
+
+void SoftwareOutputDeviceProxy::EndPaintDelegated(
+ const gfx::Rect& damage_rect) {
+ DCHECK(!waiting_on_draw_ack_);
+
+ if (!canvas_)
+ return;
+
+ layered_window_updater_->Draw(damage_rect, base::BindOnce(
+ &SoftwareOutputDeviceProxy::DrawAck, base::Unretained(this)));
+ waiting_on_draw_ack_ = true;
+
+ TRACE_EVENT_ASYNC_BEGIN0("viz", "SoftwareOutputDeviceProxy::Draw", this);
+}
+
+void SoftwareOutputDeviceProxy::DrawAck() {
+ DCHECK(waiting_on_draw_ack_);
+ DCHECK(!swap_ack_callback_.is_null());
+
+ TRACE_EVENT_ASYNC_END0("viz", "SoftwareOutputDeviceProxy::Draw", this);
+
+ waiting_on_draw_ack_ = false;
+ std::move(swap_ack_callback_).Run(viewport_pixel_size_);
+}
+
+} // namespace viz
diff --git a/components/viz/service/display_embedder/software_output_device_proxy.h b/components/viz/service/display_embedder/software_output_device_proxy.h
new file mode 100644
index 0000000000000..4f0a64830b18b
--- /dev/null
+++ b/components/viz/service/display_embedder/software_output_device_proxy.h
@@ -0,0 +1,91 @@
+#ifndef CARBONYL_SRC_BROWSER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
+#define CARBONYL_SRC_BROWSER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
+
+#include <memory>
+
+#include "base/memory/shared_memory_mapping.h"
+#include "base/threading/thread_checker.h"
+#include "build/build_config.h"
+#include "components/viz/host/host_display_client.h"
+#include "components/viz/service/display/software_output_device.h"
+#include "components/viz/service/viz_service_export.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/viz/privileged/mojom/compositing/display_private.mojom.h"
+#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
+
+#if BUILDFLAG(IS_WIN)
+#include <windows.h>
+#endif
+
+namespace viz {
+
+// Shared base class for SoftwareOutputDevice implementations.
+class SoftwareOutputDeviceBase : public SoftwareOutputDevice {
+ public:
+ SoftwareOutputDeviceBase() = default;
+ ~SoftwareOutputDeviceBase() override;
+
+ SoftwareOutputDeviceBase(const SoftwareOutputDeviceBase&) = delete;
+ SoftwareOutputDeviceBase& operator=(const SoftwareOutputDeviceBase&) = delete;
+
+ // SoftwareOutputDevice implementation.
+ void Resize(const gfx::Size& viewport_pixel_size,
+ float scale_factor) override;
+ SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
+ void EndPaint() override;
+
+ // Called from Resize() if |viewport_pixel_size_| has changed.
+ virtual void ResizeDelegated() = 0;
+
+ // Called from BeginPaint() and should return an SkCanvas.
+ virtual SkCanvas* BeginPaintDelegated() = 0;
+
+ // Called from EndPaint() if there is damage.
+ virtual void EndPaintDelegated(const gfx::Rect& damage_rect) = 0;
+
+ private:
+ bool in_paint_ = false;
+
+ THREAD_CHECKER(thread_checker_);
+};
+
+// SoftwareOutputDevice implementation that draws indirectly. An implementation
+// of mojom::LayeredWindowUpdater in the browser process handles the actual
+// drawing. Pixel backing is in SharedMemory so no copying between processes
+// is required.
+class SoftwareOutputDeviceProxy : public SoftwareOutputDeviceBase {
+ public:
+ explicit SoftwareOutputDeviceProxy(
+ mojo::PendingRemote<mojom::LayeredWindowUpdater> layered_window_updater);
+ ~SoftwareOutputDeviceProxy() override;
+
+ SoftwareOutputDeviceProxy(const SoftwareOutputDeviceProxy&) = delete;
+ SoftwareOutputDeviceProxy& operator=(const SoftwareOutputDeviceProxy&) = delete;
+
+ // SoftwareOutputDevice implementation.
+ void OnSwapBuffers(SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback, gfx::FrameData data) override;
+
+ // SoftwareOutputDeviceBase implementation.
+ void ResizeDelegated() override;
+ SkCanvas* BeginPaintDelegated() override;
+ void EndPaintDelegated(const gfx::Rect& rect) override;
+
+ private:
+ // Runs |swap_ack_callback_| after draw has happened.
+ void DrawAck();
+
+ mojo::Remote<mojom::LayeredWindowUpdater> layered_window_updater_;
+
+ std::unique_ptr<SkCanvas> canvas_;
+ bool waiting_on_draw_ack_ = false;
+ SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback_;
+
+#if !defined(WIN32)
+ base::WritableSharedMemoryMapping shm_mapping_;
+#endif
+};
+
+} // namespace viz
+
+#endif // CARBONYL_SRC_BROWSER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index aff547e8e5ed0..d2645a0be3008 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -69,6 +69,8 @@ source_set("browser") {
"//build:chromecast_buildflags",
"//build:chromeos_buildflags",
"//build/config/compiler:compiler_buildflags",
+ "//carbonyl/src/browser:renderer",
+ "//carbonyl/src/browser:viz",
"//cc",
"//cc/animation",
"//cc/mojo_embedder",
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 4eb891c32b474..6ae4005040371 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1650,7 +1650,7 @@ void WebContentsImpl::OnScreensChange(bool is_multi_screen_changed) {
// Mac display info may originate from a remote process hosting the NSWindow;
// this local process display::Screen signal should not trigger updates.
// TODO(crbug.com/1169291): Unify screen info plumbing, caching, etc.
-#if !BUILDFLAG(IS_MAC)
+// #if !BUILDFLAG(IS_MAC)
// This updates Screen attributes and fires Screen.change events as needed,
// propagating to all widgets through the VisualProperties update waterfall.
// This is triggered by system changes, not renderer IPC, so explicitly check
@@ -1662,7 +1662,7 @@ void WebContentsImpl::OnScreensChange(bool is_multi_screen_changed) {
if (!view->IsRenderWidgetHostViewChildFrame())
view->UpdateScreenInfo();
}
-#endif // !BUILDFLAG(IS_MAC)
+// #endif // !BUILDFLAG(IS_MAC)
}
void WebContentsImpl::OnScreenOrientationChange() {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 3f0ecf8749e44..196c3174e20f1 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -265,7 +265,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// Called on screen information changes; |is_multi_screen_changed| is true iff
// the plurality of connected screens changed (e.g. 1 screen <-> 2 screens).
- void OnScreensChange(bool is_multi_screen_changed);
+ void OnScreensChange(bool is_multi_screen_changed) override;
void OnScreenOrientationChange();
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 1fd156150b6b5..60be0bf1bda48 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -344,6 +344,9 @@ class WebContents : public PageNavigator,
~WebContents() override = default;
+ // Carbonyl patches
+ virtual void OnScreensChange(bool is_multi_screen_changed) = 0;
+
// Intrinsic tab state -------------------------------------------------------
// Gets/Sets the delegate.
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 2a2410d4a46c1..1900c294f2f65 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -229,6 +229,9 @@ target(link_target_type, "renderer") {
"//base:i18n",
"//build:chromecast_buildflags",
"//build:chromeos_buildflags",
+ "//carbonyl/src/browser:bridge",
+ "//carbonyl/src/browser:mojom",
+ "//carbonyl/src/browser:renderer",
"//cc",
"//cc/animation",
"//cc/mojo_embedder",
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 891efd6a9d796..379cf6c58b2b0 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -285,6 +285,7 @@
#include "third_party/skia/include/svg/SkSVGCanvas.h"
#include "third_party/skia/include/utils/SkBase64.h"
#include "third_party/skia/src/text/GlyphRun.h"
+#include "third_party/skia/src/core/SkBitmapDevice.h"
#include "third_party/skia/src/core/SkClipStackDevice.h"
#include "third_party/skia/src/core/SkDevice.h"
#include "third_party/skia/src/core/SkFontPriv.h"
@@ -2243,6 +2244,10 @@ void RenderFrameImpl::Initialize(blink::WebFrame* parent) {
);
host->ObserveTerminalRender(render_callback_);
+
+ if (!carbonyl::Bridge::BitmapMode()) {
+ SkBitmapDevice::DisableTextRendering();
+ }
}
void RenderFrameImpl::GetInterface(
diff --git a/headless/BUILD.gn b/headless/BUILD.gn
index 8018111ed9898..17120c83ee13e 100644
--- a/headless/BUILD.gn
+++ b/headless/BUILD.gn
@@ -349,6 +349,8 @@ component("headless_non_renderer") {
"lib/browser/headless_platform_event_source.h",
"lib/browser/headless_request_context_manager.cc",
"lib/browser/headless_request_context_manager.h",
+ "lib/browser/headless_screen.cc",
+ "lib/browser/headless_screen.h",
"lib/browser/headless_select_file_dialog_factory.cc",
"lib/browser/headless_select_file_dialog_factory.h",
"lib/browser/headless_web_contents_impl.cc",
@@ -416,8 +418,6 @@ component("headless_non_renderer") {
"lib/browser/headless_clipboard.h",
"lib/browser/headless_focus_client.cc",
"lib/browser/headless_focus_client.h",
- "lib/browser/headless_screen.cc",
- "lib/browser/headless_screen.h",
"lib/browser/headless_window_parenting_client.cc",
"lib/browser/headless_window_parenting_client.h",
"lib/browser/headless_window_tree_host.cc",
@@ -453,7 +453,8 @@ component("headless_non_renderer") {
"//build:branding_buildflags",
"//build:branding_buildflags",
"//build:chromeos_buildflags",
- "//carbonyl/src/browser:carbonyl",
+ "//carbonyl/src/browser:bridge",
+ "//carbonyl/src/browser:renderer",
"//components/cookie_config",
"//components/crash/core/common:common",
"//components/embedder_support",
@@ -474,6 +475,7 @@ component("headless_non_renderer") {
"//components/profile_metrics",
"//components/profile_metrics:profile_metrics",
"//components/security_state/core",
+ "//components/zoom",
"//content/public/app",
"//content/public/app:app",
"//content/public/browser",
@@ -1011,7 +1013,7 @@ executable("headless_shell") {
deps = [
":headless_shell_lib",
- "//carbonyl/src/browser:carbonyl",
+ "//carbonyl/src/browser:renderer",
]
if (!headless_use_embedded_resources) {
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc
index b6a52857e8f90..6aed55bd6062d 100644
--- a/headless/app/headless_shell.cc
+++ b/headless/app/headless_shell.cc
@@ -4,7 +4,7 @@
#include "headless/app/headless_shell.h"
-#include "carbonyl/src/browser/bridge.h"
+#include "carbonyl/src/browser/renderer.h"
#include <memory>
@@ -93,9 +93,9 @@ void HeadlessShell::OnBrowserStart(HeadlessBrowser* browser) {
HeadlessBrowserContext::Builder context_builder =
browser_->CreateBrowserContextBuilder();
- carbonyl::Bridge::GetCurrent()->StartRenderer();
+ carbonyl::Renderer::GetCurrent()->StartRenderer();
- context_builder.SetWindowSize(carbonyl::Bridge::GetCurrent()->GetSize());
+ context_builder.SetWindowSize(carbonyl::Renderer::GetCurrent()->GetSize());
// Retrieve the locale set by InitApplicationLocale() in
// headless_content_main_delegate.cc in a way that is free of side-effects.
diff --git a/headless/app/headless_shell_main.cc b/headless/app/headless_shell_main.cc
index 739df1ae1bd58..1f6184af60ef0 100644
--- a/headless/app/headless_shell_main.cc
+++ b/headless/app/headless_shell_main.cc
@@ -14,10 +14,10 @@
#endif
#include "base/at_exit.h"
-#include "carbonyl/src/browser/bridge.h"
+#include "carbonyl/src/browser/renderer.h"
int main(int argc, const char** argv) {
- carbonyl::Bridge::Main();
+ carbonyl::Renderer::Main();
#if BUILDFLAG(IS_WIN)
sandbox::SandboxInterfaceInfo sandbox_info = {nullptr};
diff --git a/headless/lib/browser/headless_browser_impl.cc b/headless/lib/browser/headless_browser_impl.cc
index 1df3ffe72c93d..5aa0bdc25e409 100644
--- a/headless/lib/browser/headless_browser_impl.cc
+++ b/headless/lib/browser/headless_browser_impl.cc
@@ -15,6 +15,7 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "components/zoom/zoom_controller.h"
#include "content/public/app/content_main.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -24,9 +25,11 @@
#include "headless/lib/browser/headless_browser_context_impl.h"
#include "headless/lib/browser/headless_browser_main_parts.h"
#include "headless/lib/browser/headless_devtools_agent_host_client.h"
+#include "headless/lib/browser/headless_screen.h"
#include "headless/lib/browser/headless_web_contents_impl.h"
#include "net/http/http_util.h"
#include "services/network/public/cpp/network_switches.h"
+#include "ui/compositor/compositor.h"
#include "ui/events/devices/device_data_manager.h"
#include "content/public/browser/render_frame_host.h"
@@ -34,6 +37,7 @@
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
#include "carbonyl/src/browser/bridge.h"
+#include "carbonyl/src/browser/renderer.h"
#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
#include "ui/events/keycodes/keyboard_codes.h"
@@ -119,7 +123,7 @@ void HeadlessBrowserImpl::set_browser_main_parts(
}
void HeadlessBrowserImpl::Resize() {
- auto size = carbonyl::Bridge::GetCurrent()->Resize();
+ auto size = carbonyl::Renderer::GetCurrent()->Resize();
auto rect = gfx::Rect(0, 0, size.width(), size.height());
for (auto* ctx: GetAllBrowserContexts()) {
@@ -133,8 +137,6 @@ void HeadlessBrowserImpl::Resize() {
PlatformSetWebContentsBounds(impl, rect);
}
}
-
- carbonyl::Bridge::GetCurrent()->Resize();
}
void HeadlessBrowserImpl::OnShutdownInput() {
@@ -436,7 +438,7 @@ void HeadlessBrowserImpl::RunOnStartCallback() {
input_thread_ = std::thread([=]() {
carbonyl::browser = this;
- carbonyl_bridge_browser_delegate delegate = {
+ carbonyl_renderer_browser_delegate delegate = {
.shutdown = []() {
if (carbonyl::browser) {
carbonyl::browser->OnShutdownInput();
@@ -500,7 +502,7 @@ void HeadlessBrowserImpl::RunOnStartCallback() {
}
};
- carbonyl::Bridge::GetCurrent()->Listen(&delegate);
+ carbonyl::Renderer::GetCurrent()->Listen(&delegate);
});
}
diff --git a/headless/lib/browser/headless_browser_impl_aura.cc b/headless/lib/browser/headless_browser_impl_aura.cc
index 80340d9f1b3b3..91be528753cdd 100644
--- a/headless/lib/browser/headless_browser_impl_aura.cc
+++ b/headless/lib/browser/headless_browser_impl_aura.cc
@@ -59,7 +59,7 @@ void HeadlessBrowserImpl::PlatformSetWebContentsBounds(
const gfx::Rect& bounds) {
// Browser's window bounds should contain all web contents, so that we're sure
// that we will actually produce visible damage when taking a screenshot.
- web_contents->window_tree_host()->SetBoundsInPixels(ScaleToEnclosedRect(bounds, carbonyl::Bridge::GetCurrent()->GetDPI()));
+ web_contents->window_tree_host()->SetBoundsInPixels(ScaleToEnclosedRect(bounds, carbonyl::Bridge::GetDPI()));
web_contents->window_tree_host()->window()->SetBounds(bounds);
gfx::NativeView native_view = web_contents->web_contents()->GetNativeView();
diff --git a/headless/lib/browser/headless_browser_impl_mac.mm b/headless/lib/browser/headless_browser_impl_mac.mm
index e2cb88fbcf708..397b2585f3d0f 100644
--- a/headless/lib/browser/headless_browser_impl_mac.mm
+++ b/headless/lib/browser/headless_browser_impl_mac.mm
@@ -6,6 +6,8 @@
#import "base/mac/scoped_objc_class_swizzler.h"
#include "base/no_destructor.h"
+#include "carbonyl/src/browser/bridge.h"
+#include "content/browser/renderer_host/render_widget_host_view_mac.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "headless/lib/browser/headless_web_contents_impl.h"
@@ -95,8 +97,13 @@ void HeadlessBrowserImpl::PlatformSetWebContentsBounds(
content::RenderWidgetHostView* host_view =
web_contents->web_contents()->GetRenderWidgetHostView();
- if (host_view)
+ if (host_view) {
host_view->SetWindowFrameInScreen(bounds);
+
+ static_cast<content::RenderWidgetHostViewMac*>(host_view)->SetCurrentDeviceScaleFactor(
+ carbonyl::Bridge::GetDPI()
+ );
+ }
}
ui::Compositor* HeadlessBrowserImpl::PlatformGetCompositor(
diff --git a/headless/lib/browser/headless_browser_main_parts_mac.mm b/headless/lib/browser/headless_browser_main_parts_mac.mm
index 718e37ef8bd3e..8ca30b9d88d5b 100644
--- a/headless/lib/browser/headless_browser_main_parts_mac.mm
+++ b/headless/lib/browser/headless_browser_main_parts_mac.mm
@@ -6,6 +6,14 @@
#import <Cocoa/Cocoa.h>
+#include "base/command_line.h"
+#include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
+#include "components/os_crypt/os_crypt.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "headless/app/headless_shell_switches.h"
#include "headless/lib/browser/headless_shell_application_mac.h"
#include "services/device/public/cpp/geolocation/geolocation_manager_impl_mac.h"
@@ -16,6 +24,7 @@ void HeadlessBrowserMainParts::PreCreateMainMessageLoop() {
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
if (!geolocation_manager_)
geolocation_manager_ = device::GeolocationManagerImpl::Create();
+
}
} // namespace headless
diff --git a/headless/lib/browser/headless_screen.cc b/headless/lib/browser/headless_screen.cc
index 89c5ccc8d7759..047d741638df2 100644
--- a/headless/lib/browser/headless_screen.cc
+++ b/headless/lib/browser/headless_screen.cc
@@ -6,14 +6,18 @@
#include <stdint.h>
-#include "ui/aura/env.h"
-#include "ui/aura/window.h"
#include "ui/base/ime/input_method.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/native_widget_types.h"
+#if !BUILDFLAG(IS_MAC)
+#include "ui/aura/env.h"
+#include "ui/aura/window.h"
+#endif
+
#include "carbonyl/src/browser/bridge.h"
+#include "carbonyl/src/browser/renderer.h"
namespace headless {
@@ -24,6 +28,7 @@ HeadlessScreen* HeadlessScreen::Create(const gfx::Size& size) {
HeadlessScreen::~HeadlessScreen() = default;
+#if !BUILDFLAG(IS_MAC)
gfx::Point HeadlessScreen::GetCursorScreenPoint() {
return aura::Env::GetInstance()->last_mouse_location();
}
@@ -31,6 +36,7 @@ gfx::Point HeadlessScreen::GetCursorScreenPoint() {
bool HeadlessScreen::IsWindowUnderCursor(gfx::NativeWindow window) {
return GetWindowAtScreenPoint(GetCursorScreenPoint()) == window;
}
+#endif
gfx::NativeWindow HeadlessScreen::GetWindowAtScreenPoint(
const gfx::Point& point) {
@@ -48,12 +54,22 @@ display::Display HeadlessScreen::GetDisplayNearestWindow(
return GetPrimaryDisplay();
}
+void HeadlessScreen::Resize() {
+ float dpi = carbonyl::Bridge::GetDPI();
+ auto size = carbonyl::Renderer::GetCurrent()->GetSize();
+ auto rect = gfx::Rect(0, 0, size.width() * dpi, size.height() * dpi);
+
+ display_.SetScaleAndBounds(dpi, rect);
+ ProcessDisplayChanged(display_, true /* is_primary */);
+}
+
HeadlessScreen::HeadlessScreen(const gfx::Rect& screen_bounds) {
+ float dpi = carbonyl::Bridge::GetDPI();
static int64_t synthesized_display_id = 2000;
- display::Display display(synthesized_display_id++);
- float dpi = carbonyl::Bridge::GetCurrent()->GetDPI();
- display.SetScaleAndBounds(dpi, ScaleToEnclosedRect(screen_bounds, dpi));
- ProcessDisplayChanged(display, true /* is_primary */);
+
+ display_ = display::Display(synthesized_display_id++);
+ display_.SetScaleAndBounds(dpi, ScaleToEnclosedRect(screen_bounds, dpi));
+ ProcessDisplayChanged(display_, true /* is_primary */);
}
} // namespace headless
diff --git a/headless/lib/browser/headless_screen.h b/headless/lib/browser/headless_screen.h
index 5ec78e5fe4685..23c073b1c86b3 100644
--- a/headless/lib/browser/headless_screen.h
+++ b/headless/lib/browser/headless_screen.h
@@ -6,7 +6,6 @@
#define HEADLESS_LIB_BROWSER_HEADLESS_SCREEN_H_
#include "base/compiler_specific.h"
-#include "ui/aura/window_observer.h"
#include "ui/display/display.h"
#include "ui/display/screen_base.h"
@@ -26,10 +25,15 @@ class HeadlessScreen : public display::ScreenBase {
~HeadlessScreen() override;
+ void Resize();
+
protected:
// display::Screen overrides:
+#if !BUILDFLAG(IS_MAC)
gfx::Point GetCursorScreenPoint() override;
bool IsWindowUnderCursor(gfx::NativeWindow window) override;
+#endif
+
gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override;
gfx::NativeWindow GetLocalProcessWindowAtPoint(
const gfx::Point& point,
@@ -39,6 +43,8 @@ class HeadlessScreen : public display::ScreenBase {
private:
explicit HeadlessScreen(const gfx::Rect& screen_bounds);
+
+ display::Display display_;
};
} // namespace headless
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
index a166a08f6ea15..091bde787d47c 100644
--- a/headless/lib/browser/headless_web_contents_impl.cc
+++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -22,7 +22,8 @@
#include "base/values.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
-#include "carbonyl/src/browser/bridge.h"
+#include "carbonyl/src/browser/renderer.h"
+#include "components/zoom/zoom_controller.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_termination_info.h"
#include "content/public/browser/devtools_agent_host.h"
@@ -335,6 +336,7 @@ HeadlessWebContentsImpl::HeadlessWebContentsImpl(
#if BUILDFLAG(ENABLE_PRINTING)
HeadlessPrintManager::CreateForWebContents(web_contents_.get());
#endif
+ zoom::ZoomController::CreateForWebContents(web_contents_.get());
UpdatePrefsFromSystemSettings(web_contents_->GetMutableRendererPrefs());
web_contents_->GetMutableRendererPrefs()->accept_languages =
browser_context->options()->accept_language();
@@ -400,7 +402,7 @@ void HeadlessWebContentsImpl::TitleWasSet(content::NavigationEntry* entry) {
if (!web_contents() || !web_contents()->GetPrimaryMainFrame()->IsActive())
return;
- carbonyl::Bridge::GetCurrent()->SetTitle(base::UTF16ToUTF8(entry->GetTitleForDisplay()));
+ carbonyl::Renderer::GetCurrent()->SetTitle(base::UTF16ToUTF8(entry->GetTitleForDisplay()));
}
void HeadlessWebContentsImpl::DidFinishNavigation(content::NavigationHandle* handle) {
@@ -411,7 +413,7 @@ void HeadlessWebContentsImpl::DidFinishNavigation(content::NavigationHandle* han
auto& nav = web_contents()->GetController();
- carbonyl::Bridge::GetCurrent()->PushNav(
+ carbonyl::Renderer::GetCurrent()->PushNav(
handle->GetURL().spec(),
nav.CanGoBack(),
nav.CanGoForward()
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm
index 9dd650de9a9a3..8cfb6e9015c3f 100644
--- a/printing/printing_context_mac.mm
+++ b/printing/printing_context_mac.mm
@@ -400,6 +400,7 @@ bool PrintingContextMac::SetDuplexModeInPrintSettings(mojom::DuplexMode mode) {
bool PrintingContextMac::SetOutputColor(int color_mode) {
const mojom::ColorModel color_model = ColorModeToColorModel(color_mode);
+#if BUILDFLAG(USE_CUPS)
if (!base::FeatureList::IsEnabled(features::kCupsIppPrintingBackend)) {
std::string color_setting_name;
std::string color_value;
@@ -412,6 +413,7 @@ bool PrintingContextMac::SetOutputColor(int color_mode) {
GetIppColorModelForModel(color_model))) {
return false;
}
+#endif
struct PpdColorSetting {
constexpr PpdColorSetting(base::StringPiece name,
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index c29495a7060d7..654438b8d7424 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -312,6 +312,7 @@ component("core") {
":generate_eventhandler_names",
":generated_settings_macros",
"//build:chromeos_buildflags",
+ "//carbonyl/src/browser:bridge",
"//components/attribution_reporting",
"//components/attribution_reporting:mojom_blink",
"//components/paint_preview/common",
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index cb116ee07c8f6..7129982acf4a6 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -116,7 +116,7 @@
#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-#include "carbonyl/src/browser/blink.h"
+#include "carbonyl/src/browser/bridge.h"
namespace blink {
@@ -1043,7 +1043,7 @@ scoped_refptr<ComputedStyle> StyleResolver::ResolveStyle(
UseCounter::Count(GetDocument(), WebFeature::kHasGlyphRelativeUnits);
}
- if (!carbonyl::blink::BitmapMode()) {
+ if (!carbonyl::Bridge::BitmapMode()) {
auto font = state.StyleBuilder().GetFontDescription();
FontFamily family;
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index ceb41d781acf6..bc6428f4f5c0d 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1678,7 +1678,7 @@ component("platform") {
"//base/allocator:buildflags",
"//build:chromecast_buildflags",
"//build:chromeos_buildflags",
- "//carbonyl/src/browser:blink",
+ "//carbonyl/src/browser:bridge",
"//cc/ipc",
"//cc/mojo_embedder",
"//components/paint_preview/common",
diff --git a/third_party/blink/renderer/platform/fonts/font.cc b/third_party/blink/renderer/platform/fonts/font.cc
index 3d1b463e9651c..4625300729523 100644
--- a/third_party/blink/renderer/platform/fonts/font.cc
+++ b/third_party/blink/renderer/platform/fonts/font.cc
@@ -49,7 +49,7 @@
#include "third_party/skia/include/core/SkTextBlob.h"
#include "ui/gfx/geometry/rect_f.h"
-#include "carbonyl/src/browser/blink.h"
+#include "carbonyl/src/browser/bridge.h"
namespace blink {
@@ -158,7 +158,7 @@ void DrawBlobs(cc::PaintCanvas* canvas,
const ShapeResultBloberizer::BlobBuffer& blobs,
const gfx::PointF& point,
cc::NodeId node_id = cc::kInvalidNodeId) {
- if (!carbonyl::blink::BitmapMode()) {
+ if (!carbonyl::Bridge::BitmapMode()) {
return;
}
@@ -237,7 +237,7 @@ void Font::DrawText(cc::PaintCanvas* canvas,
if (ShouldSkipDrawing())
return;
- if (!carbonyl::blink::BitmapMode()) {
+ if (!carbonyl::Bridge::BitmapMode()) {
auto string = StringView(
run_info.run.ToStringView(),
run_info.from,
@@ -285,7 +285,7 @@ void Font::DrawText(cc::PaintCanvas* canvas,
if (ShouldSkipDrawing())
return;
- if (!carbonyl::blink::BitmapMode()) {
+ if (!carbonyl::Bridge::BitmapMode()) {
auto string = StringView(
text_info.text,
text_info.from,
diff --git a/ui/display/BUILD.gn b/ui/display/BUILD.gn
index aadf9f2a52fd6..9b3aefc4d3b04 100644
--- a/ui/display/BUILD.gn
+++ b/ui/display/BUILD.gn
@@ -101,6 +101,7 @@ component("display") {
"//base",
"//base:i18n",
"//build:chromeos_buildflags",
+ "//carbonyl/src/browser:bridge",
"//mojo/public/cpp/bindings:struct_traits",
"//ui/display/mojom:mojom_shared_cpp_sources",
"//ui/display/util",
diff --git a/ui/display/display.cc b/ui/display/display.cc
index 1d71f3b4c9857..d670831de4ca4 100644
--- a/ui/display/display.cc
+++ b/ui/display/display.cc
@@ -26,39 +26,10 @@
namespace display {
namespace {
-// This variable tracks whether the forced device scale factor switch needs to
-// be read from the command line, i.e. if it is set to -1 then the command line
-// is checked.
-int g_has_forced_device_scale_factor = -1;
-
-// This variable caches the forced device scale factor value which is read off
-// the command line. If the cache is invalidated by setting this variable to
-// -1.0, we read the forced device scale factor again.
-float g_forced_device_scale_factor = -1.0;
-
// An allowance error epsilon caused by fractional scale factor to produce
// expected DP display size.
constexpr float kDisplaySizeAllowanceEpsilon = 0.01f;
-bool HasForceDeviceScaleFactorImpl() {
- // return base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kForceDeviceScaleFactor);
- return true;
-}
-
-float GetForcedDeviceScaleFactorImpl() {
- // double scale_in_double = 1.0;
- // if (HasForceDeviceScaleFactorImpl()) {
- // std::string value =
- // base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- // switches::kForceDeviceScaleFactor);
- // if (!base::StringToDouble(value, &scale_in_double)) {
- // LOG(ERROR) << "Failed to parse the default device scale factor:" << value;
- // scale_in_double = 1.0;
- // }
- // }
- return carbonyl::Bridge::GetCurrent()->GetDPI();
-}
-
const char* ToRotationString(display::Display::Rotation rotation) {
switch (rotation) {
case display::Display::ROTATE_0:
@@ -78,33 +49,19 @@ const char* ToRotationString(display::Display::Rotation rotation) {
// static
float Display::GetForcedDeviceScaleFactor() {
- if (g_forced_device_scale_factor < 0)
- g_forced_device_scale_factor = GetForcedDeviceScaleFactorImpl();
- return g_forced_device_scale_factor;
+ return carbonyl::Bridge::GetDPI();
}
// static
bool Display::HasForceDeviceScaleFactor() {
- if (g_has_forced_device_scale_factor == -1)
- g_has_forced_device_scale_factor = HasForceDeviceScaleFactorImpl();
- return !!g_has_forced_device_scale_factor;
+ return true;
}
// static
-void Display::ResetForceDeviceScaleFactorForTesting() {
- g_has_forced_device_scale_factor = -1;
- g_forced_device_scale_factor = -1.0;
-}
+void Display::ResetForceDeviceScaleFactorForTesting() {}
// static
-void Display::SetForceDeviceScaleFactor(double dsf) {
- // Reset any previously set values and unset the flag.
- // g_has_forced_device_scale_factor = -1;
- // g_forced_device_scale_factor = -1.0;
-
- // base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- // switches::kForceDeviceScaleFactor, base::StringPrintf("%.2f", dsf));
-}
+void Display::SetForceDeviceScaleFactor(double dsf) {}
// static
gfx::ColorSpace Display::GetForcedRasterColorProfile() {
================================================
FILE: chromium/patches/chromium/0014-Move-Skia-text-rendering-control-to-bridge.patch
================================================
From 2275364ee7e16ba6b46f0f339e34326d4a8c7584 Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Mon, 13 Feb 2023 17:13:38 +0100
Subject: [PATCH 14/14] Move Skia text rendering control to bridge
---
content/renderer/render_frame_impl.cc | 5 -----
skia/BUILD.gn | 2 +-
2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 379cf6c58b2b0..891efd6a9d796 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -285,7 +285,6 @@
#include "third_party/skia/include/svg/SkSVGCanvas.h"
#include "third_party/skia/include/utils/SkBase64.h"
#include "third_party/skia/src/text/GlyphRun.h"
-#include "third_party/skia/src/core/SkBitmapDevice.h"
#include "third_party/skia/src/core/SkClipStackDevice.h"
#include "third_party/skia/src/core/SkDevice.h"
#include "third_party/skia/src/core/SkFontPriv.h"
@@ -2244,10 +2243,6 @@ void RenderFrameImpl::Initialize(blink::WebFrame* parent) {
);
host->ObserveTerminalRender(render_callback_);
-
- if (!carbonyl::Bridge::BitmapMode()) {
- SkBitmapDevice::DisableTextRendering();
- }
}
void RenderFrameImpl::GetInterface(
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index b330273c16db3..297ffacf073fa 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -203,7 +203,7 @@ source_set("skcms") {
}
component("skia") {
- deps = []
+ deps = [ "//carbonyl/src/browser:bridge" ]
sources = [
# Chrome sources.
"config/SkUserConfig.h",
================================================
FILE: chromium/patches/skia/0001-Disable-text-rendering.patch
================================================
From 218fbf4bba772c465712c4ea442adb57968e9c22 Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Mon, 13 Feb 2023 17:18:18 +0100
Subject: [PATCH 1/2] Disable text rendering
---
src/core/SkBitmapDevice.cpp | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index b497d690f7..9631f47967 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -28,6 +28,8 @@
#include "src/image/SkImage_Base.h"
#include "src/text/GlyphRun.h"
+#include "carbonyl/src/browser/bridge.h"
+
struct Bounder {
SkRect fBounds;
bool fHasBounds;
@@ -522,8 +524,10 @@ void SkBitmapDevice::onDrawGlyphRunList(SkCanvas* canvas,
const sktext::GlyphRunList& glyphRunList,
const SkPaint& initialPaint,
const SkPaint& drawingPaint) {
- SkASSERT(!glyphRunList.hasRSXForm());
- LOOP_TILER( drawGlyphRunList(canvas, &fGlyphPainter, glyphRunList, drawingPaint), nullptr )
+ if (carbonyl::Bridge::BitmapMode()) {
+ SkASSERT(!glyphRunList.hasRSXForm());
+ LOOP_TILER( drawGlyphRunList(canvas, &fGlyphPainter, glyphRunList, drawingPaint), nullptr )
+ }
}
void SkBitmapDevice::drawVertices(const SkVertices* vertices,
================================================
FILE: chromium/patches/skia/0002-Export-some-private-APIs.patch
================================================
From a271b203a2b60f0cd450bda0fa2cc14885f1d9a8 Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Thu, 9 Feb 2023 03:38:05 +0100
Subject: [PATCH 2/2] Export some private APIs
Temporary until TextCaptureDevice moves here
---
include/utils/SkBase64.h | 2 +-
src/core/SkClipStack.h | 2 +-
src/core/SkClipStackDevice.h | 2 +-
src/core/SkDevice.h | 2 +-
src/core/SkFontPriv.h | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/utils/SkBase64.h b/include/utils/SkBase64.h
index e01028543a..beddbd2c95 100644
--- a/include/utils/SkBase64.h
+++ b/include/utils/SkBase64.h
@@ -12,7 +12,7 @@
#include <cstddef>
-struct SkBase64 {
+struct SK_API SkBase64 {
public:
enum Error {
kNoError,
diff --git a/src/core/SkClipStack.h b/src/core/SkClipStack.h
index c325d2c619..d93b9cf37f 100644
--- a/src/core/SkClipStack.h
+++ b/src/core/SkClipStack.h
@@ -30,7 +30,7 @@ class GrProxyProvider;
// (i.e., the fSaveCount in force when it was added). Restores are thus
// implemented by removing clips from fDeque that have an fSaveCount larger
// then the freshly decremented count.
-class SkClipStack {
+class SK_API SkClipStack {
public:
enum BoundsType {
// The bounding box contains all the pixels that can be written to
diff --git a/src/core/SkClipStackDevice.h b/src/core/SkClipStackDevice.h
index eff1f1a440..a8d6b4fe07 100644
--- a/src/core/SkClipStackDevice.h
+++ b/src/core/SkClipStackDevice.h
@@ -11,7 +11,7 @@
#include "src/core/SkClipStack.h"
#include "src/core/SkDevice.h"
-class SkClipStackDevice : public SkBaseDevice {
+class SK_API SkClipStackDevice : public SkBaseDevice {
public:
SkClipStackDevice(const SkImageInfo& info, const SkSurfaceProps& props)
: SkBaseDevice(info, props)
diff --git a/src/core/SkDevice.h b/src/core/SkDevice.h
index e0fed94b9b..c7194f9c1c 100644
--- a/src/core/SkDevice.h
+++ b/src/core/SkDevice.h
@@ -54,7 +54,7 @@ struct SkStrikeDeviceInfo {
const sktext::gpu::SDFTControl* const fSDFTControl;
};
-class SkBaseDevice : public SkRefCnt, public SkMatrixProvider {
+class SK_API SkBaseDevice : public SkRefCnt, public SkMatrixProvider {
public:
SkBaseDevice(const SkImageInfo&, const SkSurfaceProps&);
diff --git a/src/core/SkFontPriv.h b/src/core/SkFontPriv.h
index 95ca905bf1..a31aba8e2b 100644
--- a/src/core/SkFontPriv.h
+++ b/src/core/SkFontPriv.h
@@ -16,7 +16,7 @@
class SkReadBuffer;
class SkWriteBuffer;
-class SkFontPriv {
+class SK_API SkFontPriv {
public:
/* This is the size we use when we ask for a glyph's path. We then
* post-transform it as we draw to match the request.
================================================
FILE: chromium/patches/webrtc/0001-Disable-GIO-on-Linux.patch
================================================
From 5ad57c96f23739717bcea018baf2bc8f4157b01d Mon Sep 17 00:00:00 2001
From: Fathy Boundjadj <hey@fathy.fr>
Date: Mon, 13 Feb 2023 16:37:40 +0100
Subject: [PATCH] Disable GIO on Linux
---
modules/portal/BUILD.gn | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/portal/BUILD.gn b/modules/portal/BUILD.gn
index 36bcb53e8e..822688b1dc 100644
--- a/modules/portal/BUILD.gn
+++ b/modules/portal/BUILD.gn
@@ -85,7 +85,7 @@ if ((is_linux || is_chromeos) && rtc_use_pipewire) {
# `rtc_use_pipewire` is not set, which causes pipewire_config to not be
# included in targets. More details in: webrtc:13898
if (is_linux && !is_castos) {
- defines += [ "WEBRTC_USE_GIO" ]
+ $ defines += [ "WEBRTC_USE_GIO" ]
}
}
================================================
FILE: cliff.toml
================================================
[changelog]
header = """
# Changelog\n
All notable changes to this project will be documented in this file.\n
"""
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
- {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }}\
{%- if commit.links %} ({% for link in commit.links %}[{{link.text}}]({{link.href}}){% endfor -%}){% endif %}\
{% endfor %}
{% endfor %}\n
"""
trim = true
footer = ""
[git]
conventional_commits = true
filter_unconventional = true
split_commits = false
commit_preprocessors = [
{ pattern = "#([0-9]+)", replace = "[#${1}](https://github.com/fathyb/carbonyl/issues/${1})" }
]
commit_parsers = [
{ message = "^feat", group = "<!-- 0 -->🚀 Features" },
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
{ message = "^doc", group = "<!-- 2 -->📖 Documentation" },
{ message = "^perf", group = "<!-- 3 -->⚡ Performance"},
{ message = "^chore", skip = true },
{ body = ".*security", group = "<!-- 8 -->🔐 Security"},
]
protect_breaking_commits = false
filter_commits = false
tag_pattern = "v[0-9]*"
skip_tags = ""
ignore_tags = ""
topo_order = true
sort_commits = "oldest"
================================================
FILE: license.md
================================================
_Copyright © 2023, Fathy Boundjadj_
_All rights reserved._
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: package.json
================================================
{
"name": "carbonyl",
"version": "0.0.3",
"license": "BSD-3-Clause"
}
================================================
FILE: readme.md
================================================
<table align="center">
<tbody>
<tr>
<td>
<p></p>
<pre>
O O
\ /
O —— Cr —— O
/ \
O O</pre>
</td>
<td><h1>Carbonyl</h1></td>
</tr>
</tbody>
</table>
Carbonyl is a Chromium based browser built to run in a terminal. [Read the blog post](https://fathy.fr/carbonyl).
It supports pretty much all Web APIs including WebGL, WebGPU, audio and video playback, animations, etc..
It's snappy, starts in less than a second, runs at 60 FPS, and idles at 0% CPU usage. It does not require a window server (i.e. works in a safe-mode console), and even runs through SSH.
Carbonyl originally started as [`html2svg`](https://github.com/fathyb/html2svg) and is now the runtime behind it.
## Usage
> Carbonyl on Linux without Docker requires the same dependencies as Chromium.
### Docker
```shell
$ docker run --rm -ti fathyb/carbonyl https://youtube.com
```
### npm
```console
$ npm install --global carbonyl
$ carbonyl https://github.com
```
### Binaries
- [macOS amd64](https://github.com/fathyb/carbonyl/releases/download/v0.0.3/carbonyl.macos-amd64.zip)
- [macOS arm64](https://github.com/fathyb/carbonyl/releases/download/v0.0.3/carbonyl.macos-arm64.zip)
- [Linux amd64](https://github.com/fathyb/carbonyl/releases/download/v0.0.3/carbonyl.linux-amd64.zip)
- [Linux arm64](https://github.com/fathyb/carbonyl/releases/download/v0.0.3/carbonyl.linux-arm64.zip)
## Demo
<table>
<tbody>
<tr>
<td>
<video src="https://user-images.githubusercontent.com/5746414/213682926-f1cc2de7-a38c-4125-9257-92faecfc7e24.mp4">
</td>
<td>
<video src="https://user-images.githubusercontent.com/5746414/213682913-398d3d11-1af8-4ae6-a0cd-a7f878efd88b.mp4">
</td>
</tr>
<tr>
<td colspan="2">
<video src="https://user-images.githubusercontent.com/5746414/213682918-d6396a4f-ee23-431d-828e-4ad6a00e690e.mp4">
</td>
</tr>
</tbody>
</table>
## Known issues
- Fullscreen mode not supported yet
## Comparisons
### Lynx
Lynx is the original terminal web browser, and the oldest one still maintained.
#### Pros
- When it understands a page, Lynx has the best layout, fully optimized for the terminal
#### Cons
> Some might sound like pluses, but Browsh and Carbonyl let you disable most of those if you'd like
- Does not support a lot of modern web standards
- Cannot run JavaScript/WebAssembly
- Cannot view or play media (audio, video, DOOM)
### Browsh
Browsh is the original "normal browser into a terminal" project. It starts Firefox in headless mode and connects to it through an automation protocol.
#### Pro
- It's easier to update the underlying browser: just update Firefox
- This makes development easier: just install Firefox and compile the Go code in a few seconds
- As of today, Browsh supports extensions while Carbonyl doesn't, although it's on our roadmap
#### Cons
- It runs slower and requires more resources than Carbonyl. 50x more CPU power is needed for the same content in average, that's because Carbonyl does not downscale or copy the window framebuffer, it natively renders to the terminal resolution.
- It uses custom stylesheets to fix the layout, which is less reliable than Carbonyl's changes to its HTML engine (Blink).
## Operating System Support
As far as tested, the operating systems under are supported:
- Linux (Debian, Ubuntu and Arch tested)
- MacOS
- Windows 11 and WSL
## Contributing
Carbonyl is split in two parts: the "core" which is built into a shared library (`libcarbonyl`), and the "runtime" which dynamically loads the core (`carbonyl` executable).
The core is written in Rust and takes a few seconds to build from scratch. The runtime is a modified version of the Chromium headless shell and takes more than an hour to build from scratch.
If you're just making changes to the Rust code, build `libcarbonyl` and replace it in a release version of Carbonyl.
### Core
```console
$ cargo build
```
### Runtime
Few notes:
- Building the runtime is almost the same as building Chromium with extra steps to patch and bundle the Rust library. Scripts in the `scripts/` directory are simple wrappers around `gn`, `ninja`, etc..
- Building Chromium for arm64 on Linux requires an amd64 processor
- Carbonyl is only tested on Linux and macOS, other platforms likely require code changes to Chromium
- Chromium is huge and takes a long time to build, making your computer mostly unresponsive. An 8-core CPU such as an M1 Max or an i9 9900k with 10 Gbps fiber takes around ~1 hour to fetch and build. It requires around 100 GB of disk space.
#### Fetch
> Fetch Chromium's code.
```console
$ ./scripts/gclient.sh sync
```
#### Apply patches
> Any changes made to Chromium will be reverted, make sure to save any changes you made.
```console
$ ./scripts/patches.sh apply
```
#### Configure
```console
$ ./scripts/gn.sh args out/Default
```
> `Default` is the target name, you can use multiple ones and pick any name you'd like, i.e.:
>
> ```console
> $ ./scripts/gn.sh args out/release
> $ ./scripts/gn.sh args out/debug
> # or if you'd like to build a multi-platform image
> $ ./scripts/gn.sh args out/arm64
> $ ./scripts/gn.sh args out/amd64
> ```
When prompted, enter the following arguments:
```gn
import("//carbonyl/src/browser/args.gn")
# uncomment this to build for arm64
# target_cpu = "arm64"
# comment this to disable ccache
cc_wrapper = "env CCACHE_SLOPPINESS=time_macros ccache"
# comment this for a debug build
is_debug = false
symbol_level = 0
is_official_build = true
```
#### Build binaries
```console
$ ./scripts/build.sh Default
```
This should produce the following outputs:
- `out/Default/headless_shell`: browser binary
- `out/Default/icudtl.dat`
- `out/Default/libEGL.so`
- `out/Default/libGLESv2.so`
- `out/Default/v8_context_snapshot.bin`
#### Build Docker image
```console
# Build arm64 Docker image using binaries from the Default target
$ ./scripts/docker-build.sh Default arm64
# Build amd64 Docker image using binaries from the Default target
$ ./scripts/docker-build.sh Default amd64
```
#### Run
```
$ ./scripts/run.sh Default https://wikipedia.org
```
================================================
FILE: scripts/build.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- "$(pwd)")
export INSTALL_DEPOT_TOOLS="true"
cd "$CARBONYL_ROOT"
source scripts/env.sh
target="$1"
cpu="$2"
if [ ! -z "$target" ]; then
shift
fi
if [ ! -z "$cpu" ]; then
shift
fi
triple=$(scripts/platform-triple.sh "$cpu")
if [ -z "$CARBONYL_SKIP_CARGO_BUILD" ]; then
if [ -z "$MACOSX_DEPLOYMENT_TARGET" ]; then
export MACOSX_DEPLOYMENT_TARGET=10.13
fi
cargo build --target "$triple" --release
fi
if [ -f "build/$triple/release/libcarbonyl.dylib" ]; then
cp "build/$triple/release/libcarbonyl.dylib" "$CHROMIUM_SRC/out/$target"
install_name_tool \
-id @executable_path/libcarbonyl.dylib \
"build/$triple/release/libcarbonyl.dylib"
else
cp "build/$triple/release/libcarbonyl.so" "$CHROMIUM_SRC/out/$target"
fi
cd "$CHROMIUM_SRC/out/$target"
ninja headless:headless_shell "$@"
================================================
FILE: scripts/changelog.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- $(pwd))
cd "$CARBONYL_ROOT"
source "scripts/env.sh"
git cliff a69e8b609625b67a3e52e18f73ba5d0f49ceb7c3..HEAD "$@" > changelog.md
================================================
FILE: scripts/copy-binaries.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- $(pwd))
cd "$CARBONYL_ROOT"
source "scripts/env.sh"
target="$1"
cpu="$2"
triple=$(scripts/platform-triple.sh "$cpu")
dest="build/pre-built/$triple"
src="$CHROMIUM_SRC/out/$target"
lib_ext="so"
if [ -f "$src"/libEGL.dylib ]; then
lib_ext="dylib"
fi
rm -rf "$dest"
mkdir -p "$dest"
cd "$dest"
cp "$src/headless_shell" carbonyl
cp "$src/icudtl.dat" .
cp "$src/libEGL.$lib_ext" .
cp "$src/libGLESv2.$lib_ext" .
cp "$src"/v8_context_snapshot*.bin .
cp "$CARBONYL_ROOT/build/$triple/release/libcarbonyl.$lib_ext" .
files="carbonyl "
if [ "$lib_ext" == "so" ]; then
cp "$src/libvk_swiftshader.so" .
cp "$src/libvulkan.so.1" .
cp "$src/vk_swiftshader_icd.json" .
files+=$(echo *.so *.so.1)
fi
if [[ "$cpu" == "arm64" ]] && command -v aarch64-linux-gnu-strip; then
aarch64-linux-gnu-strip $files
else
strip $files
fi
echo "Binaries copied to $dest"
================================================
FILE: scripts/docker-build.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- "$(pwd)")
cd "$CARBONYL_ROOT"
source "scripts/env.sh"
cpu="$1"
triple=$(scripts/platform-triple.sh "$cpu" linux)
build_dir="build/docker/$triple"
rm -rf "$build_dir"
mkdir -p "build/docker"
cp -r "$CARBONYL_ROOT/build/pre-built/$triple" "$build_dir"
cp "$CARBONYL_ROOT/Dockerfile" "$build_dir"
tag="fathyb/carbonyl:$cpu"
docker buildx build "$build_dir" --load --platform "linux/$cpu" --tag "$tag"
echo "Image tag: $tag"
================================================
FILE: scripts/docker-push.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- "$(pwd)")
source "$CARBONYL_ROOT/scripts/env.sh"
tag="fathyb/carbonyl"
version="$1"
echo "Pushing arm64 image as $tag:$version-arm64"
docker tag "$tag:arm64" "$tag:$version-arm64"
docker push "$tag:$version-arm64"
echo "Pushing amd64 image as $tag:$version-amd64"
docker tag "$tag:amd64" "$tag:$version-amd64"
docker push "$tag:$version-amd64"
docker manifest create "$tag:$version" \
--amend "$tag:$version-arm64" \
--amend "$tag:$version-amd64"
docker manifest push "$tag:$version" --purge
================================================
FILE: scripts/env.sh
================================================
#!/usr/bin/env bash
set -eo pipefail
if [ -z "$CARBONYL_ROOT" ]; then
echo "CARBONYL_ROOT should be defined"
exit 2
fi
if [ -z "$CHROMIUM_ROOT" ]; then
export CHROMIUM_ROOT="$CARBONYL_ROOT/chromium"
fi
if [ -z "$CHROMIUM_SRC" ]; then
export CHROMIUM_SRC="$CHROMIUM_ROOT/src"
fi
if [ -z "$DEPOT_TOOLS_ROOT" ]; then
export DEPOT_TOOLS_ROOT="$CHROMIUM_ROOT/depot_tools"
fi
export PATH="$PATH:$DEPOT_TOOLS_ROOT"
if [ "$INSTALL_DEPOT_TOOLS" = "true" ] && [ ! -f "$DEPOT_TOOLS_ROOT/README.md" ]; then
echo "depot_tools not found, fetching submodule.."
git -C "$CARBONYL_ROOT" submodule update --init --recursive
fi
================================================
FILE: scripts/gclient.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- "$(pwd)")
export INSTALL_DEPOT_TOOLS="true"
source "$CARBONYL_ROOT/scripts/env.sh"
(
cd "$CHROMIUM_ROOT" &&
gclient "$@"
)
================================================
FILE: scripts/gn.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- "$(pwd)")
export INSTALL_DEPOT_TOOLS="true"
source "$CARBONYL_ROOT/scripts/env.sh"
(
cd "$CHROMIUM_SRC" &&
gn "$@"
)
================================================
FILE: scripts/npm-package.mjs
================================================
import fs from "fs/promises";
import path from "path";
import { fileURLToPath } from "url";
const dirname = path.dirname(fileURLToPath(import.meta.url));
const pkg = JSON.parse(
await fs.readFile(path.resolve(dirname, "../package.json"), "utf-8")
);
const version = process.env.RELEASE_MODE
? pkg.version
: `${pkg.version}-next.${process.env.VERSION_ID}`;
const manifest = {
version,
license: "BSD-3-Clause",
description: "Chromium running in your terminal",
homepage: "https://github.com/fathyb/carbonyl",
repository: "fathyb/carbonyl",
bugs: "https://github.com/fathyb/carbonyl/issues",
author: {
name: "Fathy Boundjadj",
email: "hey@fathy.fr",
url: "https://fathy.fr",
},
};
async function buildMain() {
const root = path.resolve(dirname, "../build/packages/carbonyl");
await fs.rm(root, { recursive: true, force: true });
await fs.mkdir(root, { recursive: true });
await Promise.all([
Promise.all(
["readme.md", "license.md"].map((file) =>
fs.cp(path.join(dirname, "..", file), path.join(root, file))
)
),
fs.writeFile(
path.join(root, "package.json"),
JSON.stringify(
{
name: "carbonyl",
...manifest,
files: ["index.sh", "index.sh.js", "index.js"],
bin: { carbonyl: "index.sh" },
optionalDependencies: {
"@fathyb/carbonyl-linux-amd64": version,
"@fathyb/carbonyl-linux-arm64": version,
"@fathyb/carbonyl-macos-amd64": version,
"@fathyb/carbonyl-macos-arm64": version,
},
},
null,
4
)
),
fs.writeFile(
path.join(root, "index.sh"),
["#!/usr/bin/env bash", `"$(node "$(realpath "$0")".js)" "$@"`].join(
"\n"
),
{ mode: "755" }
),
fs.writeFile(
path.join(root, "index.sh.js"),
`process.stdout.write(require('.'))`
),
fs.writeFile(
path.join(root, "index.js"),
`
const archs = {
x64: 'amd64',
arm64: 'arm64',
}
const platforms = {
linux: 'linux',
darwin: 'macos',
}
const arch = archs[process.arch]
const platform = platforms[process.platform]
if (!arch) {
throw new Error('Processor architecture not supported: ' + process.arch)
}
if (!platform) {
throw new Error('Platform not supported: ' + process.platform)
}
module.exports = require('@fathyb/carbonyl-' + platform + '-' + arch)
`
),
]);
return root;
}
async function buildPlatform([os, npmOs, llvmOs], [cpu, npmCpu, llvmCpu]) {
const pkg = `carbonyl-${os}-${cpu}`;
const root = path.resolve(dirname, `../build/packages/${pkg}`);
await fs.rm(root, { recursive: true, force: true });
await fs.mkdir(root, { recursive: true });
await Promise.all([
Promise.all(
["readme.md", "license.md"].map((file) =>
fs.cp(path.join(dirname, "..", file), path.join(root, file))
)
),
fs.cp(
path.join(dirname, `../build/pre-built/${llvmCpu}-${llvmOs}`),
path.join(root, "build"),
{ recursive: true }
),
fs.writeFile(
path.join(root, "package.json"),
JSON.stringify(
{
name: `@fathyb/${pkg}`,
...manifest,
files: ["build", "index.js"],
os: [npmOs],
cpu: [npmCpu],
},
null,
4
)
),
fs.writeFile(
path.join(root, "index.js"),
`module.exports = __dirname + '/build/carbonyl'`
),
]);
return root;
}
const [root, platforms] = await Promise.all([
buildMain(),
Promise.all(
[
["macos", "darwin", "apple-darwin"],
["linux", "linux", "unknown-linux-gnu"],
].map(
async (os) =>
await Promise.all(
[
["arm64", "arm64", "aarch64"],
["amd64", "x64", "x86_64"],
].map(async (cpu) => await buildPlatform(os, cpu))
)
)
),
]);
================================================
FILE: scripts/npm-package.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- $(pwd))
cd "$CARBONYL_ROOT"
source "scripts/env.sh"
VERSION_ID="$(git rev-parse --short HEAD)" \
node "$CARBONYL_ROOT/scripts/npm-package.mjs"
================================================
FILE: scripts/npm-publish.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- $(pwd))
cd "$CARBONYL_ROOT"
source "scripts/env.sh"
cd "build/packages"
if [ -z "$CARBONYL_PUBLISH_PLATFORM" ] && [ -z "$CARBONYL_PUBLISH_ARCH" ]; then
cd "carbonyl"
else
cd "carbonyl-$CARBONYL_PUBLISH_PLATFORM-$CARBONYL_PUBLISH_ARCH"
fi
yarn publish --non-interactive --access public "$@"
================================================
FILE: scripts/patches.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- "$(pwd)")
source "$CARBONYL_ROOT/scripts/env.sh"
cd "$CHROMIUM_SRC"
chromium_upstream="92da8189788b1b373cbd3348f73d695dfdc521b6"
skia_upstream="486deb23bc2a4d3d09c66fef52c2ad64d8b4f761"
webrtc_upstream="727080cbacd58a2f303ed8a03f0264fe1493e47a"
if [[ "$1" == "apply" ]]; then
echo "Stashing Chromium changes.."
git add -A .
git stash
echo "Applying Chromium patches.."
git checkout "$chromium_upstream"
git am --committer-date-is-author-date "$CARBONYL_ROOT/chromium/patches/chromium"/*
"$CARBONYL_ROOT/scripts/restore-mtime.sh" "$chromium_upstream"
echo "Stashing Skia changes.."
cd "$CHROMIUM_SRC/third_party/skia"
git add -A .
git stash
echo "Applying Skia patches.."
git checkout "$skia_upstream"
git am --committer-date-is-author-date "$CARBONYL_ROOT/chromium/patches/skia"/*
"$CARBONYL_ROOT/scripts/restore-mtime.sh" "$skia_upstream"
echo "Stashing WebRTC changes.."
cd "$CHROMIUM_SRC/third_party/webrtc"
git add -A .
git stash
echo "Applying WebRTC patches.."
git checkout "$webrtc_upstream"
git am --committer-date-is-author-date "$CARBONYL_ROOT/chromium/patches/webrtc"/*
"$CARBONYL_ROOT/scripts/restore-mtime.sh" "$webrtc_upstream"
echo "Patches successfully applied"
elif [[ "$1" == "save" ]]; then
if [[ -d carbonyl ]]; then
git add -A carbonyl
fi
echo "Updating Chromium patches.."
rm -rf "$CARBONYL_ROOT/chromium/patches/chromium"
git format-patch --no-signature --output-directory "$CARBONYL_ROOT/chromium/patches/chromium" "$chromium_upstream"
echo "Updating Skia patches.."
cd "$CHROMIUM_SRC/third_party/skia"
rm -rf "$CARBONYL_ROOT/chromium/patches/skia"
git format-patch --no-signature --output-directory "$CARBONYL_ROOT/chromium/patches/skia" "$skia_upstream"
echo "Updating WebRTC patches.."
cd "$CHROMIUM_SRC/third_party/webrtc"
rm -rf "$CARBONYL_ROOT/chromium/patches/webrtc"
git format-patch --no-signature --output-directory "$CARBONYL_ROOT/chromium/patches/webrtc" "$webrtc_upstream"
echo "Patches successfully updated"
else
echo "Unknown argument: $1"
exit 2
fi
================================================
FILE: scripts/platform-triple.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- $(pwd))
source "$CARBONYL_ROOT/scripts/env.sh"
cpu="$1"
platform="$2"
if [ -z "$platform" ]; then
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
platform="linux"
elif [[ "$OSTYPE" == "darwin"* ]]; then
platform="macos"
else
echo "Unsupported platform: $OSTYPE"
exit 2
fi
fi
if [ "$platform" == "linux" ]; then
platform="unknown-linux-gnu"
elif [ "$platform" == "macos" ]; then
platform="apple-darwin"
fi
if [ -z "$cpu" ]; then
cpu="$(uname -m)"
fi
if [[ "$cpu" == "arm64" ]]; then
cpu="aarch64"
elif [[ "$cpu" == "amd64" ]]; then
cpu="x86_64"
fi
echo -n "$cpu-$platform"
================================================
FILE: scripts/release.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- $(pwd))
cd "$CARBONYL_ROOT"
source "scripts/env.sh"
npm version "$1" --no-git-tag-version
"$CARBONYL_ROOT/scripts/changelog.sh" --tag "$1"
git add -A .
git commit -m "chore(release): $1"
git tag -a "v$1" -m "chore(release): $1"
================================================
FILE: scripts/restore-mtime.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- $(pwd))
source "$CARBONYL_ROOT/scripts/env.sh"
for file in $(git diff --name-only HEAD "$1"); do
mtime="$(git log --pretty=format:%cd -n 1 --date=format:%Y%m%d%H%M.%S "$file")"
touch -t "$mtime" "$file"
done
================================================
FILE: scripts/run.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- "$(pwd)")
source "$CARBONYL_ROOT/scripts/env.sh"
target="$1"
shift
"$CHROMIUM_SRC/out/$target/headless_shell" "$@"
================================================
FILE: scripts/runtime-hash.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- $(pwd))
cd "$CARBONYL_ROOT"
source "scripts/env.sh"
for file in chromium/.gclient chromium/patches/*/*.patch src/browser/*.{cc,h,gn,mojom}; do
file_sha=$(cat "$file" | openssl sha256)
result=$(echo -n "$sha/${file_sha: -64}" | openssl sha256)
sha+="${file_sha: -64} ${file}"$'\n'
done
hash=$(echo "$sha" | sort | openssl sha256)
echo -n "${hash: -16}"
================================================
FILE: scripts/runtime-pull.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- $(pwd))
cd "$CARBONYL_ROOT"
source "scripts/env.sh"
echo "Computing Chromium patches sha.."
sha="$(scripts/runtime-hash.sh)"
triple="$(scripts/platform-triple.sh "$@")"
if [ ! -f "build/pre-built/$triple.tgz" ]; then
url="https://carbonyl.fathy.fr/runtime/$sha/$triple.tgz"
echo "Downloading pre-built binaries from $url"
mkdir -p build/pre-built
if ! curl --silent --fail --output "build/pre-built/$triple.tgz" "$url"; then
echo "Pre-built binaries not available"
exit 1
fi
fi
echo "Pre-build binaries available, extracting.."
cd build/pre-built
rm -rf "$triple"
tar -xvzf "$triple.tgz"
================================================
FILE: scripts/runtime-push.sh
================================================
#!/usr/bin/env bash
export CARBONYL_ROOT=$(cd $(dirname -- "$0") && dirname -- $(pwd))
cd "$CARBONYL_ROOT"
source "scripts/env.sh"
echo "Computing Chromium patches hash.."
hash=$(scripts/runtime-hash.sh)
triple=$(scripts/platform-triple.sh "$1")
echo "Archiving binaries.."
cd build/pre-built
tar cvzf "$triple.tgz" "$triple"
echo "Binaries archived to build/pre-built/$triple.tgz"
echo "Pushing $triple.tgz to object storage.."
AWS_PAGER="" \
AWS_ACCESS_KEY_ID="$CDN_ACCESS_KEY_ID" \
AWS_SECRET_ACCESS_KEY="$CDN_SECRET_ACCESS_KEY" \
aws s3api put-object \
--endpoint-url "https://7985f304d3a79d71fb63aeb17a31fe30.r2.cloudflarestorage.com" \
--bucket "carbonyl-runtime" \
--key "runtime/$hash/$triple.tgz" \
--body "$triple.tgz"
================================================
FILE: src/browser/BUILD.gn
================================================
import("//build/config/compiler/compiler.gni")
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
sources = [ "carbonyl.mojom" ]
deps = [
"//ui/gfx/geometry/mojom",
"//skia/public/mojom",
]
}
component("bridge") {
output_name = "carbonyl_bridge"
defines = [ "CARBONYL_BRIDGE_IMPLEMENTATION" ]
sources = [
"bridge.cc",
"bridge.h",
]
}
component("viz") {
output_name = "carbonyl_viz"
defines = [ "CARBONYL_VIZ_IMPLEMENTATION" ]
sources = [
"host_display_client.cc",
"host_display_client.h",
]
deps = [
":renderer",
"//base",
"//components/viz/host",
"//services/viz/privileged/mojom",
]
}
config("lib") {
target = ""
if (current_cpu == "x64") {
target += "x86_64-"
} else if (current_cpu == "arm64") {
target += "aarch64-"
}
if (is_mac) {
target += "apple-darwin"
} else if (is_linux) {
target += "unknown-linux-gnu"
}
libs = ["carbonyl"]
lib_dirs = ["//carbonyl/build/$target/release"]
}
component("renderer") {
output_name = "carbonyl_renderer"
defines = [ "CARBONYL_RENDERER_IMPLEMENTATION" ]
sources = [
"render_service_impl.cc",
"render_service_impl.h",
"renderer.cc",
"renderer.h",
]
configs += [ ":lib" ]
deps = [
":mojom",
":bridge",
"//base",
"//skia"
]
}
================================================
FILE: src/browser/args.gn
================================================
headless_enable_commands = false
headless_use_embedded_resources = true
# Enable proprietary codecs such as H.264
ffmpeg_branding = "Chrome"
proprietary_codecs = true
# Disable unused dependencies
ozone_platform = "headless"
ozone_platform_x11 = false
use_static_angle = true
use_qt = false
use_gio = false
use_gtk = false
use_cups = false
use_dbus = false
use_glib = false
use_libpci = false
use_kerberos = false
use_vaapi_x11 = false
use_xkbcommon = false
angle_use_x11 = false
angle_use_wayland = false
rtc_use_x11 = false
rtc_use_pipewire = false
rtc_use_x11_extensions = false
# Linux only
# use_wayland_gbm = false
# use_system_libdrm = false
# use_system_minigbm = false
# Disable unused features
enable_pdf = false
enable_nacl = false
enable_ppapi = false
enable_printing = false
enable_print_content_analysis = false
enable_plugins = false
enable_rust_json = false
enable_tagged_pdf = false
enable_media_remoting = false
enable_speech_service = false
enable_component_updater = false
enable_screen_ai_service = false
enable_system_notifications = false
enable_browser_speech_service = false
enable_webui_certificate_viewer = false
================================================
FILE: src/browser/bridge.cc
================================================
#include "carbonyl/src/browser/bridge.h"
namespace {
float dpi_ = 0.0;
bool bitmap_mode_ = false;
}
namespace carbonyl {
void Bridge::Resize() {}
float Bridge::GetDPI() {
return dpi_;
}
bool Bridge::BitmapMode() {
return bitmap_mode_;
}
void Bridge::Configure(float dpi, bool bitmap_mode) {
dpi_ = dpi;
bitmap_mode_ = bitmap_mode;
}
}
================================================
FILE: src/browser/bridge.h
================================================
#ifndef CARBONYL_SRC_BROWSER_BRIDGE_H_
#define CARBONYL_SRC_BROWSER_BRIDGE_H_
#include "carbonyl/src/browser/export.h"
namespace carbonyl {
class Renderer;
class CARBONYL_BRIDGE_EXPORT Bridge {
public:
static float GetDPI();
static bool BitmapMode();
private:
friend class Renderer;
static void Resize();
static void Configure(float dpi, bool bitmap_mode);
};
}
#endif // CARBONYL_SRC_BROWSER_BRIDGE_H_
================================================
FILE: src/browser/bridge.rs
================================================
use std::ffi::{CStr, CString};
use std::io::Write;
use std::process::{Command, Stdio};
use std::sync::{mpsc, Mutex};
use std::{env, io, thread};
use libc::{c_char, c_float, c_int, c_uchar, c_uint, c_void, size_t};
use crate::cli::{CommandLine, CommandLineProgram, EnvVar};
use crate::gfx::{Cast, Color, Point, Rect, Size};
use crate::output::{RenderThread, Window};
use crate::ui::navigation::NavigationAction;
use crate::{input, utils::log};
#[repr(C)]
#[derive(Copy, Clone)]
pub struct CSize {
width: c_uint,
height: c_uint,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct CPoint {
x: c_uint,
y: c_uint,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct CRect {
origin: CPoint,
size: CSize,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct CColor {
r: u8,
g: u8,
b: u8,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct CText {
text: *const c_char,
rect: CRect,
color: CColor,
}
#[repr(C)]
pub struct RendererBridge {
cmd: CommandLine,
window: Window,
renderer: RenderThread,
}
unsafe impl Send for RendererBridge {}
unsafe impl Sync for RendererBridge {}
pub type RendererPtr = *const Mutex<RendererBridge>;
impl<T: Copy> From<CPoint> for Point<T>
where
c_uint: Cast<T>,
{
fn from(value: CPoint) -> Self {
Point::new(value.x, value.y).cast()
}
}
impl From<Size<c_uint>> for CSize {
fn from(value: Size<c_uint>) -> Self {
Self {
width: value.width,
height: value.height,
}
}
}
impl<T: Copy> From<CSize> for Size<T>
where
c_uint: Cast<T>,
{
fn from(value: CSize) -> Self {
Size::new(value.width, value.height).cast()
}
}
impl From<CColor> for Color {
fn from(value: CColor) -> Self {
Color::new(value.r, value.g, value.b)
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct BrowserDelegate {
shutdown: extern "C" fn(),
refresh: extern "C" fn(),
go_to: extern "C" fn(*const c_char),
go_back: extern "C" fn(),
go_forward: extern "C" fn(),
scroll: extern "C" fn(c_int),
key_press: extern "C" fn(c_char),
mouse_up: extern "C" fn(c_uint, c_uint),
mouse_down: extern "C" fn(c_uint, c_uint),
mouse_move: extern "C" fn(c_uint, c_uint),
post_task: extern "C" fn(extern "C" fn(*mut c_void), *mut c_void),
}
fn main() -> io::Result<Option<i32>> {
let cmd = match CommandLineProgram::parse_or_run() {
None => return Ok(Some(0)),
Some(cmd) => cmd,
};
if cmd.shell_mode {
return Ok(None);
}
let mut terminal = input::Terminal::setup();
let mut command = Command::new(env::current_exe()?);
if !cmd.bitmap {
command
.arg("--disable-threaded-scrolling")
.arg("--disable-threaded-animation");
}
let output = command
.args(cmd.args)
.env(EnvVar::ShellMode, "1")
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::piped())
.output()?;
terminal.teardown();
let code = output.status.code().unwrap_or(127);
if code != 0 || cmd.debug {
io::stderr().write_all(&output.stderr)?;
}
Ok(Some(code))
}
#[no_mangle]
pub extern "C" fn carbonyl_bridge_main() {
if let Some(code) = main().unwrap() {
std::process::exit(code)
}
}
#[no_mangle]
pub extern "C" fn carbonyl_bridge_bitmap_mode() -> bool {
CommandLine::parse().bitmap
}
#[no_mangle]
pub extern "C" fn carbonyl_bridge_get_dpi() -> c_float {
Window::read().dpi
}
#[no_mangle]
pub extern "C" fn carbonyl_renderer_create() -> RendererPtr {
let bridge = RendererBridge {
cmd: CommandLine::parse(),
window: Window::read(),
renderer: RenderThread::new(),
};
Box::into_raw(Box::new(Mutex::new(bridge)))
}
#[no_mangle]
pub extern "C" fn carbonyl_renderer_start(bridge: RendererPtr) {
{
let bridge = unsafe { bridge.as_ref() };
let mut bridge = bridge.unwrap().lock().unwrap();
bridge.renderer.enable()
}
carbonyl_renderer_resize(bridge);
}
#[no_mangle]
pub extern "C" fn carbonyl_renderer_resize(bridge: RendererPtr) {
let bridge = unsafe { bridge.as_ref() };
let mut bridge = bridge.unwrap().lock().unwrap();
let window = bridge.window.update();
let cells = window.cells.clone();
log::debug!("resizing renderer, terminal window: {:?}", window);
bridge
.renderer
.render(move |renderer| renderer.set_size(cells));
}
#[no_mangle]
pub extern "C" fn carbonyl_renderer_push_nav(
bridge: RendererPtr,
url: *const c_char,
can_go_back: bool,
can_go_forward: bool,
) {
let (bridge, url) = unsafe { (bridge.as_ref(), CStr::from_ptr(url)) };
let (mut bridge, url) = (bridge.unwrap().lock().unwrap(), url.to_owned());
bridge.renderer.render(move |renderer| {
renderer.push_nav(url.to_str().unwrap(), can_go_back, can_go_forward)
});
}
#[no_mangle]
pub extern "C" fn carbonyl_renderer_set_title(bridge: RendererPtr, title: *const c_char) {
let (bridge, title) = unsafe { (bridge.as_ref(), CStr::from_ptr(title)) };
let (mut bridge, title) = (bridge.unwrap().lock().unwrap(), title.to_owned());
bridge
.renderer
.render(move |renderer| renderer.set_title(title.to_str().unwrap()).unwrap());
}
#[no_mangle]
pub extern "C" fn carbonyl_renderer_draw_text(
bridge: RendererPtr,
text: *const CText,
text_size: size_t,
) {
let (bridge, text) = unsafe { (bridge.as_ref(), std::slice::from_raw_parts(text, text_size)) };
let mut bridge = bridge.unwrap().lock().unwrap();
let mut vec = text
.iter()
.map(|text| {
let str = unsafe { CStr::from_ptr(text.text) };
(
str.to_str().unwrap().to_owned(),
text.rect.origin.into(),
text.rect.size.into(),
text.color.into(),
)
})
.collect::<Vec<(String, Point, Size, Color)>>();
bridge.renderer.render(move |renderer| {
renderer.clear_text();
for (text, origin, size, color) in std::mem::take(&mut vec) {
renderer.draw_text(&text, origin, size, color)
}
});
}
#[derive(Clone, Copy)]
struct CallbackData(*const c_void);
impl CallbackData {
pub fn as_ptr(&self) -> *const c_void {
self.0
}
}
unsafe impl Send for CallbackData {}
unsafe impl Sync for CallbackData {}
#[no_mangle]
pub extern "C" fn carbonyl_renderer_draw_bitmap(
bridge: RendererPtr,
pixels: *const c_uchar,
pixels_size: CSize,
rect: CRect,
callback: extern "C" fn(*const c_void),
callback_data: *const c_void,
) {
let length = (pixels_size.width * pixels_size.height * 4) as usize;
let (bridge, pixels) = unsafe { (bridge.as_ref(), std::slice::from_raw_parts(pixels, length)) };
let callback_data = CallbackData(callback_data);
let mut bridge = bridge.unwrap().lock().unwrap();
bridge.renderer.render(move |renderer| {
renderer.draw_background(
pixels,
pixels_size.into(),
Rect {
size: rect.size.into(),
origin: rect.origin.into(),
},
);
callback(callback_data.as_ptr());
});
}
#[no_mangle]
pub extern "C" fn carbonyl_renderer_get_size(bridge: RendererPtr) -> CSize {
let bridge = unsafe { bridge.as_ref() };
let bridge = bridge.unwrap().lock().unwrap();
log::debug!("terminal size: {:?}", bridge.window.browser);
bridge.window.browser.into()
}
extern "C" fn post_task_handler(callback: *mut c_void) {
let mut closure = unsafe { Box::from_raw(callback as *mut Box<dyn FnMut()>) };
closure()
}
unsafe fn post_task<F>(handle: extern "C" fn(extern "C" fn(*mut c_void), *mut c_void), run: F)
where
F: FnMut() + Send + 'static,
{
let closure: *mut Box<dyn FnMut()> = Box::into_raw(Box::new(Box::new(run)));
handle(post_task_handler, closure as *mut c_void);
}
/// Function called by the C++ code to listen for input events.
///
/// This will block so the calling code should start and own a dedicated thread.
/// It will panic if there is any error.
#[no_mangle]
pub extern "C" fn carbonyl_renderer_listen(bridge: RendererPtr, delegate: *mut BrowserDelegate) {
let bridge = unsafe { &*bridge };
let delegate = unsafe { *delegate };
use input::*;
thread::spawn(move || {
macro_rules! emit {
($event:ident($($args:expr),*) => $closure:expr) => {{
let run = move || {
(delegate.$event)($($args),*);
$closure
};
unsafe { post_task(delegate.post_task, run) }
}};
($event:ident($($args:expr),*)) => {{
emit!($event($($args),*) => {})
}};
}
listen(|mut events| {
bridge.lock().unwrap().renderer.render(move |renderer| {
let get_scale = || bridge.lock().unwrap().window.scale;
let scale = |col, row| {
let scale = get_scale();
scale
.mul(((col as f32 + 0.5), (row as f32 - 0.5)))
.floor()
.cast()
.into()
};
let dispatch = |action| {
match action {
NavigationAction::Ignore => (),
NavigationAction::Forward => return true,
NavigationAction::GoBack() => emit!(go_back()),
NavigationAction::GoForward() => emit!(go_forward()),
NavigationAction::Refresh() => emit!(refresh()),
NavigationAction::GoTo(url) => {
let c_str = CString::new(url).unwrap();
emit!(go_to(c_str.as_ptr()))
}
};
return false;
};
for event in std::mem::take(&mut events) {
use Event::*;
match event {
Exit => (),
Scroll { delta } => {
let scale = get_scale();
emit!(scroll((delta as f32 * scale.height) as c_int))
}
KeyPress { key } => {
if dispatch(renderer.keypress(&key).unwrap()) {
emit!(key_press(key.char as c_char))
}
}
MouseUp { col, row } => {
if dispatch(renderer.mouse_up((col as _, row as _).into()).unwrap()) {
let (width, height) = scale(col, row);
emit!(mouse_up(width, height))
}
}
MouseDown { col, row } => {
if dispatch(renderer.mouse_down((col as _, row as _).into()).unwrap()) {
let (width, height) = scale(col, row);
emit!(mouse_down(width, height))
}
}
MouseMove { col, row } => {
if dispatch(renderer.mouse_move((col as _, row as _).into()).unwrap()) {
let (width, height) = scale(col, row);
emit!(mouse_move(width, height))
}
}
Terminal(terminal) => match terminal {
TerminalEvent::Name(name) => log::debug!("terminal name: {name}"),
TerminalEvent::TrueColorSupported => renderer.enable_true_color(),
},
}
}
})
})
.unwrap();
// Setup single-use channel
let (tx, rx) = mpsc::channel();
// Signal the browser to shutdown and notify our thread
emit!(shutdown() => tx.send(()).unwrap());
rx.recv().unwrap();
// Shutdown rendering thread
// if let Some(handle) = { bridge.lock().unwrap().renderer().stop() } {
// handle.join().unwrap()
// }
});
}
================================================
FILE: src/browser/carbonyl.mojom
================================================
// Our C++ bindings will be in the carbonyl::mojom namespace
module carbonyl.mojom;
// Import existing bindings to common structures
import "ui/gfx/geometry/mojom/geometry.mojom";
import "skia/public/mojom/skcolor.mojom";
// Define a structure to hold text to render
struct TextData {
// An UTF-8 string with the contents
string contents;
// Bounds, size only defined for clearing
gfx.mojom.RectF bounds;
// Color of the text
skia.mojom.SkColor color;
};
// The browser process runs this service
interface CarbonylRenderService {
// The renderer process calls this method
DrawText(array<TextData> data);
};
================================================
FILE: src/browser/export.h
================================================
#ifndef CARBONYL_SRC_BROWSER_BRIDGE_EXPORT_H_
#define CARBONYL_SRC_BROWSER_BRIDGE_EXPORT_H_
// CARBONYL_BRIDGE_EXPORT
#if defined(COMPONENT_BUILD)
#if defined(WIN32)
#if defined(CARBONYL_BRIDGE_IMPLEMENTATION)
#define CARBONYL_BRIDGE_EXPORT __declspec(dllexport)
#else
#define CARBONYL_BRIDGE_EXPORT __declspec(dllimport)
#endif
#else // !defined(WIN32)
#if defined(CARBONYL_BRIDGE_IMPLEMENTATION)
#define CARBONYL_BRIDGE_EXPORT __attribute__((visibility("default")))
#else
#define CARBONYL_BRIDGE_EXPORT
#endif
#endif
#else // !defined(COMPONENT_BUILD)
#define CARBONYL_BRIDGE_EXPORT
#endif
// CARBONYL_RENDERER_EXPORT
#if defined(COMPONENT_BUILD)
#if defined(WIN32)
#if defined(CARBONYL_RENDERER_IMPLEMENTATION)
#define CARBONYL_RENDERER_EXPORT __declspec(dllexport
gitextract_4jcv0hr0/
├── .cargo/
│ └── config.toml
├── .dockerignore
├── .github/
│ └── funding.yml
├── .gitignore
├── .gitmodules
├── .refloat/
│ └── config.js
├── Cargo.toml
├── Dockerfile
├── build.rs
├── changelog.md
├── chromium/
│ ├── .gclient
│ └── patches/
│ ├── chromium/
│ │ ├── 0001-Add-Carbonyl-library.patch
│ │ ├── 0002-Add-Carbonyl-service.patch
│ │ ├── 0003-Setup-shared-software-rendering-surface.patch
│ │ ├── 0004-Setup-browser-default-settings.patch
│ │ ├── 0005-Remove-some-debug-assertions.patch
│ │ ├── 0006-Setup-display-DPI.patch
│ │ ├── 0007-Disable-text-effects.patch
│ │ ├── 0008-Fix-text-layout.patch
│ │ ├── 0009-Bridge-browser-into-Carbonyl-library.patch
│ │ ├── 0010-Conditionally-enable-text-rendering.patch
│ │ ├── 0011-Rename-carbonyl-Renderer-to-carbonyl-Bridge.patch
│ │ ├── 0012-Create-separate-bridge-for-Blink.patch
│ │ ├── 0013-Refactor-rendering-bridge.patch
│ │ └── 0014-Move-Skia-text-rendering-control-to-bridge.patch
│ ├── skia/
│ │ ├── 0001-Disable-text-rendering.patch
│ │ └── 0002-Export-some-private-APIs.patch
│ └── webrtc/
│ └── 0001-Disable-GIO-on-Linux.patch
├── cliff.toml
├── license.md
├── package.json
├── readme.md
├── scripts/
│ ├── build.sh
│ ├── changelog.sh
│ ├── copy-binaries.sh
│ ├── docker-build.sh
│ ├── docker-push.sh
│ ├── env.sh
│ ├── gclient.sh
│ ├── gn.sh
│ ├── npm-package.mjs
│ ├── npm-package.sh
│ ├── npm-publish.sh
│ ├── patches.sh
│ ├── platform-triple.sh
│ ├── release.sh
│ ├── restore-mtime.sh
│ ├── run.sh
│ ├── runtime-hash.sh
│ ├── runtime-pull.sh
│ └── runtime-push.sh
└── src/
├── browser/
│ ├── BUILD.gn
│ ├── args.gn
│ ├── bridge.cc
│ ├── bridge.h
│ ├── bridge.rs
│ ├── carbonyl.mojom
│ ├── export.h
│ ├── host_display_client.cc
│ ├── host_display_client.h
│ ├── render_service_impl.cc
│ ├── render_service_impl.h
│ ├── renderer.cc
│ └── renderer.h
├── browser.rs
├── cli/
│ ├── cli.rs
│ ├── program.rs
│ └── usage.txt
├── cli.rs
├── gfx/
│ ├── color.rs
│ ├── point.rs
│ ├── rect.rs
│ ├── size.rs
│ └── vector.rs
├── gfx.rs
├── input/
│ ├── dcs/
│ │ ├── control_flow.rs
│ │ ├── parser.rs
│ │ ├── resource.rs
│ │ └── status.rs
│ ├── dcs.rs
│ ├── keyboard.rs
│ ├── listen.rs
│ ├── mouse.rs
│ ├── parser.rs
│ └── tty.rs
├── input.rs
├── lib.rs
├── output/
│ ├── cell.rs
│ ├── frame_sync.rs
│ ├── kd_tree.rs
│ ├── painter.rs
│ ├── quad.rs
│ ├── quantizer.rs
│ ├── render_thread.rs
│ ├── renderer.rs
│ ├── window.rs
│ └── xterm.rs
├── output.rs
├── ui/
│ └── navigation.rs
├── ui.rs
├── utils/
│ ├── four_bits.rs
│ ├── log.rs
│ └── try_block.rs
└── utils.rs
SYMBOL INDEX (232 symbols across 39 files)
FILE: build.rs
function link_sysroot (line 4) | fn link_sysroot() {
function link_sysroot (line 21) | fn link_sysroot() {
function link_sysroot (line 38) | fn link_sysroot() {
function main (line 42) | fn main() {
FILE: scripts/npm-package.mjs
function buildMain (line 26) | async function buildMain() {
function buildPlatform (line 96) | async function buildPlatform([os, npmOs, llvmOs], [cpu, npmCpu, llvmCpu]) {
FILE: src/browser/bridge.cc
type carbonyl (line 10) | namespace carbonyl {
FILE: src/browser/bridge.h
function namespace (line 6) | namespace carbonyl {
FILE: src/browser/bridge.rs
type CSize (line 17) | pub struct CSize {
method from (line 69) | fn from(value: Size<c_uint>) -> Self {
type CPoint (line 23) | pub struct CPoint {
type CRect (line 29) | pub struct CRect {
type CColor (line 35) | pub struct CColor {
type CText (line 42) | pub struct CText {
type RendererBridge (line 49) | pub struct RendererBridge {
type RendererPtr (line 58) | pub type RendererPtr = *const Mutex<RendererBridge>;
function from (line 64) | fn from(value: CPoint) -> Self {
function from (line 80) | fn from(value: CSize) -> Self {
method from (line 85) | fn from(value: CColor) -> Self {
type BrowserDelegate (line 92) | pub struct BrowserDelegate {
function main (line 106) | fn main() -> io::Result<Option<i32>> {
function carbonyl_bridge_main (line 145) | pub extern "C" fn carbonyl_bridge_main() {
function carbonyl_bridge_bitmap_mode (line 152) | pub extern "C" fn carbonyl_bridge_bitmap_mode() -> bool {
function carbonyl_bridge_get_dpi (line 157) | pub extern "C" fn carbonyl_bridge_get_dpi() -> c_float {
function carbonyl_renderer_create (line 162) | pub extern "C" fn carbonyl_renderer_create() -> RendererPtr {
function carbonyl_renderer_start (line 173) | pub extern "C" fn carbonyl_renderer_start(bridge: RendererPtr) {
function carbonyl_renderer_resize (line 185) | pub extern "C" fn carbonyl_renderer_resize(bridge: RendererPtr) {
function carbonyl_renderer_push_nav (line 199) | pub extern "C" fn carbonyl_renderer_push_nav(
function carbonyl_renderer_set_title (line 214) | pub extern "C" fn carbonyl_renderer_set_title(bridge: RendererPtr, title...
function carbonyl_renderer_draw_text (line 224) | pub extern "C" fn carbonyl_renderer_draw_text(
type CallbackData (line 255) | struct CallbackData(*const c_void);
method as_ptr (line 258) | pub fn as_ptr(&self) -> *const c_void {
function carbonyl_renderer_draw_bitmap (line 267) | pub extern "C" fn carbonyl_renderer_draw_bitmap(
function carbonyl_renderer_get_size (line 295) | pub extern "C" fn carbonyl_renderer_get_size(bridge: RendererPtr) -> CSi...
function post_task_handler (line 304) | extern "C" fn post_task_handler(callback: *mut c_void) {
function post_task (line 310) | unsafe fn post_task<F>(handle: extern "C" fn(extern "C" fn(*mut c_void),...
function carbonyl_renderer_listen (line 324) | pub extern "C" fn carbonyl_renderer_listen(bridge: RendererPtr, delegate...
FILE: src/browser/host_display_client.cc
type carbonyl (line 20) | namespace carbonyl {
FILE: src/browser/host_display_client.h
type base (line 15) | typedef base::RepeatingCallback<void(const gfx::Rect&, const SkBitmap&)>
FILE: src/browser/render_service_impl.cc
type carbonyl (line 7) | namespace carbonyl {
FILE: src/browser/render_service_impl.h
function namespace (line 9) | namespace carbonyl {
FILE: src/browser/renderer.cc
type carbonyl_renderer_size (line 14) | struct carbonyl_renderer_size {
type carbonyl_renderer_point (line 18) | struct carbonyl_renderer_point {
type carbonyl_renderer_rect (line 22) | struct carbonyl_renderer_rect {
type carbonyl_renderer_point (line 23) | struct carbonyl_renderer_point
type carbonyl_renderer_size (line 24) | struct carbonyl_renderer_size
type carbonyl_renderer_color (line 26) | struct carbonyl_renderer_color {
type carbonyl_renderer_text (line 31) | struct carbonyl_renderer_text {
type carbonyl_renderer (line 41) | struct carbonyl_renderer
type carbonyl_renderer (line 42) | struct carbonyl_renderer
type carbonyl_renderer (line 43) | struct carbonyl_renderer
type carbonyl_renderer_size (line 44) | struct carbonyl_renderer_size
type carbonyl_renderer (line 44) | struct carbonyl_renderer
type carbonyl_renderer (line 45) | struct carbonyl_renderer
type carbonyl_renderer (line 46) | struct carbonyl_renderer
type carbonyl_renderer (line 47) | struct carbonyl_renderer
type carbonyl_renderer (line 48) | struct carbonyl_renderer
type carbonyl_renderer_browser_delegate (line 48) | struct carbonyl_renderer_browser_delegate
type carbonyl_renderer (line 50) | struct carbonyl_renderer
type carbonyl_renderer_text (line 51) | struct carbonyl_renderer_text
type carbonyl_renderer (line 55) | struct carbonyl_renderer
type carbonyl_renderer_size (line 57) | struct carbonyl_renderer_size
type carbonyl_renderer_rect (line 58) | struct carbonyl_renderer_rect
type carbonyl_renderer_point (line 23) | struct carbonyl_renderer_point
type carbonyl_renderer_size (line 24) | struct carbonyl_renderer_size
type carbonyl (line 65) | namespace carbonyl {
type carbonyl_renderer (line 71) | struct carbonyl_renderer
function Renderer (line 82) | Renderer* Renderer::GetCurrent() {
type carbonyl_renderer_browser_delegate (line 109) | struct carbonyl_renderer_browser_delegate
type carbonyl_renderer_text (line 130) | struct carbonyl_renderer_text
FILE: src/browser/renderer.h
type carbonyl_renderer (line 13) | struct carbonyl_renderer
type carbonyl_renderer_browser_delegate (line 14) | struct carbonyl_renderer_browser_delegate {
function namespace (line 30) | namespace carbonyl {
FILE: src/cli/cli.rs
type CommandLine (line 6) | pub struct CommandLine {
method parse (line 39) | pub fn parse() -> CommandLine {
type EnvVar (line 16) | pub enum EnvVar {
method as_str (line 23) | pub fn as_str(&self) -> &'static str {
method as_ref (line 33) | fn as_ref(&self) -> &OsStr {
FILE: src/cli/program.rs
type CommandLineProgram (line 4) | pub enum CommandLineProgram {
method parse_or_run (line 11) | pub fn parse_or_run() -> Option<CommandLine> {
FILE: src/gfx/color.rs
type Color (line 5) | pub struct Color<T: Copy = u8> {
method from_iter (line 12) | pub fn from_iter<'a, T>(iter: &mut T) -> Option<Color>
method black (line 21) | pub fn black() -> Color {
FILE: src/gfx/point.rs
type Point (line 5) | pub struct Point<T: Copy = i32> {
method inside (line 11) | pub fn inside(&self, rect: Rect) -> bool {
FILE: src/gfx/rect.rs
type Rect (line 4) | pub struct Rect<P: Copy = i32, S: Copy = u32> {
function new (line 10) | pub fn new(x: P, y: P, width: S, height: S) -> Self {
FILE: src/gfx/size.rs
type Size (line 5) | pub struct Size<T: Copy = u32> {
FILE: src/gfx/vector.rs
type Vector2 (line 1) | pub trait Vector2<T>
method x (line 5) | fn x(&self) -> T;
method y (line 6) | fn y(&self) -> T;
type Vector3 (line 9) | pub trait Vector3<T>
method x (line 13) | fn x(&self) -> T;
method y (line 14) | fn y(&self) -> T;
method z (line 15) | fn z(&self) -> T;
type Cast (line 17) | pub trait Cast<T> {
method cast (line 18) | fn cast(self) -> T;
type ToIntUnchecked (line 21) | pub trait ToIntUnchecked<T> {
method to_int_unchecked (line 22) | unsafe fn to_int_unchecked(self) -> T;
FILE: src/input/dcs/parser.rs
type Sequence (line 6) | enum Sequence {
type DeviceControl (line 15) | pub struct DeviceControl {
method new (line 20) | pub fn new() -> Self {
method parse (line 24) | pub fn parse(&mut self, key: u8) -> ParseControlFlow {
FILE: src/input/dcs/resource.rs
type Sequence (line 7) | enum Sequence {
type ResourceParser (line 15) | pub struct ResourceParser {
method new (line 23) | pub fn new(code: u8) -> Self {
method parse (line 32) | pub fn parse(&mut self, key: u8) -> ParseControlFlow {
method push_char (line 55) | fn push_char(&mut self, key: u8) -> Sequence {
method parse_event (line 65) | fn parse_event(&self, key: u8) -> Option<Event> {
function read_hex_string (line 81) | fn read_hex_string(str: &[u8]) -> Option<String> {
FILE: src/input/dcs/status.rs
type Sequence (line 7) | enum Sequence {
type StatusParser (line 15) | pub struct StatusParser {
method new (line 24) | pub fn new(code: u8) -> Self {
method parse (line 32) | pub fn parse(&mut self, key: u8) -> ParseControlFlow {
method terminate (line 51) | fn terminate(&mut self) -> Sequence {
method push_char (line 59) | fn push_char(&mut self, key: u8) -> Sequence {
method push_value (line 65) | fn push_value(&mut self) -> Sequence {
method parse_event (line 73) | fn parse_event(&self, key: u8) -> Option<Event> {
FILE: src/input/keyboard.rs
type Keyboard (line 5) | pub struct Keyboard {
method new (line 29) | pub fn new() -> Self {
method key (line 34) | pub fn key(key: u8, modifiers: u8) -> Option<Event> {
method parse (line 53) | pub fn parse(&mut self, key: u8) -> ParseControlFlow {
type Key (line 10) | pub struct Key {
method from (line 70) | fn from(char: u8) -> Self {
type KeyModifiers (line 16) | pub struct KeyModifiers {
method parse (line 79) | pub fn parse(key: u8) -> Self {
type State (line 23) | enum State {
FILE: src/input/listen.rs
function listen (line 7) | pub fn listen<F>(mut callback: F) -> io::Result<()>
FILE: src/input/mouse.rs
type Mouse (line 8) | pub struct Mouse {
method new (line 16) | pub fn new() -> Self {
method parse (line 20) | pub fn parse(&mut self, key: u8) -> ParseControlFlow {
method read (line 31) | fn read(&mut self) -> Option<()> {
method get (line 50) | fn get(&mut self, key: u8) -> Option<Event> {
type Mask (line 78) | enum Mask {
type Output (line 85) | type Output = bool;
method bitand (line 87) | fn bitand(self, rhs: u32) -> bool {
FILE: src/input/parser.rs
type Parser (line 6) | pub struct Parser {
method new (line 42) | pub fn new() -> Parser {
method parse (line 46) | pub fn parse(&mut self, input: &[u8]) -> Vec<Event> {
type Sequence (line 12) | enum Sequence {
type TerminalEvent (line 23) | pub enum TerminalEvent {
type Event (line 29) | pub enum Event {
type ParseControlFlow (line 39) | pub type ParseControlFlow = ControlFlow<Option<Event>, Option<Event>>;
FILE: src/input/tty.rs
type Terminal (line 10) | pub struct Terminal {
method setup (line 24) | pub fn setup() -> Self {
method teardown (line 44) | pub fn teardown(&mut self) {
method drop (line 16) | fn drop(&mut self) {
type TTY (line 63) | enum TTY {
method stdin (line 71) | fn stdin() -> TTY {
method enter_alt_screen (line 83) | fn enter_alt_screen() -> io::Result<()> {
method quit_alt_screen (line 100) | fn quit_alt_screen() -> io::Result<()> {
method as_raw_fd (line 110) | fn as_raw_fd(self) -> RawFd {
constant SEQUENCES (line 68) | const SEQUENCES: [(u32, bool); 4] = [(1049, true), (1003, true), (1006, ...
type ToErr (line 118) | trait ToErr {
method to_err (line 119) | fn to_err(self) -> io::Result<()>;
method to_err (line 122) | fn to_err(self) -> io::Result<()> {
type TerminalSettings (line 133) | struct TerminalSettings {
method open (line 139) | fn open() -> io::Result<Self> {
method open_raw (line 151) | fn open_raw() -> io::Result<TerminalSettings> {
method make_raw (line 162) | fn make_raw(&mut self) {
method apply (line 173) | fn apply(&self) -> io::Result<()> {
FILE: src/output/cell.rs
type Grapheme (line 6) | pub struct Grapheme {
type Cell (line 16) | pub struct Cell {
method new (line 24) | pub fn new(x: u32, y: u32) -> Cell {
FILE: src/output/frame_sync.rs
type FrameSync (line 4) | pub struct FrameSync {
method new (line 10) | pub fn new(fps: f32) -> Self {
method start (line 18) | pub fn start(&mut self) {
method deadline (line 23) | pub fn deadline(&self) -> Instant {
FILE: src/output/kd_tree.rs
type KDNode (line 5) | struct KDNode {
method new (line 13) | fn new(colors: &[Color]) {
method nearest (line 20) | fn nearest(&self, color: Color<f64>, mut limit: f64) -> Option<(usize,...
FILE: src/output/painter.rs
type Painter (line 7) | pub struct Painter {
method new (line 19) | pub fn new() -> Painter {
method true_color (line 35) | pub fn true_color(&self) -> bool {
method set_true_color (line 39) | pub fn set_true_color(&mut self, true_color: bool) {
method begin (line 43) | pub fn begin(&mut self) -> io::Result<()> {
method end (line 47) | pub fn end(&mut self, cursor: Option<Point>) -> io::Result<()> {
method paint (line 65) | pub fn paint(&mut self, cell: &Cell) -> io::Result<()> {
FILE: src/output/quad.rs
function binarize_quandrant (line 5) | pub fn binarize_quandrant(
FILE: src/output/quantizer.rs
type Channel (line 4) | enum Channel {
constant COLOR_BUCKETS (line 10) | const COLOR_BUCKETS: usize = 8;
constant COLORS (line 11) | const COLORS: usize = 2_usize.pow(COLOR_BUCKETS as u32);
function palette_color (line 14) | pub fn palette_color(palette: &[Color; COLORS], color: Color) {
function distance (line 20) | fn distance(a: Color, b: Color) {}
function quantize (line 22) | pub fn quantize(pixels: &[u8]) -> [Color; COLORS] {
FILE: src/output/render_thread.rs
type RenderThread (line 14) | pub struct RenderThread {
method new (line 26) | pub fn new() -> Self {
method enable (line 35) | pub fn enable(&mut self) {
method stop (line 41) | pub fn stop(&mut self) -> Option<JoinHandle<()>> {
method render (line 51) | pub fn render<F>(&mut self, run: F)
method boot (line 59) | fn boot(rx: Receiver<Message>) {
method send (line 110) | fn send(&mut self, message: Message) {
type RenderClosure (line 19) | type RenderClosure = Box<dyn FnMut(&mut Renderer) + Send>;
type Message (line 20) | enum Message {
FILE: src/output/renderer.rs
type Renderer (line 18) | pub struct Renderer {
method new (line 26) | pub fn new() -> Renderer {
method enable_true_color (line 35) | pub fn enable_true_color(&mut self) {
method keypress (line 39) | pub fn keypress(&mut self, key: &Key) -> io::Result<NavigationAction> {
method mouse_up (line 44) | pub fn mouse_up(&mut self, origin: Point) -> io::Result<NavigationActi...
method mouse_down (line 49) | pub fn mouse_down(&mut self, origin: Point) -> io::Result<NavigationAc...
method mouse_move (line 54) | pub fn mouse_move(&mut self, origin: Point) -> io::Result<NavigationAc...
method push_nav (line 60) | pub fn push_nav(&mut self, url: &str, can_go_back: bool, can_go_forwar...
method get_size (line 64) | pub fn get_size(&self) -> Size {
method set_size (line 68) | pub fn set_size(&mut self, size: Size) {
method render (line 92) | pub fn render(&mut self) -> io::Result<()> {
method draw_background (line 127) | pub fn draw_background(&mut self, pixels: &[u8], pixels_size: Size, re...
method clear_text (line 178) | pub fn clear_text(&mut self) {
method set_title (line 184) | pub fn set_title(&self, title: &str) -> io::Result<()> {
method fill_rect (line 194) | pub fn fill_rect(&mut self, rect: Rect, color: Color) {
method draw (line 201) | pub fn draw<F>(&mut self, bounds: Rect, mut draw: F)
method draw_text (line 223) | pub fn draw_text(&mut self, string: &str, origin: Point, size: Size, c...
FILE: src/output/window.rs
type Window (line 8) | pub struct Window {
method read (line 23) | pub fn read() -> Window {
method update (line 37) | pub fn update(&mut self) -> &Self {
function parse_var (line 103) | fn parse_var<T: FromStr>(var: &str) -> Option<T> {
FILE: src/output/xterm.rs
method to_xterm (line 4) | pub fn to_xterm(&self) -> u8 {
FILE: src/ui/navigation.rs
type NavigationAction (line 11) | pub enum NavigationAction {
type NavigationElement (line 21) | pub struct NavigationElement {
type Navigation (line 27) | pub struct Navigation {
method new (line 36) | pub fn new() -> Self {
method cursor (line 46) | pub fn cursor(&self) -> Option<Point> {
method keypress (line 50) | pub fn keypress(&mut self, key: &Key) -> NavigationAction {
method display_url (line 99) | pub fn display_url(&self) -> &str {
method url_size (line 106) | pub fn url_size(&self) -> usize {
method mouse_up (line 110) | pub fn mouse_up(&mut self, origin: Point) -> NavigationAction {
method mouse_down (line 119) | pub fn mouse_down(&mut self, origin: Point) -> NavigationAction {
method mouse_move (line 142) | pub fn mouse_move(&mut self, _origin: Point) -> NavigationAction {
method push (line 146) | pub fn push(&mut self, url: &str, can_go_back: bool, can_go_forward: b...
method set_size (line 160) | pub fn set_size(&mut self, size: Size) {
method render_btn (line 164) | pub fn render_btn(&self, icon: &str, enabled: bool) -> [NavigationElem...
method render (line 191) | pub fn render(&self, size: Size) -> Vec<(Point, NavigationElement)> {
FILE: src/utils/four_bits.rs
type FourBits (line 1) | pub enum FourBits {
method new (line 21) | pub fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
FILE: src/utils/log.rs
function write (line 42) | pub fn write(level: &str, file: &str, line: u32, message: &str) {
Condensed preview — 104 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (298K chars).
[
{
"path": ".cargo/config.toml",
"chars": 29,
"preview": "[build]\ntarget-dir = \"build\"\n"
},
{
"path": ".dockerignore",
"chars": 33,
"preview": "/build\n!/build/browser\n/chromium\n"
},
{
"path": ".github/funding.yml",
"chars": 15,
"preview": "github: fathyb\n"
},
{
"path": ".gitignore",
"chars": 154,
"preview": ".DS_Store\nnode_modules/\n\n/.ccache\n/.git_cache\n/.vscode\n/build\n/chromium/*\n!/chromium/.gclient\n!/chromium/depot_tools\n!/c"
},
{
"path": ".gitmodules",
"chars": 136,
"preview": "[submodule \"chromium/depot_tools\"]\n\tpath = chromium/depot_tools\n\turl = https://chromium.googlesource.com/chromium/tools/"
},
{
"path": ".refloat/config.js",
"chars": 8581,
"preview": "import { commit } from \"refloat\";\nimport docker from \"github.com/refloat-plugins/docker\";\n\nimport pkg from \"../package.j"
},
{
"path": "Cargo.toml",
"chars": 236,
"preview": "[package]\nname = \"carbonyl\"\nversion = \"0.0.3\"\nedition = \"2021\"\n\n[dependencies]\nlibc = \"0.2\"\nunicode-width = \"0.1.10\"\nuni"
},
{
"path": "Dockerfile",
"chars": 1394,
"preview": "FROM rust:1.67 AS cross-compile\n\nRUN apt-get update && \\\n apt-get install -y \\\n zip g++-aarch64-linux-gnu g++-"
},
{
"path": "build.rs",
"chars": 1703,
"preview": "use std::path::PathBuf;\n\n#[cfg(target_arch = \"x86_64\")]\nfn link_sysroot() {\n let sysroot_path = PathBuf::from(\"./chro"
},
{
"path": "changelog.md",
"chars": 3070,
"preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\n## [0.0.3] - 2023-02-18\n\n### 🚀 Featur"
},
{
"path": "chromium/.gclient",
"chars": 286,
"preview": "solutions = [\n {\n \"name\": \"src\",\n \"url\": \"https://chromium.googlesource.com/chromium/src.git@111.0.5511.1\",\n \""
},
{
"path": "chromium/patches/chromium/0001-Add-Carbonyl-library.patch",
"chars": 1918,
"preview": "From 0ed9a390f25d73492ce1170ce229b95772fd458d Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Thu, 9"
},
{
"path": "chromium/patches/chromium/0002-Add-Carbonyl-service.patch",
"chars": 22372,
"preview": "From 795b29828fd7ac95548c4dcab483cbc3b6c1d361 Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Thu, 9"
},
{
"path": "chromium/patches/chromium/0003-Setup-shared-software-rendering-surface.patch",
"chars": 10011,
"preview": "From eea9662f4ba08a655057143d320e4e692fd92469 Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Thu, 9"
},
{
"path": "chromium/patches/chromium/0004-Setup-browser-default-settings.patch",
"chars": 1873,
"preview": "From c960c9b1f7ef3f16b27e4eaa4896e3563c88ea91 Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Thu, 9"
},
{
"path": "chromium/patches/chromium/0005-Remove-some-debug-assertions.patch",
"chars": 5672,
"preview": "From 481ff19118891fe65e80b8be0e1f4498874d3b56 Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Thu, 9"
},
{
"path": "chromium/patches/chromium/0006-Setup-display-DPI.patch",
"chars": 6139,
"preview": "From cc9c37adb3ad2613a114bd37e1fde43f83951d88 Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Sun, 1"
},
{
"path": "chromium/patches/chromium/0007-Disable-text-effects.patch",
"chars": 5276,
"preview": "From 022ed4d808369659eab4e83cd677eb974215c58c Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Thu, 9"
},
{
"path": "chromium/patches/chromium/0008-Fix-text-layout.patch",
"chars": 1758,
"preview": "From 7b1f72900f704ffecc48c66da7ccd6de205b88f7 Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Thu, 9"
},
{
"path": "chromium/patches/chromium/0009-Bridge-browser-into-Carbonyl-library.patch",
"chars": 19732,
"preview": "From 792e123bb57b1b379b0367b2568302e2cb0dc3c9 Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Thu, 9"
},
{
"path": "chromium/patches/chromium/0010-Conditionally-enable-text-rendering.patch",
"chars": 5169,
"preview": "From bdc80f35a7113b7523c4d992edc9170db082deb0 Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Sun, 1"
},
{
"path": "chromium/patches/chromium/0011-Rename-carbonyl-Renderer-to-carbonyl-Bridge.patch",
"chars": 6026,
"preview": "From fa52dbb68b7822ee4c01a697197e68ef1ab4a19c Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Sun, 1"
},
{
"path": "chromium/patches/chromium/0012-Create-separate-bridge-for-Blink.patch",
"chars": 3329,
"preview": "From 6862e372717eff278470453e800dc693f33b873c Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Sun, 1"
},
{
"path": "chromium/patches/chromium/0013-Refactor-rendering-bridge.patch",
"chars": 39760,
"preview": "From 3b67b346ec26a47b50178124d715a8320f612d4d Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Mon, 1"
},
{
"path": "chromium/patches/chromium/0014-Move-Skia-text-rendering-control-to-bridge.patch",
"chars": 1571,
"preview": "From 2275364ee7e16ba6b46f0f339e34326d4a8c7584 Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Mon, 1"
},
{
"path": "chromium/patches/skia/0001-Disable-text-rendering.patch",
"chars": 1370,
"preview": "From 218fbf4bba772c465712c4ea442adb57968e9c22 Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Mon, 1"
},
{
"path": "chromium/patches/skia/0002-Export-some-private-APIs.patch",
"chars": 2675,
"preview": "From a271b203a2b60f0cd450bda0fa2cc14885f1d9a8 Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Thu, 9"
},
{
"path": "chromium/patches/webrtc/0001-Disable-GIO-on-Linux.patch",
"chars": 763,
"preview": "From 5ad57c96f23739717bcea018baf2bc8f4157b01d Mon Sep 17 00:00:00 2001\nFrom: Fathy Boundjadj <hey@fathy.fr>\nDate: Mon, 1"
},
{
"path": "cliff.toml",
"chars": 1445,
"preview": "[changelog]\nheader = \"\"\"\n# Changelog\\n\nAll notable changes to this project will be documented in this file.\\n\n\"\"\"\nbody ="
},
{
"path": "license.md",
"chars": 1485,
"preview": "_Copyright © 2023, Fathy Boundjadj_\n_All rights reserved._\n\nRedistribution and use in source and binary forms, with or w"
},
{
"path": "package.json",
"chars": 76,
"preview": "{\n \"name\": \"carbonyl\",\n \"version\": \"0.0.3\",\n \"license\": \"BSD-3-Clause\"\n}\n"
},
{
"path": "readme.md",
"chars": 6184,
"preview": "<table align=\"center\">\n <tbody>\n <tr>\n <td>\n <p></p>\n <pre>\n O O\n \\ /\nO —— Cr —— O\n /"
},
{
"path": "scripts/build.sh",
"chars": 919,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- \"$(pwd)\")\nexport INSTALL_DEPOT_TOOLS=\"tr"
},
{
"path": "scripts/changelog.sh",
"chars": 211,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- $(pwd))\n\ncd \"$CARBONYL_ROOT\"\nsource \"scr"
},
{
"path": "scripts/copy-binaries.sh",
"chars": 959,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- $(pwd))\n\ncd \"$CARBONYL_ROOT\"\nsource \"scr"
},
{
"path": "scripts/docker-build.sh",
"chars": 508,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- \"$(pwd)\")\n\ncd \"$CARBONYL_ROOT\"\nsource \"s"
},
{
"path": "scripts/docker-push.sh",
"chars": 586,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- \"$(pwd)\")\n\nsource \"$CARBONYL_ROOT/script"
},
{
"path": "scripts/env.sh",
"chars": 644,
"preview": "#!/usr/bin/env bash\n\nset -eo pipefail\n\nif [ -z \"$CARBONYL_ROOT\" ]; then\n echo \"CARBONYL_ROOT should be defined\"\n\n "
},
{
"path": "scripts/gclient.sh",
"chars": 213,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- \"$(pwd)\")\nexport INSTALL_DEPOT_TOOLS=\"tr"
},
{
"path": "scripts/gn.sh",
"chars": 207,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- \"$(pwd)\")\nexport INSTALL_DEPOT_TOOLS=\"tr"
},
{
"path": "scripts/npm-package.mjs",
"chars": 4035,
"preview": "import fs from \"fs/promises\";\nimport path from \"path\";\nimport { fileURLToPath } from \"url\";\n\nconst dirname = path.dirnam"
},
{
"path": "scripts/npm-package.sh",
"chars": 229,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- $(pwd))\n\ncd \"$CARBONYL_ROOT\"\nsource \"scr"
},
{
"path": "scripts/npm-publish.sh",
"chars": 382,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- $(pwd))\n\ncd \"$CARBONYL_ROOT\"\nsource \"scr"
},
{
"path": "scripts/patches.sh",
"chars": 2252,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- \"$(pwd)\")\n\nsource \"$CARBONYL_ROOT/script"
},
{
"path": "scripts/platform-triple.sh",
"chars": 722,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- $(pwd))\n\nsource \"$CARBONYL_ROOT/scripts/"
},
{
"path": "scripts/release.sh",
"chars": 310,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- $(pwd))\n\ncd \"$CARBONYL_ROOT\"\nsource \"scr"
},
{
"path": "scripts/restore-mtime.sh",
"chars": 299,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- $(pwd))\n\nsource \"$CARBONYL_ROOT/scripts/"
},
{
"path": "scripts/run.sh",
"chars": 198,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- \"$(pwd)\")\n\nsource \"$CARBONYL_ROOT/script"
},
{
"path": "scripts/runtime-hash.sh",
"chars": 448,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- $(pwd))\n\ncd \"$CARBONYL_ROOT\"\nsource \"scr"
},
{
"path": "scripts/runtime-pull.sh",
"chars": 714,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- $(pwd))\n\ncd \"$CARBONYL_ROOT\"\nsource \"scr"
},
{
"path": "scripts/runtime-push.sh",
"chars": 774,
"preview": "#!/usr/bin/env bash\n\nexport CARBONYL_ROOT=$(cd $(dirname -- \"$0\") && dirname -- $(pwd))\n\ncd \"$CARBONYL_ROOT\"\nsource \"scr"
},
{
"path": "src/browser/BUILD.gn",
"chars": 1335,
"preview": "import(\"//build/config/compiler/compiler.gni\")\nimport(\"//mojo/public/tools/bindings/mojom.gni\")\n\nmojom(\"mojom\") {\n sour"
},
{
"path": "src/browser/args.gn",
"chars": 1148,
"preview": "headless_enable_commands = false\nheadless_use_embedded_resources = true\n\n# Enable proprietary codecs such as H.264\nffmpe"
},
{
"path": "src/browser/bridge.cc",
"chars": 360,
"preview": "#include \"carbonyl/src/browser/bridge.h\"\n\nnamespace {\n\nfloat dpi_ = 0.0;\nbool bitmap_mode_ = false;\n\n}\n\nnamespace carbon"
},
{
"path": "src/browser/bridge.h",
"chars": 422,
"preview": "#ifndef CARBONYL_SRC_BROWSER_BRIDGE_H_\n#define CARBONYL_SRC_BROWSER_BRIDGE_H_\n\n#include \"carbonyl/src/browser/export.h\"\n"
},
{
"path": "src/browser/bridge.rs",
"chars": 12450,
"preview": "use std::ffi::{CStr, CString};\nuse std::io::Write;\nuse std::process::{Command, Stdio};\nuse std::sync::{mpsc, Mutex};\nuse"
},
{
"path": "src/browser/carbonyl.mojom",
"chars": 642,
"preview": "// Our C++ bindings will be in the carbonyl::mojom namespace\nmodule carbonyl.mojom;\n\n// Import existing bindings to comm"
},
{
"path": "src/browser/export.h",
"chars": 1667,
"preview": "#ifndef CARBONYL_SRC_BROWSER_BRIDGE_EXPORT_H_\n#define CARBONYL_SRC_BROWSER_BRIDGE_EXPORT_H_\n\n// CARBONYL_BRIDGE_EXPORT\n#"
},
{
"path": "src/browser/host_display_client.cc",
"chars": 2286,
"preview": "#include \"carbonyl/src/browser/host_display_client.h\"\n\n#include <utility>\n\n#include \"components/viz/common/resources/res"
},
{
"path": "src/browser/host_display_client.h",
"chars": 2384,
"preview": "#ifndef CARBONYL_SRC_BROWSER_HOST_DISPLAY_CLIENT_H_\n#define CARBONYL_SRC_BROWSER_HOST_DISPLAY_CLIENT_H_\n\n#include <memor"
},
{
"path": "src/browser/render_service_impl.cc",
"chars": 647,
"preview": "#include \"carbonyl/src/browser/render_service_impl.h\"\n\n#include <iostream>\n\n#include \"carbonyl/src/browser/renderer.h\"\n\n"
},
{
"path": "src/browser/render_service_impl.h",
"chars": 985,
"preview": "#ifndef CARBONYL_SRC_BROWSER_RENDER_SERVICE_IMPL_H_\n#define CARBONYL_SRC_BROWSER_RENDER_SERVICE_IMPL_H_\n\n#include \"carbo"
},
{
"path": "src/browser/renderer.cc",
"chars": 4925,
"preview": "#include \"carbonyl/src/browser/renderer.h\"\n\n#include <memory>\n#include <iostream>\n#include <stdio.h>\n\n#include \"base/fun"
},
{
"path": "src/browser/renderer.h",
"chars": 1793,
"preview": "#ifndef CARBONYL_SRC_BROWSER_RENDERER_H_\n#define CARBONYL_SRC_BROWSER_RENDERER_H_\n\n#include <cstdint>\n#include <function"
},
{
"path": "src/browser.rs",
"chars": 32,
"preview": "mod bridge;\n\npub use bridge::*;\n"
},
{
"path": "src/cli/cli.rs",
"chars": 2786,
"preview": "use std::{env, ffi::OsStr};\n\nuse super::CommandLineProgram;\n\n#[derive(Clone, Debug)]\npub struct CommandLine {\n pub ar"
},
{
"path": "src/cli/program.rs",
"chars": 591,
"preview": "use super::CommandLine;\n\n#[derive(Clone, Debug)]\npub enum CommandLineProgram {\n Main,\n Help,\n Version,\n}\n\nimpl "
},
{
"path": "src/cli/usage.txt",
"chars": 641,
"preview": " O O Carbonyl is a Chromium based browser for the terminal.\n \\ / \nO —— Cr —— O In addition to the "
},
{
"path": "src/cli.rs",
"chars": 59,
"preview": "mod cli;\nmod program;\n\npub use cli::*;\npub use program::*;\n"
},
{
"path": "src/gfx/color.rs",
"chars": 541,
"preview": "use super::Vector3;\nuse crate::impl_vector_overload;\n\n#[derive(Clone, Copy, Debug, PartialEq)]\npub struct Color<T: Copy "
},
{
"path": "src/gfx/point.rs",
"chars": 473,
"preview": "use super::{Rect, Vector2};\nuse crate::impl_vector_overload;\n\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npub struct Po"
},
{
"path": "src/gfx/rect.rs",
"chars": 377,
"preview": "use super::{Point, Size};\n\n#[derive(Clone, Copy, Debug, PartialEq)]\npub struct Rect<P: Copy = i32, S: Copy = u32> {\n "
},
{
"path": "src/gfx/size.rs",
"chars": 219,
"preview": "use super::Vector2;\nuse crate::impl_vector_overload;\n\n#[derive(Clone, Copy, Debug, PartialEq, Default)]\npub struct Size<"
},
{
"path": "src/gfx/vector.rs",
"chars": 12186,
"preview": "pub trait Vector2<T>\nwhere\n T: Copy,\n{\n fn x(&self) -> T;\n fn y(&self) -> T;\n}\n\npub trait Vector3<T>\nwhere\n "
},
{
"path": "src/gfx.rs",
"chars": 144,
"preview": "mod color;\nmod point;\nmod rect;\nmod size;\nmod vector;\n\npub use color::*;\npub use point::*;\npub use rect::*;\npub use size"
},
{
"path": "src/input/dcs/control_flow.rs",
"chars": 565,
"preview": "#[macro_export]\nmacro_rules! control_flow {\n (break) => {\n std::ops::ControlFlow::Break(None)\n };\n ($exp"
},
{
"path": "src/input/dcs/parser.rs",
"chars": 1055,
"preview": "use crate::{control_flow, input::ParseControlFlow};\n\nuse super::{resource::*, status::*};\n\n#[derive(Default, Clone)]\nenu"
},
{
"path": "src/input/dcs/resource.rs",
"chars": 2400,
"preview": "use crate::{\n control_flow,\n input::{Event, ParseControlFlow, TerminalEvent},\n};\n\n#[derive(Copy, Clone)]\nenum Sequ"
},
{
"path": "src/input/dcs/status.rs",
"chars": 2308,
"preview": "use crate::{\n control_flow,\n input::{Event, ParseControlFlow, TerminalEvent},\n};\n\n#[derive(Default, Clone)]\nenum S"
},
{
"path": "src/input/dcs.rs",
"chars": 76,
"preview": "mod control_flow;\nmod parser;\nmod resource;\nmod status;\n\npub use parser::*;\n"
},
{
"path": "src/input/keyboard.rs",
"chars": 2508,
"preview": "use crate::control_flow;\n\nuse super::{Event, ParseControlFlow};\n\npub struct Keyboard {\n state: State,\n}\n\n#[derive(Clo"
},
{
"path": "src/input/listen.rs",
"chars": 912,
"preview": "use std::io::{self, Read};\n\nuse crate::input::*;\n\n/// Listen for input events in stdin.\n/// This will block, so it shoul"
},
{
"path": "src/input/mouse.rs",
"chars": 2230,
"preview": "use std::ops::BitAnd;\n\nuse crate::{control_flow, utils::log};\n\nuse super::{Event, ParseControlFlow};\n\n#[derive(Default, "
},
{
"path": "src/input/parser.rs",
"chars": 3138,
"preview": "use std::ops::ControlFlow;\n\nuse crate::input::*;\n\n#[derive(Default)]\npub struct Parser {\n events: Vec<Event>,\n seq"
},
{
"path": "src/input/tty.rs",
"chars": 4342,
"preview": "use std::fs::File;\nuse std::io;\nuse std::io::Write;\nuse std::mem::MaybeUninit;\nuse std::os::fd::RawFd;\nuse std::os::unix"
},
{
"path": "src/input.rs",
"chars": 177,
"preview": "mod dcs;\nmod keyboard;\nmod listen;\nmod mouse;\nmod parser;\nmod tty;\n\npub use dcs::*;\npub use keyboard::*;\npub use listen:"
},
{
"path": "src/lib.rs",
"chars": 98,
"preview": "pub mod browser;\npub mod cli;\npub mod gfx;\npub mod input;\npub mod output;\npub mod ui;\n\nmod utils;\n"
},
{
"path": "src/output/cell.rs",
"chars": 827,
"preview": "use std::rc::Rc;\n\nuse crate::gfx::{Color, Point};\n\n#[derive(Clone, PartialEq)]\npub struct Grapheme {\n /// Unicode cha"
},
{
"path": "src/output/frame_sync.rs",
"chars": 1129,
"preview": "use std::time::{Duration, Instant};\n\n/// A utility to synchronize rendering with a given FPS\npub struct FrameSync {\n "
},
{
"path": "src/output/kd_tree.rs",
"chars": 1814,
"preview": "use std::ops::Mul;\n\nuse crate::gfx::Color;\n\nstruct KDNode {\n left: Option<Box<KDNode>>,\n right: Option<Box<KDNode>"
},
{
"path": "src/output/painter.rs",
"chars": 3838,
"preview": "use std::io::{self, Stdout, Write};\n\nuse crate::gfx::{Color, Point};\n\nuse super::{binarize_quandrant, Cell};\n\npub struct"
},
{
"path": "src/output/quad.rs",
"chars": 1628,
"preview": "use crate::gfx::Color;\nuse crate::utils::FourBits::{self, *};\n\n/// Turn a quadrant of four colors into two colors and a "
},
{
"path": "src/output/quantizer.rs",
"chars": 3144,
"preview": "use crate::gfx::Color;\n\n#[derive(Clone, Copy)]\nenum Channel {\n R,\n G,\n B,\n}\n\nconst COLOR_BUCKETS: usize = 8;\nco"
},
{
"path": "src/output/render_thread.rs",
"chars": 3513,
"preview": "use std::{\n sync::mpsc::{self, Receiver, Sender},\n thread::{self, JoinHandle},\n time::Instant,\n};\n\nuse crate::c"
},
{
"path": "src/output/renderer.rs",
"chars": 9042,
"preview": "use std::{\n io::{self, Write},\n rc::Rc,\n};\n\nuse unicode_segmentation::UnicodeSegmentation;\nuse unicode_width::Unic"
},
{
"path": "src/output/window.rs",
"chars": 3116,
"preview": "use core::mem::MaybeUninit;\nuse std::str::FromStr;\n\nuse crate::{cli::CommandLine, gfx::Size, utils::log};\n\n/// A termina"
},
{
"path": "src/output/xterm.rs",
"chars": 643,
"preview": "use crate::gfx::Color;\n\nimpl Color {\n pub fn to_xterm(&self) -> u8 {\n if self.max_val() - self.min_val() < 8 {"
},
{
"path": "src/output.rs",
"chars": 283,
"preview": "// mod kd_tree;\n// mod quantizer;\nmod cell;\nmod frame_sync;\nmod painter;\nmod quad;\nmod render_thread;\nmod renderer;\nmod "
},
{
"path": "src/ui/navigation.rs",
"chars": 6206,
"preview": "use std::env;\n\nuse unicode_width::UnicodeWidthStr;\n\nuse crate::{\n gfx::{Color, Point, Size},\n input::Key,\n util"
},
{
"path": "src/ui.rs",
"chars": 20,
"preview": "pub mod navigation;\n"
},
{
"path": "src/utils/four_bits.rs",
"chars": 1060,
"preview": "pub enum FourBits {\n B0000 = 0b0000,\n B0001 = 0b0001,\n B0010 = 0b0010,\n B0011 = 0b0011,\n B0100 = 0b0100,\n"
},
{
"path": "src/utils/log.rs",
"chars": 1187,
"preview": "use std::path::Path;\n\nuse chrono::prelude::*;\n\nuse crate::utils::try_block;\n\nmacro_rules! debug {\n ($($args:expr),+) "
},
{
"path": "src/utils/try_block.rs",
"chars": 106,
"preview": "macro_rules! try_block {\n ($block:expr) => {\n (|| $block)()\n };\n}\n\npub(crate) use try_block;\n"
},
{
"path": "src/utils.rs",
"chars": 86,
"preview": "mod four_bits;\nmod try_block;\n\npub mod log;\n\nuse try_block::*;\n\npub use four_bits::*;\n"
}
]
About this extraction
This page contains the full source code of the fathyb/carbonyl GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 104 files (274.8 KB), approximately 76.6k tokens, and a symbol index with 232 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.