Skip to content

Add CEF 147, Python 3.10–3.14, Linux/macOS ARM64/Windows support with modern build system#691

Open
linesight wants to merge 125 commits into
cztomczak:cefpython147from
linesight:cefpython147-qt
Open

Add CEF 147, Python 3.10–3.14, Linux/macOS ARM64/Windows support with modern build system#691
linesight wants to merge 125 commits into
cztomczak:cefpython147from
linesight:cefpython147-qt

Conversation

@linesight
Copy link
Copy Markdown
Contributor

Overview

This PR modernizes cefpython from CEF 66 (2018) to CEF 147, adds full support
for Linux and macOS Apple Silicon, and replaces the legacy build toolchain with
a pip-installable wheel workflow. It also incorporates all work from the
cefpython123 branch (PR #679) which was never merged to master.

What's new

CEF & Python versions

  • CEF updated to 147.0.10 (Chromium 147.0.7727.118)
  • Supports Python 3.10–3.14 (64-bit); Python 2 and pre-3.10 dropped
  • Cython updated to 3.2+

Platform support

Platform Architecture Status
Windows 10+ x64 Full support
Linux (Ubuntu 20.04+ / Debian 11+) x64 Full support (GTK3/X11)
macOS 10.15+ ARM64 (Apple Silicon) Full support

Build system

  • Replaced legacy setup.py with scikit-build-core + CMake
  • build_distrib.py produces installable wheels per platform/Python version
  • CI publishes wheel artifacts for all 15 combinations (3 platforms × 5 Python versions)

CI (GitHub Actions)

  • Separate workflows for Windows, Linux, and macOS
  • Each workflow builds and runs the unit test suite across all 5 Python versions
  • CEF is downloaded once in a dedicated job and cached; all matrix jobs restore
    from cache rather than downloading independently

Linux

  • Native-windowed embedding via GTK3/X11
  • Wayland sessions: automatic XCB backend forcing with HiDPI scaling support
  • Compatible with GCC 13 / Ubuntu 24.04

macOS

  • Apple Silicon (ARM64) only — Intel Mac dropped
  • Handles Mach port rendezvous requirements for CEF 130+ subprocess isolation
  • Ad-hoc code signing for local use; wheel binaries are codesigned

Qt

  • PyQt6 and PySide6 embedding and context menu support on Linux

API changes

  • Removed APIs dropped in CEF 123+: OnPluginCrashed; SendFocusEvent kept
    as no-op stub for compatibility
  • Cookie API updated: CanSendCookie / CanSaveCookie handler signatures revised
  • All examples updated and verified on current Chromium behavior

Open issues addressed

Definitely fixed

Issue Title
#393 [gtk3.py] Blank window / browser embedding fails due to invalid X11 handle
#467 GTK 2 dependency will be removed in CEF v70+
#528 Linux: Discontinue x86 32-bit build support
#585 Use python_requires in setup.py
#609 New v66.1 release only for Windows?
#641 Problem with cefpython on Python 3.8/3.9/3.10 on Linux
#646 No support for Python 3.10
#650 Doesn't support the latest Python version
#652 Chromium 100+ support
#673 Support for Python 3.12
#676 CanSendCookie and CanSaveCookie not called by handler
#683 Error in CookieVisitor_Visit (IO thread assertion)
#685 "Please customize CefSettings.root_cache_path" warning
#686 GPU process crashes 3 times when running unit tests
#530 cef.DpiAware.EnableHighDpiSupport() doesn't work well

Likely fixed

Issue Title
#452 Linux: Crash in Qt and wxPython examples
#520 API changes due to implementing support for NetworkService
#523 Support for ozone builds / Wayland and X11 backends
#538 Mac: CEF 76 requires multiple helper app bundles
#645 Error when running qt.py example on Windows

linesight and others added 30 commits April 18, 2026 11:26
- Add tools/download_cef.py to auto-download CEF from Spotify CDN
  with SHA1 verification and progress output
- Detect vcvarsall.bat dynamically via vswhere.exe instead of
  hardcoding VS2022 Community path; fall back through known editions
- Remove dead code for VS2008/VS2010/VS2013 and simplify
  prepare_build_command()
- Make VERSION argument optional in build.py, defaulting to
  {CHROME_VERSION_MAJOR}.0 from the version header
- Add venv support notes and document download_cef.py workflow
  in Build-instructions.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pass explicit plat_name to distutils compiler.initialize() in
build_cpp_projects.py, and add --plat-name to the cython_setup.py
build_ext invocation in build.py. Without these, distutils defaults
to win32 even on 64-bit Python, causing C1905 (front/back end
incompatible) when linking against x64 CEF libraries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…er creation

Two root causes fixed to make windowed browsers work on CEF 123+:

1. Set CEF_RUNTIME_STYLE_ALLOY explicitly after SetAsChild/SetAsPopup in
   window_info.pyx. CEF 123+ defaults to Chrome runtime (no native Win32
   title bar, blank content). Also declared cef_runtime_style_t enum and
   runtime_style field in cef_win.pxd.

2. Defer CreateBrowserSync() until OnContextInitialized fires. Calling
   before context is ready causes blink.mojom.WidgetHost rejection and a
   blank window. g_pending_browsers list + CefPostTask posts creation at
   the outer message-loop level after the callback returns.

Also fix PyQt6 high-DPI sizing in qt.py: call WindowUtils.OnSize after
CreateBrowserSync() so the browser fills the HWND client rect in device
pixels rather than the smaller logical-pixel rect Qt reports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sync all CEF public headers, capi headers, and internal headers from
CEF 146 binary distribution. Includes new headers for task manager,
component updater, OSR types, color types, runtime style, and API
versioning. Update client handlers (dialog, download, lifespan, request)
for CEF 146 API changes. Update cef_types.pxd, network_error.pyx,
settings.pyx, and version header for CEF 146. Update build tools
(cython_setup.py, build_cpp_projects.py) for the new toolchain.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
osr_test.py:
- OnTextSelectionChanged: Chrome 130+ requires the Selection API to run
  inside a real user-gesture event handler to propagate the callback.
  Added selectText() onclick handler to h1 and trigger it via a real
  mouse click posted after the first OnPaint (guarantees layout is
  complete and hit-testing works). Simplified the callback handler to
  not assume a specific empty-then-selected call sequence.
- AccessibilityHandler: removed layoutComplete_True assertion — the
  layoutComplete AX event was removed from Chrome's event system in
  Chrome 130+.

main_test.py:
- V8ContextHandler: CEF 146 no longer creates an initial empty-document
  V8 context on browser creation. Removed OnContextCreatedSecondCall_True
  and OnContextReleased_True assertions which could never be satisfied.
- Added disable-popup-blocking switch to cef.Initialize — Chrome 130+
  blocks window.open() calls that lack a user gesture at the renderer
  level, preventing the popup test from running.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…sion

_detect_cefpython_binary_dir() runs at import time (bottom of common.py),
before build.py's command_line_args() can inject the default version into
sys.argv. Fall back to reading the version directly from the CEF header
file so CEFPYTHON_BINARY is resolved correctly even when no version
argument is passed on the command line.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cefpython.pyx:
- Pump the message loop (up to 200×10ms = 2s) after CefInitialize()
  until OnContextInitialized fires. This guarantees CreateBrowserSync()
  can be called immediately after Initialize() and always gets a valid
  browser, eliminating the race condition where deferred creation
  could return None when CreateBrowserSync() was called before the
  context was ready.

main_test.py:
- Remove OnAutoResize_True assertion: CEF 146 no longer triggers
  OnAutoResize for windowed (non-OSR) browsers. Consistent with the
  other Chrome 130+ behavioral changes removed in the previous commit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The ANGLE D3D11 backend in CEF 146 / Chrome 130+ triggers a CHECK failure
(STATUS_BREAKPOINT, exit_code=-2147483645) in libcef.dll during GPU
process initialization. CEF auto-recovers 3 times then falls back to
software rendering, silently degrading performance. The D3D9 backend
avoids the crash but only implements ES 2.0, causing eglCreateContext
ES 3.0 failures. Defaulting to the OpenGL ANGLE backend eliminates both
issues — it supports ES 3.0 and initializes without crashes. Users can
override by passing {"use-angle": "d3d11"} in the switches dict. Fixes cztomczak#686.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Framework fixes:
- Remove BindedFunctionExists renderer-side pre-check in V8FunctionHandler::Execute
  that raced against global registration and threw spurious "function does not exist"
  errors; browser process handles missing functions gracefully via NonCriticalError
- Fix DoJavascriptBindingsForBrowser: guard null/invalid V8 context to prevent
  crash/freeze in CEF 146, register globals synchronously (not via PostTask) when
  outside V8 execution so they are in place before queued ExecuteJavascript IPCs run
- Add Rebind() before user OnContextCreated callback in V8ContextHandler so that
  DoJavascriptBindings IPC is ordered ahead of any ExecuteJavascript the user sends
  from their callback on the same IPC channel

Example updates:
- ondomready.py: inject JS from OnContextCreated instead of OnLoadStart; OnLoadStart
  fires before the page V8 context is committed so ExecuteJavascript ran in about:blank
  where globals are not registered; wrap callback in setTimeout(0) to allow paint first
- onpagecomplete.py: replace OnLoadingStateChange with window.load + requestAnimationFrame
  via JS bindings to fire only after all resources are loaded and a paint frame is
  committed; fixes double-alert on sites with JS-initiated redirects (e.g. google.com)
  and ensures page content is visible before the alert dialog blocks the renderer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- crossdomain_bindings.py: demonstrates JS binding behaviour across a
  cross-domain auth flow (app -> auth domain -> back to app); uses a
  URL-based state machine to avoid misfire from multiple OnLoadEnd fires,
  and readyState fallback so the callback is not missed if window.load
  already fired before JS is injected
- README-snippets.md: add entry for crossdomain_bindings.py and update
  onpagecomplete.py description to reflect window.load + requestAnimationFrame

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- cookie.pyx: change CookieVisitor_Visit thread assertion from TID_IO to
  TID_UI — CEF 146 changed CookieVisitor::Visit to always fire on the UI
  thread (previously IO thread), causing AssertionError on every callback
- cookies.py: fix bug where OnLoadingStateChange checked "if is_loading"
  (fires on load start) instead of "if not is_loading" (fires on complete);
  update dead html-kit.com URL to https://www.google.com/
- network_cookies.py: update dead html-kit.com URL to https://www.google.com/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Wire GetResourceRequestHandler in RequestHandler to return a
  ResourceRequestHandler (new file) that exposes GetCookieAccessFilter,
  restoring CanSendCookie/CanSaveCookie callbacks broken since CEF 146
  moved them out of CefRequestHandler into CefCookieAccessFilter
- Add #pragma once to cookie_access_filter.h to prevent C2011 redefinition
  when included from both request_handler.h and resource_request_handler.h
- Fix Cookie.SetDomain() to accept leading-dot domains (.example.com) by
  stripping the dot before IDNA validation while preserving the original
  value stored in the cookie (RFC 2109 subdomain-matching convention)
- Update setcookie.py: replace dead html-kit.com URL with google.com,
  set cookie in OnLoadEnd and verify with VisitUrlCookies

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- cefpython_public_api.h: add PY_MINOR_VERSION cases for 3.12, 3.13, 3.14
- build.py: fix invalid escape sequences in regex strings (SyntaxWarning on 3.12+)
- cefpython3.__init__.py: add import branches for 3.12, 3.13, 3.14
- cefpython3.setup.py: add PyPI classifiers for 3.12, 3.13, 3.14
- make_installer.py: add .pyd checks and update comments for 3.12, 3.13, 3.14
- build_distrib.py: add (3,12)/(3,13)/(3,14) to version lists

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cython 0.29.36 generates code using CPython internals removed in
Python 3.13 (_PyDict_SetItem_KnownHash, _PyInterpreterState_GetConfig,
_PyLong_AsByteArray), causing CI build failures on Python 3.13+.

- requirements.txt: Cython == 0.29.36 -> == 3.2.4
- cython_setup.py: language_level 2 -> "3str"; remove c_string_type /
  c_string_encoding directives
- All .pyx files: py_string type annotations -> object (Cython 3.x
  rejects string literals assigned to ctypedef object aliases)
- All .pyx files: iteritems() -> items(), basestring -> (str, bytes),
  long -> int (Python 2 builtins removed under language_level=3str)
- cefpython_app.cpp: remove extern "C" forward declarations that
  conflicted with Cython 3.x extern "C++" default in _fixed.h
- build.py: fix_cefpython_api_header_file to write #pragma only to
  _fixed.h so Cython 3.x can overwrite its own output on rebuilds

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace IF/ELIF/ELSE compile-time conditionals with runtime sys.platform
  checks and C macro helpers in cefpython.pyx, window_info.pyx,
  window_utils_win.pyx, utils.pyx, and browser.pyx
- Replace IF-based cimport blocks in cef_platform.pxd, cef_app.pxd,
  cef_browser.pxd, cef_browser_static.pxd with generated platform_cimports.pxi
  files; add generation of src/platform_cimports.pxi and
  src/extern/cef/platform_cimports.pxi to cython_setup.py
- Fix platform-conditional char16_t typedef in cef_types.pxd using
  cdef extern from * C macro instead of IF block
- Fix nogil keyword placement (must follow except+) in wstring.pxd and
  multimap.pxd; fix size_t npos assignment in wstring.pxd
- Change 44 cdef public callback functions from except * with gil to
  noexcept with gil across handlers and core pyx files; these functions
  already catch all exceptions internally so the exception check GIL
  acquisition was redundant

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  Allows manually triggering a clean build from GitHub Actions UI by
  skipping CEF binary cache, useful for verifying the build script
  works end-to-end without relying on cached artifacts.
Cython must transpile the .pyx file before C++ projects can be compiled,
because the C++ code includes cefpython_pyXX_fixed.h which is derived from
the Cython-generated header.  The previous two-pass re-run hack let the
first C++ compile fail noisily, then re-ran the whole script.

Now build.py detects a missing API header at startup and calls
cython_setup.py --cython-only (new flag) to transpile the .pyx and produce
cefpython_pyXX.h before fix_cefpython_api_header_file() and the C++
compilation run.  The FIRST_RUN re-run machinery is removed entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the old setup.py / build_cefpython.py toolchain with a modern
scikit-build-core backend driven by CMake, enabling clean incremental dev
builds, a structured CI pipeline (compile → test → wheel), and optional
Cython profiling/line-tracing flags.

Key changes:
- CMakeLists.txt (root + per-subdir): full CMake build for the extension
  module, subprocess executable, client_handler and cpp_utils static libs;
  auto-detects CEF root; installs CEF runtime files via cmake --install
- pyproject.toml: scikit-build-core build backend, Cython >=3.2 dependency
- tools/cmake_generate_pxi.py: generates platform .pxi files at configure time
- tools/cmake_prepare_pyx.py: stages .pyx files and injects version constants
- tools/cmake_fix_header.py: patches Cython-generated header for MSVC compat
- tools/build.py: unified dev/CI entry point; --clean for full rebuild,
  --wheel for pip wheel, --enable-profiling / --enable-line-tracing for
  Cython instrumentation
- .github/workflows/ci-windows.yml: split into compile / test / wheel jobs
  with artifact hand-off; supports Python 3.10–3.14
- .gitignore: add _cmake_test/, _skbuild/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
__init__.py is source; .pyd/.dll/.exe/.pak/.dat/.bin/.json/locales/
are build outputs or CEF runtime files and should not be committed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
automate.py --prebuilt-cef requires docopt; add Install build tools step
to the test job same as compile and wheel jobs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
automate.py requires docopt; requirements.py must run first.
Fixed in compile, test, and wheel jobs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
_test_runner.py os.chdir()s to unittests/, so the repo root (where
cefpython3/ lives) falls off sys.path. Set PYTHONPATH to the workspace
root so the package is findable without installing it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Include CEF runtime files in the compile artifact so the test job
needs nothing except: checkout, setup-python, download artifact, copy,
test. No requirements.py, no CEF cache restore, no automate.py.

Also add pip cache to the wheel job's setup-python to speed up
repeated requirements.py installs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The old script searched for multiple Python installations and drove a
full build + setup.py bdist_wheel — all of that is now the CI matrix's
job. The new build_distrib.py does the one thing that still belongs
here: package the pre-built cefpython3/ directory into a .whl using
stdlib only (zipfile/hashlib), with correct dist-info/RECORD hashes.

The CI wheel job now mirrors the test job (checkout, setup-python,
download artifact, copy, build_distrib.py). Timeout drops 60 -> 15 min.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
UNAME_SYSNAME and PY_MAJOR_VERSION are Cython built-in compile-time
constants — no DEF needed. INT_MIN/INT_MAX now come from libc.limits
via a direct cimport. The two platform_cimports.pxi files use Cython's
own IF/ELIF/ELSE on UNAME_SYSNAME instead of being generated per-OS.

Removes cmake_generate_pxi.py and its CMakeLists.txt custom command
entirely — no generation step, no gitignore entries, no cmake target.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add .github/workflows/ci-linux.yml targeting ubuntu-24.04
- Update src/version/cef_version_linux.h from CEF 66 to CEF 146
- Make tools/build.py cross-platform (cmake flags, artifact paths, CEF runtime detection)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GCC 13 added -Wself-move which fires on intentional self-move test
code in CEF's ref_counted_unittest.cc. Pass -Wno-self-move when
configuring the CEF binary's build_cefclient on Linux. Safe on older
GCC where the flag is silently ignored.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d GTK3

- cef_types_linux.h: Sync with real CEF 146 — adds size_t size to
  _cef_window_info_t, cef_runtime_style_t runtime_style field, the
  full _cef_accelerated_paint_info_t + plane struct for Linux DMA-BUF,
  and missing includes (cef_types_color.h, cef_types_osr.h,
  cef_types_runtime.h). The old vendored header was from CEF ~66.

- cef_linux.h: Sync with real CEF 146 — CefWindowInfoTraits::init now
  sets s->size, set() copies runtime_style, SetAsWindowless sets
  CEF_RUNTIME_STYLE_ALLOY. CefWindowInfo uses idiomatic using-inheritance.

- client_handler/CMakeLists.txt: Add gtk+-3.0 pkg-config includes on
  Linux so dialog_handler_gtk.h (<gtk/gtk.h>) can be found.

- subprocess/CMakeLists.txt: Add gtk+-3.0 pkg-config includes for the
  cefpython_app library on Linux (cefpython_app.cpp includes <gtk/gtk.h>
  when BROWSER_PROCESS is defined).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@cztomczak
Copy link
Copy Markdown
Owner

Looks like adding compatibility.manifest fixes the GPU issue: chromiumembedded/cef#3765 (comment)

When running through python.exe you can create python.exe.manifest.

The issue with GL backend on Windows is that it is less tested, slower and has other bugs. From what I read it is a survival legacy path.

I don't know if there is an easy way to automate the fix.

It should be well documented and when someone creates final executeable using pyinstaller he should have an option to embed compatibility.manifest and not use a buggy/slower GL workaround.

If we want to make the GL backend the default fix, then it should be explicit and well documented, because it can have issues. Then we should add the use-angle=gl flag explicitilly in all .py examples with a comment that either this flag is required (but it is less tested, possibly buggy on some configurations and slower) or you need to add compatibility.manifest to python.exe or your app exe.

Do you have other ideas?

The ANGLE D3D11 GPU process crashed with STATUS_BREAKPOINT
(exit_code=-2147483645) on Windows because subprocess.exe was linked
with /MANIFEST:NO and had no supportedOS=Win10 GUID. Verified end-to-end:
with the manifest absent, --use-angle=d3d11 produces 3 GPU CHECK crashes
and falls back to software rendering; with CEF's compatibility.manifest
embedded via /MANIFEST:EMBED /MANIFESTINPUT, D3D11 init succeeds and
NVIDIA GPU is detected. The previous workaround (silently defaulting
use-angle=gl on Windows) is removed because it is no longer needed; ANGLE
GL is documented as a slower, less-tested fallback by upstream CEF.

The build references CEF's own tests/cefsimple/win/compatibility.manifest
rather than vendoring a copy, so any future change CEF makes to the
supportedOS chain is picked up automatically on the next CEF bump.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@linesight
Copy link
Copy Markdown
Contributor Author

linesight commented May 11, 2026

You were right that compatibility.manifest is the proper fix — but the binary that needs it is cefpython's own subprocess.exe, not python.exe.
python.exe already ships with the supportedOS=Win10 GUID embedded. I dumped its RT_MANIFEST resource and it contains all five supportedOS GUIDs (Vista → Win10), same as cefsimple's compatibility.manifest. Adding python.exe.manifest next to it is a no-op because Windows uses the embedded manifest when both exist. https://learn.microsoft.com/en-us/archive/blogs/junfeng/internal-manifest-vs-external-manifest Tested — still 3 GPU CHECK crashes.
subprocess.exe is the one running the GPU process. It was being built with /MANIFEST:NO and shipped with no manifest at all. That's the actual gap.

What this PR now does:

  • src/subprocess/CMakeLists.txt links subprocess.exe with /MANIFEST:EMBED /MANIFESTINPUT:/tests/cefsimple/win/compatibility.manifest. We reference CEF's own file directly — no copy of the manifest in our depot, so we automatically pick up any future change CEF makes to the supportedOS chain.
  • The Windows use-angle=gl auto-default in cefpython.pyx is removed. D3D11 is the default now, exactly as upstream Chromium intends. The "GL is a less-tested survival path" concern goes away with it.

@cztomczak
Copy link
Copy Markdown
Owner

Nice work - good fix 🙂

Will using manifest from cefclient work when building cefpython with CEF prebuilt binaries and libraries?

@linesight
Copy link
Copy Markdown
Contributor Author

Nice work - good fix 🙂

Will using manifest from cefclient work when building cefpython with CEF prebuilt binaries and libraries?

yes, it works. I have confirmed on my local development machine and github action CI

@cztomczak
Copy link
Copy Markdown
Owner

The src/include/capi/ directory should not be included.
Did you use CEF include/ directory from CEF binaries or CEF sources?

linesight added a commit to linesight/cefpython that referenced this pull request May 26, 2026
The CEF C API headers are consumed only by libcef_dll/, which cefpython
links against pre-built from the binary distribution — no cefpython
source references include/capi/. The directory was an inadvertent
copy-the-whole-tree mistake when re-vendoring CEF 123/146/147 headers.

Per maintainer feedback on PR cztomczak#691.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The CEF C API headers are consumed only by libcef_dll/, which cefpython
links against pre-built from the binary distribution — no cefpython
source references include/capi/. The directory was an inadvertent
copy-the-whole-tree mistake when re-vendoring CEF 123/146/147 headers.

Per maintainer feedback on PR cztomczak#691.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
linesight added a commit to linesight/cefpython that referenced this pull request May 26, 2026
The CEF C API headers are consumed only by libcef_dll/, which cefpython
links against pre-built from the binary distribution — no cefpython
source references include/capi/. The directory was an inadvertent
copy-the-whole-tree mistake when re-vendoring CEF 123/146/147 headers.

Per maintainer feedback on PR cztomczak#691.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@linesight
Copy link
Copy Markdown
Contributor Author

Thanks for the catch — src/include/capi/ was an inadvertent copy of the full include/ tree when re-vendoring for CEF 147. I have removed the directory in this PR

@cztomczak
Copy link
Copy Markdown
Owner

Did you test the CI workflows? I don't see any workflow runs or build artifacts in your repo.

I have enabled GitHub Actions just now. However, a new commit is required for the workflows to be triggered on this PR.

The pull_request filter only listed "master", so workflows would not
run for pull requests opened against the cefpython147 branch. Add
cefpython147 to the pull_request branch filter in all three CI
workflows so the upstream maintainer can run CI on PRs into that
branch once the workflow files are present on the base branch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@linesight
Copy link
Copy Markdown
Contributor Author

Yeah, they're tested — there are 100+ runs in my fork, all green on Linux/Windows/macOS:

https://github.com/linesight/cefpython/actions?query=branch%3Acefpython147

They don't show up here because GitHub runs PR workflows from the base branch, and the workflow files don't exist on cefpython147 yet (this PR is what adds them) — so there's nothing for it to trigger until they're on your side. Easiest path is to merge: the push to cefpython147 kicks off CI automatically. Or if you want to check first, cherry-pick .github/workflows/ onto the branch and the runs will start.

@cztomczak
Copy link
Copy Markdown
Owner

Thank you for the explanation.

Why is there only one artifact for CI Linux build #52: https://github.com/linesight/cefpython/actions/runs/26481083254
but 5 artifacts for CI Linux build #51: https://github.com/linesight/cefpython/actions/runs/25646050799
hmm?

@cztomczak
Copy link
Copy Markdown
Owner

This PR merges into cefpython147 branch that is based on CEF 123. Last commits in that branch are from Aug 8 2025. However this PR seems to contain about 40 older commits from Jan 28, 2024 to Feb 17, 2025. It wouldn't be a problem if I squashed this PR, however I don't want to do that. New commits from Apr 18, 2026 provide important context (long meaningful commit messages and info about Claude AI usage). Also this is a complex upgrade that includes changes to CI, CMake, tools, this isn't only a CEF upgrade. So commit history is relevant. Can you clean up the commit history?

@linesight
Copy link
Copy Markdown
Contributor Author

Thank you for the explanation.

Why is there only one artifact for CI Linux build #52: https://github.com/linesight/cefpython/actions/runs/26481083254 but 5 artifacts for CI Linux build #51: https://github.com/linesight/cefpython/actions/runs/25646050799 hmm?

Good catch — that's a re-run quirk, not a build issue.

Build #52 is on its 2nd attempt. The first attempt failed on the Python 3.11 job in the unit-test step. These are GUI/Chromium tests running under xvfb, and getting them to run headless in CI at all took quite a bit of work — they're now stable in the large majority of runs, but there's still a small residual flake rate from display/shared-memory timing. For a first pass of CI I think that's an acceptable tradeoff: the build and wheel steps are fully deterministic, and a one-click re-run of the occasional flaky job clears it. We can tighten the test harness further later if it proves annoying in practice.

So I just re-ran the py3.11 job. GitHub shows the latest attempt by default, and that attempt only re-ran py3.11 — hence the single artifact. The other 4 are still under Attempt 1 (attempt dropdown at top-left, or the artifacts API lists all 5). Build #51 was a single attempt, so all 5 show directly. The matrix always produces 5 Linux wheels, one per Python version.

@cztomczak
Copy link
Copy Markdown
Owner

I can see all jobs are green, but the run currently shows only a single artifact. Can you confirm where the other four wheel artifacts are visible?

@linesight
Copy link
Copy Markdown
Contributor Author

I can see all jobs are green, but the run currently shows only a single artifact. Can you confirm where the other four wheel artifacts are visible?

You can find the other 4 wheel at https://github.com/linesight/cefpython/actions/runs/26481083254/attempts/1

linesight added a commit to linesight/cefpython that referenced this pull request Jun 3, 2026
Squash-merge of 10 commits from cefpython147 to refresh PR cztomczak#691 with
the latest fixes and enhancements developed since the last sync.

Features:
* Add native Wayland support — explicit opt-in via WindowInfo;
  X11/XWayland remains the default (9c2ae77)
* Implement RenderHandler.GetScreenInfo with HiDPI support so
  high-DPI displays report accurate device scale factors (9969797)
* examples/pysdl2: support multiple popup windows with clean
  shutdown (bb24151)

Fixes:
* Sync render_handler with current CEF API (c6f2a56)
* Guard X11 error-handler install at compile time in
  cefpython.pyx (7a65e6b)
* examples/pysdl2: window resize, HiDPI rendering, mouse drag,
  Wayland DPI handling (2aff2c9)
* examples/pysdl2: scale mouse wheel by deviceScaleFactor for
  HiDPI (3e45abd)

Refactor / docs:
* Audit cef.Initialize defaults on Linux; drop dead switches and
  stale workarounds (db13d7d)
* Correct version-tagged comments to match actual upstream
  history (bd924c4)
* Drop defensive parenthetical from sandbox History comment in
  window_utils_linux.pyx (7ae0553)
linesight added a commit to linesight/cefpython that referenced this pull request Jun 3, 2026
The CEF C API headers are consumed only by libcef_dll/, which cefpython
links against pre-built from the binary distribution — no cefpython
source references include/capi/. The directory was an inadvertent
copy-the-whole-tree mistake when re-vendoring CEF 123/146/147 headers.

Per maintainer feedback on PR cztomczak#691.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@linesight
Copy link
Copy Markdown
Contributor Author

This PR merges into cefpython147 branch that is based on CEF 123. Last commits in that branch are from Aug 8 2025. However this PR seems to contain about 40 older commits from Jan 28, 2024 to Feb 17, 2025. It wouldn't be a problem if I squashed this PR, however I don't want to do that. New commits from Apr 18, 2026 provide important context (long meaningful commit messages and info about Claude AI usage). Also this is a complex upgrade that includes changes to CI, CMake, tools, this isn't only a CEF upgrade. So commit history is relevant. Can you clean up the commit history?

Cleaned up the history. The ~34 old cefpython123 commits (Jan 2024–Feb 2025) are gone — I collapsed that pre-upgrade fork state into a single baseline commit on top of cefpython147, and kept all the meaningful Apr–Jun 2026 upgrade commits (and their messages) intact, no squash. The code diff is unchanged. PR is updated via force-push.

@cztomczak
Copy link
Copy Markdown
Owner

The baseline commit says: "Baseline: cefpython123 fork state prior to CEF 146 work" However that baseline commit changes look like changes reverting to state that was before CEF 123. For example requirements.txt file - in cefpython123 fork contains "Cython 3.0.12", but that commit shows:

-Cython == 3.0.12
+Cython == 0.29.36

As if it reverted to the state before cefpython123 fork. ffd876e#diff-1ed4efd531f910f92b0dd60fadf0be32ec199b1e1f75fe71c37cdcc567938091

linesight added a commit to linesight/cefpython that referenced this pull request Jun 4, 2026
Squash-merge of 10 commits from cefpython147 to refresh PR cztomczak#691 with
the latest fixes and enhancements developed since the last sync.

Features:
* Add native Wayland support — explicit opt-in via WindowInfo;
  X11/XWayland remains the default (9c2ae77)
* Implement RenderHandler.GetScreenInfo with HiDPI support so
  high-DPI displays report accurate device scale factors (9969797)
* examples/pysdl2: support multiple popup windows with clean
  shutdown (bb24151)

Fixes:
* Sync render_handler with current CEF API (c6f2a56)
* Guard X11 error-handler install at compile time in
  cefpython.pyx (7a65e6b)
* examples/pysdl2: window resize, HiDPI rendering, mouse drag,
  Wayland DPI handling (2aff2c9)
* examples/pysdl2: scale mouse wheel by deviceScaleFactor for
  HiDPI (3e45abd)

Refactor / docs:
* Audit cef.Initialize defaults on Linux; drop dead switches and
  stale workarounds (db13d7d)
* Correct version-tagged comments to match actual upstream
  history (bd924c4)
* Drop defensive parenthetical from sandbox History comment in
  window_utils_linux.pyx (7ae0553)
linesight added a commit to linesight/cefpython that referenced this pull request Jun 4, 2026
The CEF C API headers are consumed only by libcef_dll/, which cefpython
links against pre-built from the binary distribution — no cefpython
source references include/capi/. The directory was an inadvertent
copy-the-whole-tree mistake when re-vendoring CEF 123/146/147 headers.

Per maintainer feedback on PR cztomczak#691.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@linesight
Copy link
Copy Markdown
Contributor Author

Good catch - that baseline was bogus. I've repaired the history and force-pushed. Let me know how it looks.

@cztomczak
Copy link
Copy Markdown
Owner

Thank you. Since git history was rewritten can you re-trigger builds in your repo just to be safe?

@cztomczak
Copy link
Copy Markdown
Owner

Never mind that. It looks good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants