Skip to content

martin-juul/electron-angle-patcher

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Electron Angle Patcher

Patch Electron and Chrome applications on macOS to use OpenGL rendering through the use-angle@1 setting.

Features

  • macOS Optimized: Designed specifically for macOS Electron applications
  • Auto-Discovery: Automatically finds apps in standard locations
  • Deep Scanning: Recursively searches directories comprehensively
  • Special App Support: Handles complex apps (Logitech G Hub, Teams, Brave)
  • Executable Wrapping: Modifies executables to pass --use-angle=gl
  • Network Mount Protection: Avoids scanning network-mounted volumes

Installation

Quick Start (Recommended)

Using uv (fast, 10-100x faster than pip):

# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# Clone and setup
git clone https://github.com/martin-juul/electron-angle-patcher.git
cd electron-angle-patcher
make init

Using venv (standard, built-in):

git clone https://github.com/martin-juul/electron-angle-patcher.git
cd electron-angle-patcher
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Using the setup script (interactive):

git clone https://github.com/martin-juul/electron-angle-patcher.git
cd electron-angle-patcher
./scripts/setup.sh

The setup script will:

  1. Check Python version (requires 3.10+)
  2. Optionally install uv for faster setup
  3. Create virtual environment
  4. Install dependencies
  5. Offer to run tests

From Source (Manual)

git clone https://github.com/martin-juul/electron-angle-patcher.git
cd electron-angle-patcher

# Option 1: With uv (fast)
uv venv
uv pip install -e ".[dev]"

# Option 2: With venv (standard)
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

Using pip (when published)

pip install electron-angle-patcher

Usage

Basic Usage

# Patch all detected applications
electron-angle-patcher

# List applications without patching
electron-angle-patcher --list-only

# Dry run: show what would be patched without making changes
electron-angle-patcher --dry-run

# Perform deep scan of home directory
electron-angle-patcher --deep-scan

# Enable verbose output
electron-angle-patcher -v

Advanced Usage

# Patch a specific application
electron-angle-patcher --app-path ~/Library/Application\ Support/MyApp/Local\ State --app-name "My App"

# Scan a custom directory
electron-angle-patcher --scan-dir ~/path/to/apps

# Specify custom Brave Browser path
electron-angle-patcher --brave-path ~/Applications/Brave\ Browser.app

# Specify custom lghub path
electron-angle-patcher --lghub-path ~/Applications/lghub.app

Running as Module

python -m electron_angle_patcher.cli --list-only

Development

Environment Management

This project supports uv (fast, recommended) or venv (standard).

Why uv?

  • 10-100x faster than pip
  • Better dependency resolution
  • Built-in lockfile support
  • From the creators of Ruff (which we also use)

Using uv (recommended):

# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# All make commands auto-detect and use uv if available
make init          # Set up environment with uv
make test          # Run tests with uv
make fmt           # Format with uv run ruff

Using venv (fallback):

# Standard setup
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

# Make commands auto-detect and use venv if uv is not available
make test
make fmt

Project Structure

electron-angle-patcher/
├── src/
│   └── electron_angle_patcher/
│       ├── __init__.py           # Public API exports
│       ├── app.py                # Main orchestrator (ElectronAnglePatcher)
│       ├── cli.py                # Command-line interface
│       ├── config.py             # Configuration constants
│       ├── models.py             # Data models (enums, dataclasses)
│       ├── utils.py              # Utility functions
│       ├── executable_patcher.py # Executable wrapping logic
│       ├── settings_patcher.py   # Local State file patching
│       └── scanner.py            # Directory scanning logic
├── tests/
│   ├── conftest.py               # Pytest configuration
│   ├── unit/                     # Unit tests
│   └── sandbox/                  # Test fixtures
├── scripts/
│   └── setup.sh                  # Interactive setup script
├── pyproject.toml                # Project configuration
├── Makefile                      # Common tasks (auto-detects uv)
└── README.md

Module Overview:

  • __init__.py - Public API exports, maintains backward compatibility
  • app.py - ElectronAnglePatcher main application class
  • cli.py - Command-line interface using argparse
  • config.py - Config class with all constants and settings
  • models.py - AngleVariant, PatchResult enums; AppInfo, PatchSummary dataclasses
  • utils.py - Helper functions (logging, permissions, file operations)
  • executable_patcher.py - ExecutableWrapper, BraveExecutablePatcher, LghubPatcher
  • settings_patcher.py - ChromiumSettingsPatcher for Local State files
  • scanner.py - LocalStateScanner for finding applications

Running Tests

# Run all tests
make test

# Run with coverage
make test-cov

