macvim-dev / macvim

Vim - the text editor - for macOS
https://macvim.org
Vim License
7.49k stars 680 forks source link

MacVim won't set the font `Cascadia Mono` with the typeface `Light` via the Fonts dialogue #1208

Open tenderlove opened 2 years ago

tenderlove commented 2 years ago

Describe the bug

MacVim won't set the font Cascadia Mono with the typeface Light via the Fonts picker, but can set it via set guifont.

To Reproduce

  1. Install Cascadia Code fonts from here
  2. In MacVim, do :set guifont=*, then select Cascadia Mono with typeface Light
  3. The font will not change
  4. :set guifont will verify the font doesn't change

It seems like MacVim is trying to use the name CascadiaMono-Regular_Light:h12 as the font name. But manually doing :set guifont=CascadiaMono-Regular_Light:h12 results in a "font missing" error.

:set guifont=Cascadia\ Mono\ Light:h12 will set the font correctly.

Expected behavior

I expected the font to change when clicking the font in the dialogue.

Screenshots

I made a video demonstration of the bug here.

Environment (please complete the following information):

$ vim --version
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Apr  1 2021 08:37:51)
macOS version - x86_64
Included patches: 1-2681
Compiled by GitHub Actions
Huge version with MacVim GUI.  Features included (+) or not (-):
+acl               +file_in_path      -mouse_sysmouse    -tag_old_static
+arabic            +find_in_path      +mouse_urxvt       -tag_any_white
+autocmd           +float             +mouse_xterm       -tcl
+autochdir         +folding           +multi_byte        +termguicolors
-autoservername    -footer            +multi_lang        +terminal
+balloon_eval      +fork()            -mzscheme          +terminfo
+balloon_eval_term +fullscreen        +netbeans_intg     +termresponse
+browse            +gettext           +num64             +textobjects
++builtin_terms    -hangul_input      +odbeditor         +textprop
+byte_offset       +iconv             +packages          +timers
+channel           +insert_expand     +path_extra        +title
+cindent           +ipv6              +perl/dyn          +toolbar
+clientserver      +job               +persistent_undo   +transparency
+clipboard         +jumplist          +popupwin          +user_commands
+cmdline_compl     +keymap            +postscript        +vartabs
+cmdline_hist      +lambda            +printer           +vertsplit
+cmdline_info      +langmap           +profile           +virtualedit
+comments          +libcall           +python/dyn        +visual
+conceal           +linebreak         +python3/dyn       +visualextra
+cryptv            +lispindent        +quickfix          +viminfo
+cscope            +listcmds          +reltime           +vreplace
+cursorbind        +localmap          +rightleft         +wildignore
+cursorshape       +lua/dyn           +ruby/dyn          +wildmenu
+dialog_con_gui    +menu              +scrollbind        +windows
+diff              +mksession         +signs             +writebackup
+digraphs          +modify_fname      +smartindent       -X11
+dnd               +mouse             -sound             -xfontset
-ebcdic            +mouseshape        +spell             +xim
+emacs_tags        +mouse_dec         +startuptime       -xpm
+eval              -mouse_gpm         +statusline        -xsmp
+ex_extra          -mouse_jsbterm     -sun_workshop      -xterm_clipboard
+extra_search      +mouse_netterm     +syntax            -xterm_save
-farsi             +mouse_sgr         +tag_binary        
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
  system gvimrc file: "$VIM/gvimrc"
    user gvimrc file: "$HOME/.gvimrc"
2nd user gvimrc file: "~/.vim/gvimrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
    system menu file: "$VIMRUNTIME/menu.vim"
  fall-back for $VIM: "/Applications/MacVim.app/Contents/Resources/vim"
Compilation: clang -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_MACVIM -Wall -Wno-unknown-pragmas -pipe -DMACOS_X -DMACOS_X_DARWIN -g -O2 -arch x86_64 -arch arm64 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -Wall -Wextra -Wshadow -Werror -Wno-error=missing-field-initializers -Wno-error=deprecated-declarations -Wno-error=unused-function 
Linking: clang -L. -fstack-protector-strong -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/openssl@1.1/lib -L/usr/local/opt/readline/lib -L. -fstack-protector-strong -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/openssl@1.1/lib -L/usr/local/opt/readline/lib -arch x86_64 -arch arm64 -L/usr/local/lib -o Vim -lm -lncurses -liconv /usr/local/lib/libintl.a -framework AppKit -fstack-protector -L/System/Library/Perl/5.18/darwin-thread-multi-2level/CORE

