detached 902c404

chore(deps): bump purego-cef to v0.14.1

v0.14.0 pinned the CEF API 15000 contract and fixed the struct ABI
corruption that made BrowserSettings.BackgroundColor land on
chrome_status_bubble (transparent windowless canvas). v0.14.1 restores
the global function bindings dropped by that regeneration
(DictionaryValueCreate, V8ContextGetCurrentContext, all *Create
factories) and fixes global factory ownership so created objects are
adopted without a leaked reference.

This makes the white-canvas fix in this branch effective: the opaque
white BrowserSettings.BackgroundColor now actually reaches libcef.
commit
902c404508da47722a324d2f14b2a4cfc04a2812
author
brice · · 2026-07-21 19:07 UTC
parent
1dc7dd4
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
75 files · +1836 -1983
M go.mod +1 -1
@@ -6,7 +6,7 @@ require (
66 github.com/a-h/templ v0.3.1020
77 github.com/andybalholm/brotli v1.2.2
88 github.com/bnema/purego v0.11.0-bnema.4
9- github.com/bnema/purego-cef v0.13.4
9+ github.com/bnema/purego-cef v0.14.1
1010 github.com/bnema/purego-cef2gtk v0.8.5
1111 github.com/bnema/purego-pipewire v0.1.5
1212 github.com/bnema/purego-sqlite v0.1.4
@@ -6,7 +6,7 @@ require (
6 github.com/a-h/templ v0.3.10206 github.com/a-h/templ v0.3.1020
7 github.com/andybalholm/brotli v1.2.27 github.com/andybalholm/brotli v1.2.2
8 github.com/bnema/purego v0.11.0-bnema.48 github.com/bnema/purego v0.11.0-bnema.4
9- github.com/bnema/purego-cef v0.13.49+ github.com/bnema/purego-cef v0.14.1
10 github.com/bnema/purego-cef2gtk v0.8.510 github.com/bnema/purego-cef2gtk v0.8.5
11 github.com/bnema/purego-pipewire v0.1.511 github.com/bnema/purego-pipewire v0.1.5
12 github.com/bnema/purego-sqlite v0.1.412 github.com/bnema/purego-sqlite v0.1.4
M go.sum +2 -2 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_browser_gen.go +15 -2 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_command_line_gen.go +15 -2 generated file: collapsed
A vendor/github.com/bnema/purego-cef/cef/cef_component_updater_gen.go +323 -0 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_cookie_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_drag_data_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_image_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_media_router_gen.go +24 -41
@@ -103,6 +103,19 @@ func wrapMediaRouter(ptr unsafe.Pointer) MediaRouter {
103103 return impl
104104 }
105105
106+// takeMediaRouter adopts a CEF MediaRouter pointer whose reference is already owned by
107+// the caller (as returned by a global factory function). Unlike wrapMediaRouter it
108+// does NOT call AddRef, because the C API already transferred one reference to us.
109+func takeMediaRouter(ptr unsafe.Pointer) MediaRouter {
110+ if ptr == nil {
111+ return nil
112+ }
113+ r := (*capi.CEFMediaRouterT)(ptr)
114+ impl := &mediaRouterImpl{rawPtr: r}
115+ runtime.SetFinalizer(impl, (*mediaRouterImpl).Release)
116+ return impl
117+}
118+
106119 // MediaObserver Implemented by the client to observe MediaRouter events and registered via cef_media_router_t::AddObserver. The functions of this structure will be called on the browser process UI thread.
107120 type MediaObserver = portin.MediaObserver
108121
@@ -128,15 +141,9 @@ func mediaObserverOnSinksCEFCallback() uintptr {
128141 if !ownerOK {
129142 return
130143 }
131- var sinks []MediaSink
132- if arg1 != 0 && arg0 > 0 {
133- sinksPtrs := unsafe.Slice((*uintptr)(cefCallbackPointer(arg1)), int(arg0))
134- sinks = make([]MediaSink, int(arg0))
135- for i, ptr := range sinksPtrs {
136- sinks[i] = wrapMediaSink(cefCallbackPointer(ptr))
137- }
138- }
139- impl.OnSinks(sinks)
144+ sinkscount := int(arg0)
145+ sinks := unsafe.Pointer(arg1)
146+ impl.OnSinks(sinkscount, sinks)
140147 })
141148 }
142149
@@ -149,15 +156,9 @@ func mediaObserverOnRoutesCEFCallback() uintptr {
149156 if !ownerOK {
150157 return
151158 }
152- var routes []MediaRoute
153- if arg1 != 0 && arg0 > 0 {
154- routesPtrs := unsafe.Slice((*uintptr)(cefCallbackPointer(arg1)), int(arg0))
155- routes = make([]MediaRoute, int(arg0))
156- for i, ptr := range routesPtrs {
157- routes[i] = wrapMediaRoute(cefCallbackPointer(ptr))
158- }
159- }
160- impl.OnRoutes(routes)
159+ routescount := int(arg0)
160+ routes := unsafe.Pointer(arg1)
161+ impl.OnRoutes(routescount, routes)
161162 })
162163 }
163164
@@ -221,38 +222,20 @@ type mediaObserverImpl struct {
221222 releaseOnce sync.Once
222223 }
223224
224-func (obj *mediaObserverImpl) OnSinks(sinks []MediaSink) {
225+func (obj *mediaObserverImpl) OnSinks(sinkscount int, sinks unsafe.Pointer) {
225226 if obj == nil || obj.rawPtr == nil {
226227 return
227228 }
228229 rawPtr := obj.rawPtr
229- var sinksRaw []uintptr
230- var sinksPtr unsafe.Pointer
231- if len(sinks) > 0 {
232- sinksRaw = make([]uintptr, len(sinks))
233- for i, elem := range sinks {
234- sinksRaw[i] = uintptr(extractRawPointer(elem))
235- }
236- sinksPtr = unsafe.Pointer(&sinksRaw[0])
237- }
238- rawPtr.CallOnSinks(uintptr(len(sinks)), uintptr(sinksPtr))
230+ rawPtr.CallOnSinks(uintptr(sinkscount), uintptr(sinks))
239231 }
240232
241-func (obj *mediaObserverImpl) OnRoutes(routes []MediaRoute) {
233+func (obj *mediaObserverImpl) OnRoutes(routescount int, routes unsafe.Pointer) {
242234 if obj == nil || obj.rawPtr == nil {
243235 return
244236 }
245237 rawPtr := obj.rawPtr
246- var routesRaw []uintptr
247- var routesPtr unsafe.Pointer
248- if len(routes) > 0 {
249- routesRaw = make([]uintptr, len(routes))
250- for i, elem := range routes {
251- routesRaw[i] = uintptr(extractRawPointer(elem))
252- }
253- routesPtr = unsafe.Pointer(&routesRaw[0])
254- }
255- rawPtr.CallOnRoutes(uintptr(len(routes)), uintptr(routesPtr))
238+ rawPtr.CallOnRoutes(uintptr(routescount), uintptr(routes))
256239 }
257240
258241 func (obj *mediaObserverImpl) OnRouteStateChanged(route MediaRoute, state MediaRouteConnectionState) {
@@ -784,5 +767,5 @@ func wrapMediaSource(ptr unsafe.Pointer) MediaSource {
784767 // MediaRouterGetGlobal Returns the MediaRouter object associated with the global request context. If |callback| is non-NULL it will be executed asnychronously on the UI thread after the manager's storage has been initialized. Equivalent to calling cef_request_context_t::cef_request_context_get_global_context()- >get_media_router().
785768 func MediaRouterGetGlobal(callback CompletionCallback) MediaRouter {
786769 ret := capi.CEFMediaRouterGetGlobal(extractOrWrapRawPointer(callback, func() any { return NewCompletionCallback(callback) }))
787- return wrapMediaRouter(ret)
770+ return takeMediaRouter(ret)
788771 }
@@ -103,6 +103,19 @@ func wrapMediaRouter(ptr unsafe.Pointer) MediaRouter {
103 return impl103 return impl
104 }104 }
105 105
106+// takeMediaRouter adopts a CEF MediaRouter pointer whose reference is already owned by
107+// the caller (as returned by a global factory function). Unlike wrapMediaRouter it
108+// does NOT call AddRef, because the C API already transferred one reference to us.
109+func takeMediaRouter(ptr unsafe.Pointer) MediaRouter {
110+ if ptr == nil {
111+ return nil
112+ }
113+ r := (*capi.CEFMediaRouterT)(ptr)
114+ impl := &mediaRouterImpl{rawPtr: r}
115+ runtime.SetFinalizer(impl, (*mediaRouterImpl).Release)
116+ return impl
117+}
118+
106 // MediaObserver Implemented by the client to observe MediaRouter events and registered via cef_media_router_t::AddObserver. The functions of this structure will be called on the browser process UI thread.119 // MediaObserver Implemented by the client to observe MediaRouter events and registered via cef_media_router_t::AddObserver. The functions of this structure will be called on the browser process UI thread.
107 type MediaObserver = portin.MediaObserver120 type MediaObserver = portin.MediaObserver
108 121
@@ -128,15 +141,9 @@ func mediaObserverOnSinksCEFCallback() uintptr {
128 if !ownerOK {141 if !ownerOK {
129 return142 return
130 }143 }
131- var sinks []MediaSink144+ sinkscount := int(arg0)
132- if arg1 != 0 && arg0 > 0 {145+ sinks := unsafe.Pointer(arg1)
133- sinksPtrs := unsafe.Slice((*uintptr)(cefCallbackPointer(arg1)), int(arg0))146+ impl.OnSinks(sinkscount, sinks)
134- sinks = make([]MediaSink, int(arg0))
135- for i, ptr := range sinksPtrs {
136- sinks[i] = wrapMediaSink(cefCallbackPointer(ptr))
137- }
138- }
139- impl.OnSinks(sinks)
140 })147 })
141 }148 }
142 149
@@ -149,15 +156,9 @@ func mediaObserverOnRoutesCEFCallback() uintptr {
149 if !ownerOK {156 if !ownerOK {
150 return157 return
151 }158 }
152- var routes []MediaRoute159+ routescount := int(arg0)
153- if arg1 != 0 && arg0 > 0 {160+ routes := unsafe.Pointer(arg1)
154- routesPtrs := unsafe.Slice((*uintptr)(cefCallbackPointer(arg1)), int(arg0))161+ impl.OnRoutes(routescount, routes)
155- routes = make([]MediaRoute, int(arg0))
156- for i, ptr := range routesPtrs {
157- routes[i] = wrapMediaRoute(cefCallbackPointer(ptr))
158- }
159- }
160- impl.OnRoutes(routes)
161 })162 })
162 }163 }
163 164
@@ -221,38 +222,20 @@ type mediaObserverImpl struct {
221 releaseOnce sync.Once222 releaseOnce sync.Once
222 }223 }
223 224
224-func (obj *mediaObserverImpl) OnSinks(sinks []MediaSink) {225+func (obj *mediaObserverImpl) OnSinks(sinkscount int, sinks unsafe.Pointer) {
225 if obj == nil || obj.rawPtr == nil {226 if obj == nil || obj.rawPtr == nil {
226 return227 return
227 }228 }
228 rawPtr := obj.rawPtr229 rawPtr := obj.rawPtr
229- var sinksRaw []uintptr230+ rawPtr.CallOnSinks(uintptr(sinkscount), uintptr(sinks))
230- var sinksPtr unsafe.Pointer
231- if len(sinks) > 0 {
232- sinksRaw = make([]uintptr, len(sinks))
233- for i, elem := range sinks {
234- sinksRaw[i] = uintptr(extractRawPointer(elem))
235- }
236- sinksPtr = unsafe.Pointer(&sinksRaw[0])
237- }
238- rawPtr.CallOnSinks(uintptr(len(sinks)), uintptr(sinksPtr))
239 }231 }
240 232
241-func (obj *mediaObserverImpl) OnRoutes(routes []MediaRoute) {233+func (obj *mediaObserverImpl) OnRoutes(routescount int, routes unsafe.Pointer) {
242 if obj == nil || obj.rawPtr == nil {234 if obj == nil || obj.rawPtr == nil {
243 return235 return
244 }236 }
245 rawPtr := obj.rawPtr237 rawPtr := obj.rawPtr
246- var routesRaw []uintptr238+ rawPtr.CallOnRoutes(uintptr(routescount), uintptr(routes))
247- var routesPtr unsafe.Pointer
248- if len(routes) > 0 {
249- routesRaw = make([]uintptr, len(routes))
250- for i, elem := range routes {
251- routesRaw[i] = uintptr(extractRawPointer(elem))
252- }
253- routesPtr = unsafe.Pointer(&routesRaw[0])
254- }
255- rawPtr.CallOnRoutes(uintptr(len(routes)), uintptr(routesPtr))
256 }239 }
257 240
258 func (obj *mediaObserverImpl) OnRouteStateChanged(route MediaRoute, state MediaRouteConnectionState) {241 func (obj *mediaObserverImpl) OnRouteStateChanged(route MediaRoute, state MediaRouteConnectionState) {
@@ -784,5 +767,5 @@ func wrapMediaSource(ptr unsafe.Pointer) MediaSource {
784 // MediaRouterGetGlobal Returns the MediaRouter object associated with the global request context. If |callback| is non-NULL it will be executed asnychronously on the UI thread after the manager's storage has been initialized. Equivalent to calling cef_request_context_t::cef_request_context_get_global_context()- >get_media_router().767 // MediaRouterGetGlobal Returns the MediaRouter object associated with the global request context. If |callback| is non-NULL it will be executed asnychronously on the UI thread after the manager's storage has been initialized. Equivalent to calling cef_request_context_t::cef_request_context_get_global_context()- >get_media_router().
785 func MediaRouterGetGlobal(callback CompletionCallback) MediaRouter {768 func MediaRouterGetGlobal(callback CompletionCallback) MediaRouter {
786 ret := capi.CEFMediaRouterGetGlobal(extractOrWrapRawPointer(callback, func() any { return NewCompletionCallback(callback) }))769 ret := capi.CEFMediaRouterGetGlobal(extractOrWrapRawPointer(callback, func() any { return NewCompletionCallback(callback) }))
787- return wrapMediaRouter(ret)770+ return takeMediaRouter(ret)
788 }771 }
M vendor/github.com/bnema/purego-cef/cef/cef_menu_model_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_parser_gen.go +10 -4 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_preference_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_print_settings_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_process_message_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_request_context_gen.go +16 -3 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_request_gen.go +42 -3 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_resource_bundle_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_response_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_shared_memory_region_gen.go +3 -3 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_shared_process_message_builder_gen.go +20 -4 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_stream_gen.go +34 -5 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_task_gen.go +15 -2 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_task_manager_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_thread_gen.go +14 -1 generated file: collapsed
A vendor/github.com/bnema/purego-cef/cef/cef_types_component_gen.go +45 -0 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_types_content_settings_gen.go +72 -79 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_types_gen.go +59 -52 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_urlrequest_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_v8_gen.go +166 -19 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_values_gen.go +62 -7 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_waitable_event_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_xml_reader_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/cef_zip_reader_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/test_cef_api_version_test__gen.go +86 -871 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/test_cef_test_server_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/test_cef_translator_test__gen.go +92 -50 generated file: collapsed
A vendor/github.com/bnema/purego-cef/cef/v8_helpers.go +19 -0 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/views_cef_browser_view_gen.go +15 -2 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/views_cef_display_gen.go +17 -4 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/views_cef_label_button_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/views_cef_menu_button_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/views_cef_panel_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/views_cef_scroll_view_gen.go +14 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/views_cef_textfield_gen.go +14 -60 generated file: collapsed
M vendor/github.com/bnema/purego-cef/cef/views_cef_window_gen.go +14 -1 generated file: collapsed
A vendor/github.com/bnema/purego-cef/internal/capi/cef_component_updater_gen.go +130 -0 generated file: collapsed
A vendor/github.com/bnema/purego-cef/internal/capi/cef_types_component_gen.go +11 -0 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/capi/cef_types_gen.go +1 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/capi/cef_v8_gen.go +44 -0 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/capi/register_gen.go +2 -0 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/capi/test_cef_api_version_test__gen.go +0 -459 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/capi/views_cef_textfield_gen.go +33 -107 generated file: collapsed
A vendor/github.com/bnema/purego-cef/internal/cefapi/contract.go +11 -0 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/loader/loader.go +23 -18 generated file: collapsed
A vendor/github.com/bnema/purego-cef/internal/ports/in/cef_component_updater_gen.go +24 -0 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/in/cef_media_router_gen.go +2 -2 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/in/cef_shared_memory_region_gen.go +1 -5 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/in/cef_shared_process_message_builder_gen.go +1 -5 generated file: collapsed
A vendor/github.com/bnema/purego-cef/internal/ports/in/cef_types_component_gen.go +9 -0 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/in/cef_v8_gen.go +8 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/in/cef_values_gen.go +1 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/in/test_cef_api_version_test__gen.go +8 -63 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/in/test_cef_translator_test__gen.go +8 -4 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/in/views_cef_textfield_gen.go +0 -7 generated file: collapsed
A vendor/github.com/bnema/purego-cef/internal/ports/out/cef_component_updater_gen.go +29 -0 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/out/cef_parser_gen.go +3 -3 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/out/cef_preference_gen.go +2 -2 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/out/cef_shared_process_message_builder_gen.go +1 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/out/cef_stream_gen.go +1 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/out/cef_v8_gen.go +11 -2 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/out/cef_values_gen.go +1 -1 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/out/test_cef_api_version_test__gen.go +4 -51 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/out/test_cef_translator_test__gen.go +4 -4 generated file: collapsed
M vendor/github.com/bnema/purego-cef/internal/ports/out/views_cef_textfield_gen.go +0 -7 generated file: collapsed
M vendor/modules.txt +2 -1 generated file: collapsed

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close