Delay cef2gtk GL preparation
- commit
- 40b8fb03a0ce2d32011768797692e1d331b09470
- author
- brice · · 2026-04-30 02:45 UTC
- parent
- 1d14237
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +15 -16
M internal/infrastructure/cef/factory.go +15 -16
| @@ -123,17 +123,6 @@ func (f *WebViewFactory) newWebView(ctx context.Context) (*WebView, error) { | |||
| 123 | 123 | wv.handlers = handlers | |
| 124 | 124 | wv.findCtrl = newFindController() | |
| 125 | 125 | ||
| 126 | - | var prepareErr error | |
| 127 | - | wv.runOnGTKSync(func() { | |
| 128 | - | prepareErr = viewBridge.PrepareOnGTKThread() | |
| 129 | - | }) | |
| 130 | - | if prepareErr != nil { | |
| 131 | - | if ctx != nil { | |
| 132 | - | logging.FromContext(ctx).Error().Err(prepareErr).Uint64("webview_id", uint64(id)).Msg("cef: failed to prepare cef2gtk view") | |
| 133 | - | } | |
| 134 | - | return nil, fmt.Errorf("prepare cef2gtk view: %w", prepareErr) | |
| 135 | - | } | |
| 136 | - | ||
| 137 | 126 | // Build a CEF client backed by our handlerSet. | |
| 138 | 127 | // Store on WebView to prevent GC collection before CEF AddRef's it. | |
| 139 | 128 | wv.client = purecef.NewClient(wv.handlers) | |
| @@ -159,17 +148,27 @@ func (f *WebViewFactory) configureInitialBrowserCreation( | |||
| 159 | 148 | if wv.viewBridge == nil { | |
| 160 | 149 | return | |
| 161 | 150 | } | |
| 162 | - | firstResize := true | |
| 151 | + | browserCreateScheduled := false | |
| 163 | 152 | wv.runOnGTKSync(func() { | |
| 164 | 153 | wv.removeSizeObserver = wv.viewBridge.AddSizeObserver(func(w, h int32) { | |
| 165 | - | if firstResize { | |
| 166 | - | firstResize = false | |
| 154 | + | // Size observers run on the GTK thread. Prepare the GtkGLArea only after it | |
| 155 | + | // has been packed and allocated; preparing at WebView construction time can | |
| 156 | + | // run before GTK has created a GL context. | |
| 157 | + | if !browserCreateScheduled { | |
| 158 | + | if err := wv.viewBridge.PrepareOnGTKThread(); err != nil { | |
| 159 | + | logging.FromContext(ctx).Warn(). | |
| 160 | + | Err(err). | |
| 161 | + | Uint64("webview_id", uint64(wv.id)). | |
| 162 | + | Int32("resize_width", w). | |
| 163 | + | Int32("resize_height", h). | |
| 164 | + | Msg("cef: cef2gtk view not ready after resize, will retry") | |
| 165 | + | return | |
| 166 | + | } | |
| 167 | + | browserCreateScheduled = true | |
| 167 | 168 | onFirstResize(w, h) | |
| 168 | 169 | return | |
| 169 | 170 | } | |
| 170 | 171 | ||
| 171 | - | // Size observers run on the GTK thread; the captured firstResize state is | |
| 172 | - | // therefore single-threaded. | |
| 173 | 172 | wv.mu.RLock() | |
| 174 | 173 | host := wv.host | |
| 175 | 174 | wv.mu.RUnlock() | |
| @@ -123,17 +123,6 @@ func (f *WebViewFactory) newWebView(ctx context.Context) (*WebView, error) { | |||||
| 123 | wv.handlers = handlers | 123 | wv.handlers = handlers | ||
| 124 | wv.findCtrl = newFindController() | 124 | wv.findCtrl = newFindController() | ||
| 125 | 125 | ||||
| 126 | - | var prepareErr error | |||
| 127 | - | wv.runOnGTKSync(func() { | |||
| 128 | - | prepareErr = viewBridge.PrepareOnGTKThread() | |||
| 129 | - | }) | |||
| 130 | - | if prepareErr != nil { | |||
| 131 | - | if ctx != nil { | |||
| 132 | - | logging.FromContext(ctx).Error().Err(prepareErr).Uint64("webview_id", uint64(id)).Msg("cef: failed to prepare cef2gtk view") | |||
| 133 | - | } | |||
| 134 | - | return nil, fmt.Errorf("prepare cef2gtk view: %w", prepareErr) | |||
| 135 | - | } | |||
| 136 | - | ||||
| 137 | // Build a CEF client backed by our handlerSet. | 126 | // Build a CEF client backed by our handlerSet. | ||
| 138 | // Store on WebView to prevent GC collection before CEF AddRef's it. | 127 | // Store on WebView to prevent GC collection before CEF AddRef's it. | ||
| 139 | wv.client = purecef.NewClient(wv.handlers) | 128 | wv.client = purecef.NewClient(wv.handlers) | ||
| @@ -159,17 +148,27 @@ func (f *WebViewFactory) configureInitialBrowserCreation( | |||||
| 159 | if wv.viewBridge == nil { | 148 | if wv.viewBridge == nil { | ||
| 160 | return | 149 | return | ||
| 161 | } | 150 | } | ||
| 162 | - | firstResize := true | 151 | + | browserCreateScheduled := false |
| 163 | wv.runOnGTKSync(func() { | 152 | wv.runOnGTKSync(func() { | ||
| 164 | wv.removeSizeObserver = wv.viewBridge.AddSizeObserver(func(w, h int32) { | 153 | wv.removeSizeObserver = wv.viewBridge.AddSizeObserver(func(w, h int32) { | ||
| 165 | - | if firstResize { | 154 | + | // Size observers run on the GTK thread. Prepare the GtkGLArea only after it |
| 166 | - | firstResize = false | 155 | + | // has been packed and allocated; preparing at WebView construction time can |
| 156 | + | // run before GTK has created a GL context. | |||
| 157 | + | if !browserCreateScheduled { | |||
| 158 | + | if err := wv.viewBridge.PrepareOnGTKThread(); err != nil { | |||
| 159 | + | logging.FromContext(ctx).Warn(). | |||
| 160 | + | Err(err). | |||
| 161 | + | Uint64("webview_id", uint64(wv.id)). | |||
| 162 | + | Int32("resize_width", w). | |||
| 163 | + | Int32("resize_height", h). | |||
| 164 | + | Msg("cef: cef2gtk view not ready after resize, will retry") | |||
| 165 | + | return | |||
| 166 | + | } | |||
| 167 | + | browserCreateScheduled = true | |||
| 167 | onFirstResize(w, h) | 168 | onFirstResize(w, h) | ||
| 168 | return | 169 | return | ||
| 169 | } | 170 | } | ||
| 170 | 171 | ||||
| 171 | - | // Size observers run on the GTK thread; the captured firstResize state is | |||
| 172 | - | // therefore single-threaded. | |||
| 173 | wv.mu.RLock() | 172 | wv.mu.RLock() | ||
| 174 | host := wv.host | 173 | host := wv.host | ||
| 175 | wv.mu.RUnlock() | 174 | wv.mu.RUnlock() | ||