Additional context

I tried adding some print statements in the MacVim source to see if I could figure out the issue, but I didn't get far. I don't understand how the font name is determined, or how MacVim matches that up with fonts available on the system. Sorry I can't be more help. 🙇🏻‍♂️

eirnym commented 2 years ago

Fun fact about this font: https://github.com/microsoft/terminal/issues/9375

eirnym commented 2 years ago

I suspect it's not marked as monospaced or has issues and need some additional settings to be selected properly.

eirnym commented 2 years ago

:set guifont=Cascadia\ Mono\ Light:h12 will set the font correctly.

Spaces are crucial for font selection

tenderlove commented 2 years ago

I suspect it's not marked as monospaced or has issues and need some additional settings to be selected properly.

Does a font need to be marked as monospaced? I'm able to select things like "Times New Roman" from the font picker, and it seems to work fine. AFAICT, whatever data is sent to MacVim via the font picker isn't what we need (or isn't being manipulated correctly) to look up the font.

I've found that when I pick a font from the selector, handleSetFont gets called with the string CascadiaMono-Regular_Light. I don't know how the string gets generated, so I don't know whether or not that is the correct string for the particular font.

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
  * frame #0: 0x000000010366608c Vim`set_string_option(opt_idx=137, value=<unavailable>, opt_flags=0) at optionstr.c:555:2 [opt]
    frame #1: 0x0000000103658f5b Vim`set_option_value(name=<unavailable>, number=<unavailable>, string=<unavailable>, opt_flags=<unavailable>) at option.c:4482:13 [opt] [artificial]
    frame #2: 0x00000001037ce348 Vim`-[MMBackend(self=0x00007f90c8c04540, _cmd=<unavailable>, data=<unavailable>) handleSetFont:] at MMBackend.m:2488:5 [opt]
    frame #3: 0x00000001037cbb47 Vim`-[MMBackend(self=<unavailable>, _cmd=<unavailable>) processInputQueue] at MMBackend.m:1870:9 [opt]
    frame #4: 0x00000001037c6c26 Vim`-[MMBackend waitForInput:](self=0x00007f90c8c04540, _cmd=<unavailable>, milliseconds=<unavailable>) at MMBackend.m:726:5 [opt]
    frame #5: 0x00000001037bfe29 Vim`gui_mch_wait_for_chars(wtime=-1) at gui_macvim.m:449:12 [opt]
    frame #6: 0x00000001037680a4 Vim`ui_wait_for_chars_or_timer(wtime=<unavailable>, wait_func=(Vim`gui_wait_for_chars_3 at gui.c:2953), interrupted=0x00007ffeec6ba9cc, ignore_input=<unavailable>) at ui.c:488:6 [opt]
    frame #7: 0x0000000103767c04 Vim`inchar_loop(buf="", maxlen=53, wtime=-1, tb_change_cnt=82, wait_func=(Vim`gui_wait_for_chars_or_timer at gui.c:2967), resize_func=0x0000000000000000) at ui.c:384:6 [opt]
    frame #8: 0x00000001037bc68f Vim`gui_wait_for_chars_buf(buf="", maxlen=53, wtime=-1, tb_change_cnt=82) at gui.c:3020:14 [opt]
    frame #9: 0x00000001037bc6b5 Vim`gui_inchar(buf=<unavailable>, maxlen=<unavailable>, wtime=<unavailable>, tb_change_cnt=<unavailable>) at gui.c:3053:12 [opt] [artificial]
    frame #10: 0x0000000103767a4e Vim`ui_inchar(buf="", maxlen=53, wtime=-1, tb_change_cnt=<unavailable>) at ui.c:226:11 [opt]
    frame #11: 0x00000001035eeb2a Vim`inchar(buf="", maxlen=159, wait_time=-1) at getchar.c:3576:8 [opt]
    frame #12: 0x00000001035f2adb Vim`vgetorpeek(advance=1) at getchar.c:3355:7 [opt]
    frame #13: 0x00000001035f1634 Vim`vgetc at getchar.c:1690:10 [opt]
    frame #14: 0x00000001035f35a9 Vim`safe_vgetc at getchar.c:1919:9 [opt]
    frame #15: 0x0000000103644e07 Vim`normal_cmd(oap=0x00007ffeec6bad68, toplevel=1) at normal.c:570:9 [opt]
    frame #16: 0x00000001037fdf11 Vim`main_loop(cmdwin=<unavailable>, noexmode=<unavailable>) at main.c:0 [opt]
    frame #17: 0x00000001037fd3b2 Vim`vim_main2 at main.c:939:5 [opt]
    frame #18: 0x00000001037fbceb Vim`main(argc=<unavailable>, argv=<unavailable>) at main.c:445:12 [opt]
    frame #19: 0x00007fff20388f3d libdyld.dylib`start + 1
(lldb) f 2
frame #2: 0x00000001037ce348 Vim`-[MMBackend(self=0x00007f90c8c04540, _cmd=<unavailable>, data=<unavailable>) handleSetFont:] at MMBackend.m:2488:5 [opt]
   2485          ws = CONVERT_FROM_UTF8(ws);
   2486      }
   2487  
