Skip to content

Commit 566bc03

Browse files
committed
fix(taskbar-lyric): 修复任务栏歌词鼠标命中区域错位
close #940
1 parent 2268036 commit 566bc03

3 files changed

Lines changed: 62 additions & 111 deletions

File tree

electron/main/windows/taskbar-lyric-window.ts

Lines changed: 38 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,11 @@ class TaskbarLyricWindow {
4242
private registryWatcher: RegistryWatcher | null = null;
4343
private uiaWatcher: UiaWatcher | null = null;
4444
private trayWatcher: TrayWatcher | null = null;
45-
private currentWidth = 300;
4645
private themeListener: (() => void) | null = null;
4746
private animationTimer: NodeJS.Timeout | null = null;
4847
private service: TaskbarService | null = null;
4948
private useAnimation = false;
5049
private isNativeDisposed = false;
51-
private contentWidth = 300;
52-
private maxWidthPercent = 30;
5350
private isFadingOut = false;
5451
private shouldBeVisible = false;
5552

@@ -88,13 +85,16 @@ class TaskbarLyricWindow {
8885

8986
const primaryDisplay = screen.getPrimaryDisplay();
9087
const maxWindowWidth = primaryDisplay.workAreaSize.width;
88+
// 初始尺寸故意开大(覆盖任何可能的任务栏宽高),避免 transparent+SetParent 后
89+
// Chromium 合成器视口不随 setBounds 增长、超出初始尺寸区域因 alpha=0 吞掉鼠标事件
90+
// (表现为"只有前面一点点可以操作")。后续 setBounds 只做缩小,视口始终覆盖整个 HWND
9191
this.win = createWindow({
92-
width: this.currentWidth,
93-
height: 48,
94-
minWidth: 100,
95-
minHeight: 30,
92+
width: 3000,
93+
height: 200,
94+
minWidth: 0,
95+
minHeight: 0,
9696
maxWidth: maxWindowWidth,
97-
maxHeight: 100,
97+
maxHeight: 200,
9898
type: "toolbar",
9999
frame: false,
100100
transparent: true,
@@ -149,9 +149,9 @@ class TaskbarLyricWindow {
149149
this.win.once("ready-to-show", () => {
150150
if (this.win) {
151151
this.embed();
152-
if (this.shouldBeVisible) {
153-
this.win.show();
154-
}
152+
// 不在此处 show,让 applyLayout 首次 setBounds 到正确尺寸后再触发 show
153+
// (applyLayout 里 shouldBeVisible && !isVisible 的分支会处理),
154+
// 避免 3000x200 的初始大窗口在屏幕上闪现
155155
this.updateLayout(false);
156156
sendTheme();
157157
}
@@ -198,11 +198,12 @@ class TaskbarLyricWindow {
198198
return this.win;
199199
}
200200

201-
setContentWidth(width: number) {
202-
if (this.contentWidth !== width) {
203-
this.contentWidth = width;
204-
this.debouncedUpdateLayout();
205-
}
201+
/**
202+
* 保留接口用于 manager 分发兼容(floating 模式使用);taskbar 模式不需要根据
203+
* 内容宽度动态收缩,窗口按 autoMaxWidth/maxWidth 设置占空间
204+
*/
205+
setContentWidth(_width: number) {
206+
// no-op
206207
}
207208

208209
embed() {
@@ -215,32 +216,24 @@ class TaskbarLyricWindow {
215216
}
216217
}
217218

218-
private getMaxWidthPercent(screenWidth: number) {
219+
/** 返回期望的 HWND 物理像素宽度(autoMaxWidth 开启时返回屏幕宽度,由 Rust 侧据可用空间裁剪) */
220+
private getDesiredPhysicalWidth() {
219221
const store = useStore();
220-
let maxWidthSetting = store.get("taskbar.maxWidth", 30);
221-
if (maxWidthSetting > 100) {
222-
// Assume it's pixels, convert to percent
223-
const converted = Math.round((maxWidthSetting / screenWidth) * 100);
224-
maxWidthSetting = Math.min(Math.max(converted, 10), 100);
225-
store.set("taskbar.maxWidth", maxWidthSetting);
226-
return maxWidthSetting;
222+
const primaryDisplay = screen.getPrimaryDisplay();
223+
const scaleFactor = primaryDisplay.scaleFactor;
224+
const autoMaxWidth = store.get("taskbar.autoMaxWidth", true);
225+
if (autoMaxWidth) {
226+
// 尽量撑满可用空间
227+
return Math.round(primaryDisplay.workAreaSize.width * scaleFactor);
227228
}
228-
return Math.min(Math.max(maxWidthSetting, 10), 100);
229+
const maxWidthLogical = store.get("taskbar.maxWidth", 400);
230+
return Math.round(maxWidthLogical * scaleFactor);
229231
}
230232

231233
updateLayout(animate: boolean = false) {
232234
if (!this.win || !this.service) return;
233235
this.useAnimation = animate;
234-
235-
const primaryDisplay = screen.getPrimaryDisplay();
236-
this.maxWidthPercent = this.getMaxWidthPercent(primaryDisplay.workAreaSize.width);
237-
const scaleFactor = primaryDisplay.scaleFactor;
238-
const maxWidthSetting = Math.round(
239-
(primaryDisplay.workAreaSize.width * this.maxWidthPercent) / 100,
240-
);
241-
const requestWidth = Math.round(maxWidthSetting * scaleFactor);
242-
243-
this.service.update(requestWidth);
236+
this.service.update(this.getDesiredPhysicalWidth());
244237
}
245238

246239
private applyLayout(layout: TaskbarLayout | null) {
@@ -256,17 +249,13 @@ class TaskbarLyricWindow {
256249
const scaleFactor = primaryDisplay.scaleFactor;
257250
const store = useStore();
258251
const GAP = store.get("taskbar.margin", 10) * scaleFactor;
259-
const maxWidthSetting = Math.round(
260-
(primaryDisplay.workAreaSize.width * this.maxWidthPercent) / 100,
261-
);
262252
const positionSetting = store.get("taskbar.position", "automatic") as TaskbarConfig["position"];
263-
const autoShrink = store.get("taskbar.autoShrink", false);
264-
const MAX_WIDTH_PHYSICAL = autoShrink
265-
? Math.min(maxWidthSetting, this.contentWidth) * scaleFactor
266-
: maxWidthSetting * scaleFactor;
267-
const minWidthPercent = Math.min(Math.max(store.get("taskbar.minWidth", 10), 0), 50);
268-
const MIN_WIDTH_PHYSICAL =
269-
Math.round((primaryDisplay.workAreaSize.width * minWidthPercent) / 100) * scaleFactor;
253+
// autoMaxWidth 开启时无上限(撑满可用空间),关闭时按设置的像素值(逻辑像素)限制
254+
const autoMaxWidth = store.get("taskbar.autoMaxWidth", true);
255+
const maxWidthLogical = store.get("taskbar.maxWidth", 400);
256+
const MAX_WIDTH_PHYSICAL = autoMaxWidth
257+
? Number.POSITIVE_INFINITY
258+
: maxWidthLogical * scaleFactor;
270259

271260
let targetBounds: Electron.Rectangle = {
272261
x: 0,
@@ -303,8 +292,9 @@ class TaskbarLyricWindow {
303292
const finalPhysicalY = 0;
304293
let finalPhysicalWidth = 0;
305294

295+
// 取可用空间与最大宽度限制的较小值;空间 <= 0 时返回 0 表示该侧不可用
306296
const clampWidth = (space: number) => {
307-
if (space < MIN_WIDTH_PHYSICAL) return 0;
297+
if (space <= 0) return 0;
308298
return Math.min(space, MAX_WIDTH_PHYSICAL);
309299
};
310300

@@ -319,8 +309,8 @@ class TaskbarLyricWindow {
319309
finalPhysicalX = effectiveRightAnchor - finalPhysicalWidth - GAP;
320310
shouldCenter = false; // Right Align
321311
} else if (isCentered) {
322-
// 自动判断 (Win11 居中)
323-
if (leftSpaceNet >= MIN_WIDTH_PHYSICAL) {
312+
// 自动判断 (Win11 居中): 选空间大的一侧
313+
if (leftSpaceNet >= rightSpaceNet && leftSpaceNet > 0) {
324314
finalPhysicalWidth = clampWidth(leftSpaceNet);
325315
finalPhysicalX = widgetsRightEdge + GAP;
326316
shouldCenter = true; // Left Align
@@ -336,16 +326,12 @@ class TaskbarLyricWindow {
336326
shouldCenter = false; // Right Align
337327
}
338328

339-
// processLog.info(finalPhysicalWidth, finalPhysicalX);
340-
341329
if (finalPhysicalWidth <= 0) {
342330
processLog.warn("[TaskbarLyric] 无可用空间");
343331
this.win.hide();
344332
return;
345333
}
346334

347-
this.currentWidth = Math.round(finalPhysicalWidth / scaleFactor);
348-
349335
targetBounds = {
350336
x: finalPhysicalX,
351337
y: finalPhysicalY,

src/components/Setting/config/lyric.ts

Lines changed: 19 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -993,43 +993,38 @@ export const useLyricSettings = (): SettingConfig => {
993993
}),
994994
},
995995
{
996-
key: "taskbarLyricMaxWidth",
997-
label: "最大宽度",
998-
type: "slider",
999-
description: "任务栏歌词的最大宽度占屏幕比例",
1000-
min: 10,
1001-
max: 100,
1002-
step: 1,
996+
key: "taskbarLyricAutoMaxWidth",
997+
label: "宽度自动",
998+
type: "switch",
999+
description: "开启后占满任务栏的可用空间;关闭后按最大宽度限制",
1000+
show: () => taskbarLyricConfig.mode === "taskbar",
10031001
value: computed({
1004-
get: () => taskbarLyricConfig.maxWidth,
1002+
get: () => taskbarLyricConfig.autoMaxWidth,
10051003
set: (v) => {
1006-
taskbarLyricConfig.maxWidth = v ?? 30;
1004+
taskbarLyricConfig.autoMaxWidth = v ?? true;
1005+
saveTaskbarLyricConfig({ autoMaxWidth: taskbarLyricConfig.autoMaxWidth });
10071006
},
10081007
}),
1009-
action: () => {
1010-
saveTaskbarLyricConfig({ maxWidth: taskbarLyricConfig.maxWidth });
1011-
},
1012-
suffix: "%",
10131008
},
10141009
{
1015-
key: "taskbarLyricMinWidth",
1016-
label: "最小宽度",
1010+
key: "taskbarLyricMaxWidth",
1011+
label: "最大宽度",
10171012
type: "slider",
1018-
description: "任务栏歌词可用空间低于此比例时自动隐藏",
1019-
show: () => taskbarLyricConfig.mode === "taskbar",
1020-
min: 0,
1021-
max: 50,
1022-
step: 1,
1013+
description: "超出可用空间时仍以可用空间为准,避免挤占",
1014+
show: () => taskbarLyricConfig.mode === "taskbar" && !taskbarLyricConfig.autoMaxWidth,
1015+
min: 200,
1016+
max: 800,
1017+
step: 20,
10231018
value: computed({
1024-
get: () => taskbarLyricConfig.minWidth,
1019+
get: () => taskbarLyricConfig.maxWidth,
10251020
set: (v) => {
1026-
taskbarLyricConfig.minWidth = v ?? 10;
1021+
taskbarLyricConfig.maxWidth = v ?? 400;
10271022
},
10281023
}),
10291024
action: () => {
1030-
saveTaskbarLyricConfig({ minWidth: taskbarLyricConfig.minWidth });
1025+
saveTaskbarLyricConfig({ maxWidth: taskbarLyricConfig.maxWidth });
10311026
},
1032-
suffix: "%",
1027+
suffix: "px",
10331028
},
10341029
{
10351030
key: "taskbarLyricMargin",
@@ -1049,33 +1044,6 @@ export const useLyricSettings = (): SettingConfig => {
10491044
}),
10501045
defaultValue: 10,
10511046
},
1052-
{
1053-
key: "taskbarLyricAutoShrink",
1054-
label: "自动收缩",
1055-
type: "switch",
1056-
description: "关闭后将固定占据设置的最大宽度",
1057-
show: () => taskbarLyricConfig.mode === "taskbar",
1058-
value: computed({
1059-
get: () => taskbarLyricConfig.autoShrink,
1060-
set: (v) => {
1061-
if (v) {
1062-
window.$dialog.warning({
1063-
title: "提示",
1064-
content: "可能会导致右侧对齐的任务栏歌词异常抖动,是否开启?",
1065-
positiveText: "开启",
1066-
negativeText: "取消",
1067-
onPositiveClick: () => {
1068-
taskbarLyricConfig.autoShrink = true;
1069-
saveTaskbarLyricConfig({ autoShrink: true });
1070-
},
1071-
});
1072-
} else {
1073-
taskbarLyricConfig.autoShrink = false;
1074-
saveTaskbarLyricConfig({ autoShrink: false });
1075-
}
1076-
},
1077-
}),
1078-
},
10791047
{
10801048
key: "taskbarLyricPosition",
10811049
label: "显示位置",

src/types/shared/taskbar-ipc.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,14 @@ export type Milliseconds = number;
55
export interface TaskbarConfig {
66
/** 模式 */
77
mode: "taskbar" | "floating";
8-
/** 最大宽度 */
8+
/** 宽度自动——开启时占满可用空间,关闭时按 maxWidth 限制 */
9+
autoMaxWidth: boolean;
10+
/** 最大宽度(逻辑像素)——仅在 autoMaxWidth 关闭时生效,超出可用空间时以可用空间为准 */
911
maxWidth: number;
1012
/** 位置 */
1113
position: "automatic" | "left" | "right";
12-
/** 自动收缩 */
13-
autoShrink: boolean;
1414
/** 边距 */
1515
margin: number;
16-
/** 最小宽度 */
17-
minWidth: number;
1816
/** 悬浮对齐 */
1917
floatingAlign: "left" | "right";
2018
/** 悬浮自动宽度 */
@@ -120,11 +118,10 @@ export type SyncStatePayload =
120118
/** 默认任务栏歌词配置 */
121119
export const DEFAULT_TASKBAR_CONFIG: TaskbarConfig = {
122120
mode: "taskbar",
123-
maxWidth: 30,
121+
autoMaxWidth: true,
122+
maxWidth: 400,
124123
position: "automatic",
125-
autoShrink: false,
126124
margin: 10,
127-
minWidth: 10,
128125
floatingAlign: "right",
129126
floatingAutoWidth: true,
130127
floatingWidth: 300,

0 commit comments

Comments
 (0)