Initialize atoms used in wxGTK wxDataObject on demand

This allows to avoid having to call PrepareFormats() manually which was
not only verbose, but also error-prone as proved by the fact that
wxURLDataObject used wxTextURIListDataObject which used g_fileAtom in
its ctor without calling PrepareFormats() first and meant that this
class didn't work correctly unless some other wxDataObject had been
created before it.
This commit is contained in:
Vadim Zeitlin 2022-12-06 01:44:22 +01:00
parent 5c6fa97d50
commit a577af1ca6
3 changed files with 51 additions and 53 deletions

View file

@ -70,8 +70,6 @@ private:
wxDataFormatId m_type;
NativeFormat m_format;
void PrepareFormats();
};
#endif // _WX_GTK_DATAFORM_H

View file

@ -44,7 +44,8 @@ typedef wxScopedArray<wxDataFormat> wxDataFormatArray;
static GdkAtom g_targetsAtom = nullptr;
static GdkAtom g_timestampAtom = nullptr;
extern GdkAtom g_altTextAtom;
// This is defined in src/gtk/dataobj.cpp.
extern GdkAtom wxGetAltTextAtom();
// the trace mask we use with wxLogTrace() - call
// wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here
@ -304,7 +305,7 @@ selection_handler( GtkWidget *WXUNUSED(widget),
if ( !size )
return;
wxLogTrace(TRACE_CLIPBOARD, "Valid clipboard data found");
wxLogTrace(TRACE_CLIPBOARD, "Valid clipboard data of size %d found", size);
wxCharBuffer buf(size - 1); // it adds 1 internally (for NUL)
@ -337,16 +338,18 @@ void wxClipboard::GTKOnSelectionReceived(const GtkSelectionData& sel)
{
wxCHECK_RET( m_receivedData, wxT("should be inside GetData()") );
const wxDataFormat format(gtk_selection_data_get_target(const_cast<GtkSelectionData*>(&sel)));
wxLogTrace(TRACE_CLIPBOARD, wxT("Received selection %s"),
format.GetId());
GtkSelectionData* const gsel = const_cast<GtkSelectionData*>(&sel);
const wxDataFormat format(gtk_selection_data_get_target(gsel));
wxLogTrace(TRACE_CLIPBOARD, wxT("Received selection %s, len=%d"),
format.GetId(), gtk_selection_data_get_length(gsel));
if ( !m_receivedData->IsSupportedFormat(format, wxDataObject::Set) )
return;
m_receivedData->SetData(format,
gtk_selection_data_get_length(const_cast<GtkSelectionData*>(&sel)),
gtk_selection_data_get_data(const_cast<GtkSelectionData*>(&sel)));
gtk_selection_data_get_length(gsel),
gtk_selection_data_get_data(gsel));
m_formatSupported = true;
}
@ -688,7 +691,7 @@ bool wxClipboard::IsSupported( const wxDataFormat& format )
if ( format == wxDF_UNICODETEXT )
{
// also with plain STRING format
return DoIsSupported(g_altTextAtom);
return DoIsSupported(wxGetAltTextAtom());
}
return false;

View file

@ -25,14 +25,48 @@
#include "wx/gtk/private.h"
//-------------------------------------------------------------------------
// global data
// module data
//-------------------------------------------------------------------------
GdkAtom g_textAtom = nullptr;
GdkAtom g_altTextAtom = nullptr;
GdkAtom g_pngAtom = nullptr;
GdkAtom g_fileAtom = nullptr;
GdkAtom g_htmlAtom = nullptr;
namespace
{
// Atom initialized on first access.
//
// Note that this is more than just an optimization, as we have to delay
// calling gdk_atom_intern() until after GDK initialization.
class wxGdkAtom
{
public:
// Name is literal, so we don't copy it but just store the pointer.
wxGdkAtom(const char* name) : m_name{name} {}
wxGdkAtom(const wxGdkAtom&) = delete;
wxGdkAtom& operator=(const wxGdkAtom&) = delete;
operator GdkAtom()
{
if ( !m_atom )
m_atom = gdk_atom_intern(m_name, FALSE);
return m_atom;
}
private:
const char* const m_name;
GdkAtom m_atom = nullptr;
};
wxGdkAtom g_textAtom {"UTF8_STRING"};
wxGdkAtom g_altTextAtom {"STRING"};
wxGdkAtom g_pngAtom {"image/png"};
wxGdkAtom g_fileAtom {"text/uri-list"};
wxGdkAtom g_htmlAtom {"text/html"};
} // anonymous namespace
// This is used in src/gtk/clipbrd.cpp
extern GdkAtom wxGetAltTextAtom() { return g_altTextAtom; }
//-------------------------------------------------------------------------
// wxDataFormat
@ -40,40 +74,27 @@ GdkAtom g_htmlAtom = nullptr;
wxDataFormat::wxDataFormat()
{
// do *not* call PrepareFormats() from here for 2 reasons:
//
// 1. we will have time to do it later because some other Set function
// must be called before we really need them
//
// 2. doing so prevents us from declaring global wxDataFormats because
// calling PrepareFormats (and thus gdk_atom_intern) before GDK is
// initialised will result in a crash
m_type = wxDF_INVALID;
m_format = (GdkAtom) nullptr;
}
wxDataFormat::wxDataFormat( wxDataFormatId type )
{
PrepareFormats();
SetType( type );
}
void wxDataFormat::InitFromString( const wxString &id )
{
PrepareFormats();
SetId( id );
}
wxDataFormat::wxDataFormat( NativeFormat format )
{
PrepareFormats();
SetId( format );
}
void wxDataFormat::SetType( wxDataFormatId type )
{
PrepareFormats();
m_type = type;
if (m_type == wxDF_UNICODETEXT)
@ -108,7 +129,6 @@ wxString wxDataFormat::GetId() const
void wxDataFormat::SetId( NativeFormat format )
{
PrepareFormats();
m_format = format;
if (m_format == g_textAtom)
@ -131,33 +151,10 @@ void wxDataFormat::SetId( NativeFormat format )
void wxDataFormat::SetId( const wxString& id )
{
PrepareFormats();
m_type = wxDF_PRIVATE;
m_format = gdk_atom_intern( id.ToAscii(), FALSE );
}
void wxDataFormat::PrepareFormats()
{
// VZ: GNOME included in RedHat 6.1 uses the MIME types below and not the
// atoms STRING and file:ALL as the old code was, but normal X apps
// use STRING for text selection when transferring the data via
// clipboard, for example, so do use STRING for now (GNOME apps will
// probably support STRING as well for compatibility anyhow), but use
// text/uri-list for file dnd because compatibility is not important
// here (with whom?)
if (!g_textAtom)
{
g_textAtom = gdk_atom_intern( "UTF8_STRING", FALSE );
g_altTextAtom = gdk_atom_intern( "STRING", FALSE );
}
if (!g_pngAtom)
g_pngAtom = gdk_atom_intern( "image/png", FALSE );
if (!g_fileAtom)
g_fileAtom = gdk_atom_intern( "text/uri-list", FALSE );
if (!g_htmlAtom)
g_htmlAtom = gdk_atom_intern( "text/html", FALSE );
}
//-------------------------------------------------------------------------
// wxDataObject
//-------------------------------------------------------------------------