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 if (selection_data
->length
<= 0) return;
95 size_t size
= (size_t) selection_data
->length
;
97 // make sure we got the data in the correct form
98 if (selection_data
->type
!= GDK_SELECTION_TYPE_STRING
) return;
100 clipboard
->m_receivedSize
= size
;
102 clipboard
->m_receivedData
= new char[size
+1];
104 memcpy( clipboard
->m_receivedData
, selection_data
->data
, size
);
107 //-----------------------------------------------------------------------------
109 //-----------------------------------------------------------------------------
112 selection_clear( GtkWidget
*WXUNUSED(widget
), GdkEventSelection
*WXUNUSED(event
) )
114 if (!wxTheClipboard
) return TRUE
;
116 /* the clipboard is no longer in our hands. we can delete the
117 * clipboard data. I hope I got that one right... */
119 wxTheClipboard
->SetData( (wxDataObject
*) NULL
);
124 //-----------------------------------------------------------------------------
125 // selection handler for supplying data
126 //-----------------------------------------------------------------------------
129 selection_handler( GtkWidget
*WXUNUSED(widget
), GtkSelectionData
*selection_data
, gpointer
WXUNUSED(data
) )
131 if (!wxTheClipboard
) return;
133 wxDataObject
*data_object
= wxTheClipboard
->m_data
;
135 if (!data_object
) return;
137 if (data_object
->GetDataSize() == 0) return;
141 gint len
= data_object
->GetDataSize();
142 guchar
*bin_data
= (guchar
*) malloc( len
);
143 data_object
->GetDataHere( (void*)bin_data
);
145 if (selection_data
->target
== GDK_TARGET_STRING
)
147 gtk_selection_data_set(
148 selection_data
, GDK_SELECTION_TYPE_STRING
, 8*sizeof(gchar
), bin_data
, len
);
151 else if (selection_data->target == g_textAtom)
153 gtk_selection_data_set(
154 selection_data, g_textAtom, 8*sizeof(gchar), bin_data, len );
160 //-----------------------------------------------------------------------------
162 //-----------------------------------------------------------------------------
164 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
,wxObject
)
166 wxClipboard::wxClipboard()
168 m_data
= (wxDataObject
*) NULL
;
170 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget
),
171 "selection_clear_event",
172 GTK_SIGNAL_FUNC( selection_clear
),
175 if (!g_clipboardAtom
) g_clipboardAtom
= gdk_atom_intern( "CLIPBOARD", FALSE
);
176 if (!g_textAtom
) g_textAtom
= gdk_atom_intern( "TEXT", FALSE
);
177 if (!g_targetsAtom
) g_targetsAtom
= gdk_atom_intern ("TARGETS", FALSE
);
179 m_receivedData
= (char*)NULL
;
181 m_formatSupported
= FALSE
;
182 m_targetRequested
= 0;
185 wxClipboard::~wxClipboard()
189 if (m_clipboardWidget
) gtk_widget_destroy( m_clipboardWidget
);
192 void wxClipboard::Clear()
194 /* As we have data we also own the clipboard. Once we no longer own
195 it, clear_selection is called which will set m_data to zero */
199 if (gdk_selection_owner_get( g_clipboardAtom
) == m_clipboardWidget
->window
)
201 gtk_selection_owner_set( (GtkWidget
*) NULL
, g_clipboardAtom
, GDK_CURRENT_TIME
);
205 m_data
= (wxDataObject
*) NULL
;
212 delete[] m_receivedData
;
213 m_receivedData
= (char*) NULL
;
216 m_targetRequested
= 0;
218 m_formatSupported
= FALSE
;
221 void wxClipboard::SetData( wxDataObject
*data
)
226 GTK 1.0.X cannot remove a target from a widget so if a widget
227 at first offers text and then a bitmap (and no longer text) to
228 the clipboard, we seem too have to delete it.
231 if (m_clipboardWidget
) gtk_widget_destroy( m_clipboardWidget
);
233 m_clipboardWidget
= gtk_window_new( GTK_WINDOW_POPUP
);
234 gtk_widget_realize( m_clipboardWidget
);
237 if (m_data
) delete m_data
;
241 if (!gtk_selection_owner_set( m_clipboardWidget
,
246 m_data
= (wxDataObject
*) NULL
;
250 switch (m_data
->GetPreferredFormat())
253 gtk_selection_add_handler( m_clipboardWidget
,
265 bool wxClipboard::IsSupportedFormat( wxDataFormat format
)
267 m_targetRequested
= 0;
269 if (format
== wxDF_TEXT
)
271 // m_targetRequested = g_textAtom;
272 m_targetRequested
= GDK_TARGET_STRING
;
275 if (m_targetRequested
== 0) return FALSE
;
277 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget
),
278 "selection_received",
279 GTK_SIGNAL_FUNC( targets_selection_received
),
282 m_formatSupported
= FALSE
;
284 gtk_selection_convert( m_clipboardWidget
,
289 gtk_signal_disconnect_by_func( GTK_OBJECT(m_clipboardWidget
),
290 GTK_SIGNAL_FUNC( targets_selection_received
),
293 if (!m_formatSupported
) return FALSE
;
298 bool wxClipboard::ObtainData( wxDataFormat format
)
304 delete[] m_receivedData
;
305 m_receivedData
= (char*) NULL
;
308 m_targetRequested
= 0;
310 if (format
== wxDF_TEXT
)
312 // m_targetRequested = g_textAtom;
313 m_targetRequested
= GDK_TARGET_STRING
;
316 if (m_targetRequested
== 0) return FALSE
;
318 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget
),
319 "selection_received",
320 GTK_SIGNAL_FUNC( selection_received
),
323 gtk_selection_convert( m_clipboardWidget
,
328 gtk_signal_disconnect_by_func( GTK_OBJECT(m_clipboardWidget
),
329 GTK_SIGNAL_FUNC( selection_received
),
332 if (m_receivedSize
== 0) return FALSE
;
337 size_t wxClipboard::GetDataSize() const
339 return m_receivedSize
;
342 void wxClipboard::GetDataHere( void *data
) const
344 memcpy(data
, m_receivedData
, m_receivedSize
);
347 //-----------------------------------------------------------------------------
349 //-----------------------------------------------------------------------------
351 IMPLEMENT_DYNAMIC_CLASS(wxClipboardModule
,wxModule
)
353 bool wxClipboardModule::OnInit()
355 wxTheClipboard
= new wxClipboard();
360 void wxClipboardModule::OnExit()
362 if (wxTheClipboard
) delete wxTheClipboard
;
363 wxTheClipboard
= (wxClipboard
*) NULL
;