Skip to content

Commit 2a83820

Browse files
authored
better math to handle screenshotting out of bounds (#247993)
* do better math to handle screenshotting out of bounds * better naming
1 parent 47ea00a commit 2a83820

File tree

7 files changed

+26
-12
lines changed

7 files changed

+26
-12
lines changed

src/vs/platform/native/common/native.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ export interface ICommonNativeHostService {
156156

157157
// Screenshots
158158
getScreenshot(rect?: IRectangle): Promise<VSBuffer | undefined>;
159-
getElementData(offsetX: number, offsetY: number, token: CancellationToken, cancellationId?: number): Promise<IElementData | undefined>;
159+
getElementData(rect: IRectangle, token: CancellationToken, cancellationId?: number): Promise<IElementData | undefined>;
160160

161161
// Process
162162
getProcessId(): Promise<number | undefined>;

src/vs/platform/native/electron-main/nativeHostMainService.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain
757757
return buf && VSBuffer.wrap(buf);
758758
}
759759

760-
async getElementData(windowId: number | undefined, offsetX: number = 0, offsetY: number = 0, token: CancellationToken, cancellationId?: number): Promise<IElementData | undefined> {
760+
async getElementData(windowId: number | undefined, rect: IRectangle, token: CancellationToken, cancellationId?: number): Promise<IElementData | undefined> {
761761
const window = this.windowById(windowId, windowId);
762762
if (!window?.win) {
763763
return undefined;
@@ -905,11 +905,25 @@ export class NativeHostMainService extends Disposable implements INativeHostMain
905905
debuggers.detach();
906906

907907
const zoomFactor = simpleBrowserWebview.getZoomFactor();
908+
const absoluteBounds = {
909+
x: rect.x + nodeData.bounds.x,
910+
y: rect.y + nodeData.bounds.y,
911+
width: nodeData.bounds.width,
912+
height: nodeData.bounds.height
913+
};
914+
915+
const clippedBounds = {
916+
x: Math.max(absoluteBounds.x, rect.x),
917+
y: Math.max(absoluteBounds.y, rect.y),
918+
width: Math.max(0, Math.min(absoluteBounds.x + absoluteBounds.width, rect.x + rect.width) - Math.max(absoluteBounds.x, rect.x)),
919+
height: Math.max(0, Math.min(absoluteBounds.y + absoluteBounds.height, rect.y + rect.height) - Math.max(absoluteBounds.y, rect.y))
920+
};
921+
908922
const scaledBounds = {
909-
x: (nodeData.bounds.x + offsetX) * zoomFactor,
910-
y: (nodeData.bounds.y + offsetY) * zoomFactor,
911-
width: nodeData.bounds.width * zoomFactor,
912-
height: nodeData.bounds.height * zoomFactor
923+
x: clippedBounds.x * zoomFactor,
924+
y: clippedBounds.y * zoomFactor,
925+
width: clippedBounds.width * zoomFactor,
926+
height: clippedBounds.height * zoomFactor
913927
};
914928

915929
return { outerHTML: nodeData.outerHTML, computedStyle: nodeData.computedStyle, bounds: scaledBounds };

src/vs/workbench/contrib/chat/browser/chatEditing/simpleBrowserEditorOverlay.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ class SimpleBrowserOverlayWidget {
183183
async addElementToChat(cts: CancellationTokenSource) {
184184
const editorContainer = this._container.querySelector('.editor-container') as HTMLDivElement;
185185
const editorContainerPosition = editorContainer ? editorContainer.getBoundingClientRect() : this._container.getBoundingClientRect();
186-
const elementData = await this._hostService.getElementData(editorContainerPosition.x, editorContainerPosition.y, cts.token);
186+
const elementData = await this._hostService.getElementData(editorContainerPosition, cts.token);
187187
if (!elementData) {
188188
throw new Error('Element data not found');
189189
}

src/vs/workbench/services/host/browser/host.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export interface IHostService {
132132
*/
133133
getScreenshot(rect?: IRectangle): Promise<VSBuffer | undefined>;
134134

135-
getElementData(offsetX: number, offsetY: number, token: CancellationToken): Promise<IElementData | undefined>;
135+
getElementData(rect: IRectangle, token: CancellationToken,): Promise<IElementData | undefined>;
136136

137137
//#endregion
138138

src/vs/workbench/services/host/electron-sandbox/nativeHostService.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,14 @@ class WorkbenchHostService extends Disposable implements IHostService {
201201
return this.nativeHostService.getScreenshot(rect);
202202
}
203203

204-
async getElementData(offsetX: number, offsetY: number, token: CancellationToken): Promise<IElementData | undefined> {
204+
async getElementData(rect: IRectangle, token: CancellationToken,): Promise<IElementData | undefined> {
205205
const cancelSelectionId = cancelSelectionIdPool++;
206206
const onCancelChannel = `vscode:cancelElementSelection${cancelSelectionId}`;
207207
const disposable = token.onCancellationRequested(() => {
208208
ipcRenderer.send(onCancelChannel, cancelSelectionId);
209209
});
210210
try {
211-
const elementData = await this.nativeHostService.getElementData(offsetX, offsetY, token, cancelSelectionId);
211+
const elementData = await this.nativeHostService.getElementData(rect, token, cancelSelectionId);
212212
return elementData;
213213
} catch (error) {
214214
disposable.dispose();

src/vs/workbench/test/browser/workbenchTestServices.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1579,7 +1579,7 @@ export class TestHostService implements IHostService {
15791579
async toggleFullScreen(): Promise<void> { }
15801580

15811581
async getScreenshot(rect?: IRectangle): Promise<VSBuffer | undefined> { return undefined; }
1582-
async getElementData(offsetX: number, offsetY: number, token: CancellationToken): Promise<IElementData | undefined> { return undefined; }
1582+
async getElementData(rect: IRectangle, token: CancellationToken,): Promise<IElementData | undefined> { return undefined; }
15831583

15841584
async getNativeWindowHandle(_windowId: number): Promise<VSBuffer | undefined> { return undefined; }
15851585

src/vs/workbench/test/electron-sandbox/workbenchTestServices.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ export class TestNativeHostService implements INativeHostService {
167167
async windowsGetStringRegKey(hive: 'HKEY_CURRENT_USER' | 'HKEY_LOCAL_MACHINE' | 'HKEY_CLASSES_ROOT' | 'HKEY_USERS' | 'HKEY_CURRENT_CONFIG', path: string, name: string): Promise<string | undefined> { return undefined; }
168168
async profileRenderer(): Promise<any> { throw new Error(); }
169169
async getScreenshot(rect?: IRectangle): Promise<VSBuffer | undefined> { return undefined; }
170-
async getElementData(offsetX: number, offsetY: number, token: CancellationToken, cancellationId?: number): Promise<IElementData | undefined> { return undefined; }
170+
async getElementData(rect: IRectangle, token: CancellationToken, cancellationId?: number): Promise<IElementData | undefined> { return undefined; }
171171
}
172172

173173
export class TestExtensionTipsService extends AbstractNativeExtensionTipsService {

0 commit comments

Comments
 (0)