]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/clipbrd.cpp
Fix memory leak when a spacer is added, and crash when a window is added before wxSiz...
[wxWidgets.git] / src / gtk1 / clipbrd.cpp
CommitLineData
dc86cb34 1/////////////////////////////////////////////////////////////////////////////
61b04ac6 2// Name: gtk/clipbrd.cpp
dc86cb34
RR
3// Purpose:
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
65571936 7// Licence: wxWindows licence
dc86cb34
RR
8/////////////////////////////////////////////////////////////////////////////
9
14f355c2 10#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
dc86cb34
RR
11#pragma implementation "clipbrd.h"
12#endif
13
14f355c2
VS
14// For compilers that support precompilation, includes "wx.h".
15#include "wx/wxprec.h"
16
dc86cb34
RR
17#include "wx/clipbrd.h"
18
06cfab17 19#if wxUSE_CLIPBOARD
ac57418f 20
e1ee679c 21#include "wx/dataobj.h"
034be888 22#include "wx/utils.h"
b068c4e8 23#include "wx/log.h"
034be888 24
071a2d78
RR
25#include <glib.h>
26#include <gdk/gdk.h>
27#include <gtk/gtk.h>
83624f79 28
b453e1b2
RR
29//-----------------------------------------------------------------------------
30// thread system
31//-----------------------------------------------------------------------------
32
33#if wxUSE_THREADS
b453e1b2
RR
34#endif
35
dc86cb34
RR
36//-----------------------------------------------------------------------------
37// data
38//-----------------------------------------------------------------------------
39
fd0eed64 40GdkAtom g_clipboardAtom = 0;
b527aac5 41GdkAtom g_targetsAtom = 0;
fd0eed64 42
c7d6d883
RR
43#if defined(__WXGTK20__) && wxUSE_UNICODE
44extern GdkAtom g_altTextAtom;
45#endif
46
61b04ac6
VZ
47// the trace mask we use with wxLogTrace() - call
48// wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here
49// (there will be a *lot* of them!)
cbf97a6c 50static const wxChar *TRACE_CLIPBOARD = _T("clipboard");
61b04ac6 51
dc86cb34 52//-----------------------------------------------------------------------------
b527aac5 53// reminder
dc86cb34
RR
54//-----------------------------------------------------------------------------
55
b527aac5 56/* The contents of a selection are returned in a GtkSelectionData
270c23f7 57 structure. selection/target identify the request.
b527aac5
RR
58 type specifies the type of the return; if length < 0, and
59 the data should be ignored. This structure has object semantics -
60 no fields should be modified directly, they should not be created
61 directly, and pointers to them should not be stored beyond the duration of
62 a callback. (If the last is changed, we'll need to add reference
63 counting)
64
65struct _GtkSelectionData
dc86cb34 66{
b527aac5
RR
67 GdkAtom selection;
68 GdkAtom target;
69 GdkAtom type;
61b04ac6 70 gint format;
b527aac5 71 guchar *data;
61b04ac6 72 gint length;
b527aac5
RR
73};
74
75*/
dc86cb34 76
b527aac5
RR
77//-----------------------------------------------------------------------------
78// "selection_received" for targets
79//-----------------------------------------------------------------------------
80
865bb325 81extern "C" {
b527aac5 82static void
270c23f7
VZ
83targets_selection_received( GtkWidget *WXUNUSED(widget),
84 GtkSelectionData *selection_data,
034be888 85 guint32 WXUNUSED(time),
66633398 86 wxClipboard *clipboard )
dc86cb34 87{
270c23f7 88 if ( wxTheClipboard && selection_data->length > 0 )
034be888 89 {
ca11abde 90 // make sure we got the data in the correct form
270c23f7
VZ
91 GdkAtom type = selection_data->type;
92 if ( type != GDK_SELECTION_TYPE_ATOM )
93 {
61b04ac6
VZ
94 if ( strcmp(gdk_atom_name(type), "TARGETS") )
95 {
96 wxLogTrace( TRACE_CLIPBOARD,
97 _T("got unsupported clipboard target") );
98
99 clipboard->m_waiting = FALSE;
100 return;
101 }
270c23f7 102 }
b527aac5 103
61b04ac6 104#ifdef __WXDEBUG__
270c23f7 105 wxDataFormat clip( selection_data->selection );
61b04ac6
VZ
106 wxLogTrace( TRACE_CLIPBOARD,
107 wxT("selection received for targets, clipboard %s"),
108 clip.GetId().c_str() );
109#endif // __WXDEBUG__
270c23f7
VZ
110
111 // the atoms we received, holding a list of targets (= formats)
112 GdkAtom *atoms = (GdkAtom *)selection_data->data;
11e1c70d 113
270c23f7 114 for (unsigned int i=0; i<selection_data->length/sizeof(GdkAtom); i++)
8b53e5a2 115 {
270c23f7
VZ
116 wxDataFormat format( atoms[i] );
117
61b04ac6
VZ
118 wxLogTrace( TRACE_CLIPBOARD,
119 wxT("selection received for targets, format %s"),
120 format.GetId().c_str() );
270c23f7 121
ca11abde
RR
122// printf( "format %s requested %s\n",
123// gdk_atom_name( atoms[i] ),
124// gdk_atom_name( clipboard->m_targetRequested ) );
125
270c23f7
VZ
126 if (format == clipboard->m_targetRequested)
127 {
128 clipboard->m_waiting = FALSE;
129 clipboard->m_formatSupported = TRUE;
130 return;
131 }
8b53e5a2
RR
132 }
133 }
b527aac5 134
034be888 135 clipboard->m_waiting = FALSE;
dc86cb34 136}
865bb325 137}
dc86cb34
RR
138
139//-----------------------------------------------------------------------------
b527aac5 140// "selection_received" for the actual data
dc86cb34
RR
141//-----------------------------------------------------------------------------
142
865bb325 143extern "C" {
270c23f7
VZ
144static void
145selection_received( GtkWidget *WXUNUSED(widget),
146 GtkSelectionData *selection_data,
034be888 147 guint32 WXUNUSED(time),
66633398 148 wxClipboard *clipboard )
dc86cb34 149{
034be888
RR
150 if (!wxTheClipboard)
151 {
152 clipboard->m_waiting = FALSE;
153 return;
154 }
270c23f7 155
8b53e5a2 156 wxDataObject *data_object = clipboard->m_receivedData;
1dd989e1 157
034be888
RR
158 if (!data_object)
159 {
160 clipboard->m_waiting = FALSE;
161 return;
162 }
270c23f7 163
034be888
RR
164 if (selection_data->length <= 0)
165 {
166 clipboard->m_waiting = FALSE;
167 return;
168 }
270c23f7 169
b068c4e8 170 wxDataFormat format( selection_data->target );
270c23f7 171
ca11abde 172 // make sure we got the data in the correct format
b068c4e8 173 if (!data_object->IsSupportedFormat( format ) )
034be888
RR
174 {
175 clipboard->m_waiting = FALSE;
176 return;
177 }
e2acb9ae 178
c7d6d883
RR
179#if 0
180 This seems to cause problems somehow
181 // make sure we got the data in the correct form (selection type).
182 // if so, copy data to target object
e5d6aa22 183 if (selection_data->type != GDK_SELECTION_TYPE_STRING)
8b53e5a2 184 {
e5d6aa22
RR
185 clipboard->m_waiting = FALSE;
186 return;
8b53e5a2 187 }
c7d6d883 188#endif
270c23f7 189
e5d6aa22 190 data_object->SetData( format, (size_t) selection_data->length, (const char*) selection_data->data );
270c23f7 191
8b53e5a2 192 wxTheClipboard->m_formatSupported = TRUE;
034be888 193 clipboard->m_waiting = FALSE;
dc86cb34 194}
865bb325 195}
fd0eed64
RR
196
197//-----------------------------------------------------------------------------
198// "selection_clear"
199//-----------------------------------------------------------------------------
200
865bb325 201extern "C" {
fd0eed64 202static gint
aeeb6a44 203selection_clear_clip( GtkWidget *WXUNUSED(widget), GdkEventSelection *event )
fd0eed64 204{
8b53e5a2 205 if (!wxTheClipboard) return TRUE;
270c23f7 206
aeeb6a44
RR
207 if (event->selection == GDK_SELECTION_PRIMARY)
208 {
209 wxTheClipboard->m_ownsPrimarySelection = FALSE;
210 }
211 else
212 if (event->selection == g_clipboardAtom)
213 {
214 wxTheClipboard->m_ownsClipboard = FALSE;
215 }
216 else
217 {
e5ea3f7a 218 wxTheClipboard->m_waiting = FALSE;
aeeb6a44
RR
219 return FALSE;
220 }
270c23f7 221
aeeb6a44
RR
222 if ((!wxTheClipboard->m_ownsPrimarySelection) &&
223 (!wxTheClipboard->m_ownsClipboard))
224 {
db2d879a 225 /* the clipboard is no longer in our hands. we can the delete clipboard data. */
1dd989e1 226 if (wxTheClipboard->m_data)
66633398 227 {
47cf53ef 228 wxLogTrace(TRACE_CLIPBOARD, wxT("wxClipboard will get cleared" ));
270c23f7 229
66633398
VZ
230 delete wxTheClipboard->m_data;
231 wxTheClipboard->m_data = (wxDataObject*) NULL;
232 }
aeeb6a44 233 }
270c23f7 234
e5ea3f7a 235 wxTheClipboard->m_waiting = FALSE;
8b53e5a2 236 return TRUE;
fd0eed64 237}
865bb325 238}
fd0eed64
RR
239
240//-----------------------------------------------------------------------------
241// selection handler for supplying data
242//-----------------------------------------------------------------------------
243
865bb325 244extern "C" {
fd0eed64 245static void
19d89516
VZ
246selection_handler( GtkWidget *WXUNUSED(widget),
247 GtkSelectionData *selection_data,
248 guint WXUNUSED(info),
249 guint WXUNUSED(time),
250 gpointer WXUNUSED(data) )
fd0eed64 251{
8b53e5a2 252 if (!wxTheClipboard) return;
270c23f7 253
1dd989e1 254 if (!wxTheClipboard->m_data) return;
270c23f7 255
1dd989e1 256 wxDataObject *data = wxTheClipboard->m_data;
270c23f7 257
b068c4e8
RR
258 wxDataFormat format( selection_data->target );
259
ebe47451
VS
260#ifdef __WXDEBUG__
261 wxLogTrace(TRACE_CLIPBOARD,
262 _T("clipboard data in format %s, GtkSelectionData is target=%s type=%s selection=%s"),
263 format.GetId().c_str(),
264 wxString::FromAscii(gdk_atom_name(selection_data->target)).c_str(),
265 wxString::FromAscii(gdk_atom_name(selection_data->type)).c_str(),
266 wxString::FromAscii(gdk_atom_name(selection_data->selection)).c_str()
267 );
268#endif
269
b068c4e8 270 if (!data->IsSupportedFormat( format )) return;
270c23f7 271
b068c4e8 272 int size = data->GetDataSize( format );
270c23f7 273
1dd989e1 274 if (size == 0) return;
270c23f7 275
33754c4d
VZ
276 void *d = malloc(size);
277
ca11abde 278 // Text data will be in UTF8 in Unicode mode.
33754c4d 279 data->GetDataHere( selection_data->target, d );
270c23f7 280
ebe47451
VS
281#ifdef __WXGTK20__
282 // NB: GTK+ requires special treatment of UTF8_STRING data, the text
283 // would show as UTF-8 data interpreted as latin1 (?) in other
284 // GTK+ apps if we used gtk_selection_data_set()
285 if (format == wxDataFormat(wxDF_UNICODETEXT))
286 {
287 gtk_selection_data_set_text(
288 selection_data,
289 (const gchar*)d,
290 size);
291 }
292 else
293#endif
294 {
295 gtk_selection_data_set(
296 selection_data,
297 GDK_SELECTION_TYPE_STRING,
298 8*sizeof(gchar),
299 (unsigned char*) d,
300 size );
301 }
33754c4d
VZ
302
303 free(d);
fd0eed64 304}
865bb325 305}
dc86cb34
RR
306
307//-----------------------------------------------------------------------------
308// wxClipboard
309//-----------------------------------------------------------------------------
310
311IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
312
313wxClipboard::wxClipboard()
314{
8b53e5a2 315 m_open = FALSE;
3fc93ebd 316 m_waiting = FALSE;
8b53e5a2 317
aeeb6a44
RR
318 m_ownsClipboard = FALSE;
319 m_ownsPrimarySelection = FALSE;
320
1dd989e1 321 m_data = (wxDataObject*) NULL;
8b53e5a2 322 m_receivedData = (wxDataObject*) NULL;
99c67c77 323
034be888 324 /* we use m_targetsWidget to query what formats are available */
270c23f7 325
034be888
RR
326 m_targetsWidget = gtk_window_new( GTK_WINDOW_POPUP );
327 gtk_widget_realize( m_targetsWidget );
328
270c23f7 329 gtk_signal_connect( GTK_OBJECT(m_targetsWidget),
034be888 330 "selection_received",
270c23f7 331 GTK_SIGNAL_FUNC( targets_selection_received ),
66633398 332 (gpointer) this );
270c23f7 333
034be888 334 /* we use m_clipboardWidget to get and to offer data */
270c23f7 335
8b53e5a2
RR
336 m_clipboardWidget = gtk_window_new( GTK_WINDOW_POPUP );
337 gtk_widget_realize( m_clipboardWidget );
338
270c23f7 339 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
034be888 340 "selection_received",
270c23f7 341 GTK_SIGNAL_FUNC( selection_received ),
66633398 342 (gpointer) this );
034be888 343
270c23f7 344 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
8b53e5a2 345 "selection_clear_event",
270c23f7 346 GTK_SIGNAL_FUNC( selection_clear_clip ),
66633398 347 (gpointer) NULL );
270c23f7 348
8b53e5a2 349 if (!g_clipboardAtom) g_clipboardAtom = gdk_atom_intern( "CLIPBOARD", FALSE );
8b53e5a2 350 if (!g_targetsAtom) g_targetsAtom = gdk_atom_intern ("TARGETS", FALSE);
270c23f7 351
8b53e5a2
RR
352 m_formatSupported = FALSE;
353 m_targetRequested = 0;
270c23f7 354
7e2c43b8 355 m_usePrimary = FALSE;
dc86cb34
RR
356}
357
358wxClipboard::~wxClipboard()
b527aac5 359{
270c23f7
VZ
360 Clear();
361
8b53e5a2 362 if (m_clipboardWidget) gtk_widget_destroy( m_clipboardWidget );
034be888 363 if (m_targetsWidget) gtk_widget_destroy( m_targetsWidget );
b527aac5
RR
364}
365
366void wxClipboard::Clear()
dc86cb34 367{
1dd989e1
RR
368 if (m_data)
369 {
b453e1b2
RR
370#if wxUSE_THREADS
371 /* disable GUI threads */
b453e1b2 372#endif
270c23f7 373
ca11abde
RR
374 // As we have data we also own the clipboard. Once we no longer own
375 // it, clear_selection is called which will set m_data to zero
aeeb6a44 376 if (gdk_selection_owner_get( g_clipboardAtom ) == m_clipboardWidget->window)
8b53e5a2 377 {
e5ea3f7a 378 m_waiting = TRUE;
270c23f7 379
b02da6b1
VZ
380 gtk_selection_owner_set( (GtkWidget*) NULL, g_clipboardAtom,
381 (guint32) GDK_CURRENT_TIME );
270c23f7 382
e5ea3f7a 383 while (m_waiting) gtk_main_iteration();
8b53e5a2 384 }
270c23f7 385
aeeb6a44
RR
386 if (gdk_selection_owner_get( GDK_SELECTION_PRIMARY ) == m_clipboardWidget->window)
387 {
e5ea3f7a 388 m_waiting = TRUE;
270c23f7 389
b02da6b1
VZ
390 gtk_selection_owner_set( (GtkWidget*) NULL, GDK_SELECTION_PRIMARY,
391 (guint32) GDK_CURRENT_TIME );
270c23f7 392
e5ea3f7a 393 while (m_waiting) gtk_main_iteration();
aeeb6a44 394 }
270c23f7 395
1dd989e1 396 if (m_data)
270c23f7 397 {
66633398
VZ
398 delete m_data;
399 m_data = (wxDataObject*) NULL;
400 }
270c23f7 401
b453e1b2
RR
402#if wxUSE_THREADS
403 /* re-enable GUI threads */
b453e1b2 404#endif
8b53e5a2 405 }
270c23f7 406
8b53e5a2 407 m_targetRequested = 0;
8b53e5a2
RR
408 m_formatSupported = FALSE;
409}
410
411bool wxClipboard::Open()
412{
223d09f6 413 wxCHECK_MSG( !m_open, FALSE, wxT("clipboard already open") );
270c23f7 414
8b53e5a2 415 m_open = TRUE;
270c23f7 416
8b53e5a2 417 return TRUE;
dc86cb34
RR
418}
419
75ce0581 420bool wxClipboard::SetData( wxDataObject *data )
dc86cb34 421{
223d09f6 422 wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
270c23f7 423
223d09f6 424 wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
270c23f7 425
0d2a2b60 426 Clear();
75ce0581
RR
427
428 return AddData( data );
429}
430
431bool wxClipboard::AddData( wxDataObject *data )
432{
223d09f6 433 wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
270c23f7 434
223d09f6 435 wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
270c23f7 436
ca11abde 437 // we can only store one wxDataObject
1dd989e1 438 Clear();
270c23f7 439
1dd989e1
RR
440 m_data = data;
441
ca11abde 442 // get formats from wxDataObjects
b068c4e8
RR
443 wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ];
444 m_data->GetAllFormats( array );
11e1c70d 445
ca11abde 446 // primary selection or clipboard
11e1c70d
RR
447 GdkAtom clipboard = m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
448 : g_clipboardAtom;
449
270c23f7 450
b068c4e8
RR
451 for (size_t i = 0; i < m_data->GetFormatCount(); i++)
452 {
61b04ac6
VZ
453 wxLogTrace( TRACE_CLIPBOARD,
454 wxT("wxClipboard now supports atom %s"),
455 array[i].GetId().c_str() );
11e1c70d 456
ca11abde
RR
457// printf( "added %s\n",
458// gdk_atom_name( array[i].GetFormatId() ) );
459
11e1c70d 460 gtk_selection_add_target( GTK_WIDGET(m_clipboardWidget),
270c23f7
VZ
461 clipboard,
462 array[i],
11e1c70d 463 0 ); /* what is info ? */
b068c4e8
RR
464 }
465
466 delete[] array;
270c23f7
VZ
467
468 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
d345e841 469 "selection_get",
270c23f7 470 GTK_SIGNAL_FUNC(selection_handler),
66633398 471 (gpointer) NULL );
d345e841 472
b453e1b2 473#if wxUSE_THREADS
11e1c70d 474 /* disable GUI threads */
b453e1b2 475#endif
270c23f7 476
75ce0581 477 /* Tell the world we offer clipboard data */
11e1c70d
RR
478 bool res = (gtk_selection_owner_set( m_clipboardWidget,
479 clipboard,
b02da6b1 480 (guint32) GDK_CURRENT_TIME ));
270c23f7 481
11e1c70d
RR
482 if (m_usePrimary)
483 m_ownsPrimarySelection = res;
484 else
485 m_ownsClipboard = res;
270c23f7 486
b453e1b2
RR
487#if wxUSE_THREADS
488 /* re-enable GUI threads */
b453e1b2 489#endif
270c23f7 490
11e1c70d 491 return res;
8b53e5a2 492}
db1b4961 493
8b53e5a2
RR
494void wxClipboard::Close()
495{
223d09f6 496 wxCHECK_RET( m_open, wxT("clipboard not open") );
270c23f7 497
8b53e5a2 498 m_open = FALSE;
dc86cb34
RR
499}
500
f536e0f2
VZ
501bool wxClipboard::IsOpened() const
502{
503 return m_open;
504}
505
e1ee679c 506bool wxClipboard::IsSupported( const wxDataFormat& format )
b527aac5 507{
e5d6aa22 508 /* reentrance problems */
eff869aa 509 if (m_waiting) return FALSE;
270c23f7 510
e5d6aa22 511 /* store requested format to be asked for by callbacks */
1dd989e1 512 m_targetRequested = format;
270c23f7 513
61b04ac6
VZ
514 wxLogTrace( TRACE_CLIPBOARD,
515 wxT("wxClipboard:IsSupported: requested format: %s"),
516 format.GetId().c_str() );
eff869aa 517
223d09f6 518 wxCHECK_MSG( m_targetRequested, FALSE, wxT("invalid clipboard format") );
270c23f7 519
8b53e5a2 520 m_formatSupported = FALSE;
270c23f7
VZ
521
522 /* perform query. this will set m_formatSupported to
034be888 523 TRUE if m_targetRequested is supported.
270c23f7 524 also, we have to wait for the "answer" from the
034be888
RR
525 clipboard owner which is an asynchronous process.
526 therefore we set m_waiting = TRUE here and wait
270c23f7 527 until the callback "targets_selection_received"
034be888
RR
528 sets it to FALSE */
529
530 m_waiting = TRUE;
ca35e608 531
034be888 532 gtk_selection_convert( m_targetsWidget,
66633398 533 m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
270c23f7 534 : g_clipboardAtom,
66633398 535 g_targetsAtom,
b02da6b1 536 (guint32) GDK_CURRENT_TIME );
ca35e608 537
034be888 538 while (m_waiting) gtk_main_iteration();
270c23f7 539
c7d6d883
RR
540#if defined(__WXGTK20__) && wxUSE_UNICODE
541 if (!m_formatSupported && format == wxDataFormat(wxDF_UNICODETEXT))
542 {
543 // Another try with plain STRING format
544 extern GdkAtom g_altTextAtom;
545 return IsSupported(g_altTextAtom);
546 }
547#endif
548
ebe47451 549 return m_formatSupported;
270c23f7
VZ
550}
551
e1ee679c 552bool wxClipboard::GetData( wxDataObject& data )
75ce0581 553{
223d09f6 554 wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
270c23f7 555
b068c4e8
RR
556 /* get formats from wxDataObjects */
557 wxDataFormat *array = new wxDataFormat[ data.GetFormatCount() ];
558 data.GetAllFormats( array );
270c23f7 559
b068c4e8
RR
560 for (size_t i = 0; i < data.GetFormatCount(); i++)
561 {
e5d6aa22 562 wxDataFormat format( array[i] );
270c23f7 563
61b04ac6
VZ
564 wxLogTrace( TRACE_CLIPBOARD,
565 wxT("wxClipboard::GetData: requested format: %s"),
566 format.GetId().c_str() );
270c23f7 567
b068c4e8 568 /* is data supported by clipboard ? */
270c23f7 569
11e1c70d
RR
570 /* store requested format to be asked for by callbacks */
571 m_targetRequested = format;
270c23f7 572
11e1c70d 573 wxCHECK_MSG( m_targetRequested, FALSE, wxT("invalid clipboard format") );
270c23f7 574
11e1c70d 575 m_formatSupported = FALSE;
270c23f7
VZ
576
577 /* perform query. this will set m_formatSupported to
11e1c70d 578 TRUE if m_targetRequested is supported.
270c23f7 579 also, we have to wait for the "answer" from the
11e1c70d
RR
580 clipboard owner which is an asynchronous process.
581 therefore we set m_waiting = TRUE here and wait
270c23f7 582 until the callback "targets_selection_received"
11e1c70d
RR
583 sets it to FALSE */
584
585 m_waiting = TRUE;
586
587 gtk_selection_convert( m_targetsWidget,
588 m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
270c23f7 589 : g_clipboardAtom,
11e1c70d 590 g_targetsAtom,
b02da6b1 591 (guint32) GDK_CURRENT_TIME );
11e1c70d
RR
592
593 while (m_waiting) gtk_main_iteration();
270c23f7 594
11e1c70d 595 if (!m_formatSupported) continue;
270c23f7 596
b068c4e8
RR
597 /* store pointer to data object to be filled up by callbacks */
598 m_receivedData = &data;
270c23f7 599
b068c4e8 600 /* store requested format to be asked for by callbacks */
e5d6aa22 601 m_targetRequested = format;
270c23f7 602
b068c4e8 603 wxCHECK_MSG( m_targetRequested, FALSE, wxT("invalid clipboard format") );
270c23f7 604
b068c4e8
RR
605 /* start query */
606 m_formatSupported = FALSE;
270c23f7
VZ
607
608 /* ask for clipboard contents. this will set
609 m_formatSupported to TRUE if m_targetRequested
b068c4e8 610 is supported.
270c23f7 611 also, we have to wait for the "answer" from the
b068c4e8
RR
612 clipboard owner which is an asynchronous process.
613 therefore we set m_waiting = TRUE here and wait
270c23f7 614 until the callback "targets_selection_received"
b068c4e8
RR
615 sets it to FALSE */
616
617 m_waiting = TRUE;
618
47cf53ef
VZ
619 wxLogTrace( TRACE_CLIPBOARD,
620 wxT("wxClipboard::GetData: format found, start convert") );
270c23f7 621
b068c4e8 622 gtk_selection_convert( m_clipboardWidget,
66633398 623 m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
270c23f7 624 : g_clipboardAtom,
66633398 625 m_targetRequested,
b02da6b1 626 (guint32) GDK_CURRENT_TIME );
270c23f7 627
b068c4e8 628 while (m_waiting) gtk_main_iteration();
b527aac5 629
b068c4e8
RR
630 /* this is a true error as we checked for the presence of such data before */
631 wxCHECK_MSG( m_formatSupported, FALSE, wxT("error retrieving data from clipboard") );
270c23f7 632
66633398 633 /* return success */
b068c4e8
RR
634 delete[] array;
635 return TRUE;
636 }
270c23f7 637
47cf53ef
VZ
638 wxLogTrace( TRACE_CLIPBOARD,
639 wxT("wxClipboard::GetData: format not found") );
270c23f7 640
b068c4e8
RR
641 /* return failure */
642 delete[] array;
643 return FALSE;
b527aac5
RR
644}
645
ac57418f 646#endif
ac57418f
RR
647 // wxUSE_CLIPBOARD
648