# Run specific test file
pytest tests/unit/test_config.py

# Run with verbose output
pytest -v

# Run only unit tests
pytest -m unit

# Skip slow tests
pytest -m "not slow"

Code Quality

# Format code with ruff
make fmt

# Check linting
make lint

# Run type checking
make typecheck

# Run all checks
make check

Building and Installing

# Build Python package (wheel/source)
make build

# Build standalone binary (single executable)
make build-binary

# Build single-file binary (smaller, slower startup)
make build-binary-onefile

# Install locally
make install

# Install in development mode
make dev-install

# Generate/update lockfile (uv only)
make lock

# Update all dependencies (uv only)
make update-deps

CI Pipeline

For continuous integration or automated builds, use the CI target:

# Run complete CI pipeline:
# 1. Install dependencies (creates venv if needed)
# 2. Run all tests
# 3. Build standalone binary
make ci

The CI target:

  • Auto-detects and uses uv if available, otherwise falls back to venv
  • Creates a virtual environment if it doesn't exist
  • Installs all dependencies
  • Runs the test suite
  • Builds the standalone binary
  • Reports success/failure at each step

Building Standalone Binaries

This project can be compiled into a standalone binary that doesn't require Python installation:

# Option 1: Directory-based binary (faster startup)
make build-binary
# Output: dist/electron-angle-patcher

# Option 2: Single-file binary (smaller, slower startup)
make build-binary-onefile
# Output: dist/electron-angle-patcher

# Run the binary directly
./dist/electron-angle-patcher --help
./dist/electron-angle-patcher --list-only

Binary Features:

  • Self-contained: No Python or dependencies required
  • macOS optimized: Creates native macOS executables
  • Code signed: Uses ad-hoc signature for macOS
  • Smaller size: Only includes required dependencies

Building Manually with PyInstaller:

# Install PyInstaller
pip install pyinstaller

# Build using spec file (recommended)
pyinstaller electron_angle_patcher.spec

# Or build single-file directly
pyinstaller --onefile --name electron-angle-patcher \
  --console src/electron_angle_patcher/cli.py

Make Targets

Target Description
make help Show all available commands
make init Initialize dev environment (auto-detects uv)
make install-uv Install uv package manager
make ci CI pipeline: install deps, run tests, build
make build Build Python package
make build-binary Build standalone binary
make build-binary-onefile Build single-file binary
make test Run all tests
make test-cov Run with coverage report
make fmt Format code with ruff
make lint Check code with ruff
make typecheck Run mypy type checking
make check Run all quality checks
make run Run the patcher
make run-list Run in list-only mode

Configuration

The patcher searches for Chromium/Electron applications in the following locations:

Standard Directories

  • ~/Library/Application Support
  • ~/Library/Caches
  • ~/Library/Preferences
  • ~/Library/Containers

Specific Apps

The following apps are handled specifically:

  • Logitech G Hub (Standard, Main Container, Helper)
  • Microsoft Teams (Classic and New)
  • Microsoft Edge
  • Brave Browser (executable wrapping)

Skipped Directories

The following directories are skipped during scanning:

  • .Trash
  • node_modules
  • Library/Developer
  • Library/Caches/Homebrew
  • Library/Logs
  • Network-mounted volumes

How It Works

Settings Patching

For most apps, the patcher modifies the Local State file to add:

{
  "browser": {
    "enabled_labs_experiments": [
      "use-angle@1"
    ]
  }
}

Executable Wrapping

For apps like Brave Browser and lghub, the patcher wraps the executable to pass the --use-angle=gl argument at runtime.

The original executable is backed up as <name>.original and replaced with a shell script:

#!/bin/bash
DIR="$(cd "$(dirname "$0")" && pwd)"
exec "$DIR/<name>.original" --use-angle=gl "$@"

Requirements

  • Python 3.10 or higher
  • macOS (Darwin)
  • codesign command (for re-signing apps, optional)
  • xattr command (for stripping attributes, optional)

License

MIT License

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Run make check to ensure quality
  6. Submit a pull request

Troubleshooting

"Cannot write to app" Error

Run the script with sudo:

sudo python -m electron_angle_patcher.cli

App Not Detected

Use --list-only to see what apps are detected, or use --app-path to target a specific app.

Changes Not Taking Effect

Some apps may need to be restarted for changes to take effect. Try:

  1. Quit the app completely
  2. Re-launch the app
  3. Check the flag is active (use chrome://flags in Chrome-based apps)

About

Patch Electron and Chrome applications on macOS to use OpenGL rendering through the use-angle@1 setting.

Topics

Resources

License

Stars

Watchers

Forks

Contributors