Skip to content

Commit e0750d2

Browse files
authored
Merge pull request microsoft#256802 from mjbvz/positive-crawdad
Add internal API for getting a webview's content size
2 parents 549a330 + 77590be commit e0750d2

File tree

5 files changed

+39
-15
lines changed

5 files changed

+39
-15
lines changed

src/vs/workbench/contrib/webview/browser/overlayWebview.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { IMouseWheelEvent } from '../../../../base/browser/mouseEvent.js';
99
import { CodeWindow } from '../../../../base/browser/window.js';
1010
import { Emitter } from '../../../../base/common/event.js';
1111
import { Disposable, DisposableStore, MutableDisposable } from '../../../../base/common/lifecycle.js';
12+
import { autorun, observableValue } from '../../../../base/common/observable.js';
1213
import { URI } from '../../../../base/common/uri.js';
1314
import { generateUuid } from '../../../../base/common/uuid.js';
1415
import { IContextKey, IContextKeyService, IScopedContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';
@@ -256,8 +257,10 @@ export class OverlayWebview extends Disposable implements IOverlayWebview {
256257
this._webviewEvents.add(webview.onMessage(x => { this._onMessage.fire(x); }));
257258
this._webviewEvents.add(webview.onMissingCsp(x => { this._onMissingCsp.fire(x); }));
258259
this._webviewEvents.add(webview.onDidWheel(x => { this._onDidWheel.fire(x); }));
259-
this._webviewEvents.add(webview.onDidReload(() => { this._onDidReload.fire(); }));
260260
this._webviewEvents.add(webview.onFatalError(x => { this._onFatalError.fire(x); }));
261+
this._webviewEvents.add(autorun(reader => {
262+
this.intrinsicContentSize.set(reader.readObservable(webview.intrinsicContentSize), undefined, undefined);
263+
}));
261264

262265
this._webviewEvents.add(webview.onDidScroll(x => {
263266
this._initialScrollProgress = x.scrollYPercentage;
@@ -338,9 +341,6 @@ export class OverlayWebview extends Disposable implements IOverlayWebview {
338341
private readonly _onDidClickLink = this._register(new Emitter<string>());
339342
public readonly onDidClickLink = this._onDidClickLink.event;
340343

341-
private readonly _onDidReload = this._register(new Emitter<void>());
342-
public readonly onDidReload = this._onDidReload.event;
343-
344344
private readonly _onDidScroll = this._register(new Emitter<{ readonly scrollYPercentage: number }>());
345345
public readonly onDidScroll = this._onDidScroll.event;
346346

@@ -359,6 +359,8 @@ export class OverlayWebview extends Disposable implements IOverlayWebview {
359359
private readonly _onFatalError = this._register(new Emitter<{ readonly message: string }>());
360360
public onFatalError = this._onFatalError.event;
361361

362+
public readonly intrinsicContentSize = observableValue<{ readonly width: number; readonly height: number } | undefined>('WebviewIntrinsicContentSize', undefined);
363+
362364
public async postMessage(message: any, transfer?: readonly ArrayBuffer[]): Promise<boolean> {
363365
if (this._webview.value) {
364366
return this._webview.value.postMessage(message, transfer);

src/vs/workbench/contrib/webview/browser/pre/index.html

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<meta charset="UTF-8">
66

77
<meta http-equiv="Content-Security-Policy"
8-
content="default-src 'none'; script-src 'sha256-l9e7E37hgQqoIAqcFRgQ5/0NqMMW93mQmYAsUcDUyZ4=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
8+
content="default-src 'none'; script-src 'sha256-kvB8+4EUtyEDThMIgb61H4fMe04EqjRhttNuYd028mo=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
99

1010
<!-- Disable pinch zooming -->
1111
<meta name="viewport"
@@ -1122,6 +1122,21 @@
11221122
contentWindow.focus();
11231123
}
11241124

1125+
// Get body size
1126+
const docEl = contentDocument.documentElement;
1127+
if (docEl) {
1128+
const postSize = () => {
1129+
hostMessaging.postMessage('updated-intrinsic-content-size', {
1130+
width: docEl.scrollWidth,
1131+
height: docEl.scrollHeight
1132+
});
1133+
};
1134+
1135+
const resizeObserver = new ResizeObserver(postSize);
1136+
resizeObserver.observe(docEl);
1137+
postSize();
1138+
}
1139+
11251140
pendingMessages.forEach((message) => {
11261141
contentWindow.postMessage(message.message, window.origin, message.transfer);
11271142
});

src/vs/workbench/contrib/webview/browser/webview.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { CodeWindow } from '../../../../base/browser/window.js';
99
import { equals } from '../../../../base/common/arrays.js';
1010
import { Event } from '../../../../base/common/event.js';
1111
import { IDisposable } from '../../../../base/common/lifecycle.js';
12+
import { IObservable } from '../../../../base/common/observable.js';
1213
import { isEqual } from '../../../../base/common/resources.js';
1314
import { URI } from '../../../../base/common/uri.js';
1415
import { generateUuid } from '../../../../base/common/uuid.js';
@@ -233,7 +234,13 @@ export interface IWebview extends IDisposable {
233234
readonly onDidWheel: Event<IMouseWheelEvent>;
234235

235236
readonly onDidUpdateState: Event<string | undefined>;
236-
readonly onDidReload: Event<void>;
237+
238+
/**
239+
* The natural size of the content inside the webview.
240+
*
241+
* This is computed by looking at the size of the webview's the document element.
242+
*/
243+
readonly intrinsicContentSize: IObservable<{ readonly width: number; readonly height: number } | undefined>;
237244

238245
/**
239246
* Fired when the webview cannot be loaded or is now in a non-functional state.

src/vs/workbench/contrib/webview/browser/webviewElement.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { CancellationTokenSource } from '../../../../base/common/cancellation.js
1414
import { Emitter, Event } from '../../../../base/common/event.js';
1515
import { Disposable, IDisposable, toDisposable } from '../../../../base/common/lifecycle.js';
1616
import { COI } from '../../../../base/common/network.js';
17+
import { observableValue } from '../../../../base/common/observable.js';
1718
import { URI } from '../../../../base/common/uri.js';
1819
import { generateUuid } from '../../../../base/common/uuid.js';
1920
import { localize } from '../../../../nls.js';
@@ -141,6 +142,8 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
141142
protected readonly _webviewFindWidget: WebviewFindWidget | undefined;
142143
public readonly checkImeCompletionState = true;
143144

145+
public readonly intrinsicContentSize = observableValue<{ readonly width: number; readonly height: number } | undefined>('WebviewIntrinsicContentSize', undefined);
146+
144147
private _disposed = false;
145148

146149

@@ -312,6 +315,10 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
312315
this.handleDragEvent('drag', event);
313316
}));
314317

318+
this._register(this.on('updated-intrinsic-content-size', (event) => {
319+
this.intrinsicContentSize.set({ width: event.width, height: event.height }, undefined, undefined);
320+
}));
321+
315322
if (initInfo.options.enableFindWidget) {
316323
this._webviewFindWidget = this._register(instantiationService.createInstance(WebviewFindWidget, this));
317324
}
@@ -349,9 +356,6 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
349356
private readonly _onDidClickLink = this._register(new Emitter<string>());
350357
public readonly onDidClickLink = this._onDidClickLink.event;
351358

352-
private readonly _onDidReload = this._register(new Emitter<void>());
353-
public readonly onDidReload = this._onDidReload.event;
354-
355359
private readonly _onMessage = this._register(new Emitter<WebviewMessageReceivedEvent>());
356360
public readonly onMessage = this._onMessage.event;
357361

@@ -590,11 +594,6 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
590594

591595
public reload(): void {
592596
this.doUpdateContent(this._content);
593-
594-
const subscription = this._register(this.on('did-load', () => {
595-
this._onDidReload.fire();
596-
subscription.dispose();
597-
}));
598597
}
599598

600599
public setHtml(html: string) {

src/vs/workbench/contrib/webview/browser/webviewMessages.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ export type FromWebviewMessage = {
4040
'did-keyup': KeyEvent;
4141
'did-context-menu': { clientX: number; clientY: number; context: { [key: string]: unknown } };
4242
'drag-start': void;
43-
'drag': WebViewDragEvent
43+
'drag': WebViewDragEvent;
44+
'updated-intrinsic-content-size': { width: number; height: number };
4445
};
4546

4647
interface UpdateContentEvent {

0 commit comments

Comments
 (0)