- if (!wxTheClipboard) return;
-
- wxDataObject *data_object = wxTheClipboard->m_data;
-
- if (!data_object) return;
-
- if (data_object->GetDataSize() == 0) return;
-
- gint len = data_object->GetDataSize();
- guchar *bin_data = (guchar*) malloc( len );
- data_object->GetDataHere( (void*)bin_data );
-
- if (selection_data->target == GDK_SELECTION_TYPE_STRING)
- {
- gtk_selection_data_set(
- selection_data, GDK_SELECTION_TYPE_STRING, 8*sizeof(gchar), bin_data, len );
- }
- else if (selection_data->target == g_textAtom)
- {
- gtk_selection_data_set(
- selection_data, g_textAtom, 8*sizeof(gchar), bin_data, len );
- }
- free( bin_data );
+ wxClipboard * const clipboard = wxTheClipboard;
+ if ( !clipboard )
+ return;
+
+ wxDataObject * const data = clipboard->GTKGetDataObject();
+ if ( !data )
+ return;
+
+ // ICCCM says that TIMESTAMP is a required atom.
+ // In particular, it satisfies Klipper, which polls
+ // TIMESTAMP to see if the clipboards content has changed.
+ // It shall return the time which was used to set the data.
+ if (selection_data->target == g_timestampAtom)
+ {
+ guint timestamp = GPOINTER_TO_UINT (signal_data);
+ gtk_selection_data_set(selection_data,
+ GDK_SELECTION_TYPE_INTEGER,
+ 32,
+ (guchar*)&(timestamp),
+ sizeof(timestamp));
+ wxLogTrace(TRACE_CLIPBOARD,
+ wxT("Clipboard TIMESTAMP requested, returning timestamp=%u"),
+ timestamp);
+ return;
+ }
+
+ wxDataFormat format( selection_data->target );
+
+ wxLogTrace(TRACE_CLIPBOARD,
+ wxT("clipboard data in format %s, GtkSelectionData is target=%s type=%s selection=%s timestamp=%u"),
+ format.GetId().c_str(),
+ wxString::FromAscii(wxGtkString(gdk_atom_name(selection_data->target))).c_str(),
+ wxString::FromAscii(wxGtkString(gdk_atom_name(selection_data->type))).c_str(),
+ wxString::FromAscii(wxGtkString(gdk_atom_name(selection_data->selection))).c_str(),
+ GPOINTER_TO_UINT( signal_data )
+ );
+
+ if ( !data->IsSupportedFormat( format ) )
+ return;
+
+ int size = data->GetDataSize( format );
+ if ( !size )
+ return;
+
+ wxCharBuffer buf(size - 1); // it adds 1 internally (for NUL)
+
+ // text data must be returned in UTF8 if format is wxDF_UNICODETEXT
+ if ( !data->GetDataHere(format, buf.data()) )
+ return;
+
+ // use UTF8_STRING format if requested in Unicode build but just plain
+ // STRING one in ANSI or if explicitly asked in Unicode
+#if wxUSE_UNICODE
+ if (format == wxDataFormat(wxDF_UNICODETEXT))
+ {
+ gtk_selection_data_set_text(
+ selection_data,
+ (const gchar*)buf.data(),
+ size );
+ }
+ else
+#endif // wxUSE_UNICODE
+ {
+ gtk_selection_data_set(
+ selection_data,
+ GDK_SELECTION_TYPE_STRING,
+ 8*sizeof(gchar),
+ (const guchar*)buf.data(),
+ size );
+ }
+}
+}
+
+void wxClipboard::GTKOnSelectionReceived(const GtkSelectionData& sel)
+{
+ wxCHECK_RET( m_receivedData, wxT("should be inside GetData()") );
+
+ const wxDataFormat format(sel.target);
+ wxLogTrace(TRACE_CLIPBOARD, wxT("Received selection %s"),
+ format.GetId().c_str());
+
+ if ( !m_receivedData->IsSupportedFormat(format) )
+ return;
+
+ m_receivedData->SetData(format, sel.length, sel.data);
+ m_formatSupported = true;