src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts/CellDragAndDropController/registerDragHandle
class CellDragAndDropController:	registerDragHandle(templateData: BaseCellRenderTemplate, cellRoot: HTMLElement, dragHandles: HTMLElement[], dragImageProvider: DragImageProvider): void {
		const container = templateData.container;
		for (const dragHandle of dragHandles) {
			dragHandle.setAttribute('draggable', 'true');
		}

		const onDragEnd = () => {
			if (!this.notebookEditor.notebookOptions.getLayoutConfiguration().dragAndDropEnabled || !!this.notebookEditor.isReadOnly) {
				return;
			}

			// Note, templateData may have a different element rendered into it by now
			container.classList.remove(DRAGGING_CLASS);
			this.dragCleanup();
		};
		for (const dragHandle of dragHandles) {
			templateData.templateDisposables.add(DOM.addDisposableListener(dragHandle, DOM.EventType.DRAG_END, onDragEnd));
		}

		const onDragStart = (event: DragEvent) => {
			if (!event.dataTransfer) {
				return;
			}

			if (!this.notebookEditor.notebookOptions.getLayoutConfiguration().dragAndDropEnabled || !!this.notebookEditor.isReadOnly) {
				return;
			}

			this.currentDraggedCell = templateData.currentRenderedCell!;
			this.draggedCells = this.notebookEditor.getSelections().map(range => this.notebookEditor.getCellsInRange(range)).flat();
			this.draggedCells.forEach(cell => cell.dragging = true);

			const dragImage = dragImageProvider();
			cellRoot.parentElement!.appendChild(dragImage);
			event.dataTransfer.setDragImage(dragImage, 0, 0);
			setTimeout(() => cellRoot.parentElement!.removeChild(dragImage!), 0); // Comment this out to debug drag image layout
		};
		for (const dragHandle of dragHandles) {
			templateData.templateDisposables.add(DOM.addDisposableListener(dragHandle, DOM.EventType.DRAG_START, onDragStart));
		}
	}