>From 823298202face05009808d2f00e2faa711c3882f Mon Sep 17 00:00:00 2001 From: Alan Third Date: Sat, 10 Mar 2018 00:09:09 +0000 Subject: [PATCH v2] Fix frame resize flicker on macOS (bug#30699) * src/nsterm.h (ns_enable_screen_updates): New function. * src/nsterm.m (ns_enable_screen_updates): (ns_disable_screen_updates): New functions. (disable_screen_updates_count): Count of number of times we've called NSDisableScreenUpdates. (x_set_window_size): Disable screen updates when not in a live resize loop. * src/xdisp.c (redisplay_internal): Reenable screen updates when redisplay doesn't complete due to a popup. (unwind_redisplay): Reenable screen updates. --- src/nsterm.h | 3 +++ src/nsterm.m | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/xdisp.c | 16 +++++++++++++++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/nsterm.h b/src/nsterm.h index 8b985930ec..df59a7dbd9 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -1160,6 +1160,9 @@ extern void ns_release_autorelease_pool (void *); extern const char *ns_get_defaults_value (const char *key); extern void ns_init_locale (void); +#ifdef NS_IMPL_COCOA +extern void ns_enable_screen_updates (void); +#endif /* in nsmenu */ extern void update_frame_tool_bar (struct frame *f); diff --git a/src/nsterm.m b/src/nsterm.m index 75e0b837c6..45367dd36f 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -288,6 +288,9 @@ - (NSColor *)colorUsingDefaultColorSpace static BOOL ns_fake_keydown = NO; #ifdef NS_IMPL_COCOA static BOOL ns_menu_bar_is_hidden = NO; + +/* The number of times NSDisableScreenUpdates has been called. */ +static int disable_screen_updates_count = 0; #endif /*static int debug_lock = 0; */ @@ -727,6 +730,40 @@ Free a pool and temporary objects it refers to (callable from C) } +#ifdef NS_IMPL_COCOA +/* Disabling screen updates can be used to make several actions appear + "atomic" to the end user. It seems some actions can still update + the display, though. + + When we re-enable screen updates the number of calls to + NSEnableScreenUpdates should match the number to + NSDisableScreenUpdates. + + We use this to prevent the user seeing a blank frame after it has + been resized. x_set_window_size disables updates and when + redisplay compeltes unwind_redisplay enables them again + (bug#30699). */ + +static void +ns_disable_screen_updates (void) +{ + NSDisableScreenUpdates (); + disable_screen_updates_count++; +} + +void +ns_enable_screen_updates (void) +/* Re-enable screen updates. Called from unwind_redisplay. */ +{ + while (disable_screen_updates_count > 0) + { + NSEnableScreenUpdates (); + disable_screen_updates_count--; + } +} +#endif + + static BOOL ns_menu_bar_should_be_hidden (void) /* True, if the menu bar should be hidden. */ @@ -1877,6 +1914,15 @@ -(void)remove block_input (); +#ifdef NS_IMPL_COCOA + /* To prevent showing the user a blank frame, stop updates being + flushed to the screen until after redisplay has completed. This + breaks live resize (resizing with a mouse), so don't do it if + we're in a live resize loop. */ + if (![view inLiveResize]) + ns_disable_screen_updates (); +#endif + if (pixelwise) { pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); diff --git a/src/xdisp.c b/src/xdisp.c index a97d4db607..4778f532cd 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -13918,7 +13918,15 @@ redisplay_internal (void) #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) if (popup_activated ()) - return; + { +#ifdef NS_IMPL_COCOA + /* On macOS we may have disabled screen updates due to window + resizing. We should re-enable them so the popup can be + displayed. */ + ns_enable_screen_updates (); +#endif + return; + } #endif /* I don't think this happens but let's be paranoid. */ @@ -14722,6 +14730,12 @@ unwind_redisplay (void) { redisplaying_p = false; unblock_buffer_flips (); +#ifdef NS_IMPL_COCOA + /* On macOS we may have disabled screen updates due to window + resizing. When redisplay completes we want to re-enable + them. */ + ns_enable_screen_updates (); +#endif } -- 2.16.1