X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3eef425f9a7387d771c1539bdf5e3f02060eb334..42604e44bec70f5a26cabb26653f7ca1490fb04e:/src/gtk/clipbrd.cpp?ds=sidebyside diff --git a/src/gtk/clipbrd.cpp b/src/gtk/clipbrd.cpp index 24b9da8278..6e02151f4b 100644 --- a/src/gtk/clipbrd.cpp +++ b/src/gtk/clipbrd.cpp @@ -24,18 +24,19 @@ #include "wx/clipbrd.h" #ifndef WX_PRECOMP + #include "wx/app.h" #include "wx/log.h" #include "wx/utils.h" #include "wx/dataobj.h" #endif -#include "wx/ptr_scpd.h" +#include "wx/scopedarray.h" #include "wx/scopeguard.h" +#include "wx/evtloop.h" #include "wx/gtk/private.h" -wxDECLARE_SCOPED_ARRAY(wxDataFormat, wxDataFormatArray) -wxDEFINE_SCOPED_ARRAY(wxDataFormat, wxDataFormatArray) +typedef wxScopedArray wxDataFormatArray; // ---------------------------------------------------------------------------- // data @@ -52,7 +53,7 @@ extern GdkAtom g_altTextAtom; // the trace mask we use with wxLogTrace() - call // wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here // (there will be a *lot* of them!) -#define TRACE_CLIPBOARD _T("clipboard") +#define TRACE_CLIPBOARD wxT("clipboard") // ---------------------------------------------------------------------------- // wxClipboardSync: used to perform clipboard operations synchronously @@ -68,14 +69,19 @@ class wxClipboardSync public: wxClipboardSync(wxClipboard& clipboard) { - wxASSERT_MSG( !ms_clipboard, _T("reentrancy in clipboard code") ); + wxASSERT_MSG( !ms_clipboard, wxT("reentrancy in clipboard code") ); ms_clipboard = &clipboard; } ~wxClipboardSync() { - while ( ms_clipboard ) - gtk_main_iteration(); +#if wxUSE_CONSOLE_EVENTLOOP + // ensure that there is a running event loop: this might not be the + // case if we're called before the main event loop startup + wxEventLoopGuarantor ensureEventLoop; +#endif + while (ms_clipboard) + wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_CLIPBOARD); } // this method must be called by GTK+ callbacks to indicate that we got the @@ -83,7 +89,7 @@ public: static void OnDone(wxClipboard * WXUNUSED_UNLESS_DEBUG(clipboard)) { wxASSERT_MSG( clipboard == ms_clipboard, - _T("got notification for alien clipboard") ); + wxT("got notification for alien clipboard") ); ms_clipboard = NULL; } @@ -102,7 +108,7 @@ public: private: static wxClipboard *ms_clipboard; - DECLARE_NO_COPY_CLASS(wxClipboardSync) + wxDECLARE_NO_COPY_CLASS(wxClipboardSync); }; wxClipboard *wxClipboardSync::ms_clipboard = NULL; @@ -127,34 +133,36 @@ targets_selection_received( GtkWidget *WXUNUSED(widget), wxON_BLOCK_EXIT1(wxClipboardSync::OnDone, clipboard); - if ( !selection_data || selection_data->length <= 0 ) + if (!selection_data) + return; + + const int selection_data_length = gtk_selection_data_get_length(selection_data); + if (selection_data_length <= 0) return; // make sure we got the data in the correct form - GdkAtom type = selection_data->type; + GdkAtom type = gtk_selection_data_get_data_type(selection_data); if ( type != GDK_SELECTION_TYPE_ATOM ) { if ( strcmp(wxGtkString(gdk_atom_name(type)), "TARGETS") != 0 ) { wxLogTrace( TRACE_CLIPBOARD, - _T("got unsupported clipboard target") ); + wxT("got unsupported clipboard target") ); return; } } -#ifdef __WXDEBUG__ // it's not really a format, of course, but we can reuse its GetId() method // to format this atom as string - wxDataFormat clip(selection_data->selection); + wxDataFormat clip(gtk_selection_data_get_selection(selection_data)); wxLogTrace( TRACE_CLIPBOARD, wxT("Received available formats for clipboard %s"), clip.GetId().c_str() ); -#endif // __WXDEBUG__ // the atoms we received, holding a list of targets (= formats) - const GdkAtom * const atoms = (GdkAtom *)selection_data->data; - for ( size_t i = 0; i < selection_data->length/sizeof(GdkAtom); i++ ) + const GdkAtom* const atoms = (GdkAtom*)gtk_selection_data_get_data(selection_data); + for (size_t i = 0; i < selection_data_length / sizeof(GdkAtom); i++) { const wxDataFormat format(atoms[i]); @@ -191,7 +199,7 @@ selection_received( GtkWidget *WXUNUSED(widget), wxON_BLOCK_EXIT1(wxClipboardSync::OnDone, clipboard); - if ( !selection_data || selection_data->length <= 0 ) + if (!selection_data || gtk_selection_data_get_length(selection_data) <= 0) return; clipboard->GTKOnSelectionReceived(*selection_data); @@ -258,7 +266,8 @@ selection_handler( GtkWidget *WXUNUSED(widget), if ( !clipboard ) return; - wxDataObject * const data = clipboard->GTKGetDataObject(); + wxDataObject * const data = clipboard->GTKGetDataObject( + gtk_selection_data_get_selection(selection_data)); if ( !data ) return; @@ -266,7 +275,7 @@ selection_handler( GtkWidget *WXUNUSED(widget), // 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) + if (gtk_selection_data_get_target(selection_data) == g_timestampAtom) { guint timestamp = GPOINTER_TO_UINT (signal_data); gtk_selection_data_set(selection_data, @@ -275,23 +284,21 @@ selection_handler( GtkWidget *WXUNUSED(widget), (guchar*)&(timestamp), sizeof(timestamp)); wxLogTrace(TRACE_CLIPBOARD, - _T("Clipboard TIMESTAMP requested, returning timestamp=%u"), + wxT("Clipboard TIMESTAMP requested, returning timestamp=%u"), timestamp); return; } - wxDataFormat format( selection_data->target ); + wxDataFormat format(gtk_selection_data_get_target(selection_data)); -#ifdef __WXDEBUG__ wxLogTrace(TRACE_CLIPBOARD, - _T("clipboard data in format %s, GtkSelectionData is target=%s type=%s selection=%s timestamp=%u"), + 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(), + wxString::FromAscii(wxGtkString(gdk_atom_name(gtk_selection_data_get_target(selection_data)))).c_str(), + wxString::FromAscii(wxGtkString(gdk_atom_name(gtk_selection_data_get_data_type(selection_data)))).c_str(), + wxString::FromAscii(wxGtkString(gdk_atom_name(gtk_selection_data_get_selection(selection_data)))).c_str(), GPOINTER_TO_UINT( signal_data ) ); -#endif // __WXDEBUG__ if ( !data->IsSupportedFormat( format ) ) return; @@ -331,16 +338,18 @@ selection_handler( GtkWidget *WXUNUSED(widget), void wxClipboard::GTKOnSelectionReceived(const GtkSelectionData& sel) { - wxCHECK_RET( m_receivedData, _T("should be inside GetData()") ); + wxCHECK_RET( m_receivedData, wxT("should be inside GetData()") ); - const wxDataFormat format(sel.target); - wxLogTrace(TRACE_CLIPBOARD, _T("Received selection %s"), + const wxDataFormat format(gtk_selection_data_get_target(const_cast(&sel))); + 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_receivedData->SetData(format, + gtk_selection_data_get_length(const_cast(&sel)), + gtk_selection_data_get_data(const_cast(&sel))); m_formatSupported = true; } @@ -360,41 +369,46 @@ async_targets_selection_received( GtkWidget *WXUNUSED(widget), if (!clipboard->m_sink) return; - + wxClipboardEvent *event = new wxClipboardEvent(wxEVT_CLIPBOARD_CHANGED); - - if ( !selection_data || selection_data->length <= 0 ) + event->SetEventObject( clipboard ); + + int selection_data_length = 0; + if (selection_data) + selection_data_length = gtk_selection_data_get_length(selection_data); + + if (selection_data_length <= 0) { clipboard->m_sink->QueueEvent( event ); + clipboard->m_sink.Release(); return; } // make sure we got the data in the correct form - GdkAtom type = selection_data->type; + GdkAtom type = gtk_selection_data_get_data_type(selection_data); if ( type != GDK_SELECTION_TYPE_ATOM ) { if ( strcmp(wxGtkString(gdk_atom_name(type)), "TARGETS") != 0 ) { wxLogTrace( TRACE_CLIPBOARD, - _T("got unsupported clipboard target") ); + wxT("got unsupported clipboard target") ); clipboard->m_sink->QueueEvent( event ); + clipboard->m_sink.Release(); return; } } -#ifdef __WXDEBUG__ // it's not really a format, of course, but we can reuse its GetId() method // to format this atom as string - wxDataFormat clip(selection_data->selection); + wxDataFormat clip(gtk_selection_data_get_selection(selection_data)); wxLogTrace( TRACE_CLIPBOARD, wxT("Received available formats for clipboard %s"), clip.GetId().c_str() ); -#endif // __WXDEBUG__ // the atoms we received, holding a list of targets (= formats) - const GdkAtom * const atoms = (GdkAtom *)selection_data->data; - for ( size_t i = 0; i < selection_data->length/sizeof(GdkAtom); i++ ) + const GdkAtom* const atoms = (GdkAtom*)gtk_selection_data_get_data(selection_data); + for (size_t i = 0; i < selection_data_length / sizeof(GdkAtom); i++) { const wxDataFormat format(atoms[i]); @@ -402,8 +416,9 @@ async_targets_selection_received( GtkWidget *WXUNUSED(widget), event->AddFormat( format ); } - + clipboard->m_sink->QueueEvent( event ); + clipboard->m_sink.Release(); } } @@ -435,7 +450,7 @@ wxClipboard::wxClipboard() g_signal_connect (m_targetsWidget, "selection_received", G_CALLBACK (targets_selection_received), this); - // we use m_targetsWidgetAsync to query what formats asynchronously + // we use m_targetsWidgetAsync to query what formats are available asynchronously m_targetsWidgetAsync = gtk_window_new( GTK_WINDOW_POPUP ); gtk_widget_realize( m_targetsWidgetAsync ); @@ -482,11 +497,7 @@ GdkAtom wxClipboard::GTKGetClipboardAtom() const void wxClipboard::GTKClearData(Kind kind) { wxDataObject *&data = Data(kind); - if ( data ) - { - delete data; - data = NULL; - } + wxDELETE(data); } bool wxClipboard::SetSelectionOwner(bool set) @@ -500,8 +511,8 @@ bool wxClipboard::SetSelectionOwner(bool set) if ( !rc ) { - wxLogTrace(TRACE_CLIPBOARD, _T("Failed to %sset selection owner"), - set ? _T("") : _T("un")); + wxLogTrace(TRACE_CLIPBOARD, wxT("Failed to %sset selection owner"), + set ? wxT("") : wxT("un")); } return rc; @@ -520,13 +531,17 @@ void wxClipboard::AddSupportedTarget(GdkAtom atom) bool wxClipboard::IsSupportedAsync(wxEvtHandler *sink) { + if (m_sink.get()) + return false; // currently busy, come back later + + wxCHECK_MSG( sink, false, wxT("no sink given") ); + m_sink = sink; - gtk_selection_convert( m_targetsWidgetAsync, GTKGetClipboardAtom(), g_targetsAtom, (guint32) GDK_CURRENT_TIME ); - + return true; } @@ -561,8 +576,10 @@ bool wxClipboard::DoIsSupported(const wxDataFormat& format) void wxClipboard::Clear() { + gtk_selection_clear_targets( m_clipboardWidget, GTKGetClipboardAtom() ); + if ( gdk_selection_owner_get(GTKGetClipboardAtom()) == - m_clipboardWidget->window ) + gtk_widget_get_window(m_clipboardWidget) ) { wxClipboardSync sync(*this); @@ -665,10 +682,11 @@ bool wxClipboard::GetData( wxDataObject& data ) { wxCHECK_MSG( m_open, false, wxT("clipboard not open") ); - // get all supported formats from wxDataObjects - const size_t count = data.GetFormatCount(); + // get all supported formats from wxDataObjects: notice that we are setting + // the object data, so we need them in "Set" direction + const size_t count = data.GetFormatCount(wxDataObject::Set); wxDataFormatArray formats(new wxDataFormat[count]); - data.GetAllFormats(formats.get()); + data.GetAllFormats(formats.get(), wxDataObject::Set); for ( size_t i = 0; i < count; i++ ) { @@ -722,4 +740,27 @@ bool wxClipboard::GetData( wxDataObject& data ) return false; } +wxDataObject* wxClipboard::GTKGetDataObject( GdkAtom atom ) +{ + if ( atom == GDK_NONE ) + return Data(); + + if ( atom == GDK_SELECTION_PRIMARY ) + { + wxLogTrace(TRACE_CLIPBOARD, wxT("Primary selection requested" )); + + return Data( wxClipboard::Primary ); + } + else if ( atom == g_clipboardAtom ) + { + wxLogTrace(TRACE_CLIPBOARD, wxT("Clipboard data requested" )); + + return Data( wxClipboard::Clipboard ); + } + else // some other selection, we're not concerned + { + return (wxDataObject*)NULL; + } +} + #endif // wxUSE_CLIPBOARD