diff --git a/src/vs/workbench/contrib/notebook/browser/controller/cellOutputActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/cellOutputActions.ts index 956222d7a36..fa43716b286 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/cellOutputActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/cellOutputActions.ts @@ -55,7 +55,7 @@ registerAction2(class CopyCellOutputAction extends Action2 { const mimeType = outputViewModel.pickedMimeType?.mimeType; if (mimeType?.startsWith('image/')) { - const focusOptions = { skipReveal: true, outputId: outputViewModel.model.outputId }; + const focusOptions = { skipReveal: true, outputId: outputViewModel.model.outputId, altOutputId: outputViewModel.model.alternativeOutputId }; await notebookEditor.focusNotebookCell(outputViewModel.cellViewModel as ICellViewModel, 'output', focusOptions); notebookEditor.copyOutputImage(outputViewModel); } else { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 4f1d98b86bb..158b98692fe 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -152,6 +152,7 @@ export interface IFocusNotebookCellOptions { readonly focusEditorLine?: number; readonly minimalScrolling?: boolean; readonly outputId?: string; + readonly altOutputId?: string; } //#endregion diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index ba8ae7da1db..3830664287b 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -2350,7 +2350,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD } const focusElementId = options?.outputId ?? cell.id; - this._webview.focusOutput(focusElementId, this._webviewFocused); + this._webview.focusOutput(focusElementId, options?.altOutputId, this._webviewFocused); cell.updateEditState(CellEditState.Preview, 'focusNotebookCell'); cell.focusMode = CellFocusMode.Output; diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index b2359655e6d..aaed4af8425 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -1548,7 +1548,8 @@ export class BackLayerWebView extends Themable { async copyImage(output: ICellOutputViewModel): Promise { this._sendMessageToWebview({ type: 'copyImage', - outputId: output.model.outputId + outputId: output.model.outputId, + altOutputId: output.model.alternativeOutputId }); } @@ -1608,7 +1609,7 @@ export class BackLayerWebView extends Themable { this.webview?.focus(); } - focusOutput(cellOrOutputId: string, viewFocused: boolean) { + focusOutput(cellOrOutputId: string, backupId: string | undefined, viewFocused: boolean) { if (this._disposed) { return; } @@ -1620,6 +1621,7 @@ export class BackLayerWebView extends Themable { this._sendMessageToWebview({ type: 'focus-output', cellOrOutputId: cellOrOutputId, + backupId: backupId }); } diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts index e74e173ae33..f16d781611a 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts @@ -269,11 +269,13 @@ export interface IShowOutputMessage { export interface ICopyImageMessage { readonly type: 'copyImage'; readonly outputId: string; + readonly altOutputId: string; } export interface IFocusOutputMessage { readonly type: 'focus-output'; readonly cellOrOutputId: string; + readonly backupId?: string; } export interface IAckOutputHeight { diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts index 4715e64aa08..cadaa48312f 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts @@ -474,8 +474,9 @@ async function webviewPreloads(ctx: PreloadContext) { }); }; - function focusFirstFocusableOrContainerInOutput(cellOrOutputId: string) { - const cellOutputContainer = document.getElementById(cellOrOutputId); + function focusFirstFocusableOrContainerInOutput(cellOrOutputId: string, backupId?: string) { + const cellOutputContainer = document.getElementById(cellOrOutputId) ?? + backupId ? document.getElementById(backupId!) : undefined; if (cellOutputContainer) { if (cellOutputContainer.contains(document.activeElement)) { return; @@ -1362,17 +1363,17 @@ async function webviewPreloads(ctx: PreloadContext) { }); }; - const copyOutputImage = async (outputId: string, retries = 5) => { + const copyOutputImage = async (outputId: string, altOutputId: string, retries = 5) => { if (!document.hasFocus() && retries > 0) { // copyImage can be called from outside of the webview, which means this function may be running whilst the webview is gaining focus. // Since navigator.clipboard.write requires the document to be focused, we need to wait for focus. // We cannot use a listener, as there is a high chance the focus is gained during the setup of the listener resulting in us missing it. - setTimeout(() => { copyOutputImage(outputId, retries - 1); }, 20); + setTimeout(() => { copyOutputImage(outputId, altOutputId, retries - 1); }, 20); return; } try { - const image = document.getElementById(outputId)?.querySelector('img'); + const image = document.getElementById(outputId)?.querySelector('img') || document.getElementById(altOutputId)?.querySelector('img'); if (image) { await navigator.clipboard.write([new ClipboardItem({ 'image/png': new Promise((resolve) => { @@ -1501,7 +1502,7 @@ async function webviewPreloads(ctx: PreloadContext) { } case 'copyImage': { - await copyOutputImage(event.data.outputId); + await copyOutputImage(event.data.outputId, event.data.altOutputId); break; } @@ -1524,7 +1525,7 @@ async function webviewPreloads(ctx: PreloadContext) { break; } case 'focus-output': - focusFirstFocusableOrContainerInOutput(event.data.cellOrOutputId); + focusFirstFocusableOrContainerInOutput(event.data.cellOrOutputId, event.data.backupId); break; case 'decorations': { let outputContainer = document.getElementById(event.data.cellId);