Add CEF 147, Python 3.10–3.14, Linux/macOS ARM64/Windows support with modern build system#691
Add CEF 147, Python 3.10–3.14, Linux/macOS ARM64/Windows support with modern build system#691linesight wants to merge 162 commits into
Conversation
Fixes: cztomczak#546 Had to include harfbuzz manually as newer Pango change this. See: eiskaltdcpp/eiskaltdcpp#413 https://gitlab.gnome.org/GNOME/pango/-/issues/387 Also had to add `-Wno-deprecated-declarations` to get this to compile because of the following errors that didn't seem to be coming from this code directly: warning: ‘GTimeVal’ is deprecated: Use 'GDateTime' instead warning: ‘GTypeDebugFlags’ is deprecated
…k#484). These callbacks were never called previously. Rename --no-run-examples flag to --unittests in build scripts.
… code at frame.pyx
…nd CanSaveCookie; restore network_cookies.py and make slight tweak to use CanSendCookie and CanSaveCookie
- screenshot.py: add macOS switches matching osr_test.py; remove dead switches (enable-begin-frame-scheduling, disable-surfaces not present anywhere in CEF 146 source) from the macOS path - osr_test.py: drop --no-sandbox (cefpython.pyx already sets no_sandbox=1 at the C level) and --in-process-gpu (macos-14-arm64 CI has real Apple Silicon GPU; subprocess is ad-hoc signed in the test setup step); update comments to cite actual mechanism (restricted bootstrap namespace for ad-hoc-only signed processes) verified against CEF source - ci-macos.yml wheel job: ad-hoc codesign subprocess and .so before packaging so installed wheels don't ship unsigned binaries; unsigned subprocess binary is the root cause of GPU_DEAD_ON_ARRIVAL (exit code 1003) on macOS 14+ Gatekeeper Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ZipFile.write() does not preserve Unix file mode bits, so the subprocess binary inside the wheel lost its +x permission. pip extracts it as a non-executable file, and CEF cannot launch the renderer process, leaving browser windows blank. Use ZipInfo.from_file() which stores the real file mode in the zip entry's external_attr field. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…LTO on Linux GCC's alias analysis loses track of object sizes when small ref-counted classes are inlined across translation units during LTO, triggering spurious -Wstringop-overflow warnings on the atomic ref_count_ write. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
cp -r does not preserve permissions, so subprocess lost its +x bit before build_distrib zipped it into the wheel. The ZipInfo.from_file() fix in a68d6b1 preserves whatever mode is on disk — but by the time the wheel job copies files into cefpython3/, the permission was already gone. Add chmod +x to match what the test job already does. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Merge compile/test/wheel into a single matrix job per Python version so that each version's pipeline is fully independent — a 3.11 failure no longer delays the 3.10 wheel. Extract CEF download into a dedicated job to avoid 5 concurrent downloads of the same 600 MB archive from Spotify's CDN. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
GCC's lto-wrapper re-compiles combined IR during linking and doesn't propagate -Wno-* flags from the compile phase, so the false-positive -Wstringop-overflow warnings resurfaced at link time. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
qt.py: override QT_QPA_PLATFORM=xcb unconditionally on Linux for all Qt bindings (PyQt5/PyQt6/PySide6). Wayland desktops such as KDE Plasma on Kubuntu often pre-set QT_QPA_PLATFORM=wayland in the session environment; setdefault was insufficient to override it, causing CEF to open a detached top-level window instead of embedding into the Qt widget. window_info.pyx: add a warnings.warn() in SetAsChild when parentWindowHandle is 0 and WAYLAND_DISPLAY is set. This catches the same misconfiguration for any toolkit (Qt, GTK, SDL2) and points the developer to the correct per-toolkit env var fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Linux qt.py: force QT_QPA_PLATFORM=xcb on Linux for all Qt bindings before QApplication is created. On Wayland desktops (e.g. KDE Plasma on Kubuntu) the session environment often pre-sets QT_QPA_PLATFORM=wayland; setdefault was insufficient to override it, causing CEF to receive a non-X11 window handle and open a detached top-level window instead of embedding into the Qt widget. qt.py: add CefWidget._phys() and apply it to the initial embed rect and all SetBounds calls on Linux for PyQt6/PySide6. Qt6 enables AA_EnableHighDpiScaling by default so width()/height() return logical pixels; CEF expects physical pixels. Without this fix, a display at 125-200% DPI causes the browser to fill only the top-left fraction of the window and resizing does not correct it. PyQt5 is unaffected as it uses the hidden_window/XReparentWindow path where X11 geometry drives browser sizing independently of SetBounds. window_info.pyx: warn when SetAsChild receives parentWindowHandle=0 on Linux in a Wayland session (WAYLAND_DISPLAY set). Fires at the caller site via stacklevel=2 and lists the per-toolkit env var fix for Qt, GTK, and SDL2. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Matches the pattern already used in ci-linux.yml and ci-windows.yml: a dedicated download-cef job saves the cache, and each compile matrix job restores from it rather than downloading independently. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Matches the pattern already used in ci-linux.yml and ci-windows.yml: a dedicated download-cef job saves the cache, and each compile matrix job restores from it rather than downloading independently. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…pi.h The #else branch with hardcoded version-specific include paths was only reachable by the old root-level build.py which no longer exists; all builds now go through CMake which always defines CEFPYTHON_API_H_FILE. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes the third-party `packaging` dependency from all example scripts. The upstream master branch has no such requirement, and the version checks only need simple numeric comparisons that a split+tuple handles cleanly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…itions CefFrame::GetBrowser() can return a null CefRefPtr while a frame is being created or destroyed during rapid navigation (e.g. heavy pages with many iframes). The naked .get().GetIdentifier() chain in GetPyFrame() was a latent SIGSEGV; all handler entry points that call GetPyFrame() or dereference the frame's browser pointer now return their safe defaults when the browser pointer is NULL. Affected files: - src/frame.pyx: store GetBrowser() result, check .get() before chaining - src/handlers/load_handler.pyx: OnLoadStart / OnLoadEnd / OnLoadError - src/handlers/display_handler.pyx: OnAddressChange - src/handlers/v8context_handler.pyx: OnContextCreated - src/handlers/request_handler.pyx: OnBeforeBrowse, OnBeforeResourceLoad, GetResourceHandler, OnResourceRedirect, GetAuthCredentials - src/handlers/cookie_access_filter.pyx: CanSendCookie, CanSaveCookie - src/handlers/lifespan_handler.pyx: OnBeforePopup Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t variance Move onclick from <h1> to <body> and click at viewport center (400,300) instead of hardcoded h1 coordinates (200,43). selectText() now selects the h1 via querySelector rather than ev.target, so any click on the page reliably triggers OnTextSelectionChanged regardless of font metrics or rendering differences in CI environments. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Hi, thank you for the PR. If this is continuation of changes started in cepfython123 branch - then I have created branch cefpython147, please send the PR against that branch. It will make reviewing easier. Changes in cefpython123 were already reviewed and were good. Regarding #686 GPU process crashes 3 times when running unit tests - was this an issue with upstream CEF 123 or was this a problem with cefpython? "CI publishes wheel artifacts for all 15 combinations (3 platforms × 5 Python versions)" - sounds awesome! |
|
#686 is fixed by this particular commit linesight@d8d32ea It is indeed continuation of prevoius work of cefpython123. After I opened this pull request, I seem cannot change pull request target branch (lack of permission?). Can you edit this pull request target branch? |
|
Is there an upstream CEF issue for that GPU issue? I've changed the base branch to cefpython147 - there are merge conflicts now. |
…7-qt # Conflicts: # .gitignore # README.md # api/Browser.md # docs/Build-instructions.md # examples/hello_world.py # examples/pywin32.py # examples/qt.py # examples/screenshot.py # examples/tkinter_.py # examples/tutorial.py # examples/wxpython.py # src/browser.pyx # src/cefpython.pyx # src/client_handler/cookie_access_filter.h # src/client_handler/dialog_handler.cpp # src/client_handler/dialog_handler.h # src/client_handler/request_handler.cpp # src/client_handler/request_handler.h # src/common/cefpython_public_api.h # src/cookie.pyx # src/extern/cef/cef_cookie.pxd # src/extern/cef/cef_types.pxd # src/frame.pyx # src/handlers/cookie_access_filter.pyx # src/handlers/render_handler.pyx # src/handlers/request_handler.pyx # src/handlers/v8context_handler.pyx # src/include/base/cef_bind.h # src/include/base/cef_build.h # src/include/base/cef_callback.h # src/include/base/cef_callback_helpers.h # src/include/base/cef_compiler_specific.h # src/include/base/cef_ref_counted.h # src/include/base/cef_scoped_refptr.h # src/include/base/cef_weak_ptr.h # src/include/base/internal/README-TRANSFER.txt # src/include/base/internal/cef_bind_internal.h # src/include/base/internal/cef_callback_internal.h # src/include/base/internal/cef_net_error_list.h # src/include/cef_api_hash.h # src/include/cef_api_version_test.h # src/include/cef_app.h # src/include/cef_application_mac.h # src/include/cef_base.h # src/include/cef_browser.h # src/include/cef_browser_process_handler.h # src/include/cef_command_handler.h # src/include/cef_command_ids.h # src/include/cef_command_line.h # src/include/cef_config.h # src/include/cef_dialog_handler.h # src/include/cef_display_handler.h # src/include/cef_download_handler.h # src/include/cef_download_item.h # src/include/cef_frame.h # src/include/cef_frame_handler.h # src/include/cef_life_span_handler.h # src/include/cef_media_router.h # src/include/cef_pack_resources.h # src/include/cef_pack_strings.h # src/include/cef_permission_handler.h # src/include/cef_preference.h # src/include/cef_render_handler.h # src/include/cef_request_context.h # src/include/cef_request_handler.h # src/include/cef_resource_bundle.h # src/include/cef_resource_bundle_handler.h # src/include/cef_sandbox_win.h # src/include/cef_test_server.h # src/include/cef_v8.h # src/include/cef_version.h # src/include/internal/cef_app_win.h # src/include/internal/cef_linux.h # src/include/internal/cef_string_wrappers.h # src/include/internal/cef_time.h # src/include/internal/cef_types.h # src/include/internal/cef_types_content_settings.h # src/include/internal/cef_types_linux.h # src/include/internal/cef_types_mac.h # src/include/internal/cef_types_win.h # src/include/internal/cef_types_wrappers.h # src/include/internal/cef_win.h # src/include/test/cef_translator_test.h # src/include/views/cef_browser_view.h # src/include/views/cef_browser_view_delegate.h # src/include/views/cef_display.h # src/include/views/cef_view.h # src/include/views/cef_window.h # src/include/views/cef_window_delegate.h # src/javascript_callback.pyx # src/process_message_utils.pyx # src/response.pyx # src/settings.pyx # src/subprocess/cefpython_app.cpp # src/version/cef_version_win.h # src/web_request.pyx # src/window_info.pyx # tools/automate.py # tools/build.py # tools/build_cpp_projects.py # tools/build_distrib.py # tools/common.py # tools/cython_setup.py # tools/installer/cefpython3.__init__.py # tools/installer/cefpython3.setup.py # tools/make_installer.py # tools/requirements.txt
Merge conflict is now fixed. Regarding the GPU issue: I wasn't super knowledgeable about the root cause, I found some reference issue at chromiumembedded/cef#3765, cefsharp/CefSharp#4707 . I simply used an acceptable workaround to silence the error without letting CEF fall back to software rendering. Using |
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)
|
Looks like adding compatibility.manifest fixes the GPU issue: chromiumembedded/cef#3765 (comment) When running through 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 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>
|
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. What this PR now does:
|
|
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 |
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
cefpython123branch (PR #679) which was never merged to master.What's new
CEF & Python versions
Platform support
Build system
setup.pywith scikit-build-core + CMakebuild_distrib.pyproduces installable wheels per platform/Python versionCI (GitHub Actions)
from cache rather than downloading independently
Linux
macOS
Qt
API changes
OnPluginCrashed;SendFocusEventkeptas no-op stub for compatibility
CanSendCookie/CanSaveCookiehandler signatures revisedOpen issues addressed
Definitely fixed
Likely fixed