Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions CefGlue.Interop.Gen/include/cef_api_versions.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@
#define CEF_API_HASH_15000 "210767725a6feb2e4becd3956b648cab6a006712"
#endif

// Next version last updated July 10, 2026.
// Next version last updated August 04, 2026.
#define CEF_API_VERSION_999998 999998
#if defined(OS_WIN)
#define CEF_API_HASH_999998 "71146b4350a01d3805e7ea990eb034e6ef4d53db"
Expand All @@ -289,14 +289,14 @@
#define CEF_API_HASH_999998 "210767725a6feb2e4becd3956b648cab6a006712"
#endif

// Experimental version last updated July 10, 2026.
// Experimental version last updated August 04, 2026.
#define CEF_API_VERSION_999999 999999
#if defined(OS_WIN)
#define CEF_API_HASH_999999 "c63591fb321ac707f8710f296a8ae1ec05a575db"
#define CEF_API_HASH_999999 "98f8c0d3b73ee1ade0ea70e5e67f48116fa2b3f3"
#elif defined(OS_MAC)
#define CEF_API_HASH_999999 "0934859000c911cdd75907f63f2ef8e485706e5b"
#define CEF_API_HASH_999999 "f7f0a19b29e2f1cb7dec42ee3ef26fc571da8a8e"
#elif defined(OS_LINUX)
#define CEF_API_HASH_999999 "a5d187477e0cbe23eb1043c2f1868582b7018260"
#define CEF_API_HASH_999999 "8aba464ae9af72f65a1584199dd81fc3557c75b1"
#endif

