Skip to content

Implement getcellpixels() for MacVim #1554

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/MacVim/MMBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
#endif
}

@property (nonatomic, readonly) NSSize cellSize;

+ (MMBackend *)sharedInstance;

- (void)setBackgroundColor:(int)color;
Expand Down
16 changes: 16 additions & 0 deletions src/MacVim/MMBackend.m
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ - (void)focusChange:(BOOL)on;
- (void)handleToggleToolbar;
- (void)handleScrollbarEvent:(NSData *)data;
- (void)handleSetFont:(NSData *)data;
- (void)handleCellSize:(NSData *)data;
- (void)handleDropFiles:(NSData *)data;
- (void)handleDropString:(NSData *)data;
- (void)startOdbEditWithArguments:(NSDictionary *)args;
Expand Down Expand Up @@ -1328,6 +1329,9 @@ - (oneway void)processInput:(int)msgid data:(in bycopy NSData *)data
// modified files when we get here.
isTerminating = YES;
getout(0);
} else if (UpdateCellSizeMsgID == msgid) {
// Immediately handle simple state updates to they can be reflected in Vim.
[self handleCellSize:data];
} else {
// First remove previous instances of this message from the input
// queue, else the input queue may fill up as a result of Vim not being
Expand Down Expand Up @@ -2705,6 +2709,18 @@ - (void)handleSetFont:(NSData *)data
CONVERT_FROM_UTF8_FREE(s);
}

- (void)handleCellSize:(NSData *)data
{
if (!data) return;

const void *bytes = [data bytes];

// Don't use gui.char_width/height because for simplicity we set those to
// 1. We store the cell size separately (it's only used for
// getcellpixels()).
memcpy(&_cellSize, bytes, sizeof(NSSize));
}

- (void)handleDropFiles:(NSData *)data
{
// TODO: Get rid of this method; instead use Vim script directly. At the
Expand Down
8 changes: 8 additions & 0 deletions src/MacVim/MMVimController.m
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,14 @@ - (void)handleMessage:(int)msgid data:(NSData *)data
}

[windowController setFont:font];

// Notify Vim of updated cell size for getcellpixels(). Note that
// this is asynchronous, which means getcellpixels() will not be
// immediately reflected after setting guifont.
NSSize cellsize = windowController.vimView.textView.cellSize;
[self sendMessage:UpdateCellSizeMsgID
data:[NSData dataWithBytes:&cellsize length:sizeof(cellsize)]];

[name release];
}
break;
Expand Down
1 change: 1 addition & 0 deletions src/MacVim/MacVim.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ extern const char * const MMVimMsgIDStrings[];
MSG(ScrollbarEventMsgID) \
MSG(SetFontMsgID) \
MSG(SetWideFontMsgID) \
MSG(UpdateCellSizeMsgID) \
MSG(VimShouldCloseMsgID) \
MSG(SetDefaultColorsMsgID) \
MSG(SetTablineColorsMsgID) \
Expand Down
11 changes: 11 additions & 0 deletions src/MacVim/gui_macvim.m
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,9 @@
// correspondence (assuming all characters have the same dimensions).
gui.scrollbar_width = gui.scrollbar_height = 0;

// For simplicity we just set char width/height to 1 as the GUI is
// decoupled from Vim anyway so Vim doesn't need to know the accurate
// pixel sizes.
gui.char_height = 1;
gui.char_width = 1;
gui.char_ascent = 0;
Expand Down Expand Up @@ -1664,6 +1667,14 @@
return OK;
}

void
gui_mch_calc_cell_size(struct cellsize *cs_out)
{
NSSize cellsize = [MMBackend sharedInstance].cellSize;
cs_out->cs_xpixel = round(cellsize.width);
cs_out->cs_ypixel = round(cellsize.height);
}