-> 2488      set_option_value((char_u*)"guifont", 0, s, 0);
   2489  
   2490      if (ws && gui.wide_font != NOFONT) {
   2491          // NOTE: This message is sent on Cmd-+/Cmd-- and as such should only
Vim`-[MMBackend(Private) handleSetFont:]:
->  0x1037ce348 <+392>: testq  %r13, %r13
    0x1037ce34b <+395>: je     0x1037ce371               ; <+433> at MMBackend.m
    0x1037ce34d <+397>: leaq   0xb6764(%rip), %rax       ; gui
    0x1037ce354 <+404>: cmpq   $0x0, 0x100(%rax)
(lldb) p s
(char_u *) $7 = 0x00007f90d8c278e0 "CascadiaMono-Regular_Light:h11"
(lldb) 

I guess this string is being put in to the inputQueue, but I'm not sure how.

tenderlove commented 2 years ago

Ok, so the string is getting in to the queue via [MMBackend processInput:data:], which I guess is getting that string from CoreFoundation:

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 7.1
  * frame #0: 0x00000001037c8b53 Vim`-[MMBackend processInput:data:](self=0x00007f90c8c04540, _cmd="processInput:data:", msgid=38, data=35 bytes) at MMBackend.m:1271:9 [opt]
    frame #1: 0x00007fff204486fc CoreFoundation`__invoking___ + 140
    frame #2: 0x00007fff2044859d CoreFoundation`-[NSInvocation invoke] + 305
    frame #3: 0x00007fff204780e5 CoreFoundation`-[NSInvocation invokeWithTarget:] + 70
    frame #4: 0x00007fff20446fd6 CoreFoundation`___forwarding___ + 819
    frame #5: 0x00007fff20446c18 CoreFoundation`_CF_forwarding_prep_0 + 120
    frame #6: 0x00007fff204486fc CoreFoundation`__invoking___ + 140
    frame #7: 0x00007fff2044859d CoreFoundation`-[NSInvocation invoke] + 305
    frame #8: 0x00007fff21296c5c Foundation`-[NSConnection dispatchInvocation:] + 150
    frame #9: 0x00007fff21294a2b Foundation`-[NSConnection handleRequest:sequence:] + 1332
    frame #10: 0x00007fff21293b4d Foundation`-[NSConnection handlePortCoder:] + 1093
    frame #11: 0x00007fff212931bd Foundation`-[NSConnection dispatchWithComponents:] + 53
    frame #12: 0x00007fff2123576d Foundation`__NSFireMachPort + 242
    frame #13: 0x00007fff20491a88 CoreFoundation`__CFMachPortPerform + 288
    frame #14: 0x00007fff20465a44 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
    frame #15: 0x00007fff20465925 CoreFoundation`__CFRunLoopDoSource1 + 619
    frame #16: 0x00007fff20463faf CoreFoundation`__CFRunLoopRun + 2400
    frame #17: 0x00007fff20462f8c CoreFoundation`CFRunLoopRunSpecific + 563
    frame #18: 0x00000001037c6b86 Vim`-[MMBackend waitForInput:](self=0x00007f90c8c04540, _cmd=<unavailable>, milliseconds=<unavailable>) at MMBackend.m:708:16 [opt]
    frame #19: 0x00000001037bfe29 Vim`gui_mch_wait_for_chars(wtime=-1) at gui_macvim.m:449:12 [opt]
    frame #20: 0x00000001037680a4 Vim`ui_wait_for_chars_or_timer(wtime=<unavailable>, wait_func=(Vim`gui_wait_for_chars_3 at gui.c:2953), interrupted=0x00007ffeec6ba9cc, ignore_input=<unavailable>) at ui.c:488:6 [opt]
    frame #21: 0x0000000103767c04 Vim`inchar_loop(buf="", maxlen=53, wtime=-1, tb_change_cnt=82, wait_func=(Vim`gui_wait_for_chars_or_timer at gui.c:2967), resize_func=0x0000000000000000) at ui.c:384:6 [opt]
    frame #22: 0x00000001037bc68f Vim`gui_wait_for_chars_buf(buf="", maxlen=53, wtime=-1, tb_change_cnt=82) at gui.c:3020:14 [opt]
    frame #23: 0x00000001037bc6b5 Vim`gui_inchar(buf=<unavailable>, maxlen=<unavailable>, wtime=<unavailable>, tb_change_cnt=<unavailable>) at gui.c:3053:12 [opt] [artificial]
    frame #24: 0x0000000103767a4e Vim`ui_inchar(buf="", maxlen=53, wtime=-1, tb_change_cnt=<unavailable>) at ui.c:226:11 [opt]
    frame #25: 0x00000001035eeb2a Vim`inchar(buf="", maxlen=159, wait_time=-1) at getchar.c:3576:8 [opt]
    frame #26: 0x00000001035f2adb Vim`vgetorpeek(advance=1) at getchar.c:3355:7 [opt]
    frame #27: 0x00000001035f1634 Vim`vgetc at getchar.c:1690:10 [opt]
    frame #28: 0x00000001035f35a9 Vim`safe_vgetc at getchar.c:1919:9 [opt]
    frame #29: 0x0000000103644e07 Vim`normal_cmd(oap=0x00007ffeec6bad68, toplevel=1) at normal.c:570:9 [opt]
    frame #30: 0x00000001037fdf11 Vim`main_loop(cmdwin=<unavailable>, noexmode=<unavailable>) at main.c:0 [opt]
    frame #31: 0x00000001037fd3b2 Vim`vim_main2 at main.c:939:5 [opt]
    frame #32: 0x00000001037fbceb Vim`main(argc=<unavailable>, argv=<unavailable>) at main.c:445:12 [opt]
    frame #33: 0x00007fff20388f3d libdyld.dylib`start + 1
(lldb) f
frame #0: 0x00000001037c8b53 Vim`-[MMBackend processInput:data:](self=0x00007f90c8c04540, _cmd="processInput:data:", msgid=38, data=35 bytes) at MMBackend.m:1271:9 [opt]
   1268      // TODO: Process mouse events here as well?  Anything else?
   1269      //
   1270  
-> 1271      if (KeyDownMsgID == msgid) {
   1272          if (!data) return;
   1273          const void *bytes = [data bytes];
   1274          unsigned mods = *((unsigned*)bytes);  bytes += sizeof(unsigned);
Vim`-[MMBackend processInput:data:]:
->  0x1037c8b53 <+35>: cmpl   $0x51, %edx
    0x1037c8b56 <+38>: je     0x1037c8ca5               ; <+373> at MMBackend.m
    0x1037c8b5c <+44>: cmpl   $0x3b, %edx
    0x1037c8b5f <+47>: je     0x1037c8c71               ; <+321> at MMBackend.m
(lldb) me read `[data bytes]` -c `[data length]`
0x7f90b8f0f2a0: 00 00 30 41 1b 00 00 00 43 61 73 63 61 64 69 61  ..0A....Cascadia
0x7f90b8f0f2b0: 4d 6f 6e 6f 2d 52 65 67 75 6c 61 72 5f 4c 69 67  Mono-Regular_Lig
0x7f90b8f0f2c0: 68 74 00                                         ht.
(lldb) 

This is very odd.

tenderlove commented 2 years ago

I should have read the README in src/MacVim 😅

This stack trace is telling me that the front end MacVim process is sending that string to the backend Vim process. So I need to find the place in the front end process that's getting this string.