#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<wxDataFormat> wxDataFormatArray;
// ----------------------------------------------------------------------------
// data
~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
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
// ============================================================================
//-----------------------------------------------------------------------------
}
}
-#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;
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(),
wxString::FromAscii(wxGtkString(gdk_atom_name(selection_data->selection))).c_str(),
GPOINTER_TO_UINT( signal_data )
);
-#endif // __WXDEBUG__
if ( !data->IsSupportedFormat( format ) )
return;
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
// ============================================================================
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 );
);
}
+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") );