// Oldest supported CEF version.
Expand Down
16 changes: 16 additions & 0 deletions CefGlue.Interop.Gen/include/cef_browser.h
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,22 @@ class CefBrowserHost : public virtual CefBaseRefCounted {
/*--cef()--*/
virtual void SendExternalBeginFrame() = 0;

#if CEF_API_ADDED(CEF_EXPERIMENTAL)
///
/// Release a surface leased by CefRenderHandler::OnAcceleratedPaint.
/// |surface_id| is the value delivered in CefAcceleratedPaintInfo. This
/// method is only used when window rendering is disabled.
///
/// While a lease is held the surface is not returned to the capture pool and
/// its texture handle stays valid, so it may be sampled after the paint
/// callback returns. The pool is small, so release each surface as soon as it
/// is no longer in use or capture will stall. Releasing an id that is unknown
/// or already released does nothing.
///
/*--cef(added=experimental)--*/
virtual void ReleaseAcceleratedPaintSurface(uint64_t surface_id) = 0;
#endif

///
/// Send a key event to the browser.
///
Expand Down
17 changes: 10 additions & 7 deletions CefGlue.Interop.Gen/include/cef_render_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,16 @@ class CefRenderHandler : public virtual CefBaseRefCounted {
/// opened with Metal or OpenGL, and on Linux it contains several planes, each
/// with an fd to the underlying system native buffer.
///
/// The underlying implementation uses a pool to deliver frames. As a result,
/// the handle may differ every frame depending on how many frames are
/// in-progress. The handle's resource cannot be cached and cannot be accessed
/// outside of this callback. It should be reopened each time this callback is
/// executed and the contents should be copied to a texture owned by the
/// client application. The contents of |info| will be released back to the
/// pool after this callback returns.
/// The underlying implementation uses a pool to deliver frames, so the handle
/// may differ every frame depending on how many frames are in-progress.
///
/// |info| carries a surface_id identifying a lease on the surface. While the
/// lease is held the surface is not returned to the pool and its handle stays
/// valid, so the handle may be opened once and sampled well after this
/// callback returns; there is no need to copy the contents here. Release the
/// lease with CefBrowserHost::ReleaseAcceleratedPaintSurface once the surface
/// is no longer in use. The pool is small, so a client that does not release
/// promptly will stall capture.
///
/*--cef()--*/
virtual void OnAcceleratedPaint(CefRefPtr<CefBrowser> browser,
Expand Down
10 changes: 5 additions & 5 deletions CefGlue.Interop.Gen/include/cef_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,18 @@
#ifndef CEF_INCLUDE_CEF_VERSION_H_
#define CEF_INCLUDE_CEF_VERSION_H_

#define CEF_VERSION "150.0.11+gb887805+chromium-150.0.7871.115"
#define CEF_VERSION "150.0.23-2026-08-04-surface-lease.3556+ge7ab2e1+chromium-150.0.7871.187"
#define CEF_VERSION_MAJOR 150
#define CEF_VERSION_MINOR 0
#define CEF_VERSION_PATCH 11
#define CEF_COMMIT_NUMBER 3544
#define CEF_COMMIT_HASH "b88780525f76c1c1d67d30b87e3b16bb37955175"
#define CEF_VERSION_PATCH 23
#define CEF_COMMIT_NUMBER 3556
#define CEF_COMMIT_HASH "e7ab2e15e1973d318458b5882a448be97ebd08c7"
#define COPYRIGHT_YEAR 2026

#define CHROME_VERSION_MAJOR 150
#define CHROME_VERSION_MINOR 0
#define CHROME_VERSION_BUILD 7871
#define CHROME_VERSION_PATCH 115
#define CHROME_VERSION_PATCH 187

#define CEF_SANDBOX_COMPAT_HASH "6c5b35ad81055c14"

Expand Down
14 changes: 14 additions & 0 deletions CefGlue.Interop.Gen/include/internal/cef_types_osr.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <stddef.h>
#include <stdint.h>

#include "include/cef_api_hash.h"
#include "include/internal/cef_types_geometry.h"

#ifdef __cplusplus
Expand Down Expand Up @@ -112,6 +113,19 @@ typedef struct _cef_accelerated_paint_info_common_t {
///
uint8_t has_capture_counter;

#if CEF_API_ADDED(CEF_EXPERIMENTAL)
///
/// Opaque identifier for a leased surface, or 0 when no lease was granted.
///
/// While a lease is held the surface is not returned to the capture pool and
/// its texture handle stays valid, so the client may keep sampling it after
/// the paint callback returns. A lease must be released once the surface is
/// no longer in use; the pool is small, and holding leases indefinitely
/// stalls capture.
///
uint64_t surface_id;
#endif

} cef_accelerated_paint_info_common_t;

#ifdef __cplusplus
Expand Down
5 changes: 3 additions & 2 deletions CefGlue.Interop.Gen/include/internal/cef_types_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,9 @@ typedef struct _cef_window_info_t {

///
/// Structure containing shared texture information for the OnAcceleratedPaint
/// callback. Resources will be released to the underlying pool for reuse when
/// the callback returns from client code.
/// callback. Resources are returned to the underlying pool when the lease
/// identified by |extra.surface_id| is released, or when the callback returns
/// if no lease was granted.
///
typedef struct _cef_accelerated_paint_info_t {
///
Expand Down
56 changes: 45 additions & 11 deletions CefGlue.Interop.Gen/make_interop.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,29 @@ def make_struct_file(cls):
'body': indent + ('\n'+indent).join(body)
}

def get_added_version(func):
"""The API version that introduced a method, as a sortable number.

A method with no 'added' attribute belongs to the original surface and sorts first.
'experimental' is the highest version there is, so it sorts last."""
added = func.get_attrib('added')
if added is None:
return 0
if added == 'experimental':
return 999999
return int(added)

def sort_by_added_version(funcs):
"""Order struct members the way CEF's own translator does: by the version that added them, then by
declaration order.

This is what keeps the C API layout stable across versions. A member added later is appended after every
member of earlier versions, wherever its C++ declaration happens to sit, so a client built against an older
version still finds the members it knows at the offsets it expects. Following declaration order instead puts
a newly added member in the middle of the struct and silently shifts every member below it, which reads as
calls landing on the wrong function pointer at runtime."""
return sorted(funcs, key=get_added_version)

def get_funcs(cls, base = True, inherited = True):
funcs = []

Expand All @@ -184,7 +207,7 @@ def get_funcs(cls, base = True, inherited = True):
current_cls = classes.pop()
if current_cls is None:
break
for func in current_cls.get_virtual_funcs():
for func in sort_by_added_version(current_cls.get_virtual_funcs()):
funcs.append( get_func_parts(func, i) )
i += 1

Expand Down Expand Up @@ -823,7 +846,7 @@ def make_version_cs(content, api_hash_content, api_versions_content):
result.append('public const int CHROME_VERSION_PATCH = %s;' % __get_version_constant(content, "CHROME_VERSION_PATCH"))
result.append("");

api_details = get_cef_api_details(api_versions_content)
api_details = get_cef_api_details(api_versions_content, api_hash_content)
result.append('public const int CEF_API_VERSION = %s;' % api_details["API_VERSION"])
result.append('public const string CEF_API_HASH_PLATFORM_WIN = "%s";' % api_details["OS_WIN"])
result.append('public const string CEF_API_HASH_PLATFORM_MACOS = "%s";' % api_details["OS_MAC"])
Expand All @@ -850,17 +873,28 @@ def make_version_cs(content, api_hash_content, api_versions_content):
'body': indent + ('\n'+indent).join(body)
}

def get_cef_api_details(content):
def get_cef_api_details(content, api_hash_content):
"""Pick the API version these bindings declare, and the hashes that go with it.

The version is not bookkeeping: a client announces it by calling cef_api_hash(version) before initializing,
and the library then builds its C API structs to match. Announce an explicit version and every method added
since is compiled out of those structs, so the field a binding reads is a different method's pointer, or
past the end of the struct. Calls into it crash.

So the version has to match the headers the interop was generated from. We generate against the experimental
surface, because our own additions live there: experimental is where CEF puts API that is not yet frozen into
a numbered version. Explicit versions buy forward and backward compatibility across a range of CEF releases,
which is worth having and which we give up here deliberately, since we ship the libcef we bind against.
"""
lines = content.splitlines()
# Find the last API version
match_version = re.search(r"#define\s+CEF_API_VERSION_LAST\s+(CEF_API_VERSION_\d+)", content)

# The number lives in cef_api_hash.h; the hashes keyed by it live in cef_api_versions.h.
match_version = re.search(r"#define\s+CEF_API_VERSION_EXPERIMENTAL\s+(\d+)", api_hash_content)
if not match_version:
raise ValueError("CEF_API_VERSION_LAST not found in the file")

last_version = match_version.group(1)
last_version_number = last_version.split('_')[-1]

raise ValueError("CEF_API_VERSION_EXPERIMENTAL not found in cef_api_hash.h")

last_version_number = match_version.group(1)

# Extract OS-specific hashes
details = { "API_VERSION": last_version_number }
current_os = None
Expand Down
Loading