feat(workspace): implement popup tracking and universal window.close() handling
- commit
- 30637f80b6ce9a7fc0e43d5c952a0c7b8f66a3e6
- author
- bamen · · 2025-09-20 06:03 UTC
- parent
- d542439
- signature
- unsigned
1 file · +33 -0
M internal/app/browser/workspace_manager.go +33 -0
| @@ -22,6 +22,7 @@ type paneNode struct { | |||
| 22 | 22 | container uintptr // GtkPaned for branch nodes, stable WebView container for leaves | |
| 23 | 23 | orientation webkit.Orientation | |
| 24 | 24 | isLeaf bool | |
| 25 | + | isPopup bool // Track if this is a popup pane for OAuth auto-close | |
| 25 | 26 | hoverToken uintptr | |
| 26 | 27 | } | |
| 27 | 28 | ||
| @@ -1321,6 +1322,38 @@ func (wm *WorkspaceManager) HandlePopup(source *webkit.WebView, url string) *web | |||
| 1321 | 1322 | return nil | |
| 1322 | 1323 | } | |
| 1323 | 1324 | ||
| 1325 | + | // Mark the new pane as a popup for auto-close handling | |
| 1326 | + | // The viewToNode mapping is created inside insertPopupPane, so look it up now | |
| 1327 | + | newNode := wm.viewToNode[newView] | |
| 1328 | + | if newNode != nil { | |
| 1329 | + | newNode.isPopup = true | |
| 1330 | + | log.Printf("[workspace] Marked pane as popup for auto-close handling") | |
| 1331 | + | } else { | |
| 1332 | + | log.Printf("[workspace] Warning: could not find node for popup WebView in viewToNode map") | |
| 1333 | + | } | |
| 1334 | + | ||
| 1335 | + | // Register close handler for popup auto-close on window.close() | |
| 1336 | + | // Always register this for popups, regardless of node lookup | |
| 1337 | + | newView.RegisterCloseHandler(func() { | |
| 1338 | + | log.Printf("[workspace] Popup requesting close via window.close()") | |
| 1339 | + | ||
| 1340 | + | // Look up the node at close time | |
| 1341 | + | if node := wm.viewToNode[newView]; node != nil && node.isPopup { | |
| 1342 | + | log.Printf("[workspace] Closing popup pane") | |
| 1343 | + | // Brief delay to allow any final redirects to complete | |
| 1344 | + | time.AfterFunc(200*time.Millisecond, func() { | |
| 1345 | + | webkit.IdleAdd(func() bool { | |
| 1346 | + | if err := wm.closePane(node); err != nil { | |
| 1347 | + | log.Printf("[workspace] Failed to close popup pane: %v", err) | |
| 1348 | + | } | |
| 1349 | + | return false | |
| 1350 | + | }) | |
| 1351 | + | }) | |
| 1352 | + | } else { | |
| 1353 | + | log.Printf("[workspace] Could not find popup node for close handler") | |
| 1354 | + | } | |
| 1355 | + | }) | |
| 1356 | + | ||
| 1324 | 1357 | // Load the URL if provided | |
| 1325 | 1358 | if url != "" { | |
| 1326 | 1359 | if err := newView.LoadURL(url); err != nil { | |
| @@ -22,6 +22,7 @@ type paneNode struct { | |||||
| 22 | container uintptr // GtkPaned for branch nodes, stable WebView container for leaves | 22 | container uintptr // GtkPaned for branch nodes, stable WebView container for leaves | ||
| 23 | orientation webkit.Orientation | 23 | orientation webkit.Orientation | ||
| 24 | isLeaf bool | 24 | isLeaf bool | ||
| 25 | + | isPopup bool // Track if this is a popup pane for OAuth auto-close | |||
| 25 | hoverToken uintptr | 26 | hoverToken uintptr | ||
| 26 | } | 27 | } | ||
| 27 | 28 | ||||
| @@ -1321,6 +1322,38 @@ func (wm *WorkspaceManager) HandlePopup(source *webkit.WebView, url string) *web | |||||
| 1321 | return nil | 1322 | return nil | ||
| 1322 | } | 1323 | } | ||
| 1323 | 1324 | ||||
| 1325 | + | // Mark the new pane as a popup for auto-close handling | |||
| 1326 | + | // The viewToNode mapping is created inside insertPopupPane, so look it up now | |||
| 1327 | + | newNode := wm.viewToNode[newView] | |||
| 1328 | + | if newNode != nil { | |||
| 1329 | + | newNode.isPopup = true | |||
| 1330 | + | log.Printf("[workspace] Marked pane as popup for auto-close handling") | |||
| 1331 | + | } else { | |||
| 1332 | + | log.Printf("[workspace] Warning: could not find node for popup WebView in viewToNode map") | |||
| 1333 | + | } | |||
| 1334 | + | ||||
| 1335 | + | // Register close handler for popup auto-close on window.close() | |||
| 1336 | + | // Always register this for popups, regardless of node lookup | |||
| 1337 | + | newView.RegisterCloseHandler(func() { | |||
| 1338 | + | log.Printf("[workspace] Popup requesting close via window.close()") | |||
| 1339 | + | ||||
| 1340 | + | // Look up the node at close time | |||
| 1341 | + | if node := wm.viewToNode[newView]; node != nil && node.isPopup { | |||
| 1342 | + | log.Printf("[workspace] Closing popup pane") | |||
| 1343 | + | // Brief delay to allow any final redirects to complete | |||
| 1344 | + | time.AfterFunc(200*time.Millisecond, func() { | |||
| 1345 | + | webkit.IdleAdd(func() bool { | |||
| 1346 | + | if err := wm.closePane(node); err != nil { | |||
| 1347 | + | log.Printf("[workspace] Failed to close popup pane: %v", err) | |||
| 1348 | + | } | |||
| 1349 | + | return false | |||
| 1350 | + | }) | |||
| 1351 | + | }) | |||
| 1352 | + | } else { | |||
| 1353 | + | log.Printf("[workspace] Could not find popup node for close handler") | |||
| 1354 | + | } | |||
| 1355 | + | }) | |||
| 1356 | + | ||||
| 1324 | // Load the URL if provided | 1357 | // Load the URL if provided | ||
| 1325 | if url != "" { | 1358 | if url != "" { | ||
| 1326 | if err := newView.LoadURL(url); err != nil { | 1359 | if err := newView.LoadURL(url); err != nil { | ||