private registerListeners()

in patched-vscode/src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts [255:402]


	private registerListeners(): void {
		this.toDispose.push(this.editor.onMouseDown(async (e: IEditorMouseEvent) => {
			if (!this.debugService.getAdapterManager().hasEnabledDebuggers()) {
				return;
			}

			const model = this.editor.getModel();
			if (!e.target.position
				|| !model
				|| e.target.type !== MouseTargetType.GUTTER_GLYPH_MARGIN
				|| e.target.detail.isAfterLines
				|| !this.marginFreeFromNonDebugDecorations(e.target.position.lineNumber)
				// don't return early if there's a breakpoint
				&& !e.target.element?.className.includes('breakpoint')
			) {
				return;
			}
			const canSetBreakpoints = this.debugService.canSetBreakpointsIn(model);
			const lineNumber = e.target.position.lineNumber;
			const uri = model.uri;

			if (e.event.rightButton || (env.isMacintosh && e.event.leftButton && e.event.ctrlKey)) {
				// handled by editor gutter context menu
				return;
			} else {
				const breakpoints = this.debugService.getModel().getBreakpoints({ uri, lineNumber });

				if (breakpoints.length) {
					const isShiftPressed = e.event.shiftKey;
					const enabled = breakpoints.some(bp => bp.enabled);

					if (isShiftPressed) {
						breakpoints.forEach(bp => this.debugService.enableOrDisableBreakpoints(!enabled, bp));
					} else if (!env.isLinux && breakpoints.some(bp => !!bp.condition || !!bp.logMessage || !!bp.hitCondition || !!bp.triggeredBy)) {
						// Show the dialog if there is a potential condition to be accidently lost.
						// Do not show dialog on linux due to electron issue freezing the mouse #50026
						const logPoint = breakpoints.every(bp => !!bp.logMessage);
						const breakpointType = logPoint ? nls.localize('logPoint', "Logpoint") : nls.localize('breakpoint', "Breakpoint");

						const disabledBreakpointDialogMessage = nls.localize(
							'breakpointHasConditionDisabled',
							"This {0} has a {1} that will get lost on remove. Consider enabling the {0} instead.",
							breakpointType.toLowerCase(),
							logPoint ? nls.localize('message', "message") : nls.localize('condition', "condition")
						);
						const enabledBreakpointDialogMessage = nls.localize(
							'breakpointHasConditionEnabled',
							"This {0} has a {1} that will get lost on remove. Consider disabling the {0} instead.",
							breakpointType.toLowerCase(),
							logPoint ? nls.localize('message', "message") : nls.localize('condition', "condition")
						);

						await this.dialogService.prompt({
							type: severity.Info,
							message: enabled ? enabledBreakpointDialogMessage : disabledBreakpointDialogMessage,
							buttons: [
								{
									label: nls.localize({ key: 'removeLogPoint', comment: ['&& denotes a mnemonic'] }, "&&Remove {0}", breakpointType),
									run: () => breakpoints.forEach(bp => this.debugService.removeBreakpoints(bp.getId()))
								},
								{
									label: nls.localize('disableLogPoint', "{0} {1}", enabled ? nls.localize({ key: 'disable', comment: ['&& denotes a mnemonic'] }, "&&Disable") : nls.localize({ key: 'enable', comment: ['&& denotes a mnemonic'] }, "&&Enable"), breakpointType),
									run: () => breakpoints.forEach(bp => this.debugService.enableOrDisableBreakpoints(!enabled, bp))
								}
							],
							cancelButton: true
						});
					} else {
						if (!enabled) {
							breakpoints.forEach(bp => this.debugService.enableOrDisableBreakpoints(!enabled, bp));
						} else {
							breakpoints.forEach(bp => this.debugService.removeBreakpoints(bp.getId()));
						}
					}
				} else if (canSetBreakpoints) {
					if (e.event.middleButton) {
						const action = this.configurationService.getValue<IDebugConfiguration>('debug').gutterMiddleClickAction;
						if (action !== 'none') {
							let context: BreakpointWidgetContext;
							switch (action) {
								case 'logpoint':
									context = BreakpointWidgetContext.LOG_MESSAGE;
									break;
								case 'conditionalBreakpoint':
									context = BreakpointWidgetContext.CONDITION;
									break;
								case 'triggeredBreakpoint':
									context = BreakpointWidgetContext.TRIGGER_POINT;
							}
							this.showBreakpointWidget(lineNumber, undefined, context);
						}
					} else {
						this.debugService.addBreakpoints(uri, [{ lineNumber }]);
					}
				}
			}
		}));

		if (!(BrowserFeatures.pointerEvents && isSafari)) {
			/**
			 * We disable the hover feature for Safari on iOS as
			 * 1. Browser hover events are handled specially by the system (it treats first click as hover if there is `:hover` css registered). Below hover behavior will confuse users with inconsistent expeirence.
			 * 2. When users click on line numbers, the breakpoint hint displays immediately, however it doesn't create the breakpoint unless users click on the left gutter. On a touch screen, it's hard to click on that small area.
			 */
			this.toDispose.push(this.editor.onMouseMove((e: IEditorMouseEvent) => {
				if (!this.debugService.getAdapterManager().hasEnabledDebuggers()) {
					return;
				}

				let showBreakpointHintAtLineNumber = -1;
				const model = this.editor.getModel();
				if (model && e.target.position && (e.target.type === MouseTargetType.GUTTER_GLYPH_MARGIN || e.target.type === MouseTargetType.GUTTER_LINE_NUMBERS) && this.debugService.canSetBreakpointsIn(model) &&
					this.marginFreeFromNonDebugDecorations(e.target.position.lineNumber)) {
					const data = e.target.detail;
					if (!data.isAfterLines) {
						showBreakpointHintAtLineNumber = e.target.position.lineNumber;
					}
				}
				this.ensureBreakpointHintDecoration(showBreakpointHintAtLineNumber);
			}));
			this.toDispose.push(this.editor.onMouseLeave(() => {
				this.ensureBreakpointHintDecoration(-1);
			}));
		}


		this.toDispose.push(this.editor.onDidChangeModel(async () => {
			this.closeBreakpointWidget();
			await this.setDecorations();
		}));
		this.toDispose.push(this.debugService.getModel().onDidChangeBreakpoints(() => {
			if (!this.ignoreBreakpointsChangeEvent && !this.setDecorationsScheduler.isScheduled()) {
				this.setDecorationsScheduler.schedule();
			}
		}));
		this.toDispose.push(this.debugService.onDidChangeState(() => {
			// We need to update breakpoint decorations when state changes since the top stack frame and breakpoint decoration might change
			if (!this.setDecorationsScheduler.isScheduled()) {
				this.setDecorationsScheduler.schedule();
			}
		}));
		this.toDispose.push(this.editor.onDidChangeModelDecorations(() => this.onModelDecorationsChanged()));
		this.toDispose.push(this.configurationService.onDidChangeConfiguration(async (e) => {
			if (e.affectsConfiguration('debug.showBreakpointsInOverviewRuler') || e.affectsConfiguration('debug.showInlineBreakpointCandidates')) {
				await this.setDecorations();
			}
		}));
	}