Skip to content

Fix notebook UI overlap #129286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
8 changes: 6 additions & 2 deletions src/vs/workbench/browser/parts/editor/editorGroupView.ts
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@ import { IFilesConfigurationService, AutoSaveMode } from 'vs/workbench/services/
import { withNullAsUndefined } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';

export class EditorGroupView extends Themable implements IEditorGroupView {

@@ -147,7 +148,8 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
@ILogService private readonly logService: ILogService,
@IEditorService private readonly editorService: EditorServiceImpl,
@IFilesConfigurationService private readonly filesConfigurationService: IFilesConfigurationService,
@IUriIdentityService private readonly uriIdentityService: IUriIdentityService
@IUriIdentityService private readonly uriIdentityService: IUriIdentityService,
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService
) {
super(themeService);

@@ -489,7 +491,9 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Show active editor (intentionally not using async to keep
// `restoreEditors` from executing in same stack)
return this.doShowEditor(activeEditor, { active: true, isNew: false /* restored */ }, options).then(() => {

// Update visibility when restored as the editor start as visible but
// could be hidden if panel is maximized
this.onDidVisibilityChange(this.layoutService.isVisible(Parts.EDITOR_PART));
Comment on lines 493 to +496
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed for the edge case when we have a notebook editor open but with the panel maximized and then reload the window. When the editors are restored they start as visible but are actually hidden as the panel is maximized

// Set focused now if this is the active group and focus has
// not changed meanwhile. This prevents focus from being
// stolen accidentally on startup when the user already
Original file line number Diff line number Diff line change
@@ -224,7 +224,7 @@ export class InteractiveEditor extends EditorPane {
// there currently is a widget which we still own so
// we need to hide it before getting a new widget
if (this.#notebookWidget.value) {
this.#notebookWidget.value.onWillHide();
this.#notebookWidget.value.setVisible(false);
}

if (this.#codeEditorWidget) {
@@ -309,6 +309,7 @@ export class InteractiveEditor extends EditorPane {
this.layout(this.#dimension);
}
}));
this.#notebookWidget.value!.setVisible(this.isVisible());

const editorModel = input.resolveInput(this.#notebookWidget.value?.activeKernel?.supportedLanguages[0] ?? 'plaintext');
this.#codeEditorWidget.setModel(editorModel);
@@ -561,16 +562,12 @@ export class InteractiveEditor extends EditorPane {
override setEditorVisible(visible: boolean, group: IEditorGroup | undefined): void {
super.setEditorVisible(visible, group);

if (!visible) {
if (this.input && this.#notebookWidget.value) {
this.#notebookWidget.value.onWillHide();
}
}
this.#notebookWidget.value?.setVisible(visible);
}

override clearInput() {
if (this.#notebookWidget.value) {
this.#notebookWidget.value.onWillHide();
this.#notebookWidget.value.setVisible(false);
}

if (this.#codeEditorWidget) {
14 changes: 5 additions & 9 deletions src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
Original file line number Diff line number Diff line change
@@ -151,11 +151,8 @@ export class NotebookEditor extends EditorPane {

if (!visible) {
this._saveEditorViewState(this.input);
if (this.input && this._widget.value) {
// the widget is not transfered to other editor inputs
this._widget.value.onWillHide();
}
}
this._widget.value?.setVisible(visible);
}

override focus() {
@@ -183,9 +180,7 @@ export class NotebookEditor extends EditorPane {

// there currently is a widget which we still own so
// we need to hide it before getting a new widget
if (this._widget.value) {
this._widget.value.onWillHide();
}
this._widget.value?.setVisible(false);

this._widget = this.instantiationService.invokeFunction(this._notebookWidgetService.retrieveWidget, group, input);
this._widgetDisposableStore.add(this._widget.value!.onDidChangeModel(() => this._onDidChangeModel.fire()));
@@ -223,12 +218,13 @@ export class NotebookEditor extends EditorPane {

const viewState = this._loadNotebookEditorViewState(input);

this._widget.value?.setParentContextKeyService(this._contextKeyService);
this._widget.value!.setParentContextKeyService(this._contextKeyService);
await this._widget.value!.setModel(model.notebook, viewState);
const isReadOnly = input.hasCapability(EditorInputCapabilities.Readonly);
await this._widget.value!.setOptions({ ...options, isReadOnly });
this._widgetDisposableStore.add(this._widget.value!.onDidFocus(() => this._onDidFocusWidget.fire()));
this._widgetDisposableStore.add(this._widget.value!.onDidBlur(() => this._onDidBlurWidget.fire()));
this._widget.value!.setVisible(this.isVisible());

this._widgetDisposableStore.add(this._editorDropService.createEditorDropTarget(this._widget.value!.getDomNode(), {
containsGroup: (group) => this.group?.id === group.id
@@ -295,7 +291,7 @@ export class NotebookEditor extends EditorPane {

if (this._widget.value) {
this._saveEditorViewState(this.input);
this._widget.value.onWillHide();
this._widget.value.setVisible(false);
}
super.clearInput();
}
Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@ export class NotebookEditorWidgetService implements INotebookEditorService {
// --- group-based editor borrowing...

private _disposeWidget(widget: NotebookEditorWidget): void {
widget.onWillHide();
widget.setVisible(false);
const domNode = widget.getDomNode();
widget.dispose();
domNode.remove();
Original file line number Diff line number Diff line change
@@ -290,12 +290,6 @@ export class NotebookEditorToolbar extends Disposable {

layout(dimension: DOM.Dimension) {
this._dimension = dimension;

if (!this._useGlobalToolbar) {
this.domNode.style.display = 'none';
} else {
this.domNode.style.display = 'flex';
}
this._computeSizes();
}

27 changes: 9 additions & 18 deletions src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
Original file line number Diff line number Diff line change
@@ -394,7 +394,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this.layoutService.container.appendChild(this._overlayContainer);
this._createBody(this._overlayContainer);
this._generateFontInfo();
this._isVisible = true;
this._editorFocus = NOTEBOOK_EDITOR_FOCUSED.bindTo(this.scopedContextKeyService);
this._outputFocus = NOTEBOOK_OUTPUT_FOCUSED.bindTo(this.scopedContextKeyService);
this._editorEditable = NOTEBOOK_EDITOR_EDITABLE.bindTo(this.scopedContextKeyService);
@@ -1354,7 +1353,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
await this._resolveWebview();

// make sure that the webview is not visible otherwise users will see pre-rendered markdown cells in wrong position as the list view doesn't have a correct `top` offset yet
this._webview!.element.style.visibility = 'hidden';
this._list.layout(0, 0);
// warm up can take around 200ms to load markdown libraries, etc.
await this._warmupViewport(viewModel, viewState);

@@ -1366,16 +1365,13 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
* - markdown cell -> request to webview to (10ms, basically just latency between UI and iframe)
* - code cell -> render in place
*/
this._list.layout(0, 0);
this._list.attachViewModel(viewModel);

// now the list widget has a correct contentHeight/scrollHeight
// setting scrollTop will work properly
// after setting scroll top, the list view will update `top` of the scrollable element, e.g. `top: -584px`
this._list.scrollTop = viewState?.scrollPosition?.top ?? 0;
this._debug('finish initial viewport warmup and view state restore.');
this._webview!.element.style.visibility = 'visible';

}

private async _warmupViewport(viewModel: NotebookViewModel, viewState: INotebookEditorViewState | undefined) {
@@ -1540,11 +1536,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
return;
}

if (dimension.width <= 0 || dimension.height <= 0) {
this.onWillHide();
return;
}

if (shadowElement) {
const containerRect = shadowElement.getBoundingClientRect();

@@ -1570,7 +1561,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this._list.updateOptions({ additionalScrollHeight: this._allowScrollBeyondLastLine() ? Math.max(0, (dimension.height - topInserToolbarHeight - 50)) : topInserToolbarHeight });
}

this._overlayContainer.style.visibility = 'visible';
this._overlayContainer.style.display = 'block';
this._overlayContainer.style.position = 'absolute';

@@ -1593,7 +1583,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor

//#region Focus tracker
focus() {
this._isVisible = true;
this._editorFocus.set(true);

if (this._webviewFocused) {
@@ -1617,12 +1606,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this._onDidFocusEditorWidget.fire();
}

onWillHide() {
this._isVisible = false;
this._editorFocus.set(false);
this._overlayContainer.style.visibility = 'hidden';
this._overlayContainer.style.left = '-50000px';
this._notebookTopToolbarContainer.style.display = 'none';
setVisible(visible: boolean) {
this._isVisible = visible;
if (visible) {
this._overlayContainer.style.visibility = 'visible';
} else {
this._editorFocus.set(false);
this._overlayContainer.style.visibility = 'hidden';
}
}

updateEditorFocus() {
Original file line number Diff line number Diff line change
@@ -1280,11 +1280,6 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
override layout(height?: number, width?: number): void {
this._isInLayout = true;
super.layout(height, width);
if (this.renderHeight === 0) {
this.view.domNode.style.visibility = 'hidden';
} else {
this.view.domNode.style.visibility = 'initial';
}
this._isInLayout = false;
}