void
gui_mch_beep(void)
Expand Down
7 changes: 7 additions & 0 deletions src/evalfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5425,8 +5425,15 @@ f_getcellpixels(typval_T *argvars UNUSED, typval_T *rettv)
if (gui.in_use)
{
// success pixel size and no gui.
#ifdef FEAT_GUI_MACVIM
struct cellsize cs;
gui_mch_calc_cell_size(&cs);
list_append_number(rettv->vval.v_list, (varnumber_T)cs.cs_xpixel);
list_append_number(rettv->vval.v_list, (varnumber_T)cs.cs_ypixel);
#else
list_append_number(rettv->vval.v_list, (varnumber_T)gui.char_width);
list_append_number(rettv->vval.v_list, (varnumber_T)gui.char_height);
#endif
}
else
#endif
Expand Down
11 changes: 10 additions & 1 deletion src/os_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -4442,7 +4442,16 @@ mch_report_winsize(int fd, int rows, int cols)

// calcurate and set tty pixel size
struct cellsize cs;
mch_calc_cell_size(&cs);
#if defined(FEAT_GUI) && defined(FEAT_GUI_MACVIM)
if (gui.in_use)
{
gui_mch_calc_cell_size(&cs);
}
else
#endif
{
mch_calc_cell_size(&cs);
}

if (cs.cs_xpixel == -1)
{
Expand Down
1 change: 1 addition & 0 deletions src/proto/gui_macvim.pro
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ void gui_mch_set_font(GuiFont font);
void gui_mch_expand_font(optexpand_T *args, void *param, int (*add_match)(char_u *val));
int gui_mch_adjust_charheight(void);
int gui_mch_adjust_charwidth(void);
void gui_mch_calc_cell_size(struct cellsize *cs_out);
void gui_mch_beep(void);
char_u *gui_mch_browse(int saving, char_u *title, char_u *dflt, char_u *ext, char_u *initdir, char_u *filter);
char_u *gui_mch_browsedir(char_u *title, char_u *initdir);
Expand Down
7 changes: 7 additions & 0 deletions src/terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -4831,8 +4831,15 @@ parse_csi(
#ifdef FEAT_GUI
if (gui.in_use)
{
#ifdef FEAT_GUI_MACVIM
struct cellsize cs;
gui_mch_calc_cell_size(&cs);
x += wp->w_wincol * cs.cs_xpixel;
y += W_WINROW(wp) * cs.cs_ypixel;
#else
x += wp->w_wincol * gui.char_width;
y += W_WINROW(wp) * gui.char_height;
#endif
}
else
#endif
Expand Down
26 changes: 26 additions & 0 deletions src/testdir/test_functions.vim
Original file line number Diff line number Diff line change
Expand Up @@ -4338,6 +4338,32 @@ func Test_getcellpixels_gui()
endif
endfunc

" Test for getcellpixels() for MacVim
func Test_getcellpixels_macvim()
CheckGui
CheckRunVimInTerminal
if has("gui_running") && has('gui_macvim')
" MacVim works asynchronously and getcellpixels() does not immediately
" work either at launch or after guifont has been changed. It's a
" deliberate design decision. Right now the caller has to wait for MacVim
" to update the state before getcellpixels() will reflect the correct
" value, hence the need for multiple wait's here.
call WaitForAssert({-> assert_notequal(0, getcellpixels()[0], 'Uninitialized getcellpixels')})
call assert_equal([7, 13], getcellpixels()) " Default font is Menlo:h11
set guifont=Menlo:h13
call WaitForAssert({-> assert_equal([8, 15], getcellpixels())})

" Also test hosting a terminal and have that be updated
let buf = RunVimInTerminal('', #{})
call term_sendkeys(buf, ":redi @\"\<CR>")
call term_sendkeys(buf, ":echo getcellpixels()\<CR>")
call term_sendkeys(buf, ":redi END\<CR>")
call term_sendkeys(buf, "P")
call WaitForAssert({-> assert_equal(string(getcellpixels()), term_getline(buf, 3))}, 1000)
call StopVimInTerminal(buf)
endif
endfunc

func Str2Blob(s)
return list2blob(str2list(a:s))
endfunc
Expand Down