根本原因: 點穿狀態一直是 renderer 判定後再用 IPC 叫主程序切換。renderer 只要例外、 卡住或狀態錯亂(例如視窗永遠不取得焦點、Windows 對背景視窗的 capture 有限制, 放開的那一下落在視窗外就收不到 mouseup,pressed 從此卡在 true),主程序就 再也收不到切換指令,寵物永遠點不到。另外 2.0.8 起每 2 秒的置頂重宣告會在 右鍵選單開著時把寵物視窗抬到選單上面,2.0.10 改成整個方框接滑鼠後,被蓋住 的選單項目就點不到了。 影響: 偶發「不能拖曳、不能右鍵」,而且發生時沒有任何可查的狀態或紀錄。 修法: 1. 主程序每 50 ms 自己輪詢游標,對照 renderer 回報的人物方框與氣泡矩形 (pet:hit-rects)直接呼叫 setIgnoreMouseEvents;決策邏輯抽成 lib/hit-test.js。 renderer 沒回報或掛掉時用版面公式算方框當備援,並自動重載。 2. 拖曳不管因 mouseup、逾時(20 秒)或其他原因結束,都送 pet:drag-ended 讓 renderer 清掉按住/拖曳狀態。 3. 右鍵選單開著時暫停置頂重宣告。 4. /state 回傳 bounds 與 mouse 診斷(是否點穿、游標相對座標、是否在方框/ 氣泡、矩形來源、切換與輪詢次數、renderer 錯誤、拖曳結束原因);renderer 例外、拖曳開始/結束、選單開關寫入事件紀錄。 版號 2.0.11。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
24 lines
1.0 KiB
JavaScript
24 lines
1.0 KiB
JavaScript
"use strict";
|
|
// 點穿決策的純邏輯,由主程序使用;抽出來是為了能在 node 直接單元測試(main.js 一載入就 require electron)。
|
|
|
|
function inside(r, p) {
|
|
return !!r && !!p && p.x >= r.x && p.x < r.x + r.w && p.y >= r.y && p.y < r.y + r.h;
|
|
}
|
|
|
|
// 人物方框在視窗內的位置,與 renderer 的版面一致(#stage 水平置中、上方保留氣泡高度、底部留白)。
|
|
// renderer 活著時會回報實際量到的矩形,這只是它還沒回報或掛掉時的備援。
|
|
function petBoxRect(bounds, scale, { petW, petH, bubbleH }) {
|
|
const w = Math.round(petW * scale);
|
|
const h = Math.round(petH * scale);
|
|
return { x: Math.round((bounds.width - w) / 2), y: bubbleH, w, h };
|
|
}
|
|
|
|
// 這一刻視窗該不該點穿:拖曳中一律接滑鼠;否則游標在人物方框或氣泡上才接,其餘穿透。
|
|
function wantIgnore({ rel, box, bubble, dragging }) {
|
|
if (dragging) return false;
|
|
if (!rel) return true;
|
|
return !(inside(box, rel) || inside(bubble, rel));
|
|
}
|
|
|
|
module.exports = { inside, petBoxRect, wantIgnore };
|