Task #661: 드래그 선택 중 커서/스크롤 튐 정정 (closes #661)#718
Conversation
closes #658 4 commits 단계별 보존 (작업지시자 직접 결정): - e0ce874 Task #658: Add selection rect diagnostics - f3c7fc0 Task #658: Fix selection rect line boundaries - 99b3a5a Task #658: Reduce selection drag DOM churn - 5fa80bf Task #658: Finalize selection drag fix report 본질 정정: - 선택 rect 시작/끝 위치 영역의 cursor hit bias 영역 추가 — 줄바꿈 경계 영역 영역의 같은 문자 오프셋 영역 영역 이전 줄 끝 vs 다음 줄 시작 영역 구분 - SelectionRenderer 영역의 highlight div 영역 재사용 + 동일 rect 반복 렌더링 skip 영역 (DOM churn 영역 정정) - 드래그 영역 caret 업데이트 영역 가벼운 처리 영역 경로 추가 본 환경 검증: - cherry-pick 충돌 0건 (orders/20260507.md 자동 머지) - cargo test --release ALL PASS (1165 lib + issue_658 2/2) - TypeScript 빌드 통과 - clippy clean PR: #664 컨트리뷰터: @postmelee (Taegyu Lee) 후속 분리: #661 (드래그 시작 영역 영역 커서/스크롤 위치 튐 영역) → PR #718 영역
PR #664 (Task #658): rhwp-studio 드래그 선택 하이라이트 오버플로우 수정 - merge commit: c6bf769 (4 commits 단계별 보존 no-ff merge — 작업지시자 직접 결정) - 본질 정정: cursor hit bias (cursor_nav.rs +118/-53) + selection-renderer DOM churn 정정 - 본 환경 결정적 검증 1165 lib + issue_658 2/2 + TypeScript clean + clippy clean - WASM 빌드 4,584,723 bytes - 작업지시자 시각 판정 ★ 통과 (exam_social.hwp 드래그 선택 페이지 폭 안 정합) 컨트리뷰터: @postmelee (Taegyu Lee) — 다회 사이클 영역 (PR #663 close → #664 재제출) 후속 분리: #661 (드래그 시작 영역 영역 커서/스크롤 위치 튐 영역) → PR #718 영역 closes #658 산출물: - mydocs/pr/archives/pr_664_review.md - mydocs/pr/archives/pr_664_report.md - mydocs/orders/20260508.md 갱신
본질: 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>
- 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>
|
@postmelee PR 머지 완료되었습니다 (devel 처리 결과
충돌 해결 안내 (메인테이너 통합 정정) 본 PR base =
6번째 commit "Align drag caret update with devel" 는 메인테이너 통합 정정 영역에 이미 포함되어 빈 commit 영역으로 skip 처리. 검증
메모리 룰 정합
잔존 후속: Issue #717 OPEN (PR #725 별도 처리 영역) 처리 보고서: |
본질 진단 (소스 정밀 추적) - scrollTop 변경 영역: viewport-manager (API), canvas-view (초기 로드), input-handler (drag autoscroll PR #718, scrollCaretIntoView) - scrollCaretIntoView 호출 영역: updateCaret() 안 단일 호출 (line 1609) - updateCaret() 호출 영역: 키보드/마우스/programmatic 30+ 곳 가설 도출 - 가설 A (단순 scrollbar): native scrollbar 영역 의 mousedown/mouseup 이 document level 발동 안 됨 → onMouseUp chain 미발동 → 본 결함 설명 부재 - 가설 B (drag-during-scroll): 사용자 가 텍스트 클릭 (isDragging=true) + mouseup 안 한 채 scrollbar 까지 drag → scrollbar 위 mouseup → onMouseUp 발동 → updateCaret → scrollCaretIntoView → caret 원본 위치 scroll back - 가설 C: 다른 trigger 영역 (focus, scrollend 등) — Stage 2 의 정정 + 작업지시자 시각 검증 으로 confirm 산출물 - mydocs/plans/task_m100_779.md (수행계획서) - mydocs/plans/task_m100_779_impl.md (구현계획서) - mydocs/working/task_m100_779_stage1.md (본 보고서) 후속 (Stage 2) - updateCaret(skipScroll: boolean = false) 시그니처 확장 - onMouseUp 의 updateCaret(true) 변경 (가설 A/B 영역) - 작업지시자 browser 시각 검증 으로 confirm
본질 - updateCaret() 영역 의 scrollCaretIntoView() 호출 영역 이 cursor 변경 trigger 없는 mouseup (drag-during-scroll 패턴) 영역 의 caret 원본 위치 자동 복귀 결함 발동. - onMouseUp 영역 의 updateCaret() 호출 영역 의 본질: selection 종료 영역 의 visual cleanup 영역 (caret 위치 자체 변경 부재). scroll 호출 영역 의 의도 부재. 정정 - updateCaret(skipScroll: boolean = false) 시그니처 확장. 기본값 false 으로 기존 30+ 곳 호출 영역 무영향 (opt-in skip) 영역 좁힘. - skipScroll true 시 scrollCaretIntoView 호출 skip. - onMouseUp 영역 (input-handler-mouse.ts:1390) 의 updateCaret() → updateCaret(true) 변경. 영역 좁힘 (회귀 부재 가드) - 키보드 영역 (input-handler-keyboard.ts 20+ 곳): 기본값 false → 기존 동작 - programmatic cursor move (moveCursorTo, enterInlineEditing 등): 기본값 false → 기존 - onMouseDown 영역 의 cursor placement (input-handler-mouse.ts 8+ 곳): 기본값 false → 기존 - 드래그 selection autoscroll (PR #718, updateTextSelectionDragAutoScroll): 별도 path → 보존 검증 - tsc --noEmit: clean - npm run build: 성공 (4.6 MB WASM, 707 KB index.js) - cargo test --lib --release: 1217 passed (rust lib 무영향) 후속 (Stage 3) - 작업지시자 시각 판정 (수동 시나리오 1~5) - e2e 회귀 가드 (선택) — scroll-page-preserve.test.mjs
Stage 3 검증
- tsc --noEmit: clean
- npm run build: 성공 (WASM 4.6 MB, index.js 707 KB)
- cargo test --lib --release: 1217 passed
- cargo clippy --release --lib: 신규 경고 0
- 작업지시자 시각 판정: ★ 통과 ("해결 완료")
- 시나리오 1: 본 결함 해소 (scrollbar drag → release → 위치 보존)
- 시나리오 2: cursor click 정상 (회귀 부재)
- 시나리오 3: 키보드 navigation 정상 (회귀 부재)
- 시나리오 4: 드래그 selection autoscroll PR #718 정상 (회귀 부재)
- 시나리오 5: wheel scroll 정상 (회귀 부재)
Stage 4 산출물
- mydocs/working/task_m100_779_stage3.md
- mydocs/report/task_m100_779_report.md (최종)
- mydocs/orders/20260510.md (메인테이너 본인 영역 신규 등록)
권위 사례 강화
- feedback_hancom_compat_specific_over_general: opt-in skipScroll 영역 좁힘
- feedback_pr_supersede_chain: PR #718 (Task #661) 후속 영역
- feedback_visual_judgment_authority: 작업지시자 시각 판정 confirm
후속
- e2e 회귀 가드 (별도 task) — scroll-page-preserve.test.mjs
…k-scroll 정정 @jangster77 영역 rhwp-studio editor 영역 drag-during-scroll 결함 정정. 본질: 사용자 텍스트 클릭 (caret p.1) → 마우스 보유 상태 영역 scrollbar drag → release 시 mouseup listener 가 scrollbar release catch → updateCaret → scrollCaretIntoView → caret 원본 위치 자동 scroll back. 정정 (input-handler.ts +11/-3 + input-handler-mouse.ts +7/-1, 본질 +18/-4): - updateCaret(skipScroll: boolean = false) 시그니처 확장 - onMouseUp 영역 updateCaret(true) — opt-in skip 영역 좁힘 - 30+ 기존 호출 무영향 (키보드/programmatic/onMouseDown/PR #718 autoscroll 보존) 거버넌스 +617 (Stage 1 진단 + Stage 2 GREEN + Stage 3+4 검증/보고서 + 거버넌스 문서). 검증: - tsc --noEmit ✅ - cargo test --release ALL GREEN - cargo clippy --release -- -D warnings 통과 - 광범위 sweep 170/170 same - WASM 4.68 MB 재빌드 - 작업지시자 웹 에디터 시각 판정 ✅ 통과 (5 시나리오 — 본 결함 해소 + cursor click + 키보드 + 드래그 selection autoscroll + wheel scroll 회귀 부재) closes #779
표 셀 내부 텍스트 드래그 선택 시 선택 하이라이트 미렌더링 결함 정정 (Issue #669). 본질: 드래그 중 hitTest 가 셀 내부 빈 영역에서 본문 레벨 위치 반환 → anchor(셀) ↔ focus(본문) 혼합 → updateSelection() 영역 영역 selectionRenderer.clear() 호출 → 선택 미렌더링. 정정 (input-handler.ts:1014 updateTextSelectionDragFromPointer 래퍼 안 +14): - anchor 셀 내부일 때 hit 가 같은 셀 컨텍스트 (parentParaIndex/controlIndex/cellIndex 모두 일치) 가 아니면 cursor.moveTo 건너뜀 - 셀 내 선택 유지 본 환경 충돌 수동 해결: HEAD (devel) 영역 영역 PR #718 (Task #661) updateTextSelectionDragFromPointer 래퍼 사용 영역 영역 incoming 의 onMouseMove 영역 영역 직접 hit + moveTo 영역 영역 비대칭. 본 환경 영역 영역 셀 가드 영역 영역 input-handler.ts 의 래퍼 안 적용 (PR #718 정합성 보존). 검증: - tsc --noEmit ✅ - cargo test --release ALL GREEN - 광범위 sweep 170/170 same - WASM 4.68 MB 재빌드 - 작업지시자 웹 에디터 시각 검증 ✅ 통과 closes #669
Summary
rhwp-studio에서 텍스트 드래그 선택 중 커서와 스크롤 위치가 포인터와 무관하게 튀는 문제를 정정합니다. Closes rhwp-studio: 텍스트 드래그 선택 중 커서와 스크롤 위치가 튀는 현상 #661scrollCaretIntoView()를 호출하지 않고, 포인터가 편집 영역 상/하단 edge에 들어온 경우에만 별도 RAF 루프로 자동 스크롤합니다.mousemove를 드래그 동안만 등록하고 종료/dispose()에서 해제합니다.Root cause
변경 사항
InputHandler.updateCaretDuringDrag()추가updateCaret()과 달리scrollCaretIntoView()를 호출하지 않습니다.devel에 없는 선행 #664의CaretRenderer.updateLive()에 의존하지 않도록 기존CaretRenderer.update()를 사용합니다.startTextSelectionDrag()updateTextSelectionDragPointer()updateTextSelectionDragFromPointer()stopTextSelectionDrag()rhwp-studio/e2e/drag-selection-autoscroll.test.mjs추가Test plan
cargo test— 1254 passed, 0 failed, 3 ignoredcargo clippy -- -D warningscd rhwp-studio && npm run buildcd rhwp-studio && CHROME_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" npm run e2e:drag-autoscroll -- --mode=headlessscrollTop:0 -> 1529hasSelection:trueselection.end.paragraphIndex:69highlightCount:70git diff --check upstream/devel...HEADPR 구성 메모
upstream/devel(de1c2d0)에서pr-task661브랜치를 새로 만들고 rhwp-studio: 텍스트 드래그 선택 중 커서와 스크롤 위치가 튀는 현상 #661 범위만 재적용했습니다.devel기준 diff에 섞이지 않도록 정리했습니다.CONTRIBUTING.md의 문서 위치 규칙에 맞춰mydocs/report/task_m100_661_report.md에 배치했습니다.관련 자료
mydocs/plans/task_m100_661.mdmydocs/plans/task_m100_661_impl.mdmydocs/working/task_m100_661_stage{1..4}.mdmydocs/report/task_m100_661_report.md