1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "clipbrd.h"
14 #include "wx/clipbrd.h"
16 //-----------------------------------------------------------------------------
18 //-----------------------------------------------------------------------------
20 wxClipboard
*wxTheClipboard
= (wxClipboard
*) NULL
;
22 GdkAtom g_textAtom
= 0;
23 GdkAtom g_clipboardAtom
= 0;
24 GdkAtom g_targetsAtom
= 0;
26 //-----------------------------------------------------------------------------
28 //-----------------------------------------------------------------------------
30 /* The contents of a selection are returned in a GtkSelectionData
31 structure. selection/target identify the request.
32 type specifies the type of the return; if length < 0, and
33 the data should be ignored. This structure has object semantics -
34 no fields should be modified directly, they should not be created
35 directly, and pointers to them should not be stored beyond the duration of
36 a callback. (If the last is changed, we'll need to add reference
39 struct _GtkSelectionData
51 //-----------------------------------------------------------------------------
52 // "selection_received" for targets
53 //-----------------------------------------------------------------------------
56 targets_selection_received( GtkWidget
*WXUNUSED(widget
),
57 GtkSelectionData
*selection_data
,
58 wxClipboard
*clipboard
)
60 if (!wxTheClipboard
) return;
62 if (selection_data
->length
<= 0) return;
64 // make sure we got the data in the correct form
65 if (selection_data
->type
!= GDK_SELECTION_TYPE_ATOM
) return;
67 // the atoms we received, holding a list of targets (= formats)
68 GdkAtom
*atoms
= (GdkAtom
*)selection_data
->data
;
70 for (unsigned int i
=0; i
<selection_data
->length
/sizeof(GdkAtom
); i
++)
72 if (atoms
[i
] == clipboard
->m_targetRequested
)
74 clipboard
->m_formatSupported
= TRUE
;
82 //-----------------------------------------------------------------------------
83 // "selection_received" for the actual data
84 //-----------------------------------------------------------------------------
87 selection_received( GtkWidget
*WXUNUSED(widget
),
88 GtkSelectionData
*selection_data
,
89 wxClipboard
*clipboard
)
91 if (!wxTheClipboard
) return;
93 wxDataObject
*data_object
= clipboard
->m_receivedData
;
95 if (!data_object
) return;
97 if (selection_data
->length
<= 0) return;
99 // make sure we got the data in the correct format
101 if (data_object
->m_formatAtom
!= selection_data
->target
) return;
103 // make sure we got the data in the correct form (selection type).
104 // if so, copy data to target object
106 switch (data_object
->GetFormat())
110 if (selection_data
->type
!= GDK_SELECTION_TYPE_STRING
) return;
112 wxTextDataObject
*text_object
= (wxTextDataObject
*) data_object
;
114 wxString text
= (const char*) selection_data
->data
;
116 text_object
->SetText( text
);
123 if (selection_data
->type
!= GDK_SELECTION_TYPE_BITMAP
) return;
132 if (selection_data
->type
!= GDK_SELECTION_TYPE_STRING
) return;
134 wxPrivateDataObject
*private_object
= (wxPrivateDataObject
*) data_object
;
136 private_object
->SetData( (const char*) selection_data
->data
, (size_t) selection_data
->length
);
147 wxTheClipboard
->m_formatSupported
= TRUE
;
150 //-----------------------------------------------------------------------------
152 //-----------------------------------------------------------------------------
155 selection_clear( GtkWidget
*WXUNUSED(widget
), GdkEventSelection
*WXUNUSED(event
) )
157 if (!wxTheClipboard
) return TRUE
;
159 // the clipboard is no longer in our hands. we have to delete the
162 wxTheClipboard
->m_dataObjects
.Clear();
167 //-----------------------------------------------------------------------------
168 // selection handler for supplying data
169 //-----------------------------------------------------------------------------
172 selection_handler( GtkWidget
*WXUNUSED(widget
), GtkSelectionData
*selection_data
, gpointer
WXUNUSED(data
) )
174 if (!wxTheClipboard
) return;
176 wxNode
*node
= wxTheClipboard
->m_dataObjects
.First();
180 wxDataObject
*data_object
= (wxDataObject
*)node
->Data();
182 if (data_object
->m_formatAtom
!= selection_data
->target
)
188 switch (data_object
->GetFormat())
192 wxTextDataObject
*text_object
= (wxTextDataObject
*) data_object
;
194 wxString text
= text_object
->GetText();
196 char *s
= WXSTRINGCAST text
;
197 int len
= (int) text
.Length();
199 gtk_selection_data_set(
201 GDK_SELECTION_TYPE_STRING
,
211 // wxBitmapDataObject *private_object = (wxBitmapDataObject*) data_object;
213 // how do we do that ?
220 wxPrivateDataObject
*private_object
= (wxPrivateDataObject
*) data_object
;
222 if (private_object
->GetDataSize() == 0) return;
224 gtk_selection_data_set(
226 GDK_SELECTION_TYPE_STRING
,
228 (unsigned char*) private_object
->GetData(),
229 (int) private_object
->GetDataSize() );
240 //-----------------------------------------------------------------------------
242 //-----------------------------------------------------------------------------
244 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
,wxObject
)
246 wxClipboard::wxClipboard()
250 m_dataObjects
.DeleteContents( TRUE
);
252 m_receivedData
= (wxDataObject
*) NULL
;
254 m_clipboardWidget
= gtk_window_new( GTK_WINDOW_POPUP
);
255 gtk_widget_realize( m_clipboardWidget
);
257 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget
),
258 "selection_clear_event",
259 GTK_SIGNAL_FUNC( selection_clear
),
262 if (!g_clipboardAtom
) g_clipboardAtom
= gdk_atom_intern( "CLIPBOARD", FALSE
);
263 if (!g_textAtom
) g_textAtom
= gdk_atom_intern( "TEXT", FALSE
);
264 if (!g_targetsAtom
) g_targetsAtom
= gdk_atom_intern ("TARGETS", FALSE
);
266 m_formatSupported
= FALSE
;
267 m_targetRequested
= 0;
270 wxClipboard::~wxClipboard()
274 if (m_clipboardWidget
) gtk_widget_destroy( m_clipboardWidget
);
277 void wxClipboard::Clear()
279 if (m_dataObjects
.GetCount())
281 /* As we have data we also own the clipboard. Once we no longer own
282 it, clear_selection is called which will set m_data to zero */
284 if (gdk_selection_owner_get( g_clipboardAtom
) == m_clipboardWidget
->window
)
286 gtk_selection_owner_set( (GtkWidget
*) NULL
, g_clipboardAtom
, GDK_CURRENT_TIME
);
289 m_dataObjects
.Clear();
292 m_targetRequested
= 0;
294 m_formatSupported
= FALSE
;
297 bool wxClipboard::Open()
299 wxCHECK_MSG( !m_open
, FALSE
, "clipboard already open" );
306 bool wxClipboard::SetData( wxDataObject
*data
)
308 wxCHECK_MSG( data
, FALSE
, "data is invalid" );
310 wxNode
*node
= m_dataObjects
.First();
314 wxDataObject
*d
= (wxDataObject
*)node
->Data();
316 if (d
->GetFormat() == data
->GetFormat())
318 m_dataObjects
.DeleteNode( node
);
326 m_dataObjects
.Append( data
);
328 wxCHECK_MSG( m_open
, FALSE
, "clipboard not open" );
330 if (data
->GetFormat() == wxDF_PRIVATE
)
332 wxPrivateDataObject
* pd
= (wxPrivateDataObject
*) data
;
334 wxCHECK_MSG( !pd
->GetId().IsEmpty(), FALSE
, "private clipboard format requires ID string" );
336 data
->m_formatAtom
= GetTargetAtom( data
->GetFormat(), pd
->GetId() );
340 data
->m_formatAtom
= GetTargetAtom( data
->GetFormat() );
343 // Add handlers if someone requests data
345 gtk_selection_add_handler( m_clipboardWidget
,
351 // Tell the world we offer clipboard data
353 if (!gtk_selection_owner_set( m_clipboardWidget
,
363 void wxClipboard::Close()
365 wxCHECK_RET( m_open
, "clipboard not open" );
370 bool wxClipboard::IsSupportedFormat( wxDataFormat format
, const wxString
&id
)
372 m_targetRequested
= GetTargetAtom( format
, id
);
374 if (m_targetRequested
== 0) return FALSE
;
376 // add handler for target (= format) query
378 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget
),
379 "selection_received",
380 GTK_SIGNAL_FUNC( targets_selection_received
),
383 m_formatSupported
= FALSE
;
385 // perform query. this will set m_formatSupported to
386 // TRUE if m_targetRequested is supported
388 gtk_selection_convert( m_clipboardWidget
,
393 gtk_signal_disconnect_by_func( GTK_OBJECT(m_clipboardWidget
),
394 GTK_SIGNAL_FUNC( targets_selection_received
),
397 if (!m_formatSupported
) return FALSE
;
402 bool wxClipboard::GetData( wxDataObject
*data
)
404 wxCHECK_MSG( m_open
, FALSE
, "clipboard not open" );
406 m_receivedData
= data
;
408 wxCHECK_MSG( m_receivedData
, FALSE
, "invalid data object" );
410 if (m_receivedData
->GetFormat() == wxDF_PRIVATE
)
412 wxPrivateDataObject
* pd
= (wxPrivateDataObject
*) m_receivedData
;
414 wxCHECK_MSG( !pd
->GetId().IsEmpty(), FALSE
, "private clipboard format requires ID string" );
416 m_targetRequested
= GetTargetAtom( m_receivedData
->GetFormat(), pd
->GetId() );
420 m_targetRequested
= GetTargetAtom( m_receivedData
->GetFormat() );
423 data
->m_formatAtom
= m_targetRequested
;
425 wxCHECK_MSG( m_targetRequested
, FALSE
, "unsupported clipboard format" );
427 m_formatSupported
= FALSE
;
429 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget
),
430 "selection_received",
431 GTK_SIGNAL_FUNC( selection_received
),
434 gtk_selection_convert( m_clipboardWidget
,
439 gtk_signal_disconnect_by_func( GTK_OBJECT(m_clipboardWidget
),
440 GTK_SIGNAL_FUNC( selection_received
),
443 wxCHECK_MSG( m_formatSupported
, FALSE
, "error retrieving data from clipboard" );
448 GdkAtom
wxClipboard::GetTargetAtom( wxDataFormat format
, const wxString
&id
)
450 // What is X representation of that format?
456 return GDK_TARGET_STRING
;
462 return GDK_TARGET_BITMAP
;
468 // we create our own X representation
470 return gdk_atom_intern( WXSTRINGCAST( id
), FALSE
);
482 //-----------------------------------------------------------------------------
484 //-----------------------------------------------------------------------------
486 IMPLEMENT_DYNAMIC_CLASS(wxClipboardModule
,wxModule
)
488 bool wxClipboardModule::OnInit()
490 wxTheClipboard
= new wxClipboard();
495 void wxClipboardModule::OnExit()
497 if (wxTheClipboard
) delete wxTheClipboard
;
498 wxTheClipboard
= (wxClipboard
*) NULL
;