argus-eye 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/config.d.ts +4 -0
- package/lib/fullscreen.d.ts +45 -9
- package/lib/index.mjs +178 -36
- package/package.json +1 -1
- package/readme.md +35 -2
package/lib/config.d.ts
CHANGED
|
@@ -8,6 +8,10 @@ export interface ResolvedConfig {
|
|
|
8
8
|
backoff: number;
|
|
9
9
|
color: boolean;
|
|
10
10
|
detectFullscreen: boolean;
|
|
11
|
+
/** 永不视为 busy 的应用名列表(不区分大小写、子串匹配)。空数组 = 用默认列表。 */
|
|
12
|
+
allowApps: string[];
|
|
13
|
+
/** 强制视为 busy 的应用名列表。优先级高于 allowApps。 */
|
|
14
|
+
busyApps: string[];
|
|
11
15
|
}
|
|
12
16
|
export interface CliFlags {
|
|
13
17
|
help?: boolean;
|
package/lib/fullscreen.d.ts
CHANGED
|
@@ -8,24 +8,43 @@ export interface ActiveWindowInfo {
|
|
|
8
8
|
width: number;
|
|
9
9
|
height: number;
|
|
10
10
|
};
|
|
11
|
-
|
|
11
|
+
contentBounds?: {
|
|
12
12
|
x: number;
|
|
13
13
|
y: number;
|
|
14
14
|
width: number;
|
|
15
15
|
height: number;
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* 默认的"允许截图"应用名(不区分大小写、子串匹配)。
|
|
20
|
+
* 这些是即使全屏也是普通工作 / 浏览场景,应当能被群友看到的应用。
|
|
21
|
+
*/
|
|
22
|
+
export declare const DEFAULT_ALLOW_APPS: string[];
|
|
23
|
+
export interface FullscreenDetectorOptions {
|
|
24
|
+
enabled: boolean;
|
|
25
|
+
/** 不算 busy 的应用名(不区分大小写、子串匹配)。 */
|
|
26
|
+
allowApps?: string[];
|
|
27
|
+
/** 强制视为 busy 的应用名(不区分大小写、子串匹配)。优先级高于 allowApps。 */
|
|
28
|
+
busyApps?: string[];
|
|
29
|
+
}
|
|
30
|
+
export interface FullscreenCheckResult {
|
|
31
|
+
busy: boolean;
|
|
32
|
+
/** 命中的判定原因,方便排查 */
|
|
33
|
+
reason?: 'allow_app' | 'busy_app' | 'fullscreen_geometry';
|
|
34
|
+
}
|
|
18
35
|
/**
|
|
19
36
|
* 检测器:懒加载 `get-windows`(原生 npm 包,gyp 编译)。
|
|
20
37
|
* 该模块在某些平台 / 环境(Wayland、CI 容器、缺乏权限的 macOS)上不可用,
|
|
21
38
|
* 这种情况下返回 undefined,调用方按"无法判断"处理。
|
|
22
39
|
*/
|
|
23
40
|
export declare class FullscreenDetector {
|
|
24
|
-
private
|
|
41
|
+
private options;
|
|
25
42
|
private mod?;
|
|
26
43
|
private loading?;
|
|
27
44
|
private warnedFailure;
|
|
28
|
-
|
|
45
|
+
private allowApps;
|
|
46
|
+
private busyApps;
|
|
47
|
+
constructor(options: FullscreenDetectorOptions);
|
|
29
48
|
setEnabled(enabled: boolean): void;
|
|
30
49
|
isEnabled(): boolean;
|
|
31
50
|
/**
|
|
@@ -33,15 +52,32 @@ export declare class FullscreenDetector {
|
|
|
33
52
|
*/
|
|
34
53
|
getActiveWindow(): Promise<ActiveWindowInfo | undefined>;
|
|
35
54
|
/**
|
|
36
|
-
*
|
|
55
|
+
* 综合判定当前窗口是否应当视为 busy。
|
|
56
|
+
*
|
|
57
|
+
* 优先级:
|
|
58
|
+
* 1. allowApps 命中 → 永不 busy(即使 F11 全屏 chrome)
|
|
59
|
+
* 2. busyApps 命中 → 永远 busy
|
|
60
|
+
* 3. 几何全屏:bounds 起点贴近 (0,0) AND `contentBounds == bounds`
|
|
61
|
+
* AND 覆盖整块显示器 → busy
|
|
62
|
+
*/
|
|
63
|
+
check(win: ActiveWindowInfo, display: {
|
|
64
|
+
width?: number;
|
|
65
|
+
height?: number;
|
|
66
|
+
}): FullscreenCheckResult;
|
|
67
|
+
private matchAny;
|
|
68
|
+
/**
|
|
69
|
+
* 几何上是否是真正的全屏(区别于"最大化窗口")。
|
|
37
70
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
71
|
+
* 关键观察(Windows 上):
|
|
72
|
+
* - 最大化的普通窗口:`bounds.x = -7, bounds.y = -7`(aero 边框 overscan),
|
|
73
|
+
* `contentBounds` 比 `bounds` 小一圈(标题栏 / 边框被排除)
|
|
74
|
+
* - 真正的全屏(F11 / 全屏游戏):`bounds.x = 0, bounds.y = 0`,
|
|
75
|
+
* `contentBounds == bounds`,整体尺寸贴合整块显示器
|
|
41
76
|
*
|
|
42
|
-
*
|
|
43
|
-
* 用户的意图是「看到某个独占应用就别曝光画面」。
|
|
77
|
+
* macOS / Linux 通常没有 contentBounds,退化为只看起点和尺寸。
|
|
44
78
|
*/
|
|
79
|
+
private isFullscreenGeometry;
|
|
80
|
+
/** 兼容旧名字。新代码用 `check`。 */
|
|
45
81
|
isFullscreen(win: ActiveWindowInfo, display: {
|
|
46
82
|
width?: number;
|
|
47
83
|
height?: number;
|
package/lib/index.mjs
CHANGED
|
@@ -72,9 +72,82 @@ async function capture(options = {}) {
|
|
|
72
72
|
__name(capture, "capture");
|
|
73
73
|
|
|
74
74
|
// src/fullscreen.ts
|
|
75
|
+
var DEFAULT_ALLOW_APPS = [
|
|
76
|
+
// browsers
|
|
77
|
+
"chrome",
|
|
78
|
+
"edge",
|
|
79
|
+
"firefox",
|
|
80
|
+
"safari",
|
|
81
|
+
"opera",
|
|
82
|
+
"brave",
|
|
83
|
+
"vivaldi",
|
|
84
|
+
"arc",
|
|
85
|
+
// IDE / editors
|
|
86
|
+
"code",
|
|
87
|
+
// VS Code
|
|
88
|
+
"cursor",
|
|
89
|
+
"visual studio",
|
|
90
|
+
"devenv",
|
|
91
|
+
"idea",
|
|
92
|
+
"webstorm",
|
|
93
|
+
"pycharm",
|
|
94
|
+
"goland",
|
|
95
|
+
"rider",
|
|
96
|
+
"clion",
|
|
97
|
+
"rustrover",
|
|
98
|
+
"phpstorm",
|
|
99
|
+
"datagrip",
|
|
100
|
+
"fleet",
|
|
101
|
+
"sublime",
|
|
102
|
+
"atom",
|
|
103
|
+
"notepad",
|
|
104
|
+
"typora",
|
|
105
|
+
"obsidian",
|
|
106
|
+
"notion",
|
|
107
|
+
"logseq",
|
|
108
|
+
// shells / terminals
|
|
109
|
+
"windowsterminal",
|
|
110
|
+
"powershell",
|
|
111
|
+
"pwsh",
|
|
112
|
+
"cmd",
|
|
113
|
+
"conhost",
|
|
114
|
+
"wezterm",
|
|
115
|
+
"iterm",
|
|
116
|
+
"alacritty",
|
|
117
|
+
"kitty",
|
|
118
|
+
"tabby",
|
|
119
|
+
"hyper",
|
|
120
|
+
// file managers
|
|
121
|
+
"explorer",
|
|
122
|
+
"finder",
|
|
123
|
+
// common IM / collab
|
|
124
|
+
"wechat",
|
|
125
|
+
"weixin",
|
|
126
|
+
"qq",
|
|
127
|
+
"tim",
|
|
128
|
+
"telegram",
|
|
129
|
+
"discord",
|
|
130
|
+
"slack",
|
|
131
|
+
"teams",
|
|
132
|
+
"zoom",
|
|
133
|
+
"feishu",
|
|
134
|
+
"lark",
|
|
135
|
+
"dingtalk",
|
|
136
|
+
// office
|
|
137
|
+
"word",
|
|
138
|
+
"excel",
|
|
139
|
+
"powerpoint",
|
|
140
|
+
"wps",
|
|
141
|
+
"acrobat",
|
|
142
|
+
"sumatra"
|
|
143
|
+
];
|
|
75
144
|
var FullscreenDetector = class {
|
|
76
|
-
constructor(
|
|
77
|
-
this.
|
|
145
|
+
constructor(options) {
|
|
146
|
+
this.options = options;
|
|
147
|
+
this.allowApps = (options.allowApps ?? DEFAULT_ALLOW_APPS).map(
|
|
148
|
+
(s) => s.toLowerCase()
|
|
149
|
+
);
|
|
150
|
+
this.busyApps = (options.busyApps ?? []).map((s) => s.toLowerCase());
|
|
78
151
|
}
|
|
79
152
|
static {
|
|
80
153
|
__name(this, "FullscreenDetector");
|
|
@@ -82,17 +155,19 @@ var FullscreenDetector = class {
|
|
|
82
155
|
mod;
|
|
83
156
|
loading;
|
|
84
157
|
warnedFailure = false;
|
|
158
|
+
allowApps;
|
|
159
|
+
busyApps;
|
|
85
160
|
setEnabled(enabled) {
|
|
86
|
-
this.enabled = enabled;
|
|
161
|
+
this.options.enabled = enabled;
|
|
87
162
|
}
|
|
88
163
|
isEnabled() {
|
|
89
|
-
return this.enabled;
|
|
164
|
+
return this.options.enabled;
|
|
90
165
|
}
|
|
91
166
|
/**
|
|
92
167
|
* 获取当前活动窗口。无法获取时返回 undefined。
|
|
93
168
|
*/
|
|
94
169
|
async getActiveWindow() {
|
|
95
|
-
if (!this.enabled) return void 0;
|
|
170
|
+
if (!this.options.enabled) return void 0;
|
|
96
171
|
const mod = await this.load();
|
|
97
172
|
if (!mod) return void 0;
|
|
98
173
|
try {
|
|
@@ -105,7 +180,8 @@ var FullscreenDetector = class {
|
|
|
105
180
|
return {
|
|
106
181
|
app: win.owner?.name ?? "",
|
|
107
182
|
title: win.title ?? "",
|
|
108
|
-
bounds: win.bounds
|
|
183
|
+
bounds: win.bounds,
|
|
184
|
+
contentBounds: win.contentBounds
|
|
109
185
|
};
|
|
110
186
|
} catch (err) {
|
|
111
187
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -114,28 +190,64 @@ var FullscreenDetector = class {
|
|
|
114
190
|
}
|
|
115
191
|
}
|
|
116
192
|
/**
|
|
117
|
-
*
|
|
193
|
+
* 综合判定当前窗口是否应当视为 busy。
|
|
118
194
|
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
195
|
+
* 优先级:
|
|
196
|
+
* 1. allowApps 命中 → 永不 busy(即使 F11 全屏 chrome)
|
|
197
|
+
* 2. busyApps 命中 → 永远 busy
|
|
198
|
+
* 3. 几何全屏:bounds 起点贴近 (0,0) AND `contentBounds == bounds`
|
|
199
|
+
* AND 覆盖整块显示器 → busy
|
|
200
|
+
*/
|
|
201
|
+
check(win, display) {
|
|
202
|
+
const app = win.app.toLowerCase();
|
|
203
|
+
const title = win.title.toLowerCase();
|
|
204
|
+
if (this.matchAny(this.busyApps, app, title)) {
|
|
205
|
+
return { busy: true, reason: "busy_app" };
|
|
206
|
+
}
|
|
207
|
+
if (this.matchAny(this.allowApps, app, title)) {
|
|
208
|
+
return { busy: false, reason: "allow_app" };
|
|
209
|
+
}
|
|
210
|
+
if (this.isFullscreenGeometry(win, display)) {
|
|
211
|
+
return { busy: true, reason: "fullscreen_geometry" };
|
|
212
|
+
}
|
|
213
|
+
return { busy: false };
|
|
214
|
+
}
|
|
215
|
+
matchAny(patterns, ...haystack) {
|
|
216
|
+
if (patterns.length === 0) return false;
|
|
217
|
+
return patterns.some((p) => haystack.some((h) => h.includes(p)));
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* 几何上是否是真正的全屏(区别于"最大化窗口")。
|
|
221
|
+
*
|
|
222
|
+
* 关键观察(Windows 上):
|
|
223
|
+
* - 最大化的普通窗口:`bounds.x = -7, bounds.y = -7`(aero 边框 overscan),
|
|
224
|
+
* `contentBounds` 比 `bounds` 小一圈(标题栏 / 边框被排除)
|
|
225
|
+
* - 真正的全屏(F11 / 全屏游戏):`bounds.x = 0, bounds.y = 0`,
|
|
226
|
+
* `contentBounds == bounds`,整体尺寸贴合整块显示器
|
|
122
227
|
*
|
|
123
|
-
*
|
|
124
|
-
* 用户的意图是「看到某个独占应用就别曝光画面」。
|
|
228
|
+
* macOS / Linux 通常没有 contentBounds,退化为只看起点和尺寸。
|
|
125
229
|
*/
|
|
126
|
-
|
|
230
|
+
isFullscreenGeometry(win, display) {
|
|
127
231
|
if (!display.width || !display.height) return false;
|
|
128
|
-
const { bounds } = win;
|
|
232
|
+
const { bounds, contentBounds } = win;
|
|
129
233
|
if (bounds.width <= 0 || bounds.height <= 0) return false;
|
|
234
|
+
if (Math.abs(bounds.x) > 1 || Math.abs(bounds.y) > 1) return false;
|
|
235
|
+
if (contentBounds) {
|
|
236
|
+
const sameOrigin = contentBounds.x === bounds.x && contentBounds.y === bounds.y;
|
|
237
|
+
const sameSize = contentBounds.width === bounds.width && contentBounds.height === bounds.height;
|
|
238
|
+
if (!sameOrigin || !sameSize) return false;
|
|
239
|
+
}
|
|
130
240
|
const widthRatio = bounds.width / display.width;
|
|
131
241
|
const heightRatio = bounds.height / display.height;
|
|
132
242
|
const ratioMismatch = Math.abs(widthRatio - heightRatio) / Math.max(widthRatio, heightRatio);
|
|
133
243
|
if (ratioMismatch > 0.02) return false;
|
|
134
244
|
const scale = (widthRatio + heightRatio) / 2;
|
|
135
245
|
const dpiScales = [1, 0.8, 2 / 3, 4 / 7, 0.5, 4 / 9, 0.4];
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
246
|
+
return dpiScales.some((s) => Math.abs(scale - s) < 0.01);
|
|
247
|
+
}
|
|
248
|
+
/** 兼容旧名字。新代码用 `check`。 */
|
|
249
|
+
isFullscreen(win, display) {
|
|
250
|
+
return this.check(win, display).busy;
|
|
139
251
|
}
|
|
140
252
|
load() {
|
|
141
253
|
if (this.mod) return Promise.resolve(this.mod);
|
|
@@ -198,7 +310,13 @@ var ArgusClient = class {
|
|
|
198
310
|
this.config = config;
|
|
199
311
|
this.version = version;
|
|
200
312
|
this.hooks = hooks;
|
|
201
|
-
this.fullscreen = new FullscreenDetector(
|
|
313
|
+
this.fullscreen = new FullscreenDetector({
|
|
314
|
+
enabled: config.detectFullscreen,
|
|
315
|
+
// 用户传的 allowApps 与默认列表合并(用户的不区分大小写补丁是为了
|
|
316
|
+
// 不会因为忘记加常见应用而误伤)
|
|
317
|
+
allowApps: [...DEFAULT_ALLOW_APPS, ...config.allowApps],
|
|
318
|
+
busyApps: config.busyApps
|
|
319
|
+
});
|
|
202
320
|
}
|
|
203
321
|
static {
|
|
204
322
|
__name(this, "ArgusClient");
|
|
@@ -375,18 +493,21 @@ var ArgusClient = class {
|
|
|
375
493
|
if (this.fullscreen.isEnabled()) {
|
|
376
494
|
const win = await this.fullscreen.getActiveWindow();
|
|
377
495
|
const display = publicIndex !== void 0 ? this.displays[publicIndex] : void 0;
|
|
378
|
-
if (win && display
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
496
|
+
if (win && display) {
|
|
497
|
+
const result = this.fullscreen.check(win, display);
|
|
498
|
+
if (result.busy) {
|
|
499
|
+
logger.info(
|
|
500
|
+
`peek #${frame.id} → busy (${result.reason}): ${win.app || win.title || "fullscreen"}`
|
|
501
|
+
);
|
|
502
|
+
this.send({
|
|
503
|
+
type: "peek_busy",
|
|
504
|
+
id: frame.id,
|
|
505
|
+
app: win.app,
|
|
506
|
+
title: win.title,
|
|
507
|
+
reason: result.reason ?? "fullscreen"
|
|
508
|
+
});
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
390
511
|
}
|
|
391
512
|
}
|
|
392
513
|
const start2 = Date.now();
|
|
@@ -500,9 +621,11 @@ var HELP_TEXT = `argus-eye [options]
|
|
|
500
621
|
--no-reconnect 禁用断线重连
|
|
501
622
|
--backoff <ms> 重连最大间隔(默认 30000)
|
|
502
623
|
--no-detect-fullscreen
|
|
503
|
-
关闭"全屏即拒拍"
|
|
504
|
-
|
|
505
|
-
|
|
624
|
+
关闭"全屏即拒拍"行为(默认开启)。
|
|
625
|
+
--allow-app <name> 不视为 busy 的应用关键词(可重复)。
|
|
626
|
+
会与默认白名单(chrome / edge / vscode / 终端 / IM 等)合并。
|
|
627
|
+
--busy-app <name> 强制视为 busy 的应用关键词(可重复),
|
|
628
|
+
优先级高于 allow-app。例如 --busy-app valorant --busy-app csgo
|
|
506
629
|
--config <path> JSON 配置文件
|
|
507
630
|
--no-color 关闭着色输出
|
|
508
631
|
-h, --help 显示帮助
|
|
@@ -522,6 +645,7 @@ function parseArgs(argv) {
|
|
|
522
645
|
version: ["v"]
|
|
523
646
|
},
|
|
524
647
|
string: ["server", "token", "name", "config", "format", "display"],
|
|
648
|
+
array: ["allowApp", "busyApp"],
|
|
525
649
|
number: ["backoff"],
|
|
526
650
|
boolean: [
|
|
527
651
|
"help",
|
|
@@ -558,7 +682,9 @@ function parseArgs(argv) {
|
|
|
558
682
|
reconnect: asBoolean(parsed.reconnect) ?? asBoolean(fileConfig.reconnect) ?? true,
|
|
559
683
|
backoff: asNumber(parsed.backoff) ?? asNumber(fileConfig.backoff) ?? 3e4,
|
|
560
684
|
color: asBoolean(parsed.color) ?? true,
|
|
561
|
-
detectFullscreen: asBoolean(parsed.detectFullscreen) ?? asBoolean(fileConfig.detectFullscreen) ?? true
|
|
685
|
+
detectFullscreen: asBoolean(parsed.detectFullscreen) ?? asBoolean(fileConfig.detectFullscreen) ?? true,
|
|
686
|
+
allowApps: asStringArray(parsed.allowApp) ?? asStringArray(fileConfig.allowApps) ?? [],
|
|
687
|
+
busyApps: asStringArray(parsed.busyApp) ?? asStringArray(fileConfig.busyApps) ?? []
|
|
562
688
|
};
|
|
563
689
|
if (parsed.listDisplays) {
|
|
564
690
|
return {
|
|
@@ -572,7 +698,9 @@ function parseArgs(argv) {
|
|
|
572
698
|
reconnect: merged.reconnect ?? true,
|
|
573
699
|
backoff: merged.backoff ?? 3e4,
|
|
574
700
|
color: merged.color ?? true,
|
|
575
|
-
detectFullscreen: merged.detectFullscreen ?? true
|
|
701
|
+
detectFullscreen: merged.detectFullscreen ?? true,
|
|
702
|
+
allowApps: merged.allowApps ?? [],
|
|
703
|
+
busyApps: merged.busyApps ?? []
|
|
576
704
|
}
|
|
577
705
|
};
|
|
578
706
|
}
|
|
@@ -595,7 +723,9 @@ function parseArgs(argv) {
|
|
|
595
723
|
reconnect: merged.reconnect ?? true,
|
|
596
724
|
backoff: merged.backoff ?? 3e4,
|
|
597
725
|
color: merged.color ?? true,
|
|
598
|
-
detectFullscreen: merged.detectFullscreen ?? true
|
|
726
|
+
detectFullscreen: merged.detectFullscreen ?? true,
|
|
727
|
+
allowApps: merged.allowApps ?? [],
|
|
728
|
+
busyApps: merged.busyApps ?? []
|
|
599
729
|
}
|
|
600
730
|
};
|
|
601
731
|
}
|
|
@@ -656,6 +786,18 @@ function asDisplay(v) {
|
|
|
656
786
|
return void 0;
|
|
657
787
|
}
|
|
658
788
|
__name(asDisplay, "asDisplay");
|
|
789
|
+
function asStringArray(v) {
|
|
790
|
+
if (Array.isArray(v)) {
|
|
791
|
+
const out = v.map((x) => typeof x === "string" ? x.trim() : "").filter((x) => x.length > 0);
|
|
792
|
+
return out.length > 0 ? out : void 0;
|
|
793
|
+
}
|
|
794
|
+
if (typeof v === "string" && v.length > 0) {
|
|
795
|
+
const out = v.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
796
|
+
return out.length > 0 ? out : void 0;
|
|
797
|
+
}
|
|
798
|
+
return void 0;
|
|
799
|
+
}
|
|
800
|
+
__name(asStringArray, "asStringArray");
|
|
659
801
|
|
|
660
802
|
// src/index.ts
|
|
661
803
|
var require2 = createRequire(import.meta.url);
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -35,10 +35,43 @@ argus-eye [options]
|
|
|
35
35
|
|
|
36
36
|
## 全屏检测
|
|
37
37
|
|
|
38
|
-
CLI
|
|
38
|
+
CLI 默认开启全屏检测:当截屏时检测到当前焦点窗口是**真正的全屏**(典型如全屏游戏),
|
|
39
39
|
就向服务端返回一段「客户端正忙:xxx」的提示而不是真截图。
|
|
40
40
|
群友看到的是程序名("League of Legends" / "Bilibili" 等),看不到画面。
|
|
41
|
-
|
|
41
|
+
|
|
42
|
+
判定规则(按优先级从高到低):
|
|
43
|
+
|
|
44
|
+
1. `--busy-app` 显式黑名单命中 → 视为忙
|
|
45
|
+
2. `--allow-app` 命中(默认包含 chrome、edge、firefox、vscode、cursor、idea、
|
|
46
|
+
终端、explorer、QQ、微信、Discord、Office 等常见应用)→ 永远不忙
|
|
47
|
+
3. 几何上是真全屏:起点贴 `(0, 0)`、`bounds == contentBounds`、覆盖整块显示器
|
|
48
|
+
→ 视为忙
|
|
49
|
+
|
|
50
|
+
第二条让最大化的 Chrome / VSCode 这种正常工作场景照常出图;
|
|
51
|
+
第三条用 `bounds == contentBounds` 区分"真全屏"和"最大化"
|
|
52
|
+
(最大化窗口在 Windows 上 `bounds.x = -7` 且 `contentBounds` 比 `bounds` 小一圈)。
|
|
53
|
+
|
|
54
|
+
例:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# 把 valorant / csgo / lol 直接列到黑名单
|
|
58
|
+
argus-eye -s ... -t ... --busy-app valorant --busy-app csgo --busy-app "league of legends"
|
|
59
|
+
|
|
60
|
+
# 把"魔兽世界"也加进白名单(如果你想被群友看到)
|
|
61
|
+
argus-eye -s ... -t ... --allow-app wow
|
|
62
|
+
|
|
63
|
+
# 关掉这个行为
|
|
64
|
+
argus-eye -s ... -t ... --no-detect-fullscreen
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
也可以写在 `~/.argus-eye.json`:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"busyApps": ["valorant", "csgo", "league of legends"],
|
|
72
|
+
"allowApps": ["mygame"]
|
|
73
|
+
}
|
|
74
|
+
```
|
|
42
75
|
|
|
43
76
|
底层使用 [`get-windows`](https://www.npmjs.com/package/get-windows)(optional dependency)。
|
|
44
77
|
该包是原生 napi 模块,部分平台(Linux Wayland)不支持,加载失败时会自动降级为永远「不忙」。
|