#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
// 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
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();
+ // 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;
+
+ while (ms_clipboard)
+ wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_CLIPBOARD);
}
// this method must be called by GTK+ callbacks to indicate that we got the
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;
}
private:
static wxClipboard *ms_clipboard;
- DECLARE_NO_COPY_CLASS(wxClipboardSync)
+ wxDECLARE_NO_COPY_CLASS(wxClipboardSync);
};
wxClipboard *wxClipboardSync::ms_clipboard = NULL;
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);
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;
(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 );
-#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(),
GPOINTER_TO_UINT( signal_data )
);
-#endif // __WXDEBUG__
if ( !data->IsSupportedFormat( format ) )
return;
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"),
+ wxLogTrace(TRACE_CLIPBOARD, wxT("Received selection %s"),
format.GetId().c_str());
if ( !m_receivedData->IsSupportedFormat(format) )
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;
}
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);
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;
event->AddFormat( format );
}
-
+
clipboard->m_sink->QueueEvent( event );
+ clipboard->m_sink.Release();
}
}
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 );
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;
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;
}
void wxClipboard::Clear()
{
+ gtk_selection_clear_targets( m_clipboardWidget, GTKGetClipboardAtom() );
+
if ( gdk_selection_owner_get(GTKGetClipboardAtom()) ==
m_clipboardWidget->window )
{
{
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++ )
{