"전체에서 시작해 포커스 쥔 놈으로 좁히고, 거기다 글을 물어봐. 세 걸음이면 입력이 손에 들어와."
전역에서 포커스로
읽는 건 질문 몇 개가 이어진 짧은 사슬이야. 시스템 전역 요소를 만들고, 거기서 kAXFocusedUIElementAttribute 를 가져와. 그러면 지금 앞에 있는 앱에서 키보드 포커스를 쥔 요소가 나와. 그게 어느 앱인지는 내가 알 필요도 없어. AX 가 '지금 포커스 쥔 놈' 을 알아서 찾아주거든. 그 요소가 앞으로 캐물을 마디고.
긁어놓은 글 물어보기
그 요소한테 두 가지를 더 물어봐. kAXSelectedTextAttribute 로 하이라이트된 글자를, kAXSelectedTextRangeAttribute 로 어디서 어디까지인지를. 둘 다 필요해. 글은 {input} 이 되고, 범위는 나중에 결과를 원래 자리에 정확히 돌려놓을 때 쓰거든. 이 범위를 지금, 읽는 그 순간에 챙겨두는 게 왕복이 끝난 뒤에도 제자리에 딱 맞춰 넣을 수 있게 해줘.
시스템 전역 요소
kAXFocusedUIElementAttribute -> 포커스 쥔 요소
kAXSelectedTextAttribute -> "하이라이트된 글"
kAXSelectedTextRangeAttribute -> 범위 { 시작, 길이 }
글은 {input} 이 되고, 범위는 넣을 때 쓰려고 기억해둔다.
아무것도 안 긁혀 있을 때
칠 때마다 뭔가 긁혀 있는 건 아니야. 그냥 커서만 깜빡이고 있을 수도 있지. 그것도 에러가 아니라 멀쩡한 상태고. Flint 의 규칙은 분명해. 긁어놓은 글이 있으면 그게 {input} 이 되고 결과가 그 자리를 대신해. 없으면 입력이 비고, 매크로가 만든 글이 뭘 대신하는 대신 커서 자리에 들어가. 그래서 읽는 쪽은 '빈 채로 긁혔다' 랑 '포커스된 요소가 아예 없다' 를 구별해서 알려줘야 해. 그 둘이 이후에 완전히 다른 길로 갈라지거든.
범위는 넣을 때 말고 읽을 때 챙겨. 긁어놓은 글만 잡아두고 범위는 나중에 넣을 때 다시 구하고 싶어져. 그러지 마. 넣을 즈음이면 긁어놓은 게 이미 사라졌을 수 있거든. 칠 때 챙긴 범위는 '그 순간 내가 뭘 하려 했는지' 에 대한 사실이야. 왕복이 끝난 뒤 다시 읽으면 그새 달라진 딴 세상을 읽는 거고. 글이랑 범위는 처음에 같이 챙겨.
역할까지 같이 물어봐. 온 김에
kAXRoleAttribute 랑 kAXSubroleAttribute 도 챙겨. 대상이 어떤 종류인지 알려주거든. 여러 줄 글 칸인지, 검색 칸인지, 비밀번호 칸인지. 나중에 어떻게 넣을지에도 쓰이고, 무엇보다 비밀번호 칸은 아예 안 건드리는 데(Track 7) 필요해. 읽을 때 질문 하나 더 던져두면 나중에 짐작할 일이 없어져.