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