diff --git a/src/MacVim/MMBackend.h b/src/MacVim/MMBackend.h index e8271f2ded..93c3cdb997 100644 --- a/src/MacVim/MMBackend.h +++ b/src/MacVim/MMBackend.h @@ -57,6 +57,8 @@ #endif } +@property (nonatomic, readonly) NSSize cellSize; + + (MMBackend *)sharedInstance; - (void)setBackgroundColor:(int)color; diff --git a/src/MacVim/MMBackend.m b/src/MacVim/MMBackend.m index 21ade18abb..87b2d6b9f7 100644 --- a/src/MacVim/MMBackend.m +++ b/src/MacVim/MMBackend.m @@ -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; @@ -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 @@ -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 diff --git a/src/MacVim/MMVimController.m b/src/MacVim/MMVimController.m index 4d0a295722..05eb56f11a 100644 --- a/src/MacVim/MMVimController.m +++ b/src/MacVim/MMVimController.m @@ -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; diff --git a/src/MacVim/MacVim.h b/src/MacVim/MacVim.h index 3d2b17425f..46dbd2b0ea 100644 --- a/src/MacVim/MacVim.h +++ b/src/MacVim/MacVim.h @@ -300,6 +300,7 @@ extern const char * const MMVimMsgIDStrings[]; MSG(ScrollbarEventMsgID) \ MSG(SetFontMsgID) \ MSG(SetWideFontMsgID) \ + MSG(UpdateCellSizeMsgID) \ MSG(VimShouldCloseMsgID) \ MSG(SetDefaultColorsMsgID) \ MSG(SetTablineColorsMsgID) \ diff --git a/src/MacVim/gui_macvim.m b/src/MacVim/gui_macvim.m index 7ea4212c11..2526f37b64 100644 --- a/src/MacVim/gui_macvim.m +++ b/src/MacVim/gui_macvim.m @@ -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; @@ -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) diff --git a/src/evalfunc.c b/src/evalfunc.c index 43e56767cb..0312218274 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -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 diff --git a/src/os_unix.c b/src/os_unix.c index bf82fd81d3..790f8281ed 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -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) { diff --git a/src/proto/gui_macvim.pro b/src/proto/gui_macvim.pro index 7d27521d5d..eaa46b200f 100644 --- a/src/proto/gui_macvim.pro +++ b/src/proto/gui_macvim.pro @@ -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); diff --git a/src/terminal.c b/src/terminal.c index f644fb5e97..8a4e459c3f 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -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 diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 8ecc3a6710..5c77fb3160 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -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 @\"\") + call term_sendkeys(buf, ":echo getcellpixels()\") + call term_sendkeys(buf, ":redi END\") + 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