From dc10323b7c9d795e036136bbb50732f6380a71cc Mon Sep 17 00:00:00 2001 From: zipg Date: Wed, 26 Aug 2026 10:04:44 +0800 Subject: [PATCH] fix(grid): restore first double-click cell editing --- apps/desktop/src/components/grid/DataGrid.vue | 19 +++++++++++-------- .../grid/__tests__/DataGridSurfaces.spec.ts | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index c45a6bf054..3fe5f9472d 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -7088,8 +7088,13 @@ function canvasColumnAt(contentX: number): number { return low; } +function canvasEventSurface(event: MouseEvent): HTMLCanvasElement | null { + const currentTarget = event.currentTarget; + return currentTarget instanceof HTMLCanvasElement ? currentTarget : activeCanvasSurface(); +} + function canvasHitTest(event: MouseEvent): { rowIndex: number; visibleColIdx: number; rowNumber: boolean } | null { - const canvas = activeCanvasSurface(); + const canvas = canvasEventSurface(event); const scroller = canvasScrollerElement(); if (!canvas || !scroller) return null; const rect = canvas.getBoundingClientRect(); @@ -7203,8 +7208,8 @@ function onDomGridWheel(event: WheelEvent) { function onCanvasMouseMove(event: MouseEvent) { stopReleasedSelectionGesture(event); + const cursorSurface = canvasEventSurface(event); if (columnHeaderPointerInteractionActive()) { - const cursorSurface = activeCanvasSurface(); if (cursorSurface) cursorSurface.style.cursor = "default"; onCanvasMouseLeave(); return; @@ -7219,7 +7224,6 @@ function onCanvasMouseMove(event: MouseEvent) { } : null; const actualColIdx = next ? visibleColumnIndexes.value[next.visibleColIdx] : undefined; - const cursorSurface = activeCanvasSurface(); if (cursorSurface) { const overBooleanInteractive = booleanCellsUseCheckbox.value && hit != null && !hit.rowNumber && hitItem != null && actualColIdx !== undefined && isBooleanGridCell(hitItem, actualColIdx) && canEditCellItem(hitItem, actualColIdx) && booleanInteractiveHitFromCanvasEvent(hitItem, hit, actualColIdx, event); @@ -7271,7 +7275,7 @@ function clearCanvasDetailHover(event?: MouseEvent) { function booleanCheckboxHitFromCanvasEvent(item: RowItem, hit: { rowIndex: number; visibleColIdx: number }, actualColIdx: number, event: MouseEvent): boolean { if (item.data[actualColIdx] === null) return false; - const canvas = activeCanvasSurface(); + const canvas = canvasEventSurface(event); const canvasRect = canvas?.getBoundingClientRect(); const cellRect = canvasCellViewportRect(hit.rowIndex, hit.visibleColIdx); if (!canvasRect || !cellRect) return false; @@ -7288,7 +7292,7 @@ function booleanCheckboxHitFromCanvasEvent(item: RowItem, hit: { rowIndex: numbe function booleanNullTextHitFromCanvasEvent(item: RowItem, hit: { rowIndex: number; visibleColIdx: number }, actualColIdx: number, event: MouseEvent): boolean { if (item.data[actualColIdx] !== null) return false; - const canvas = activeCanvasSurface(); + const canvas = canvasEventSurface(event); const canvasRect = canvas?.getBoundingClientRect(); const cellRect = canvasCellViewportRect(hit.rowIndex, hit.visibleColIdx); if (!canvasRect || !cellRect) return false; @@ -12949,6 +12953,7 @@ function currentGridContextMenuItems(): ContextMenuItem[] { width: `${totalWidth}px`, height: `${canvasContentHeight}px`, }" + @dblclick="onCanvasDblClick" > -
+
diff --git a/apps/desktop/src/components/grid/__tests__/DataGridSurfaces.spec.ts b/apps/desktop/src/components/grid/__tests__/DataGridSurfaces.spec.ts index c3e1e1b846..e1cf49ce40 100644 --- a/apps/desktop/src/components/grid/__tests__/DataGridSurfaces.spec.ts +++ b/apps/desktop/src/components/grid/__tests__/DataGridSurfaces.spec.ts @@ -142,6 +142,22 @@ describe("DataGrid canvas surfaces", () => { expect(dataGridSource).toContain("const canvas = inactiveCanvasSurface();"); expect(dataGridSource).toContain("canvasUsingBackSurface.value = !canvasUsingBackSurface.value;"); }); + + it("uses the canvas that actually received the event during a surface flip", () => { + expect(dataGridSource).toContain("function canvasEventSurface(event: MouseEvent): HTMLCanvasElement | null"); + expect(dataGridSource).toContain("const currentTarget = event.currentTarget;"); + expect(dataGridSource).toContain("return currentTarget instanceof HTMLCanvasElement ? currentTarget : activeCanvasSurface();"); + expect(dataGridSource).toContain("const canvas = canvasEventSurface(event);"); + + const canvasMouseMove = dataGridSource.slice(dataGridSource.indexOf("function onCanvasMouseMove"), dataGridSource.indexOf("function onCanvasMouseLeave")); + expect(canvasMouseMove).toContain("const cursorSurface = canvasEventSurface(event);"); + }); + + it("handles double clicks on the stable canvas container", () => { + expect(dataGridSource).toContain('@dblclick="onCanvasDblClick"'); + expect(dataGridSource.match(/@dblclick="onCanvasDblClick"/g)).toHaveLength(1); + expect(dataGridSource).toContain("@dblclick.stop"); + }); }); describe("DataGridSearchBar", () => {