To: vim_dev@googlegroups.com Subject: Patch 8.0.1449 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.1449 Problem: Slow redrawing with DirectX. Solution: Avoid calling gui_mch_flush() unnecessarily, especially when updating the cursor. (Ken Takata, closes #2560) Files: runtime/doc/options.txt, src/channel.c, src/edit.c, src/getchar.c, src/gui.c, src/gui_dwrite.cpp, src/gui_dwrite.h, src/gui_w32.c, src/macros.h, src/main.c, src/message.c, src/netbeans.c, src/proto/gui.pro, src/proto/term.pro, src/screen.c, src/search.c, src/term.c, src/ui.c *** ../vim-8.0.1448/runtime/doc/options.txt 2017-12-05 13:22:08.414402079 +0100 --- runtime/doc/options.txt 2018-01-31 20:43:44.619740451 +0100 *************** *** 6017,6023 **** 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) See this URL for detail (except for scrlines): https://msdn.microsoft.com/en-us/library/dd368190.aspx --- 6122,6128 ---- 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 (deprecated) See this URL for detail (except for scrlines): https://msdn.microsoft.com/en-us/library/dd368190.aspx *************** *** 6051,6073 **** 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. Example: > set encoding=utf-8 --- 6156,6164 ---- See this URL for detail: https://msdn.microsoft.com/en-us/library/dd368170.aspx ! 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 *** ../vim-8.0.1448/src/channel.c 2017-12-09 19:13:08.579678220 +0100 --- src/channel.c 2018-01-31 20:43:44.619740451 +0100 *************** *** 2207,2220 **** ex_redraw(&ea); showruler(FALSE); setcursor(); ! out_flush(); ! #ifdef FEAT_GUI ! if (gui.in_use) ! { ! gui_update_cursor(TRUE, FALSE); ! gui_mch_flush(); ! } ! #endif } else if (STRCMP(cmd, "expr") == 0 || STRCMP(cmd, "call") == 0) { --- 2207,2213 ---- ex_redraw(&ea); showruler(FALSE); setcursor(); ! out_flush_cursor(TRUE, FALSE); } else if (STRCMP(cmd, "expr") == 0 || STRCMP(cmd, "call") == 0) { *** ../vim-8.0.1448/src/edit.c 2017-11-28 20:47:36.782817313 +0100 --- src/edit.c 2018-01-31 20:43:44.623740392 +0100 *************** *** 3451,3457 **** compl_orig_text = NULL; compl_enter_selects = FALSE; /* clear v:completed_item */ ! set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); } /* --- 3451,3457 ---- compl_orig_text = NULL; compl_enter_selects = FALSE; /* clear v:completed_item */ ! set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED)); } /* *************** *** 3553,3560 **** { /* Show the cursor after the match, not after the redrawn text. */ setcursor(); ! out_flush(); ! gui_update_cursor(FALSE, FALSE); } #endif compl_restarting = TRUE; --- 3553,3559 ---- { /* Show the cursor after the match, not after the redrawn text. */ setcursor(); ! out_flush_cursor(FALSE, FALSE); } #endif compl_restarting = TRUE; *************** *** 4704,4710 **** * flicker, thus we can't do that. */ changed_cline_bef_curs(); /* clear v:completed_item */ ! set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc()); } /* --- 4703,4709 ---- * flicker, thus we can't do that. */ changed_cline_bef_curs(); /* clear v:completed_item */ ! set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc_lock(VAR_FIXED)); } /* *************** *** 4724,4730 **** /* Set completed item. */ /* { word, abbr, menu, kind, info } */ ! dict = dict_alloc(); if (dict != NULL) { dict_add_nr_str(dict, "word", 0L, --- 4723,4729 ---- /* Set completed item. */ /* { word, abbr, menu, kind, info } */ ! dict = dict_alloc_lock(VAR_FIXED); if (dict != NULL) { dict_add_nr_str(dict, "word", 0L, *************** *** 4936,4943 **** { /* Show the cursor after the match, not after the redrawn text. */ setcursor(); ! out_flush(); ! gui_update_cursor(FALSE, FALSE); } #endif --- 4935,4941 ---- { /* Show the cursor after the match, not after the redrawn text. */ setcursor(); ! out_flush_cursor(FALSE, FALSE); } #endif *** ../vim-8.0.1448/src/getchar.c 2017-11-25 17:14:29.600189562 +0100 --- src/getchar.c 2018-01-31 20:43:44.623740392 +0100 *************** *** 2972,2987 **** 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 ! } #endif } --- 2972,2981 ---- if (wait_time == -1L || wait_time > 100L) /* flush output before waiting */ { cursor_on(); ! out_flush_cursor(FALSE, FALSE); ! #if defined(FEAT_GUI) && defined(FEAT_MOUSESHAPE) ! if (gui.in_use && postponed_mouseshape) ! update_mouseshape(-1); #endif } *** ../vim-8.0.1448/src/gui.c 2017-12-19 19:42:37.385969952 +0100 --- src/gui.c 2018-01-31 20:43:44.623740392 +0100 *************** *** 55,60 **** --- 55,61 ---- 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,1982 **** gui.dragged_sb = SBAR_NONE; #endif ! gui_mch_flush(); /* In case vim decides to take a nap */ } /* --- 1977,1983 ---- gui.dragged_sb = SBAR_NONE; #endif ! gui_may_flush(); /* In case vim decides to take a nap */ } /* *************** *** 2004,2009 **** --- 2005,2038 ---- * 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,3688 **** /* 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); --- 3711,3716 ---- *************** *** 4122,4129 **** setcursor(); } # endif ! out_flush(); ! gui_update_cursor(FALSE, TRUE); #else add_to_input_buf(bytes, byte_count); add_long_to_buf((long_u)value, bytes); --- 4150,4156 ---- setcursor(); } # endif ! out_flush_cursor(FALSE, TRUE); #else add_to_input_buf(bytes, byte_count); add_long_to_buf((long_u)value, bytes); *************** *** 4486,4492 **** --- 4513,4521 ---- * 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,4804 **** */ #if 1 gui.in_focus = in_focus; ! out_flush(); /* make sure output has been written */ ! gui_update_cursor(TRUE, FALSE); # ifdef FEAT_XIM xim_set_focus(in_focus); --- 4826,4832 ---- */ #if 1 gui.in_focus = in_focus; ! out_flush_cursor(TRUE, FALSE); # ifdef FEAT_XIM xim_set_focus(in_focus); *************** *** 5157,5165 **** curwin->w_valid &= ~VALID_CROW; } # endif ! out_flush(); /* make sure output has been written */ ! gui_update_cursor(TRUE, FALSE); ! gui_mch_flush(); } #endif --- 5185,5191 ---- curwin->w_valid &= ~VALID_CROW; } # endif ! out_flush_cursor(TRUE, FALSE); } #endif *************** *** 5516,5524 **** maketitle(); #endif setcursor(); ! out_flush(); ! gui_update_cursor(FALSE, FALSE); ! gui_mch_flush(); } entered = FALSE; --- 5542,5548 ---- maketitle(); #endif setcursor(); ! out_flush_cursor(FALSE, FALSE); } entered = FALSE; *** ../vim-8.0.1448/src/gui_dwrite.cpp 2017-12-14 13:15:12.722867837 +0100 --- src/gui_dwrite.cpp 2018-01-31 20:43:44.623740392 +0100 *************** *** 286,291 **** --- 286,292 ---- ID2D1DCRenderTarget *mRT; ID2D1GdiInteropRenderTarget *mGDIRT; ID2D1SolidColorBrush *mBrush; + ID2D1Bitmap *mBitmap; IDWriteFactory *mDWriteFactory; #ifdef FEAT_DIRECTX_COLOR_EMOJI *************** *** 319,324 **** --- 320,327 ---- void SetFont(HFONT hFont); + void Rebind(); + void BindDC(HDC hdc, const RECT *rect); HRESULT SetDrawingMode(DrawingMode mode); *************** *** 335,340 **** --- 338,345 ---- void SetPixel(int x, int y, COLORREF color); + void Scroll(int x, int y, const RECT *rc); + void Flush(); void SetRenderingParams( *************** *** 596,601 **** --- 601,607 ---- mRT(NULL), mGDIRT(NULL), mBrush(NULL), + mBitmap(NULL), mDWriteFactory(NULL), #ifdef FEAT_DIRECTX_COLOR_EMOJI mDWriteFactory2(NULL), *************** *** 616,624 **** _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, --- 622,627 ---- *************** *** 662,667 **** --- 665,671 ---- #ifdef FEAT_DIRECTX_COLOR_EMOJI SafeRelease(&mDWriteFactory2); #endif + SafeRelease(&mBitmap); SafeRelease(&mBrush); SafeRelease(&mGDIRT); SafeRelease(&mRT); *************** *** 704,716 **** } if (SUCCEEDED(hr)) ! { ! if (mHDC != NULL) ! { ! mRT->BindDC(mHDC, &mBindRect); ! mRT->SetTransform(D2D1::IdentityMatrix()); ! } ! } return hr; } --- 708,714 ---- } if (SUCCEEDED(hr)) ! Rebind(); return hr; } *************** *** 718,723 **** --- 716,722 ---- void DWriteContext::DiscardDeviceResources() { + SafeRelease(&mBitmap); SafeRelease(&mBrush); SafeRelease(&mGDIRT); SafeRelease(&mRT); *************** *** 899,911 **** } void ! DWriteContext::BindDC(HDC hdc, const RECT *rect) { ! Flush(); ! mRT->BindDC(hdc, rect); mRT->SetTransform(D2D1::IdentityMatrix()); mHDC = hdc; mBindRect = *rect; } HRESULT --- 898,933 ---- } 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) + { mHDC = hdc; mBindRect = *rect; + + if (mRT == NULL) + CreateDeviceResources(); + else + { + Flush(); + Rebind(); + } } HRESULT *************** *** 1081,1086 **** --- 1103,1151 ---- } 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,1245 **** --- 1305,1317 ---- } 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) *** ../vim-8.0.1448/src/gui_dwrite.h 2017-12-05 13:22:08.414402079 +0100 --- src/gui_dwrite.h 2018-01-31 20:43:44.623740392 +0100 *************** *** 74,79 **** --- 74,80 ---- 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); *** ../vim-8.0.1448/src/gui_w32.c 2017-12-14 13:15:12.722867837 +0100 --- src/gui_w32.c 2018-01-31 20:43:44.627740333 +0100 *************** *** 36,42 **** 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); --- 36,41 ---- *************** *** 61,67 **** 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; ) --- 60,65 ---- *************** *** 124,130 **** } else if (STRCMP(name, "scrlines") == 0) { ! dx_scrlines = atoi((char *)value); } else return FAIL; --- 122,128 ---- } else if (STRCMP(name, "scrlines") == 0) { ! /* Deprecated. Simply ignore it. */ } else return FAIL; *************** *** 159,165 **** } } s_directx_enabled = dx_enable; - s_directx_scrlines = dx_scrlines; return OK; # else --- 157,162 ---- *************** *** 3129,3137 **** 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); --- 3126,3131 ---- *************** *** 3141,3156 **** #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) #endif { intel_gpu_workaround(); --- 3135,3144 ---- #if defined(FEAT_DIRECTX) if (IS_ENABLE_DIRECTX()) { ! DWriteContext_Scroll(s_dwc, 0, -num_lines * gui.char_height, &rc); ! DWriteContext_Flush(s_dwc); } ! else #endif { intel_gpu_workaround(); *************** *** 3180,3188 **** 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); --- 3168,3173 ---- *************** *** 3192,3207 **** #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) #endif { intel_gpu_workaround(); --- 3177,3186 ---- #if defined(FEAT_DIRECTX) if (IS_ENABLE_DIRECTX()) { ! DWriteContext_Scroll(s_dwc, 0, num_lines * gui.char_height, &rc); ! DWriteContext_Flush(s_dwc); } ! else #endif { intel_gpu_workaround(); *************** *** 4024,4030 **** --- 4003,4012 ---- * 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,4656 **** --- 4633,4639 ---- 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,4664 **** --- 4642,4649 ---- } else _OnScroll(hwnd, hwndCtl, zDelta >= 0 ? SB_PAGEUP : SB_PAGEDOWN, 0); + mch_enable_flush(); + gui_may_flush(); } #ifdef USE_SYSMENU_FONT *** ../vim-8.0.1448/src/macros.h 2017-10-28 21:08:38.983456981 +0200 --- src/macros.h 2018-01-31 20:43:44.627740333 +0100 *************** *** 365,370 **** * 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) --- 365,381 ---- * 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) ! ! /* ! * 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 *** ../vim-8.0.1448/src/main.c 2017-12-18 18:14:43.455768463 +0100 --- src/main.c 2018-01-31 20:43:44.627740333 +0100 *************** *** 1242,1248 **** --- 1242,1252 ---- 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,1293 **** --- 1287,1299 ---- || 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,4222 **** /* 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 return res; } --- 4218,4224 ---- /* A client can tell us to redraw, but not to display the cursor, so do * that here. */ setcursor(); ! out_flush_cursor(FALSE, FALSE); return res; } *** ../vim-8.0.1448/src/message.c 2017-11-18 18:51:08.121770760 +0100 --- src/message.c 2018-01-31 20:43:44.627740333 +0100 *************** *** 2316,2322 **** --- 2316,2324 ---- 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 *)" ")) { *** ../vim-8.0.1448/src/netbeans.c 2017-11-18 22:13:04.745908763 +0100 --- src/netbeans.c 2018-01-31 20:43:44.631740274 +0100 *************** *** 121,134 **** update_screen(CLEAR); setcursor(); cursor_on(); ! out_flush(); ! #ifdef FEAT_GUI ! if (gui.in_use) ! { ! gui_update_cursor(TRUE, FALSE); ! gui_mch_flush(); ! } ! #endif } #define NB_DEF_HOST "localhost" --- 121,127 ---- update_screen(CLEAR); setcursor(); cursor_on(); ! out_flush_cursor(TRUE, FALSE); } #define NB_DEF_HOST "localhost" *************** *** 1848,1861 **** update_screen(VALID); setcursor(); cursor_on(); ! out_flush(); ! #ifdef FEAT_GUI ! if (gui.in_use) ! { ! gui_update_cursor(TRUE, FALSE); ! gui_mch_flush(); ! } ! #endif /* Quit a hit-return or more prompt. */ if (State == HITRETURN || State == ASKMORE) { --- 1841,1848 ---- update_screen(VALID); setcursor(); cursor_on(); ! out_flush_cursor(TRUE, FALSE); ! /* Quit a hit-return or more prompt. */ if (State == HITRETURN || State == ASKMORE) { *************** *** 2248,2261 **** 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 /* Quit a hit-return or more prompt. */ if (State == HITRETURN || State == ASKMORE) { --- 2235,2242 ---- update_screen(NOT_VALID); setcursor(); cursor_on(); ! out_flush_cursor(TRUE, FALSE); ! /* Quit a hit-return or more prompt. */ if (State == HITRETURN || State == ASKMORE) { *************** *** 2307,2321 **** /* 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 } --- 2288,2294 ---- /* ALT_INPUT_LOCK_OFF; */ setcursor(); /* restore the cursor position */ ! out_flush_cursor(TRUE, FALSE); } *************** *** 2569,2582 **** update_screen(CLEAR); setcursor(); cursor_on(); ! out_flush(); ! #ifdef FEAT_GUI ! if (gui.in_use) ! { ! gui_update_cursor(TRUE, FALSE); ! gui_mch_flush(); ! } ! #endif } /* --- 2542,2548 ---- update_screen(CLEAR); setcursor(); cursor_on(); ! out_flush_cursor(TRUE, FALSE); } /* *** ../vim-8.0.1448/src/proto/gui.pro 2017-12-18 18:14:43.451768484 +0100 --- src/proto/gui.pro 2018-01-31 20:43:44.631740274 +0100 *************** *** 25,30 **** --- 25,33 ---- 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); *** ../vim-8.0.1448/src/proto/term.pro 2017-10-15 21:44:40.357078773 +0200 --- src/proto/term.pro 2018-01-31 20:43:44.631740274 +0100 *************** *** 12,17 **** --- 12,18 ---- 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); *** ../vim-8.0.1448/src/screen.c 2017-12-22 21:12:28.415253582 +0100 --- src/screen.c 2018-01-31 20:43:44.631740274 +0100 *************** *** 468,483 **** setcursor(); } cursor_on(); - out_flush(); #ifdef FEAT_GUI ! if (gui.in_use) ! { /* 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(); ! } #endif --redrawing_for_callback; --- 468,481 ---- setcursor(); } cursor_on(); #ifdef FEAT_GUI ! if (gui.in_use && !gui_mch_is_blink_off()) /* Don't update the cursor when it is blinking and off to avoid * flicker. */ ! out_flush_cursor(FALSE, FALSE); ! else ! #else ! out_flush(); #endif --redrawing_for_callback; *************** *** 800,808 **** * done. */ if (gui.in_use) { - out_flush(); /* required before updating the cursor */ if (did_undraw && !gui_mch_is_blink_off()) { /* Put the GUI position where the cursor was, gui_update_cursor() * uses that. */ gui.col = gui_cursor_col; --- 798,809 ---- * done. */ if (gui.in_use) { 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,819 **** --- 812,823 ---- 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,870 **** * done. */ if (gui.in_use) { ! out_flush(); /* required before updating the cursor */ ! gui_update_cursor(FALSE, FALSE); gui_update_scrollbars(FALSE); } # endif --- 867,873 ---- * done. */ if (gui.in_use) { ! out_flush_cursor(FALSE, FALSE); gui_update_scrollbars(FALSE); } # endif *** ../vim-8.0.1448/src/search.c 2017-11-16 22:20:35.028615026 +0100 --- src/search.c 2018-01-31 20:43:44.631740274 +0100 *************** *** 2675,2688 **** 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 /* 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. */ --- 2675,2682 ---- showruler(FALSE); setcursor(); cursor_on(); /* make sure that the cursor is shown */ ! 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. */ *** ../vim-8.0.1448/src/term.c 2017-12-09 15:11:20.387922557 +0100 --- src/term.c 2018-01-31 20:43:44.631740274 +0100 *************** *** 2501,2506 **** --- 2501,2527 ---- } } + /* + * 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(). *** ../vim-8.0.1448/src/ui.c 2017-12-18 18:14:43.455768463 +0100 --- src/ui.c 2018-01-31 20:43:44.631740274 +0100 *************** *** 245,251 **** 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; if (wtime > 0) remaining -= due_time; } --- 245,251 ---- 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 FAIL; if (wtime > 0) remaining -= due_time; } *************** *** 578,588 **** update_curbuf(INVERTED_ALL); setcursor(); cursor_on(); ! out_flush(); ! # ifdef FEAT_GUI ! if (gui.in_use) ! gui_update_cursor(TRUE, FALSE); ! # endif } } #endif --- 578,584 ---- update_curbuf(INVERTED_ALL); setcursor(); cursor_on(); ! out_flush_cursor(TRUE, FALSE); } } #endif *************** *** 3331,3343 **** setcursor(); } cursor_on(); /* redrawing may have switched it off */ ! out_flush(); # ifdef FEAT_GUI if (gui.in_use) - { - gui_update_cursor(FALSE, TRUE); gui_update_scrollbars(FALSE); - } # endif } #ifdef FEAT_TITLE --- 3327,3336 ---- setcursor(); } cursor_on(); /* redrawing may have switched it off */ ! out_flush_cursor(FALSE, TRUE); # ifdef FEAT_GUI if (gui.in_use) gui_update_scrollbars(FALSE); # endif } #ifdef FEAT_TITLE *** ../vim-8.0.1448/src/version.c 2018-01-31 20:15:25.675643331 +0100 --- src/version.c 2018-01-31 20:44:36.502991020 +0100 *************** *** 773,774 **** --- 773,776 ---- { /* Add new patch number below this line */ + /**/ + 1449, /**/ -- They now pass three KNIGHTS impaled to a tree. With their feet off the ground, with one lance through the lot of them, they are skewered up like a barbecue. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///