Skip to content

fix: 표 셀 빈 영역 hitTest 컨텍스트 이탈 정정 (closes #717)#725

Closed
postmelee wants to merge 1 commit into
edwardkim:develfrom
postmelee:fix/issue-717-table-cell-hit-test
Closed

fix: 표 셀 빈 영역 hitTest 컨텍스트 이탈 정정 (closes #717)#725
postmelee wants to merge 1 commit into
edwardkim:develfrom
postmelee:fix/issue-717-table-cell-hit-test

Conversation

@postmelee

@postmelee postmelee commented May 8, 2026

Copy link
Copy Markdown
Collaborator

요약

  • samples/exam_social.hwp 1/4쪽 왼쪽 자료 표의 제목 행 빈 영역을 클릭하면 커서가 페이지 하단 번호 표(32) 쪽으로 이동하던 문제를 수정했습니다.
  • hit_test_native()가 표/셀 bbox 메타를 보완할 때 cellIndex만으로 다른 표의 TextRun 컨텍스트를 섞던 문제를 제거했습니다.
  • 중첩 표 내부의 빈 영역 클릭도 전체 cellPath를 보존하도록 보강했습니다.
  • 회색 헤더 내부표의 초저높이 빈 셀 입력 가시성 문제는 실제 파일 구조/UX 정책 영역으로 판단해 후속 작업으로 분리했습니다.

Closes #717

시각적 변경사항 비교

변경 전

2026-05-09.00.23.06.mov

변경 후

2026-05-09.00.23.22.mov

원인

src/document_core/queries/cursor_rect.rs::hit_test_native()에서 TableCell bbox 메타를 보완할 때 cellIndex만 기준으로 TextRun을 찾았습니다.

HWP 문서에서는 여러 표와 바탕쪽 표가 모두 cellIndex=0 같은 낮은 인덱스를 반복 사용합니다. 이 때문에 클릭 좌표는 s0:pi=1 ci=0 자료 표 내부였지만, hit-test 결과가 페이지 하단 번호 표 쪽 컨텍스트로 오염될 수 있었습니다.

후속 확인 중에는 중첩 표의 TableCell bbox가 전체 cellPath를 잃고 최외곽 표의 셀처럼 반환되는 문제도 확인했습니다. 예를 들어 회색 헤더 내부표의 빈 영역은 [(0,0,0),(1,1,0)] 경로로 들어가야 하지만, 기존 로직은 내부표 cellIndex=1을 최외곽 1x1 표의 cellIndex=1처럼 다룰 수 있었습니다.

변경 사항

  • RunInfoCellBboxInfo에 소속 표 RenderNode id를 기록했습니다.
  • 셀 bbox 메타 보완 시 같은 표 RenderNode id 범위 안의 TextRun만 사용하도록 제한했습니다.
  • Table 노드에서 이미 채워진 최외곽 메타는 유지하고, 중첩 표에는 같은 표 안의 TextRun cell_context를 템플릿으로 사용해 전체 cellPath를 복원했습니다.
  • 클릭 좌표가 여러 셀 bbox에 동시에 포함되면 메타가 있는 후보 중 가장 작은 bbox를 선택하도록 했습니다.
  • 셀 내부 TextRun 검색도 최외곽 셀만 비교하지 않고 같은 표 RenderNode id와 최내곽 cellIndex를 함께 비교하도록 했습니다.
  • TextRun이 없는 빈 셀 fallback도 복원된 전체 cellPath를 반환하도록 했습니다.

회귀 테스트

tests/issue_717_table_cell_hit_test.rs를 추가했습니다.

검증 좌표:

케이스 좌표 기대
자료 표 제목 행 빈 영역 page=0, x=191.0, y=356.0 parentParaIndex=1, controlIndex=0, caret가 자료 표 안에 유지
자료 표 회색 헤더 내부표 빈 영역 page=0, x=100.0, y=350.0 cellPath=[(0,0,0),(1,1,0)], path 기반 삽입/커서 조회 가능
<보기> 표 빈 영역 page=0, x=110.0, y=865.0 parentParaIndex=6, controlIndex=0, caret가 <보기> 표 안에 유지

회색 헤더 내부표 케이스는 hit-test 결과만 보지 않고, 반환된 cellPathX를 삽입한 뒤 getTextInCellByPath()getCursorRectByPath()가 정상 동작하는지까지 확인합니다.

검증

  • cargo test --test issue_717_table_cell_hit_test -- --nocapture
    • 3 passed
  • cargo test --lib --release
    • 1166 passed / 2 ignored
  • cd rhwp-studio && npm run build
    • 통과
  • 작업 중 추가 확인
    • cargo test --test issue_595
    • cargo test --test issue_658_text_selection_rects
    • docker-compose --env-file .env.docker run --rm wasm

후속 작업

작업지시자 시각 확인에서 회색 헤더 내부표의 극단적으로 낮은 빈 셀에 텍스트가 입력되지만 보이지 않는 현상을 확인했습니다.

해당 셀은 실제 파일 구조상 높이 약 5.1px의 장식/간격용 내부표 셀입니다. 입력 경로 자체는 이 PR에서 올바른 cellPath로 들어가도록 정정됐으므로, 이 잔여 현상은 #717의 커서 이탈 결함 범위를 넘는 “초저높이 빈 셀 편집 진입/표 선택 UX 정책” 후속 작업으로 분리했습니다.

본 PR 영역

  • src/document_core/queries/cursor_rect.rs
  • tests/issue_717_table_cell_hit_test.rs
  • mydocs/plans/task_m100_717.md
  • mydocs/plans/task_m100_717_impl.md
  • mydocs/working/task_m100_717_stage{1..5}.md
  • mydocs/report/task_m100_717_report.md
  • mydocs/orders/20260508.md

@postmelee postmelee marked this pull request as ready for review May 8, 2026 15:25
edwardkim added a commit that referenced this pull request May 9, 2026
본질: rhwp-studio 영역 의 텍스트 드래그 선택 중 커서 / 스크롤 위치 영역
포인터 영역 무관 영역 의 튐 결함 정정.

기존 경로: mousemove 마다 hit-test → cursor focus 이동 → caret 갱신 +
scrollCaretIntoView() 호출 → 선택 focus 의 다른 페이지/문단 순간 이동 시
스크롤 컨테이너 가 caret rect 추적 → 사용자 드래그 위치 ↔ 문서 스크롤
함께 튐.

정정 (드래그 중 caret 갱신 + 스크롤 책임 분리):
1. caret: 선택 상태 표시만 갱신 (scrollCaretIntoView 부재)
2. 스크롤: 포인터 edge 감지만 담당 (RAF 루프 + edge 48 px + step 2~20 px)
3. 편집 영역 외부 영역 도 드래그 지속 (document-level mousemove 등록/해제)
4. 포인터 좌표 저장 + 스크롤 발생 시 동일 좌표로 hit-test 재계산

신규 헬퍼 (input-handler.ts +128 LOC):
- startTextSelectionDrag / stopTextSelectionDrag
- updateTextSelectionDragPointer / updateTextSelectionDragFromPointer
- hitTestFromClientPoint (clientX/Y parameter 분리)
- updateTextSelectionDragAutoScroll / runTextSelectionDragAutoScroll
- updateCaretDuringDrag (드래그 중 caret 갱신)

input-handler-mouse.ts (+6/-9):
- 3 곳 isDragging=true → startTextSelectionDrag(e) (드래그 시작 시 포인터
  좌표 보존 + document mousemove 등록)
- mousemove 분기: hit-test 직접 호출 → updateTextSelectionDragFromPointer
  래퍼 (저장된 포인터 좌표 사용)
- mouseup: isDragging=false → stopTextSelectionDrag

회귀 가드 e2e (drag-selection-autoscroll.test.mjs +86 LOC):
- 70줄 문서 + 첫 줄 → 하단 edge 드래그
- scrollTop 0 → 1529 / hasSelection=true / focus 문단 69 / highlight 70

메인테이너 통합 정정 영역 (충돌 해결):
- input-handler-mouse.ts (mousemove 분기): PR #718 영역 의
  updateTextSelectionDragFromPointer 영역 채택
- input-handler.ts (hitTestFromClientPoint): PR #718 영역 의 clientX/Y
  parameter 영역 + devel 영역 의 PR #693 (Task #685+#689) getPageAtPoint
  (그리드 모드 click 좌표 정합) 영역 통합
- input-handler.ts (updateCaretDuringDrag): PR #718 영역 의
  scrollCaretIntoView 부재 본질 + devel 영역 의 PR #664 (Task #658)
  caret.updateLive (깜박임 타이머 유지 본질) 영역 통합

검증:
- cargo test --release: lib 1173 + 통합 ALL GREEN, failed 0
- cargo clippy --release: 신규 경고 0
- npx tsc --noEmit (rhwp-studio): clean
- npm run build (rhwp-studio): PWA 정상

분리된 후속:
- Issue #717: 표 셀 빈 영역 클릭 hit-test (PR #725 별도 처리 영역)

Closes #661

Co-Authored-By: Taegyu Lee <86018802+postmelee@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim added a commit that referenced this pull request May 9, 2026
- mydocs/pr/archives/pr_718_review.md (검토 문서, 충돌 본질 분석 + 메인테이너 통합 정정 방향)
- mydocs/pr/archives/pr_718_report.md (처리 보고서, 3건 충돌 해결 명시)
- mydocs/plans/archives/task_m100_661{,_impl}.md
- mydocs/orders/20260509.md: PR #718 행 + 본 사이클 패턴 라인 추가

처리 결과:
- 옵션 A — 5 commits 단계별 보존 cherry-pick + 메인테이너 통합 정정 + no-ff merge (95eea5f)
- 작업지시자 시각 판정 ★ 통과 (웹 에디터, 블럭 드래그 선택 기능)
- 충돌 3건 메인테이너 통합 정정 (PR #693 getPageAtPoint + PR #664 updateLive 영역 + PR #718 본질 영역 양립)
- WASM 빌드 4,607,734 bytes
- Issue #661 close 자동 정합

분리된 후속: Issue #717 OPEN (PR #725 별도 처리 영역)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim added a commit that referenced this pull request May 9, 2026
PR #725 (@postmelee) 옵션 A 처리 — 1 commit cherry-pick + no-ff merge.

본질 정정 (cursor_rect.rs):
- RunInfo / CellBboxInfo 영역 table_id: Option<u32> 추가 (소속 표 RenderNode id)
- collect_runs() 영역 current_table_id 인자 추가 — Table 노드 진입 시 Some(node.id) 자식 전파
- cell_bboxes meta 보완 영역 영역 r.table_id == cb.table_id 격리 (같은 표 영역 만 매칭)
- 중첩 표 영역 cellPath 보존 — innermost() 영역 cell_index 매칭 + cell_context 클론 + 최내곽 cell_index/cell_para_index/text_direction 갱신
- clicked_cell 선택 영역 영역 가장 작은 bbox (.min_by_key on w*h) — 중첩 표 내부 셀 우선
- 빈 셀 fallback 영역 전체 cellPath 직렬화 (path entries → JSON 배열)

회귀 가드 3건 신규 (tests/issue_717_table_cell_hit_test.rs):
- 자료 표 제목 행 빈 영역 클릭 영역 자료 표 안 caret 유지
- 회색 헤더 내부표 빈 영역 영역 cellPath=[(0,0,0),(1,1,0)] 보존 + path 기반 X 삽입 영역 getTextInCellByPath/getCursorRectByPath 정상
- <보기> 표 빈 영역 영역 caret <보기> 표 안 유지

자기 검증:
- cargo build --release ✅
- cargo test --release: ALL GREEN, failed 0 (신규 3 PASS)
- cargo clippy: 48 errors 영역 모두 기존 코드 (devel 52 → 본 PR 48, 4건 정정 영역) — 본 PR 무관
- 광범위 sweep: 7 fixture / 170 페이지 / 회귀 0 ✅
- 시각 판정 면제 합리 — cursor_rect.rs query API, 시각 출력 무영향, 회귀 가드 통과

후속 분리 (PR 본문 명시):
- 회색 헤더 내부표 영역 의 극단적 낮은 빈 셀 (~5.1px) 영역 영역 입력 가시성 영역 영역 별건 — "초저높이 빈 셀 편집 진입/표 선택 UX 정책" 영역 후속

closes #717
edwardkim added a commit that referenced this pull request May 9, 2026
- mydocs/pr/archives/pr_725_review.md: 검토 문서 archives 이동
- mydocs/pr/archives/pr_725_report.md: 처리 보고서 작성
  · cursor_rect.rs 영역 table_id 격리 + 중첩 표 cellPath 보존
  · 회귀 가드 3건 신규 + 광범위 sweep 170/170 same
  · 시각 판정 면제 합리 (query API + 시각 출력 무영향)
- mydocs/plans/archives/task_m100_717.md(_impl).md: plans archives 이동
- mydocs/orders/20260510.md: PR #725 항목 추가 (5/10 사이클 패턴 영역 영역 PR #720/#723/#725 영역 3건)
@edwardkim

Copy link
Copy Markdown
Owner

@postmelee 님, 검토 + 머지 완료했습니다.

처리 결과

옵션 A (1 commit cherry-pick + no-ff merge `bbf01424`) 로 처리.

자기 검증

  • `cargo build --release` ✅
  • `cargo test --release --test issue_717_table_cell_hit_test` ✅ 3 PASS (신규 회귀 가드)
  • `cargo test --release` (전체) ✅ ALL GREEN, failed 0
  • 광범위 sweep (7 fixture / 170 페이지) ✅ 170 same / 0 diff
  • `cargo clippy` 48 errors 영역 영역 모두 기존 코드 (devel 시점 52 → 본 PR 영역 4건 정정 영역) — 본 PR 영역 영역 변경 파일 영역 영역 신규 lint 부재

시각 판정 면제

`cursor_rect.rs` query API 만 변경 영역 — SVG/PNG 시각 출력 무영향 영역. 회귀 가드 3건 + 광범위 sweep 0 회귀 보장 영역 → `feedback_visual_judgment_authority` 정합 영역 영역 면제 합리. PR 본문 영역 영역 before/after 영상 첨부 영역 영역 시각 입증 정합.

본질 정정 영역

`table_id` 영역 영역 의 격리 영역 영역 `cellIndex` 일반화 영역 결함 본질 영역. 중첩 표 영역 `cellPath` 영역 보존 (path 기반 `getCursorRectByPath()` / `getTextInCellByPath()` API 정합). `feedback_hancom_compat_specific_over_general` 영역 의 권위 사례 영역 — case 가드 영역 영역 일반화 보다 안전.

처리 보고서: `mydocs/pr/archives/pr_725_report.md`.

후속 분리 (PR 본문 명시 영역 정합)

회색 헤더 내부표 영역 의 극단적 낮은 빈 셀 (~5.1px) 영역 영역 입력 가시성 영역 영역 별건 — "초저높이 빈 셀 편집 진입/표 선택 UX 정책" 영역 후속 작업.

@postmelee 님 15+ 사이클 (rhwp-studio editor 영역 핵심) 컨트리뷰션 영역 영역 5/10 사이클 영역 PR #720/#723/#725 영역 3건 처리 완료 영역.

@edwardkim edwardkim closed this May 9, 2026
This was referenced May 9, 2026
@postmelee postmelee deleted the fix/issue-717-table-cell-hit-test branch June 7, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants