From e92212874edf6a7b7a8659f66a9e467e3c37f73e Mon Sep 17 00:00:00 2001 From: Mike Gulick Date: Wed, 22 Jul 2020 21:10:05 -0400 Subject: [PATCH] Support duplicate clipboard updates Instead of using the contents of the clipboard to determine if the user has copied any text, use a sequence number that is updated whenever text is copied. Consider the following scenario (as described in #1090): 1. User copies text 'abc' on remote machine via mosh. 2. User copies text 'xyz' on local machine. 3. User copies text 'abc' on remote machine again. The local clipboard will still has 'xyz' because the most recent copy text 'abc' matches the last text copied via mosh, so it does not detect that the user copied new text and does not update the local clipboard. This patch updates detection of newly copied text via a sequence number. This number is an 8-bit unsigned integer that is updated every time new text is copied. This will roll over after 256 clipboard updates, but that is fine as we only care about it being different than the last value. Fixes #1090. Fixes #637. --- src/terminal/terminaldisplay.cc | 2 +- src/terminal/terminalframebuffer.cc | 7 +++++-- src/terminal/terminalframebuffer.h | 11 +++++++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/terminal/terminaldisplay.cc b/src/terminal/terminaldisplay.cc index 7f508efd7..6cb2fd039 100644 --- a/src/terminal/terminaldisplay.cc +++ b/src/terminal/terminaldisplay.cc @@ -111,7 +111,7 @@ std::string Display::new_frame( bool initialized, const Framebuffer &last, const } /* has clipboard changed? */ - if (f.get_clipboard() != frame.last_frame.get_clipboard()) { + if (f.get_clipboard_seqnum() != frame.last_frame.get_clipboard_seqnum()) { frame.append( "\033]52;" ); const title_type &clipboard( f.get_clipboard() ); for ( title_type::const_iterator i = clipboard.begin(); diff --git a/src/terminal/terminalframebuffer.cc b/src/terminal/terminalframebuffer.cc index 2751f3b7d..1b7406d62 100644 --- a/src/terminal/terminalframebuffer.cc +++ b/src/terminal/terminalframebuffer.cc @@ -78,7 +78,8 @@ DrawState::DrawState( int s_width, int s_height ) } Framebuffer::Framebuffer( int s_width, int s_height ) - : rows(), icon_name(), window_title(), clipboard(), bell_count( 0 ), title_initialized( false ), ds( s_width, s_height ) + : rows(), icon_name(), window_title(), clipboard(), bell_count( 0 ), + title_initialized( false ), clipboard_seqnum( 0 ), ds( s_width, s_height ) { assert( s_height > 0 ); assert( s_width > 0 ); @@ -90,7 +91,7 @@ Framebuffer::Framebuffer( int s_width, int s_height ) Framebuffer::Framebuffer( const Framebuffer &other ) : rows( other.rows ), icon_name( other.icon_name ), window_title( other.window_title ), clipboard( other.clipboard ), bell_count( other.bell_count ), - title_initialized( other.title_initialized ), ds( other.ds ) + title_initialized( other.title_initialized ), clipboard_seqnum( other.clipboard_seqnum ), ds( other.ds ) { } @@ -103,6 +104,7 @@ Framebuffer & Framebuffer::operator=( const Framebuffer &other ) clipboard = other.clipboard; bell_count = other.bell_count; title_initialized = other.title_initialized; + clipboard_seqnum = other.clipboard_seqnum; ds = other.ds; } return *this; @@ -384,6 +386,7 @@ void Framebuffer::reset( void ) rows = rows_type( height, newrow() ); window_title.clear(); clipboard.clear(); + clipboard_seqnum = 0; /* do not reset bell_count */ } diff --git a/src/terminal/terminalframebuffer.h b/src/terminal/terminalframebuffer.h index de9386977..91d88e709 100644 --- a/src/terminal/terminalframebuffer.h +++ b/src/terminal/terminalframebuffer.h @@ -382,6 +382,7 @@ namespace Terminal { title_type clipboard; unsigned int bell_count; bool title_initialized; /* true if the window title has been set via an OSC */ + uint8_t clipboard_seqnum; row_pointer newrow( void ) { @@ -452,7 +453,13 @@ namespace Terminal { bool is_title_initialized( void ) const { return title_initialized; } void set_icon_name( const title_type &s ) { icon_name = s; } void set_window_title( const title_type &s ) { window_title = s; } - void set_clipboard( const title_type &s ) { clipboard = s; } + void set_clipboard( const title_type &s ) + { + clipboard = s; + // Rolling over 255 -> 0 is okay + clipboard_seqnum++; + } + uint8_t get_clipboard_seqnum ( void ) const { return clipboard_seqnum; } const title_type & get_icon_name( void ) const { return icon_name; } const title_type & get_window_title( void ) const { return window_title; } const title_type & get_clipboard( void ) const { return clipboard; } @@ -469,7 +476,7 @@ namespace Terminal { bool operator==( const Framebuffer &x ) const { - return ( rows == x.rows ) && ( window_title == x.window_title ) && ( clipboard == x.clipboard ) && ( bell_count == x.bell_count ) && ( ds == x.ds ); + return ( rows == x.rows ) && ( window_title == x.window_title ) && ( clipboard == x.clipboard ) && ( clipboard_seqnum == x.clipboard_seqnum ) && ( bell_count == x.bell_count ) && ( ds == x.ds ); } }; }