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