# HG changeset patch # User Christian Brabandt # Date 1517428808 -3600 # Node ID 808625d4b71ba217713bdc138e95fb105e9938dc # Parent 46794b7ab97ac3d536f3e17228e7fdab2d1ca818 patch 8.0.1449: slow redrawing with DirectX commit https://github.com/vim/vim/commit/a338adcf222b6a24e26ea5ae6a2ad27f914acb38 Author: Bram Moolenaar Date: Wed Jan 31 20:51:47 2018 +0100 patch 8.0.1449: slow redrawing with DirectX Problem: Slow redrawing with DirectX. Solution: Avoid calling gui_mch_flush() unnecessarily, especially when updating the cursor. (Ken Takata, closes #2560) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -6122,7 +6122,7 @@ A jump table for the options with a shor geom pixelGeometry int 0 - 2 (see below) renmode renderingMode int 0 - 6 (see below) taamode textAntialiasMode int 0 - 3 (see below) - scrlines Scroll Lines int >= 0 (see below) + scrlines Scroll Lines int (deprecated) See this URL for detail (except for scrlines): https://msdn.microsoft.com/en-us/library/dd368190.aspx @@ -6156,23 +6156,9 @@ A jump table for the options with a shor See this URL for detail: https://msdn.microsoft.com/en-us/library/dd368170.aspx - For scrlines: threshold for lines to be scrolled. - 0 - Always use scrolling. (default) - 1 - Use full page redrawing. - > 1 - If the lines to be scrolled is grater or equal to the - specified value, use redrawing. Otherwise use - scrolling. - - If you feel scrolling a page (CTRL-F) is too slow with DirectX - renderer, try this "scrlines" option. - When set it "1", Vim uses full page redrawing instead of - scrolling. Redrawing a page is faster than scrolling a - page in some environments. - After that, when you feel scrolling lines (CTRL-Y) becomes - slow, please try "2" or greater value for this option. - It works threshold line number to switch scrolling to - redrawing. Scrolling a few lines might be faster than - redrawing a page in some environments. + For scrlines: + This was used for optimizing scrolling behavior, however this + is now deprecated. If specified, it is simply ignored. Example: > set encoding=utf-8 diff --git a/src/channel.c b/src/channel.c --- a/src/channel.c +++ b/src/channel.c @@ -2207,14 +2207,7 @@ channel_exe_cmd(channel_T *channel, ch_p ex_redraw(&ea); showruler(FALSE); setcursor(); - out_flush(); -#ifdef FEAT_GUI - if (gui.in_use) - { - gui_update_cursor(TRUE, FALSE); - gui_mch_flush(); - } -#endif + out_flush_cursor(TRUE, FALSE); } else if (STRCMP(cmd, "expr") == 0 || STRCMP(cmd, "call") == 0) { diff --git a/src/edit.c b/src/edit.c --- a/src/edit.c +++ b/src/edit.c @@ -3451,7 +3451,7 @@ ins_compl_clear(void) compl_orig_text = NULL; compl_enter_selects = FALSE; /* clear v:completed_item */ - set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); + set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED)); } /* @@ -3553,8 +3553,7 @@ ins_compl_new_leader(void) { /* Show the cursor after the match, not after the redrawn text. */ setcursor(); - out_flush(); - gui_update_cursor(FALSE, FALSE); + out_flush_cursor(FALSE, FALSE); } #endif compl_restarting = TRUE; @@ -4704,7 +4703,7 @@ ins_compl_delete(void) * flicker, thus we can't do that. */ changed_cline_bef_curs(); /* clear v:completed_item */ - set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); + set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED)); } /* @@ -4724,7 +4723,7 @@ ins_compl_insert(int in_compl_func) /* Set completed item. */ /* { word, abbr, menu, kind, info } */ - dict = dict_alloc(); + dict = dict_alloc_lock(VAR_FIXED); if (dict != NULL) { dict_add_nr_str(dict, "word", 0L, @@ -4936,8 +4935,7 @@ ins_compl_next( { /* Show the cursor after the match, not after the redrawn text. */ setcursor(); - out_flush(); - gui_update_cursor(FALSE, FALSE); + out_flush_cursor(FALSE, FALSE); } #endif diff --git a/src/getchar.c b/src/getchar.c --- a/src/getchar.c +++ b/src/getchar.c @@ -2972,16 +2972,10 @@ inchar( if (wait_time == -1L || wait_time > 100L) /* flush output before waiting */ { cursor_on(); - out_flush(); -#ifdef FEAT_GUI - if (gui.in_use) - { - gui_update_cursor(FALSE, FALSE); -# ifdef FEAT_MOUSESHAPE - if (postponed_mouseshape) - update_mouseshape(-1); -# endif - } + out_flush_cursor(FALSE, FALSE); +#if defined(FEAT_GUI) && defined(FEAT_MOUSESHAPE) + if (gui.in_use && postponed_mouseshape) + update_mouseshape(-1); #endif } diff --git a/src/gui.c b/src/gui.c --- a/src/gui.c +++ b/src/gui.c @@ -55,6 +55,7 @@ enum { static void gui_attempt_start(void); static int can_update_cursor = TRUE; /* can display the cursor */ +static int disable_flush = 0; /* If > 0, gui_mch_flush() is disabled. */ /* * The Athena scrollbars can move the thumb to after the end of the scrollbar, @@ -1976,7 +1977,7 @@ gui_write( gui.dragged_sb = SBAR_NONE; #endif - gui_mch_flush(); /* In case vim decides to take a nap */ + gui_may_flush(); /* In case vim decides to take a nap */ } /* @@ -2004,6 +2005,34 @@ gui_can_update_cursor(void) * after scrolling. */ } +/* + * Disable issuing gui_mch_flush(). + */ + void +gui_disable_flush(void) +{ + ++disable_flush; +} + +/* + * Enable issuing gui_mch_flush(). + */ + void +gui_enable_flush(void) +{ + --disable_flush; +} + +/* + * Issue gui_mch_flush() if it is not disabled. + */ + void +gui_may_flush(void) +{ + if (disable_flush == 0) + gui_mch_flush(); +} + static void gui_outstr(char_u *s, int len) { @@ -3682,7 +3711,6 @@ gui_update_tabline(void) /* Updating the tabline uses direct GUI commands, flush * outstanding instructions first. (esp. clear screen) */ out_flush(); - gui_mch_flush(); if (!showit != !shown) gui_mch_show_tabline(showit); @@ -4122,8 +4150,7 @@ gui_drag_scrollbar(scrollbar_T *sb, long setcursor(); } # endif - out_flush(); - gui_update_cursor(FALSE, TRUE); + out_flush_cursor(FALSE, TRUE); #else add_to_input_buf(bytes, byte_count); add_long_to_buf((long_u)value, bytes); @@ -4486,7 +4513,9 @@ gui_do_scroll(void) * disappear when losing focus after a scrollbar drag. */ if (wp->w_redr_type < type) wp->w_redr_type = type; + mch_disable_flush(); updateWindow(wp); /* update window, status line, and cmdline */ + mch_enable_flush(); } #ifdef FEAT_INS_EXPAND @@ -4797,8 +4826,7 @@ gui_focus_change(int in_focus) */ #if 1 gui.in_focus = in_focus; - out_flush(); /* make sure output has been written */ - gui_update_cursor(TRUE, FALSE); + out_flush_cursor(TRUE, FALSE); # ifdef FEAT_XIM xim_set_focus(in_focus); @@ -5157,9 +5185,7 @@ gui_update_screen(void) curwin->w_valid &= ~VALID_CROW; } # endif - out_flush(); /* make sure output has been written */ - gui_update_cursor(TRUE, FALSE); - gui_mch_flush(); + out_flush_cursor(TRUE, FALSE); } #endif @@ -5516,9 +5542,7 @@ gui_handle_drop( maketitle(); #endif setcursor(); - out_flush(); - gui_update_cursor(FALSE, FALSE); - gui_mch_flush(); + out_flush_cursor(FALSE, FALSE); } entered = FALSE; diff --git a/src/gui_dwrite.cpp b/src/gui_dwrite.cpp --- a/src/gui_dwrite.cpp +++ b/src/gui_dwrite.cpp @@ -286,6 +286,7 @@ struct DWriteContext { ID2D1DCRenderTarget *mRT; ID2D1GdiInteropRenderTarget *mGDIRT; ID2D1SolidColorBrush *mBrush; + ID2D1Bitmap *mBitmap; IDWriteFactory *mDWriteFactory; #ifdef FEAT_DIRECTX_COLOR_EMOJI @@ -319,6 +320,8 @@ struct DWriteContext { void SetFont(HFONT hFont); + void Rebind(); + void BindDC(HDC hdc, const RECT *rect); HRESULT SetDrawingMode(DrawingMode mode); @@ -335,6 +338,8 @@ struct DWriteContext { void SetPixel(int x, int y, COLORREF color); + void Scroll(int x, int y, const RECT *rc); + void Flush(); void SetRenderingParams( @@ -596,6 +601,7 @@ DWriteContext::DWriteContext() : mRT(NULL), mGDIRT(NULL), mBrush(NULL), + mBitmap(NULL), mDWriteFactory(NULL), #ifdef FEAT_DIRECTX_COLOR_EMOJI mDWriteFactory2(NULL), @@ -616,9 +622,6 @@ DWriteContext::DWriteContext() : _RPT2(_CRT_WARN, "D2D1CreateFactory: hr=%p p=%p\n", hr, mD2D1Factory); if (SUCCEEDED(hr)) - hr = CreateDeviceResources(); - - if (SUCCEEDED(hr)) { hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED, @@ -662,6 +665,7 @@ DWriteContext::~DWriteContext() #ifdef FEAT_DIRECTX_COLOR_EMOJI SafeRelease(&mDWriteFactory2); #endif + SafeRelease(&mBitmap); SafeRelease(&mBrush); SafeRelease(&mGDIRT); SafeRelease(&mRT); @@ -704,13 +708,7 @@ DWriteContext::CreateDeviceResources() } if (SUCCEEDED(hr)) - { - if (mHDC != NULL) - { - mRT->BindDC(mHDC, &mBindRect); - mRT->SetTransform(D2D1::IdentityMatrix()); - } - } + Rebind(); return hr; } @@ -718,6 +716,7 @@ DWriteContext::CreateDeviceResources() void DWriteContext::DiscardDeviceResources() { + SafeRelease(&mBitmap); SafeRelease(&mBrush); SafeRelease(&mGDIRT); SafeRelease(&mRT); @@ -899,13 +898,36 @@ DWriteContext::SetFont(HFONT hFont) } void +DWriteContext::Rebind() +{ + SafeRelease(&mBitmap); + + mRT->BindDC(mHDC, &mBindRect); + mRT->SetTransform(D2D1::IdentityMatrix()); + + D2D1_BITMAP_PROPERTIES props = { + {DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE}, + 96.0f, 96.0f + }; + mRT->CreateBitmap( + D2D1::SizeU(mBindRect.right - mBindRect.left, + mBindRect.bottom - mBindRect.top), + props, &mBitmap); +} + + void DWriteContext::BindDC(HDC hdc, const RECT *rect) { - Flush(); - mRT->BindDC(hdc, rect); - mRT->SetTransform(D2D1::IdentityMatrix()); mHDC = hdc; mBindRect = *rect; + + if (mRT == NULL) + CreateDeviceResources(); + else + { + Flush(); + Rebind(); + } } HRESULT @@ -1081,6 +1103,49 @@ DWriteContext::SetPixel(int x, int y, CO } void +DWriteContext::Scroll(int x, int y, const RECT *rc) +{ + SetDrawingMode(DM_DIRECTX); + mRT->Flush(); + + D2D1_RECT_U srcRect; + D2D1_POINT_2U destPoint; + if (x >= 0) + { + srcRect.left = rc->left; + srcRect.right = rc->right - x; + destPoint.x = rc->left + x; + } + else + { + srcRect.left = rc->left - x; + srcRect.right = rc->right; + destPoint.x = rc->left; + } + if (y >= 0) + { + srcRect.top = rc->top; + srcRect.bottom = rc->bottom - y; + destPoint.y = rc->top + y; + } + else + { + srcRect.top = rc->top - y; + srcRect.bottom = rc->bottom; + destPoint.y = rc->top; + } + mBitmap->CopyFromRenderTarget(&destPoint, mRT, &srcRect); + + D2D1_RECT_F destRect = { + FLOAT(destPoint.x), FLOAT(destPoint.y), + FLOAT(destPoint.x + srcRect.right - srcRect.left), + FLOAT(destPoint.y + srcRect.bottom - srcRect.top) + }; + mRT->DrawBitmap(mBitmap, destRect, 1.0F, + D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR, destRect); +} + + void DWriteContext::Flush() { SetDrawingMode(DM_GDI); @@ -1240,6 +1305,13 @@ DWriteContext_SetPixel(DWriteContext *ct } void +DWriteContext_Scroll(DWriteContext *ctx, int x, int y, const RECT *rc) +{ + if (ctx != NULL) + ctx->Scroll(x, y, rc); +} + + void DWriteContext_Flush(DWriteContext *ctx) { if (ctx != NULL) diff --git a/src/gui_dwrite.h b/src/gui_dwrite.h --- a/src/gui_dwrite.h +++ b/src/gui_dwrite.h @@ -74,6 +74,7 @@ void DWriteContext_FillRect(DWriteContex void DWriteContext_DrawLine(DWriteContext *ctx, int x1, int y1, int x2, int y2, COLORREF color); void DWriteContext_SetPixel(DWriteContext *ctx, int x, int y, COLORREF color); +void DWriteContext_Scroll(DWriteContext *ctx, int x, int y, const RECT *rc); void DWriteContext_Flush(DWriteContext *ctx); void DWriteContext_Close(DWriteContext *ctx); diff --git a/src/gui_w32.c b/src/gui_w32.c --- a/src/gui_w32.c +++ b/src/gui_w32.c @@ -36,7 +36,6 @@ static DWriteContext *s_dwc = NULL; static int s_directx_enabled = 0; static int s_directx_load_attempted = 0; -static int s_directx_scrlines = 0; # define IS_ENABLE_DIRECTX() (s_directx_enabled && s_dwc != NULL && enc_utf8) static int directx_enabled(void); static void directx_binddc(void); @@ -61,7 +60,6 @@ gui_mch_set_rendering_options(char_u *s) int dx_geom = 0; int dx_renmode = 0; int dx_taamode = 0; - int dx_scrlines = 0; /* parse string as rendering options. */ for (p = s; p != NULL && *p != NUL; ) @@ -124,7 +122,7 @@ gui_mch_set_rendering_options(char_u *s) } else if (STRCMP(name, "scrlines") == 0) { - dx_scrlines = atoi((char *)value); + /* Deprecated. Simply ignore it. */ } else return FAIL; @@ -159,7 +157,6 @@ gui_mch_set_rendering_options(char_u *s) } } s_directx_enabled = dx_enable; - s_directx_scrlines = dx_scrlines; return OK; # else @@ -3129,9 +3126,6 @@ gui_mch_delete_lines( int num_lines) { RECT rc; -#if defined(FEAT_DIRECTX) - int use_redraw = 0; -#endif rc.left = FILL_X(gui.scroll_region_left); rc.right = FILL_X(gui.scroll_region_right + 1); @@ -3141,16 +3135,10 @@ gui_mch_delete_lines( #if defined(FEAT_DIRECTX) if (IS_ENABLE_DIRECTX()) { - if (s_directx_scrlines > 0 && s_directx_scrlines <= num_lines) - { - gui_redraw(rc.left, rc.top, - rc.right - rc.left + 1, rc.bottom - rc.top + 1); - use_redraw = 1; - } - else - DWriteContext_Flush(s_dwc); - } - if (!use_redraw) + DWriteContext_Scroll(s_dwc, 0, -num_lines * gui.char_height, &rc); + DWriteContext_Flush(s_dwc); + } + else #endif { intel_gpu_workaround(); @@ -3180,9 +3168,6 @@ gui_mch_insert_lines( int num_lines) { RECT rc; -#if defined(FEAT_DIRECTX) - int use_redraw = 0; -#endif rc.left = FILL_X(gui.scroll_region_left); rc.right = FILL_X(gui.scroll_region_right + 1); @@ -3192,16 +3177,10 @@ gui_mch_insert_lines( #if defined(FEAT_DIRECTX) if (IS_ENABLE_DIRECTX()) { - if (s_directx_scrlines > 0 && s_directx_scrlines <= num_lines) - { - gui_redraw(rc.left, rc.top, - rc.right - rc.left + 1, rc.bottom - rc.top + 1); - use_redraw = 1; - } - else - DWriteContext_Flush(s_dwc); - } - if (!use_redraw) + DWriteContext_Scroll(s_dwc, 0, num_lines * gui.char_height, &rc); + DWriteContext_Flush(s_dwc); + } + else #endif { intel_gpu_workaround(); @@ -4024,7 +4003,10 @@ gui_mch_browse( * position, but don't actually scroll by setting "dont_scroll". */ dont_scroll = !allow_scrollbar; + mch_disable_flush(); gui_drag_scrollbar(sb, val, dragging); + mch_enable_flush(); + gui_may_flush(); s_busy_processing = FALSE; dont_scroll = dont_scroll_save; @@ -4651,6 +4633,7 @@ init_mouse_wheel(void) if (mouse_scroll_lines == 0) init_mouse_wheel(); + mch_disable_flush(); if (mouse_scroll_lines > 0 && mouse_scroll_lines < (size > 2 ? size - 2 : 1)) { @@ -4659,6 +4642,8 @@ init_mouse_wheel(void) } else _OnScroll(hwnd, hwndCtl, zDelta >= 0 ? SB_PAGEUP : SB_PAGEDOWN, 0); + mch_enable_flush(); + gui_may_flush(); } #ifdef USE_SYSMENU_FONT diff --git a/src/macros.h b/src/macros.h --- a/src/macros.h +++ b/src/macros.h @@ -365,6 +365,17 @@ * HIKEY2DI() converts a hashitem key pointer to a dictitem pointer. * HI2DI() converts a hashitem pointer to a dictitem pointer. */ -# define DI2HIKEY(di) ((di)->di_key) -# define HIKEY2DI(p) ((dictitem_T *)(p - offsetof(dictitem_T, di_key))) -# define HI2DI(hi) HIKEY2DI((hi)->hi_key) +#define DI2HIKEY(di) ((di)->di_key) +#define HIKEY2DI(p) ((dictitem_T *)(p - offsetof(dictitem_T, di_key))) +#define HI2DI(hi) HIKEY2DI((hi)->hi_key) + +/* + * Flush control functions. + */ +#ifdef FEAT_GUI +# define mch_enable_flush() gui_enable_flush() +# define mch_disable_flush() gui_disable_flush() +#else +# define mch_enable_flush() +# define mch_disable_flush() +#endif diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c @@ -1242,7 +1242,11 @@ main_loop( if (VIsual_active) update_curbuf(INVERTED);/* update inverted part */ else if (must_redraw) + { + mch_disable_flush(); /* Stop issuing gui_mch_flush(). */ update_screen(0); + mch_enable_flush(); + } else if (redraw_cmdline || clear_cmdline) showmode(); redraw_statuslines(); @@ -1283,11 +1287,13 @@ main_loop( || conceal_cursor_line(curwin) || need_cursor_line_redraw)) { + mch_disable_flush(); /* Stop issuing gui_mch_flush(). */ if (conceal_old_cursor_line != conceal_new_cursor_line && conceal_old_cursor_line <= curbuf->b_ml.ml_line_count) update_single_line(curwin, conceal_old_cursor_line); update_single_line(curwin, conceal_new_cursor_line); + mch_enable_flush(); curwin->w_valid &= ~VALID_CROW; } # endif @@ -4212,11 +4218,7 @@ eval_client_expr_to_string(char_u *expr) /* A client can tell us to redraw, but not to display the cursor, so do * that here. */ setcursor(); - out_flush(); -#ifdef FEAT_GUI - if (gui.in_use) - gui_update_cursor(FALSE, FALSE); -#endif + out_flush_cursor(FALSE, FALSE); return res; } diff --git a/src/message.c b/src/message.c --- a/src/message.c +++ b/src/message.c @@ -2316,7 +2316,9 @@ msg_scroll_up(void) gui_undraw_cursor(); #endif /* scrolling up always works */ + mch_disable_flush(); screen_del_lines(0, 0, 1, (int)Rows, TRUE, 0, NULL); + mch_enable_flush(); if (!can_clear((char_u *)" ")) { diff --git a/src/netbeans.c b/src/netbeans.c --- a/src/netbeans.c +++ b/src/netbeans.c @@ -121,14 +121,7 @@ netbeans_close(void) update_screen(CLEAR); setcursor(); cursor_on(); - out_flush(); -#ifdef FEAT_GUI - if (gui.in_use) - { - gui_update_cursor(TRUE, FALSE); - gui_mch_flush(); - } -#endif + out_flush_cursor(TRUE, FALSE); } #define NB_DEF_HOST "localhost" @@ -1848,14 +1841,8 @@ nb_do_cmd( update_screen(VALID); setcursor(); cursor_on(); - out_flush(); -#ifdef FEAT_GUI - if (gui.in_use) - { - gui_update_cursor(TRUE, FALSE); - gui_mch_flush(); - } -#endif + out_flush_cursor(TRUE, FALSE); + /* Quit a hit-return or more prompt. */ if (State == HITRETURN || State == ASKMORE) { @@ -2248,14 +2235,8 @@ nb_do_cmd( update_screen(NOT_VALID); setcursor(); cursor_on(); - out_flush(); -#ifdef FEAT_GUI - if (gui.in_use) - { - gui_update_cursor(TRUE, FALSE); - gui_mch_flush(); - } -#endif + out_flush_cursor(TRUE, FALSE); + /* Quit a hit-return or more prompt. */ if (State == HITRETURN || State == ASKMORE) { @@ -2307,15 +2288,7 @@ coloncmd(char *cmd, ...) /* ALT_INPUT_LOCK_OFF; */ setcursor(); /* restore the cursor position */ - out_flush(); /* make sure output has been written */ - -#ifdef FEAT_GUI - if (gui.in_use) - { - gui_update_cursor(TRUE, FALSE); - gui_mch_flush(); - } -#endif + out_flush_cursor(TRUE, FALSE); } @@ -2569,14 +2542,7 @@ netbeans_open(char *params, int doabort) update_screen(CLEAR); setcursor(); cursor_on(); - out_flush(); -#ifdef FEAT_GUI - if (gui.in_use) - { - gui_update_cursor(TRUE, FALSE); - gui_mch_flush(); - } -#endif + out_flush_cursor(TRUE, FALSE); } /* diff --git a/src/proto/gui.pro b/src/proto/gui.pro --- a/src/proto/gui.pro +++ b/src/proto/gui.pro @@ -25,6 +25,9 @@ void gui_update_cursor_later(void); void gui_write(char_u *s, int len); void gui_dont_update_cursor(int undraw); void gui_can_update_cursor(void); +void gui_disable_flush(void); +void gui_enable_flush(void); +void gui_may_flush(void); int gui_outstr_nowrap(char_u *s, int len, int flags, guicolor_T fg, guicolor_T bg, int back); void gui_undraw_cursor(void); void gui_redraw(int x, int y, int w, int h); diff --git a/src/proto/term.pro b/src/proto/term.pro --- a/src/proto/term.pro +++ b/src/proto/term.pro @@ -12,6 +12,7 @@ int term_is_gui(char_u *name); char_u *tltoa(unsigned long i); void termcapinit(char_u *name); void out_flush(void); +void out_flush_cursor(int force, int clear_selection); void out_flush_check(void); void out_trash(void); void out_char(unsigned c); diff --git a/src/screen.c b/src/screen.c --- a/src/screen.c +++ b/src/screen.c @@ -468,16 +468,14 @@ redraw_after_callback(int call_update_sc setcursor(); } cursor_on(); - out_flush(); #ifdef FEAT_GUI - if (gui.in_use) - { + if (gui.in_use && !gui_mch_is_blink_off()) /* Don't update the cursor when it is blinking and off to avoid * flicker. */ - if (!gui_mch_is_blink_off()) - gui_update_cursor(FALSE, FALSE); - gui_mch_flush(); - } + out_flush_cursor(FALSE, FALSE); + else +#else + out_flush(); #endif --redrawing_for_callback; @@ -800,9 +798,12 @@ update_screen(int type_arg) * done. */ if (gui.in_use) { - out_flush(); /* required before updating the cursor */ if (did_undraw && !gui_mch_is_blink_off()) { + mch_disable_flush(); + out_flush(); /* required before updating the cursor */ + mch_enable_flush(); + /* Put the GUI position where the cursor was, gui_update_cursor() * uses that. */ gui.col = gui_cursor_col; @@ -811,9 +812,12 @@ update_screen(int type_arg) gui.col = mb_fix_col(gui.col, gui.row); # endif gui_update_cursor(FALSE, FALSE); + gui_may_flush(); screen_cur_col = gui.col; screen_cur_row = gui.row; } + else + out_flush(); gui_update_scrollbars(FALSE); } #endif @@ -863,8 +867,7 @@ update_finish(void) * done. */ if (gui.in_use) { - out_flush(); /* required before updating the cursor */ - gui_update_cursor(FALSE, FALSE); + out_flush_cursor(FALSE, FALSE); gui_update_scrollbars(FALSE); } # endif diff --git a/src/search.c b/src/search.c --- a/src/search.c +++ b/src/search.c @@ -2675,14 +2675,8 @@ showmatch( showruler(FALSE); setcursor(); cursor_on(); /* make sure that the cursor is shown */ - out_flush(); -#ifdef FEAT_GUI - if (gui.in_use) - { - gui_update_cursor(TRUE, FALSE); - gui_mch_flush(); - } -#endif + out_flush_cursor(TRUE, FALSE); + /* Restore dollar_vcol(), because setcursor() may call curs_rows() * which resets it if the matching position is in a previous line * and has a higher column number. */ diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -2501,6 +2501,27 @@ out_flush(void) } } +/* + * out_flush_cursor(): flush the output buffer and redraw the cursor + */ + void +out_flush_cursor( + int force UNUSED, /* when TRUE, update cursor even when not moved */ + int clear_selection UNUSED) /* clear selection under cursor */ +{ + mch_disable_flush(); + out_flush(); + mch_enable_flush(); +#ifdef FEAT_GUI + if (gui.in_use) + { + gui_update_cursor(force, clear_selection); + gui_may_flush(); + } +#endif +} + + #if defined(FEAT_MBYTE) || defined(PROTO) /* * Sometimes a byte out of a multi-byte character is written with out_char(). diff --git a/src/ui.c b/src/ui.c --- a/src/ui.c +++ b/src/ui.c @@ -245,7 +245,7 @@ ui_wait_for_chars_or_timer( if (interrupted != NULL && *interrupted) /* Nothing available, but need to return so that side effects get * handled, such as handling a message on a channel. */ - return FALSE; + return FAIL; if (wtime > 0) remaining -= due_time; } @@ -578,11 +578,7 @@ clip_lose_selection(VimClipboard *cbd) update_curbuf(INVERTED_ALL); setcursor(); cursor_on(); - out_flush(); -# ifdef FEAT_GUI - if (gui.in_use) - gui_update_cursor(TRUE, FALSE); -# endif + out_flush_cursor(TRUE, FALSE); } } #endif @@ -3331,13 +3327,10 @@ ui_focus_change( setcursor(); } cursor_on(); /* redrawing may have switched it off */ - out_flush(); + out_flush_cursor(FALSE, TRUE); # ifdef FEAT_GUI if (gui.in_use) - { - gui_update_cursor(FALSE, TRUE); gui_update_scrollbars(FALSE); - } # endif } #ifdef FEAT_TITLE diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -772,6 +772,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1449, +/**/ 1448, /**/ 1447,