Skip to content

Commit 5a1565c

Browse files
committed
Move scroll event emitting through view model (fixes microsoft#97447)
1 parent 1620c36 commit 5a1565c

6 files changed

Lines changed: 126 additions & 42 deletions

File tree

src/vs/base/common/scrollable.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,18 @@ export const enum ScrollbarVisibility {
1313
}
1414

1515
export interface ScrollEvent {
16+
oldWidth: number;
17+
oldScrollWidth: number;
18+
oldScrollLeft: number;
19+
1620
width: number;
1721
scrollWidth: number;
1822
scrollLeft: number;
1923

24+
oldHeight: number;
25+
oldScrollHeight: number;
26+
oldScrollTop: number;
27+
2028
height: number;
2129
scrollHeight: number;
2230
scrollTop: number;
@@ -134,10 +142,18 @@ export class ScrollState implements IScrollDimensions, IScrollPosition {
134142
const scrollTopChanged = (this.scrollTop !== previous.scrollTop);
135143

136144
return {
145+
oldWidth: previous.width,
146+
oldScrollWidth: previous.scrollWidth,
147+
oldScrollLeft: previous.scrollLeft,
148+
137149
width: this.width,
138150
scrollWidth: this.scrollWidth,
139151
scrollLeft: this.scrollLeft,
140152

153+
oldHeight: previous.height,
154+
oldScrollHeight: previous.scrollHeight,
155+
oldScrollTop: previous.scrollTop,
156+
141157
height: this.height,
142158
scrollHeight: this.scrollHeight,
143159
scrollTop: this.scrollTop,

src/vs/editor/browser/view/viewImpl.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -305,15 +305,6 @@ export class View extends ViewEventHandler {
305305
}
306306
public onFocusChanged(e: viewEvents.ViewFocusChangedEvent): boolean {
307307
this.domNode.setClassName(this.getEditorClassName());
308-
if (e.isFocused) {
309-
this.outgoingEvents.emitViewFocusGained();
310-
} else {
311-
this.outgoingEvents.emitViewFocusLost();
312-
}
313-
return false;
314-
}
315-
public onScrollChanged(e: viewEvents.ViewScrollChangedEvent): boolean {
316-
this.outgoingEvents.emitScrollChanged(e);
317308
return false;
318309
}
319310
public onThemeChanged(e: viewEvents.ViewThemeChangedEvent): boolean {

src/vs/editor/browser/view/viewOutgoingEvents.ts

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import { MouseTarget } from 'vs/editor/browser/controller/mouseTarget';
99
import { IEditorMouseEvent, IMouseTarget, IPartialEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
1010
import { Position } from 'vs/editor/common/core/position';
1111
import { Range } from 'vs/editor/common/core/range';
12-
import { IScrollEvent } from 'vs/editor/common/editorCommon';
13-
import * as viewEvents from 'vs/editor/common/view/viewEvents';
1412
import { IViewModel, ICoordinatesConverter } from 'vs/editor/common/viewModel/viewModel';
1513
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
1614

@@ -20,9 +18,6 @@ export interface EventCallback<T> {
2018

2119
export class ViewOutgoingEvents extends Disposable {
2220

23-
public onDidScroll: EventCallback<IScrollEvent> | null = null;
24-
public onDidGainFocus: EventCallback<void> | null = null;
25-
public onDidLoseFocus: EventCallback<void> | null = null;
2621
public onKeyDown: EventCallback<IKeyboardEvent> | null = null;
2722
public onKeyUp: EventCallback<IKeyboardEvent> | null = null;
2823
public onContextMenu: EventCallback<IEditorMouseEvent> | null = null;
@@ -41,24 +36,6 @@ export class ViewOutgoingEvents extends Disposable {
4136
this._viewModel = viewModel;
4237
}
4338

44-
public emitScrollChanged(e: viewEvents.ViewScrollChangedEvent): void {
45-
if (this.onDidScroll) {
46-
this.onDidScroll(e);
47-
}
48-
}
49-
50-
public emitViewFocusGained(): void {
51-
if (this.onDidGainFocus) {
52-
this.onDidGainFocus(undefined);
53-
}
54-
}
55-
56-
public emitViewFocusLost(): void {
57-
if (this.onDidLoseFocus) {
58-
this.onDidLoseFocus(undefined);
59-
}
60-
}
61-
6239
public emitKeyDown(e: IKeyboardEvent): void {
6340
if (this.onKeyDown) {
6441
this.onKeyDown(e);

src/vs/editor/browser/widget/codeEditorWidget.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,6 +1515,12 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
15151515
case OutgoingViewModelEventKind.ContentSizeChanged:
15161516
this._onDidContentSizeChange.fire(e);
15171517
break;
1518+
case OutgoingViewModelEventKind.FocusChanged:
1519+
this._editorTextFocus.setValue(e.hasFocus);
1520+
break;
1521+
case OutgoingViewModelEventKind.ScrollChanged:
1522+
this._onDidScrollChange.fire(e);
1523+
break;
15181524
}
15191525
}));
15201526

@@ -1596,14 +1602,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
15961602
};
15971603
}
15981604

1599-
const onDidChangeTextFocus = (textFocus: boolean) => {
1600-
this._editorTextFocus.setValue(textFocus);
1601-
};
1602-
16031605
const viewOutgoingEvents = new ViewOutgoingEvents(viewModel);
1604-
viewOutgoingEvents.onDidScroll = (e) => this._onDidScrollChange.fire(e);
1605-
viewOutgoingEvents.onDidGainFocus = () => onDidChangeTextFocus(true);
1606-
viewOutgoingEvents.onDidLoseFocus = () => onDidChangeTextFocus(false);
16071606
viewOutgoingEvents.onKeyDown = (e) => this._onKeyDown.fire(e);
16081607
viewOutgoingEvents.onKeyUp = (e) => this._onKeyUp.fire(e);
16091608
viewOutgoingEvents.onContextMenu = (e) => this._onContextMenu.fire(e);

src/vs/editor/common/viewModel/viewModelEventDispatcher.ts

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ export class ViewModelEventDispatcher extends Disposable {
5454
return;
5555
}
5656
const event = this._outgoingEvents.shift()!;
57+
if (event.isNoOp()) {
58+
continue;
59+
}
5760
this._onEvent.fire(event);
5861
}
5962
}
@@ -143,6 +146,8 @@ export class ViewModelEventDispatcher extends Disposable {
143146

144147
export const enum OutgoingViewModelEventKind {
145148
ContentSizeChanged,
149+
FocusChanged,
150+
ScrollChanged,
146151
}
147152

148153
export class ContentSizeChangedEvent implements IContentSizeChangedEvent {
@@ -166,9 +171,100 @@ export class ContentSizeChangedEvent implements IContentSizeChangedEvent {
166171
this.contentHeightChanged = (this._oldContentHeight !== this.contentHeight);
167172
}
168173

169-
public merge(other: ContentSizeChangedEvent): ContentSizeChangedEvent {
174+
public isNoOp(): boolean {
175+
return (!this.contentWidthChanged && !this.contentHeightChanged);
176+
}
177+
178+
179+
public merge(other: OutgoingViewModelEvent): ContentSizeChangedEvent {
180+
if (other.kind !== OutgoingViewModelEventKind.ContentSizeChanged) {
181+
return this;
182+
}
170183
return new ContentSizeChangedEvent(this._oldContentWidth, this._oldContentHeight, other.contentWidth, other.contentHeight);
171184
}
172185
}
173186

174-
export type OutgoingViewModelEvent = ContentSizeChangedEvent;
187+
export class FocusChangedEvent {
188+
189+
public readonly kind = OutgoingViewModelEventKind.FocusChanged;
190+
191+
readonly oldHasFocus: boolean;
192+
readonly hasFocus: boolean;
193+
194+
constructor(oldHasFocus: boolean, hasFocus: boolean) {
195+
this.oldHasFocus = oldHasFocus;
196+
this.hasFocus = hasFocus;
197+
}
198+
199+
public isNoOp(): boolean {
200+
return (this.oldHasFocus === this.hasFocus);
201+
}
202+
203+
public merge(other: OutgoingViewModelEvent): FocusChangedEvent {
204+
if (other.kind !== OutgoingViewModelEventKind.FocusChanged) {
205+
return this;
206+
}
207+
return new FocusChangedEvent(this.oldHasFocus, other.hasFocus);
208+
}
209+
}
210+
211+
export class ScrollChangedEvent {
212+
213+
public readonly kind = OutgoingViewModelEventKind.ScrollChanged;
214+
215+
private readonly _oldScrollWidth: number;
216+
private readonly _oldScrollLeft: number;
217+
private readonly _oldScrollHeight: number;
218+
private readonly _oldScrollTop: number;
219+
220+
public readonly scrollWidth: number;
221+
public readonly scrollLeft: number;
222+
public readonly scrollHeight: number;
223+
public readonly scrollTop: number;
224+
225+
public readonly scrollWidthChanged: boolean;
226+
public readonly scrollLeftChanged: boolean;
227+
public readonly scrollHeightChanged: boolean;
228+
public readonly scrollTopChanged: boolean;
229+
230+
constructor(
231+
oldScrollWidth: number, oldScrollLeft: number, oldScrollHeight: number, oldScrollTop: number,
232+
scrollWidth: number, scrollLeft: number, scrollHeight: number, scrollTop: number,
233+
) {
234+
this._oldScrollWidth = oldScrollWidth;
235+
this._oldScrollLeft = oldScrollLeft;
236+
this._oldScrollHeight = oldScrollHeight;
237+
this._oldScrollTop = oldScrollTop;
238+
239+
this.scrollWidth = scrollWidth;
240+
this.scrollLeft = scrollLeft;
241+
this.scrollHeight = scrollHeight;
242+
this.scrollTop = scrollTop;
243+
244+
this.scrollWidthChanged = (this._oldScrollWidth !== this.scrollWidth);
245+
this.scrollLeftChanged = (this._oldScrollLeft !== this.scrollLeft);
246+
this.scrollHeightChanged = (this._oldScrollHeight !== this.scrollHeight);
247+
this.scrollTopChanged = (this._oldScrollTop !== this.scrollTop);
248+
}
249+
250+
public isNoOp(): boolean {
251+
return (!this.scrollWidthChanged && !this.scrollLeftChanged && !this.scrollHeightChanged && !this.scrollTopChanged);
252+
}
253+
254+
255+
public merge(other: OutgoingViewModelEvent): ScrollChangedEvent {
256+
if (other.kind !== OutgoingViewModelEventKind.ScrollChanged) {
257+
return this;
258+
}
259+
return new ScrollChangedEvent(
260+
this._oldScrollWidth, this._oldScrollLeft, this._oldScrollHeight, this._oldScrollTop,
261+
other.scrollWidth, other.scrollLeft, other.scrollHeight, other.scrollTop
262+
);
263+
}
264+
}
265+
266+
export type OutgoingViewModelEvent = (
267+
ContentSizeChangedEvent
268+
| FocusChangedEvent
269+
| ScrollChangedEvent
270+
);

src/vs/editor/common/viewModel/viewModelImpl.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { Cursor } from 'vs/editor/common/controller/cursor';
3030
import { PartialCursorState, CursorState, IColumnSelectData, EditOperationType, CursorConfiguration } from 'vs/editor/common/controller/cursorCommon';
3131
import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents';
3232
import { IWhitespaceChangeAccessor } from 'vs/editor/common/viewLayout/linesLayout';
33-
import { ViewModelEventDispatcher, OutgoingViewModelEvent } from 'vs/editor/common/viewModel/viewModelEventDispatcher';
33+
import { ViewModelEventDispatcher, OutgoingViewModelEvent, FocusChangedEvent, ScrollChangedEvent } from 'vs/editor/common/viewModel/viewModelEventDispatcher';
3434
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
3535

3636
const USE_IDENTITY_LINES_COLLECTION = true;
@@ -112,6 +112,10 @@ export class ViewModel extends Disposable implements IViewModel {
112112
this._tokenizeViewportSoon.schedule();
113113
}
114114
this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewScrollChangedEvent(e));
115+
this._eventDispatcher.emitOutgoingEvent(new ScrollChangedEvent(
116+
e.oldScrollWidth, e.oldScrollLeft, e.oldScrollHeight, e.oldScrollTop,
117+
e.scrollWidth, e.scrollLeft, e.scrollHeight, e.scrollTop
118+
));
115119
}));
116120

117121
this._register(this.viewLayout.onDidContentSizeChange((e) => {
@@ -172,6 +176,7 @@ export class ViewModel extends Disposable implements IViewModel {
172176
this.hasFocus = hasFocus;
173177
this.cursor.setHasFocus(hasFocus);
174178
this._eventDispatcher.emitSingleViewEvent(new viewEvents.ViewFocusChangedEvent(hasFocus));
179+
this._eventDispatcher.emitOutgoingEvent(new FocusChangedEvent(!hasFocus, hasFocus));
175180
}
176181

177182
public onDidColorThemeChange(): void {

0 commit comments

Comments
 (0)