Skip to content

Commit eccf3d1

Browse files
da-liiiclaude
andcommitted
[1145] 修复 focus icons 缓存永远 MISS:缓存 key 剔除 invisible 载荷
push-focus 给菜单项注入 (invisible (tree->path t)),路径随光标位置 变化,毒化 get_menu_widget 的展开结果判等,menu_cache 永远 MISS, 每次进入数学模式都全量 make_menu_widget(~41ms)并重建 QAction。 新增 scheme 函数 menu-cache-normalize 归一化展开结果中的 invisible 载荷;get_menu_widget 改用归一化 key 做判等与缓存索引。invisible 载荷本就不参与 widget 构建,行为零变化。实测重复进入数学模式 update_menus 从 166-173ms 降至 121-156ms。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent a4d5b7a commit eccf3d1

3 files changed

Lines changed: 86 additions & 45 deletions

File tree

TeXmacs/progs/kernel/gui/menu-widget.scm

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,17 @@
15021502
) ;cond
15031503
) ;tm-define
15041504

1505+
(tm-define (menu-cache-normalize r)
1506+
(:type (-> object object))
1507+
(:synopsis "Normalize expanded menu @r for use as menu cache key")
1508+
;; invisible 项的载荷(如 push-focus 注入的文档路径)不影响 widget 构建,
1509+
;; 但会让展开结果随光标位置变化,毒化缓存判等,故归一化剔除。
1510+
(cond ((and (pair? r) (== (car r) 'invisible)) (list 'invisible))
1511+
((pair? r) (cons (menu-cache-normalize (car r)) (menu-cache-normalize (cdr r))))
1512+
(else r)
1513+
) ;cond
1514+
) ;tm-define
1515+
15051516
(define-table menu-expand-table
15061517
(--- ,(lambda (p) `(--- ,@(menu-expand-list (cdr p)))))
15071518
(| ,(lambda (p) `(| ,@(menu-expand-list (cdr p)))))

TeXmacs/tests/1145.scm

Lines changed: 66 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,55 +26,82 @@
2626
(define (log-step label)
2727
(display "[1145-step] ")
2828
(display label)
29-
(newline))
29+
(newline)
30+
) ;define
3031

3132
;; 每步间隔 step-delay-ms:lambda 返回剩余毫秒表示继续等待,返回 #t 表示完成。
3233

3334
(define (run-chain steps on-done)
3435
(if (null? steps)
35-
(on-done)
36-
(exec-delayed-pause
37-
(let ((start (texmacs-time)))
38-
(lambda ()
39-
(let ((left (- (+ start step-delay-ms) (texmacs-time))))
40-
(if (> left 0)
41-
left
42-
(begin
43-
(log-step (caar steps))
44-
((cdar steps))
45-
;; 同步触发 C++ update_menus,不依赖 idle/焦点
46-
(update-menus)
47-
(run-chain (cdr steps) on-done)
48-
#t))))))))
36+
(on-done)
37+
(exec-delayed-pause (let ((start (texmacs-time)))
38+
(lambda ()
39+
(let ((left (- (+ start step-delay-ms) (texmacs-time))))
40+
(if (> left 0)
41+
left
42+
(begin
43+
(log-step (caar steps))
44+
((cdar steps))
45+
;; 同步触发 C++ update_menus,不依赖 idle/焦点
46+
(update-menus)
47+
(run-chain (cdr steps) on-done)
48+
#t
49+
) ;begin
50+
) ;if
51+
) ;let
52+
) ;lambda
53+
) ;let
54+
) ;exec-delayed-pause
55+
) ;if
56+
) ;define
4957

5058
(tm-define (test_1145)
5159
(new-document)
5260
(let* ((phase-a
5361
;; A: 纯文本输入 5 步,每步插 6 个字符
54-
(let loop ((i 0) (acc '()))
55-
(if (>= i 5) (reverse acc)
56-
(loop (+ i 1)
57-
(cons (cons (string-append "A: type text " (number->string i))
58-
(lambda () (insert "abcdef")))
59-
acc)))))
62+
(let loop
63+
((i 0) (acc '()))
64+
(if (>= i 5)
65+
(reverse acc)
66+
(loop (+ i 1)
67+
(cons (cons (string-append "A: type text " (number->string i))
68+
(lambda () (insert "abcdef"))
69+
) ;cons
70+
acc
71+
) ;cons
72+
) ;loop
73+
) ;if
74+
) ;let
75+
) ;phase-a
6076
(phase-b
6177
;; B: 5 轮 进出数学模式
62-
(let loop ((i 0) (acc '()))
63-
(if (>= i 5) acc
64-
(loop (+ i 1)
65-
(append
66-
acc
67-
(list
68-
(cons (string-append "B" (number->string i) ": insert math")
69-
(lambda () (insert '(math "x"))))
70-
(cons (string-append "B" (number->string i) ": enter math")
71-
(lambda () (go-left)))
72-
(cons (string-append "B" (number->string i) ": type in math")
73-
(lambda () (insert "y")))
74-
(cons (string-append "B" (number->string i) ": exit math")
75-
(lambda () (go-right))))))))))
78+
(let loop
79+
((i 0) (acc '()))
80+
(if (>= i 5)
81+
acc
82+
(loop (+ i 1)
83+
(append acc
84+
(list (cons (string-append "B" (number->string i) ": insert math")
85+
(lambda () (insert '(math "x")))
86+
) ;cons
87+
(cons (string-append "B" (number->string i) ": enter math")
88+
(lambda () (go-left))
89+
) ;cons
90+
(cons (string-append "B" (number->string i) ": type in math")
91+
(lambda () (insert "y"))
92+
) ;cons
93+
(cons (string-append "B" (number->string i) ": exit math")
94+
(lambda () (go-right))
95+
) ;cons
96+
) ;list
97+
) ;append
98+
) ;loop
99+
) ;if
100+
) ;let
101+
) ;phase-b
102+
) ;
76103
(run-chain (append phase-a phase-b)
77-
(lambda ()
78-
(display "[1145-step] done, quit")
79-
(newline)
80-
(quit-TeXmacs)))))
104+
(lambda () (display "[1145-step] done, quit") (newline) (quit-TeXmacs))
105+
) ;run-chain
106+
) ;let*
107+
) ;tm-define

src/Texmacs/Window/tm_window.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -415,15 +415,18 @@ tm_window_rep::get_menu_widget (int which, string menu, widget& w) {
415415
object xmenu= call ("menu-expand", eval ("'" * menu));
416416
bench_end ("menu-expand");
417417
the_drd= old_drd;
418+
// 缓存判等用归一化 key:剔除 invisible 载荷(如 push-focus 注入的光标
419+
// 路径),避免缓存 key 随光标位置变化而永远 MISS。
420+
object xkey= call ("menu-cache-normalize", xmenu);
418421
// tab 栏(which==4):xmenu 含每次新建的 lambda,无法用 equal 比较,故用
419422
// 稳定签名判等。签名不变(如切 tab)=> 跳过重建,保持上次 widget。
420423
if (which == 4) {
421424
string sig= as_string (call ("tabpage-menu-signature"));
422425
if (sig == tab_menu_signature) return false;
423426
tab_menu_signature= sig;
424427
}
425-
if (menu_cache->contains (xmenu)) {
426-
if (menu_current[which] == xmenu) {
428+
if (menu_cache->contains (xkey)) {
429+
if (menu_current[which] == xkey) {
427430
if (which >= 0 && which < 12) {
428431
menu_diag_equal[which]++;
429432
std_bench << "[1145] menu which=" << which
@@ -441,8 +444,8 @@ tm_window_rep::get_menu_widget (int which, string menu, widget& w) {
441444
<< " cache=" << menu_diag_cache[which]
442445
<< " miss=" << menu_diag_miss[which] << ")\n";
443446
}
444-
menu_current (which)= xmenu;
445-
w = menu_cache[xmenu];
447+
menu_current (which)= xkey;
448+
w = menu_cache[xkey];
446449
return true;
447450
}
448451
}
@@ -453,15 +456,15 @@ tm_window_rep::get_menu_widget (int which, string menu, widget& w) {
453456
<< " cache=" << menu_diag_cache[which]
454457
<< " miss=" << menu_diag_miss[which] << ")\n";
455458
}
456-
menu_current (which)= xmenu;
459+
menu_current (which)= xkey;
457460
object umenu = eval ("'" * menu);
458461
bench_start ("make_menu_widget");
459462
if (which == 10 || which == 11) w= make_menu_widget (umenu, 400, 1000);
460463
else w= make_menu_widget (umenu);
461464
bench_end ("make_menu_widget");
462465
if (menu_caching)
463466
if (which >= 10 || as_bool (call ("cache-menu?", xmenu))) {
464-
menu_cache (xmenu)= w;
467+
menu_cache (xkey)= w;
465468
}
466469
return true;
467470
}

0 commit comments

Comments
 (0)