Ensure the clipboard contents are stored properly on GTK.

See https://github.com/wxWidgets/wxWidgets/pull/1953
This commit is contained in:
Vadim Zeitlin 2020-07-13 15:33:58 +02:00
commit 69e27acf0d
3 changed files with 31 additions and 9 deletions

View File

@ -53,6 +53,13 @@
} }
@endcode @endcode
@note On GTK, the clipboard behavior can vary depending on the configuration of
the end-user's machine. In order for the clipboard data to persist after
the window closes, a clipboard manager must be installed. Some clipboard
managers will automatically flush the clipboard after each new piece of
data is added, while others will not. The @Flush() function will force
the clipboard manager to flush the data.
@library{wxcore} @library{wxcore}
@category{dnd} @category{dnd}
@ -99,6 +106,10 @@ public:
Currently this method is implemented in MSW and GTK and always returns @false Currently this method is implemented in MSW and GTK and always returns @false
otherwise. otherwise.
@note On GTK, only the non-primary selection can be flushed. Calling this function
when the clipboard is using the primary selection will return @false and not
make any data available after the program exits.
@return @false if the operation is unsuccessful for any reason. @return @false if the operation is unsuccessful for any reason.
*/ */
virtual bool Flush(); virtual bool Flush();

View File

@ -151,7 +151,8 @@ void MyFrame::OnFlush(wxCommandEvent &WXUNUSED(event))
return; return;
} }
if ( !wxTheClipboard->AddData(new wxTextDataObject("Text from wx clipboard sample")) ) wxString clipData = wxString::Format("Text from wx clipboard sample at %s" , wxDateTime::Now().Format());
if ( !wxTheClipboard->AddData(new wxTextDataObject(clipData)) )
{ {
m_textctrl->AppendText("Failed to put text on clipboard.\n"); m_textctrl->AppendText("Failed to put text on clipboard.\n");
return; return;

View File

@ -41,7 +41,6 @@ typedef wxScopedArray<wxDataFormat> wxDataFormatArray;
// data // data
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
static GdkAtom g_clipboardAtom = 0;
static GdkAtom g_targetsAtom = 0; static GdkAtom g_targetsAtom = 0;
static GdkAtom g_timestampAtom = 0; static GdkAtom g_timestampAtom = 0;
@ -231,7 +230,7 @@ selection_clear_clip( GtkWidget *WXUNUSED(widget), GdkEventSelection *event )
kind = wxClipboard::Primary; kind = wxClipboard::Primary;
} }
else if (event->selection == g_clipboardAtom) else if ( event->selection == GDK_SELECTION_CLIPBOARD )
{ {
wxLogTrace(TRACE_CLIPBOARD, wxT("Lost clipboard" )); wxLogTrace(TRACE_CLIPBOARD, wxT("Lost clipboard" ));
@ -306,6 +305,8 @@ selection_handler( GtkWidget *WXUNUSED(widget),
if ( !size ) if ( !size )
return; return;
wxLogTrace(TRACE_CLIPBOARD, "Valid clipboard data found");
wxCharBuffer buf(size - 1); // it adds 1 internally (for NUL) wxCharBuffer buf(size - 1); // it adds 1 internally (for NUL)
// text data must be returned in UTF8 if format is wxDF_UNICODETEXT // text data must be returned in UTF8 if format is wxDF_UNICODETEXT
@ -469,8 +470,6 @@ wxClipboard::wxClipboard()
G_CALLBACK (selection_clear_clip), NULL); G_CALLBACK (selection_clear_clip), NULL);
// initialize atoms we use if not done yet // initialize atoms we use if not done yet
if ( !g_clipboardAtom )
g_clipboardAtom = gdk_atom_intern( "CLIPBOARD", FALSE );
if ( !g_targetsAtom ) if ( !g_targetsAtom )
g_targetsAtom = gdk_atom_intern ("TARGETS", FALSE); g_targetsAtom = gdk_atom_intern ("TARGETS", FALSE);
if ( !g_timestampAtom ) if ( !g_timestampAtom )
@ -492,7 +491,7 @@ wxClipboard::~wxClipboard()
GdkAtom wxClipboard::GTKGetClipboardAtom() const GdkAtom wxClipboard::GTKGetClipboardAtom() const
{ {
return m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY return m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
: g_clipboardAtom; : (GdkAtom)GDK_SELECTION_CLIPBOARD;
} }
void wxClipboard::GTKClearData(Kind kind) void wxClipboard::GTKClearData(Kind kind)
@ -595,8 +594,19 @@ void wxClipboard::Clear()
bool wxClipboard::Flush() bool wxClipboard::Flush()
{ {
gtk_clipboard_store( gtk_clipboard_get( GTKGetClipboardAtom() ) ); // Only store the non-primary clipboard when flushing. The primary clipboard is a scratch-space
return true; // formed using the currently selected text.
if ( !m_usePrimary )
{
GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
gtk_clipboard_set_can_store(clipboard, NULL, 0);
gtk_clipboard_store(clipboard);
return true;
}
return false;
} }
bool wxClipboard::Open() bool wxClipboard::Open()
@ -762,7 +772,7 @@ wxDataObject* wxClipboard::GTKGetDataObject( GdkAtom atom )
return Data( wxClipboard::Primary ); return Data( wxClipboard::Primary );
} }
else if ( atom == g_clipboardAtom ) else if ( atom == GDK_SELECTION_CLIPBOARD )
{ {
wxLogTrace(TRACE_CLIPBOARD, wxT("Clipboard data requested" )); wxLogTrace(TRACE_CLIPBOARD, wxT("Clipboard data requested" ));