X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/157a8f700278715161c66a418124459a6dc501dc..52147d1c4bb54b904253e388da76747e459157c0:/src/gtk/clipbrd.cpp diff --git a/src/gtk/clipbrd.cpp b/src/gtk/clipbrd.cpp index dc2b4c4782..538a80e7af 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 @@ -74,8 +75,8 @@ public: ~wxClipboardSync() { - while ( ms_clipboard ) - gtk_main_iteration(); + while (ms_clipboard) + wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_CLIPBOARD); } // this method must be called by GTK+ callbacks to indicate that we got the @@ -102,13 +103,13 @@ public: private: static wxClipboard *ms_clipboard; - DECLARE_NO_COPY_CLASS(wxClipboardSync) + wxDECLARE_NO_COPY_CLASS(wxClipboardSync); }; wxClipboard *wxClipboardSync::ms_clipboard = NULL; // ============================================================================ -// clipboard ca;backs implementation +// clipboard callbacks implementation // ============================================================================ //----------------------------------------------------------------------------- @@ -143,14 +144,12 @@ targets_selection_received( GtkWidget *WXUNUSED(widget), } } -#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); 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; @@ -282,7 +281,6 @@ selection_handler( GtkWidget *WXUNUSED(widget), wxDataFormat format( selection_data->target ); -#ifdef __WXDEBUG__ wxLogTrace(TRACE_CLIPBOARD, _T("clipboard data in format %s, GtkSelectionData is target=%s type=%s selection=%s timestamp=%u"), format.GetId().c_str(), @@ -291,7 +289,6 @@ selection_handler( GtkWidget *WXUNUSED(widget), wxString::FromAscii(wxGtkString(gdk_atom_name(selection_data->selection))).c_str(), GPOINTER_TO_UINT( signal_data ) ); -#endif // __WXDEBUG__ if ( !data->IsSupportedFormat( format ) ) return; @@ -344,6 +341,71 @@ void wxClipboard::GTKOnSelectionReceived(const GtkSelectionData& sel) m_formatSupported = true; } +//----------------------------------------------------------------------------- +// asynchronous "selection_received" for targets +//----------------------------------------------------------------------------- + +extern "C" { +static void +async_targets_selection_received( GtkWidget *WXUNUSED(widget), + GtkSelectionData *selection_data, + guint32 WXUNUSED(time), + wxClipboard *clipboard ) +{ + if ( !clipboard ) // Assert? + return; + + if (!clipboard->m_sink) + return; + + wxClipboardEvent *event = new wxClipboardEvent(wxEVT_CLIPBOARD_CHANGED); + event->SetEventObject( clipboard ); + + if ( !selection_data || 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; + if ( type != GDK_SELECTION_TYPE_ATOM ) + { + if ( strcmp(wxGtkString(gdk_atom_name(type)), "TARGETS") != 0 ) + { + wxLogTrace( TRACE_CLIPBOARD, + _T("got unsupported clipboard target") ); + + clipboard->m_sink->QueueEvent( event ); + clipboard->m_sink.Release(); + return; + } + } + + // 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); + wxLogTrace( TRACE_CLIPBOARD, + wxT("Received available formats for clipboard %s"), + clip.GetId().c_str() ); + + // 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 wxDataFormat format(atoms[i]); + + wxLogTrace(TRACE_CLIPBOARD, wxT("\t%s"), format.GetId().c_str()); + + event->AddFormat( format ); + } + + clipboard->m_sink->QueueEvent( event ); + clipboard->m_sink.Release(); +} +} + // ============================================================================ // wxClipboard implementation // ============================================================================ @@ -372,6 +434,13 @@ wxClipboard::wxClipboard() g_signal_connect (m_targetsWidget, "selection_received", G_CALLBACK (targets_selection_received), this); + // we use m_targetsWidgetAsync to query what formats are available asynchronously + m_targetsWidgetAsync = gtk_window_new( GTK_WINDOW_POPUP ); + gtk_widget_realize( m_targetsWidgetAsync ); + + g_signal_connect (m_targetsWidgetAsync, "selection_received", + G_CALLBACK (async_targets_selection_received), this); + // we use m_clipboardWidget to get and to offer data m_clipboardWidget = gtk_window_new( GTK_WINDOW_POPUP ); gtk_widget_realize( m_clipboardWidget ); @@ -448,6 +517,22 @@ 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; +} + bool wxClipboard::DoIsSupported(const wxDataFormat& format) { wxCHECK_MSG( format, false, wxT("invalid clipboard format") );