Skip to content

rhwp-studio: master page 글상자 더블클릭 시 첫 페이지로 점프 — 한컴 mismatch (fixture: hwpctl_Action_Table__v1.1.hwp 16p) #686

@johndoekim

Description

@johndoekim

본질

samples/hwpctl_Action_Table__v1.1.hwp (16p, landscape, margin_bottom=0) 의 페이지 16 하단 자동번호(Page) 텍스트박스 (master page 글상자 — secIdx=0, paraIdx=0, controlIdx=0 anchored) 를 더블클릭 시:

환경 동작
한컴 문서 마지막 } 캐럿 (= master page 위 dblclick 을 본문 가장 가까운 caret 으로 fallback)
RHWP viewport 가 첫 페이지 부근으로 점프 (사용자 보고: "페이지 2, 3 이동", e2e 측정: scroll −11288px, visible pages = [0, 1])

정량 측정 (e2e, 2026-05-07)

rhwp-studio/e2e/body-outside-click-fallback.test.mjs + 정밀 측정 (페이지 번호 textbox bbox 정확한 위치 click).

Step 1 — Layout dump (page 15):

{ "controls": [
    {"type": "shape", "x": 113.4, "y": 740, "w": 75.6, "h": 21.5,
     "secIdx": 0, "paraIdx": 0, "controlIdx": 0},  // ← 자동번호 글상자
    {"type": "shape", "x": 113.4, "y": 736.8, "w": 895.7, "h": 4, ...}  // 단 구분선
]}

자동번호 글상자: secIdx=0, paraIdx=0, controlIdx=0 — section 0 의 paragraph 0 (master page) 에 anchored.

Step 2 — 글상자 정확한 위치 (151.2, 750.75) 단일 click:

scroll: 12023 → 12023 (delta=0)
isInPictureObjectSelection=true
selectedPicRef = {sec:0, ppi:0, ci:0, type:'shape'}

→ shape 객체 선택. scroll 변화 없음.

Step 3 — 같은 위치 더블 click:

scroll: 12023 → 735 (delta=−11288)
pos = {sec:0, para:0, char:0, ppi:0, ci:0, cellIdx:0}
isInTextBox=true  ★
rectPg=0  ★ (cursor.getRect().pageIndex)
visible pages after dblclick: [0, 1]  ★

isInTextBox=true 분기 진입, cursor 가 sec 0 paragraph 0 의 control 0 cell 0 (master page 글상자 안) 으로 이동, cursor.getRect().pageIndex = 0 (master page 가 first-attached 된 page 0 의 좌표 반환), scrollCaretIntoView 가 page 0 부근으로 스크롤.

코드 경로

input-handler-mouse.ts:onMouseDown 의 흐름:

  1. (single click) wasm.hitTest 가 parentParaIndex=0, controlIndex=0, cellIndex=0 등 cell hit 반환 (master page 글상자의 cell 0)
  2. (single click) 글상자가 picture 로도 인식되어 findPictureAtClick 이 shape ref 반환 → isInPictureObjectSelection 모드 진입
  3. (dblclick) 두 번째 mousedown 시 picture 모드 안에서 hit 의 isTextBox=true 분기 (input-handler-mouse.ts:643-657) 진입 → cursor.moveTo(hit) + this.updateCaret() 호출
  4. updateCaret() 안의 scrollCaretIntoView(rect) (input-handler.ts:1505) 가 rect.pageIndex=0 (master page first-attached 페이지) 으로 스크롤 → 첫 페이지 점프

한컴 정합 정정 방향

A) findPictureAtClick / hit.isTextBox 분기에서 master page 출처 글상자는 제외paraIdx=0 으로 anchored 된 control (= master page 의 control) 은 일반 본문 fallback 으로 진행.

B) 또는 hit 의 cursorRect.pageIndex 가 click 페이지 (pageIdx) 와 다르면 fallback.

권장: A — 의미적으로 master page 위 click 은 본문 click. 한컴도 동일.

회귀 영역 (정정 시 점검)

  • 일반 본문 글상자 (paraIdx > 0 또는 master page 외 origin) dblclick → textbox edit 진입 정상 동작 유지
  • master page 글상자 single click → shape 객체 선택 모드는 보존? 또는 한컴 정합 (master page 위 click 은 무동작)?
  • master page 의 자동번호(Page) 외 다른 control (그림, 이미지, 도형) 도 동일 점프 발생하는지 횡적 검증

우선순위

Medium — 단일 fixture 직접 재현. 다른 양식 (표지, 이력서 양식 등 master page 활용) 에서도 잠재적 재현 가능. 사용자 인지 시 page navigation 혼란 큼.

fixture

  • samples/hwpctl_Action_Table__v1.1.hwp
    • 16 페이지, landscape (가로 297×210mm)
    • margin_left=30, margin_right=30, margin_top=0, margin_bottom=0, margin_header=15, margin_footer=15 (mm)
    • 바탕쪽 2개 (Both, 자동번호 Page 글상자 포함)
  • 재현: cd rhwp-studio && npx vite & node e2e/body-outside-click-fallback.test.mjs --mode=headless

참고

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions