]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/clipbrd.cpp
Fixed caret droppings left when scrolling
[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!)
cbf97a6c 40static const wxChar *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
1dd989e1 398 if (m_data)
270c23f7 399 {
66633398
VZ
400 delete m_data;
401 m_data = (wxDataObject*) NULL;
402 }
270c23f7 403
b453e1b2
RR
404#if wxUSE_THREADS
405 /* re-enable GUI threads */
b453e1b2 406#endif
8b53e5a2 407 }
270c23f7 408
8b53e5a2 409 m_targetRequested = 0;
de6185e2 410 m_formatSupported = false;
8b53e5a2
RR
411}
412
413bool wxClipboard::Open()
414{
de6185e2 415 wxCHECK_MSG( !m_open, false, wxT("clipboard already open") );
270c23f7 416
de6185e2 417 m_open = true;
270c23f7 418
de6185e2 419 return true;
dc86cb34
RR
420}
421
75ce0581 422bool wxClipboard::SetData( wxDataObject *data )
dc86cb34 423{
de6185e2 424 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
270c23f7 425
de6185e2 426 wxCHECK_MSG( data, false, wxT("data is invalid") );
270c23f7 427
0d2a2b60 428 Clear();
75ce0581
RR
429
430 return AddData( data );
431}
432
433bool wxClipboard::AddData( wxDataObject *data )
434{
de6185e2 435 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
270c23f7 436
de6185e2 437 wxCHECK_MSG( data, false, wxT("data is invalid") );
270c23f7 438
ca11abde 439 // we can only store one wxDataObject
1dd989e1 440 Clear();
270c23f7 441
1dd989e1
RR
442 m_data = data;
443
ca11abde 444 // get formats from wxDataObjects
b068c4e8
RR
445 wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ];
446 m_data->GetAllFormats( array );
11e1c70d 447
ca11abde 448 // primary selection or clipboard
11e1c70d
RR
449 GdkAtom clipboard = m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
450 : g_clipboardAtom;
451
d394f0c9
MR
452 // by default provide TIMESTAMP as a target
453 gtk_selection_add_target( GTK_WIDGET(m_clipboardWidget),
454 clipboard,
455 g_timestampAtom,
456 0 );
270c23f7 457
b068c4e8
RR
458 for (size_t i = 0; i < m_data->GetFormatCount(); i++)
459 {
61b04ac6
VZ
460 wxLogTrace( TRACE_CLIPBOARD,
461 wxT("wxClipboard now supports atom %s"),
462 array[i].GetId().c_str() );
11e1c70d 463
3d257b8d 464// printf( "added %s\n",
ca11abde 465// gdk_atom_name( array[i].GetFormatId() ) );
3d257b8d 466
11e1c70d 467 gtk_selection_add_target( GTK_WIDGET(m_clipboardWidget),
270c23f7
VZ
468 clipboard,
469 array[i],
11e1c70d 470 0 ); /* what is info ? */
b068c4e8
RR
471 }
472
473 delete[] array;
270c23f7 474
9fa72bd2 475 g_signal_connect (m_clipboardWidget, "selection_get",
d394f0c9
MR
476 G_CALLBACK (selection_handler),
477 GUINT_TO_POINTER (gtk_get_current_event_time()) );
d345e841 478
b453e1b2 479#if wxUSE_THREADS
11e1c70d 480 /* disable GUI threads */
b453e1b2 481#endif
270c23f7 482
75ce0581 483 /* Tell the world we offer clipboard data */
11e1c70d
RR
484 bool res = (gtk_selection_owner_set( m_clipboardWidget,
485 clipboard,
b02da6b1 486 (guint32) GDK_CURRENT_TIME ));
270c23f7 487
11e1c70d
RR
488 if (m_usePrimary)
489 m_ownsPrimarySelection = res;
490 else
491 m_ownsClipboard = res;
270c23f7 492
b453e1b2
RR
493#if wxUSE_THREADS
494 /* re-enable GUI threads */
b453e1b2 495#endif
270c23f7 496
11e1c70d 497 return res;
8b53e5a2 498}
db1b4961 499
8b53e5a2
RR
500void wxClipboard::Close()
501{
223d09f6 502 wxCHECK_RET( m_open, wxT("clipboard not open") );
270c23f7 503
de6185e2 504 m_open = false;
dc86cb34
RR
505}
506
f536e0f2
VZ
507bool wxClipboard::IsOpened() const
508{
509 return m_open;
510}
511
e1ee679c 512bool wxClipboard::IsSupported( const wxDataFormat& format )
b527aac5 513{
e5d6aa22 514 /* reentrance problems */
de6185e2 515 if (m_waiting) return false;
270c23f7 516
e5d6aa22 517 /* store requested format to be asked for by callbacks */
1dd989e1 518 m_targetRequested = format;
270c23f7 519
61b04ac6
VZ
520 wxLogTrace( TRACE_CLIPBOARD,
521 wxT("wxClipboard:IsSupported: requested format: %s"),
522 format.GetId().c_str() );
eff869aa 523
de6185e2 524 wxCHECK_MSG( m_targetRequested, false, wxT("invalid clipboard format") );
270c23f7 525
de6185e2 526 m_formatSupported = false;
270c23f7
VZ
527
528 /* perform query. this will set m_formatSupported to
de6185e2 529 true if m_targetRequested is supported.
270c23f7 530 also, we have to wait for the "answer" from the
034be888 531 clipboard owner which is an asynchronous process.
de6185e2 532 therefore we set m_waiting = true here and wait
270c23f7 533 until the callback "targets_selection_received"
de6185e2 534 sets it to false */
034be888 535
de6185e2 536 m_waiting = true;
ca35e608 537
034be888 538 gtk_selection_convert( m_targetsWidget,
66633398 539 m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
270c23f7 540 : g_clipboardAtom,
66633398 541 g_targetsAtom,
b02da6b1 542 (guint32) GDK_CURRENT_TIME );
ca35e608 543
034be888 544 while (m_waiting) gtk_main_iteration();
270c23f7 545
5e081315 546#if wxUSE_UNICODE
c7d6d883
RR
547 if (!m_formatSupported && format == wxDataFormat(wxDF_UNICODETEXT))
548 {
549 // Another try with plain STRING format
550 extern GdkAtom g_altTextAtom;
551 return IsSupported(g_altTextAtom);
552 }
553#endif
554
ebe47451 555 return m_formatSupported;
270c23f7
VZ
556}
557
e1ee679c 558bool wxClipboard::GetData( wxDataObject& data )
75ce0581 559{
de6185e2 560 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
270c23f7 561
b068c4e8
RR
562 /* get formats from wxDataObjects */
563 wxDataFormat *array = new wxDataFormat[ data.GetFormatCount() ];
564 data.GetAllFormats( array );
270c23f7 565
b068c4e8
RR
566 for (size_t i = 0; i < data.GetFormatCount(); i++)
567 {
e5d6aa22 568 wxDataFormat format( array[i] );
270c23f7 569
61b04ac6
VZ
570 wxLogTrace( TRACE_CLIPBOARD,
571 wxT("wxClipboard::GetData: requested format: %s"),
572 format.GetId().c_str() );
270c23f7 573
b068c4e8 574 /* is data supported by clipboard ? */
270c23f7 575
11e1c70d
RR
576 /* store requested format to be asked for by callbacks */
577 m_targetRequested = format;
270c23f7 578
de6185e2 579 wxCHECK_MSG( m_targetRequested, false, wxT("invalid clipboard format") );
270c23f7 580
de6185e2 581 m_formatSupported = false;
270c23f7
VZ
582
583 /* perform query. this will set m_formatSupported to
de6185e2 584 true if m_targetRequested is supported.
270c23f7 585 also, we have to wait for the "answer" from the
11e1c70d 586 clipboard owner which is an asynchronous process.
de6185e2 587 therefore we set m_waiting = true here and wait
270c23f7 588 until the callback "targets_selection_received"
de6185e2 589 sets it to false */
11e1c70d 590
de6185e2 591 m_waiting = true;
11e1c70d
RR
592
593 gtk_selection_convert( m_targetsWidget,
594 m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
270c23f7 595 : g_clipboardAtom,
11e1c70d 596 g_targetsAtom,
b02da6b1 597 (guint32) GDK_CURRENT_TIME );
11e1c70d
RR
598
599 while (m_waiting) gtk_main_iteration();
270c23f7 600
11e1c70d 601 if (!m_formatSupported) continue;
270c23f7 602
b068c4e8
RR
603 /* store pointer to data object to be filled up by callbacks */
604 m_receivedData = &data;
270c23f7 605
b068c4e8 606 /* store requested format to be asked for by callbacks */
e5d6aa22 607 m_targetRequested = format;
270c23f7 608
de6185e2 609 wxCHECK_MSG( m_targetRequested, false, wxT("invalid clipboard format") );
270c23f7 610
b068c4e8 611 /* start query */
de6185e2 612 m_formatSupported = false;
270c23f7
VZ
613
614 /* ask for clipboard contents. this will set
de6185e2 615 m_formatSupported to true if m_targetRequested
b068c4e8 616 is supported.
270c23f7 617 also, we have to wait for the "answer" from the
b068c4e8 618 clipboard owner which is an asynchronous process.
de6185e2 619 therefore we set m_waiting = true here and wait
270c23f7 620 until the callback "targets_selection_received"
de6185e2 621 sets it to false */
b068c4e8 622
de6185e2 623 m_waiting = true;
b068c4e8 624
47cf53ef
VZ
625 wxLogTrace( TRACE_CLIPBOARD,
626 wxT("wxClipboard::GetData: format found, start convert") );
270c23f7 627
b068c4e8 628 gtk_selection_convert( m_clipboardWidget,
66633398 629 m_usePrimary ? (GdkAtom)GDK_SELECTION_PRIMARY
270c23f7 630 : g_clipboardAtom,
66633398 631 m_targetRequested,
b02da6b1 632 (guint32) GDK_CURRENT_TIME );
270c23f7 633
b068c4e8 634 while (m_waiting) gtk_main_iteration();
b527aac5 635
b068c4e8 636 /* this is a true error as we checked for the presence of such data before */
de6185e2 637 wxCHECK_MSG( m_formatSupported, false, wxT("error retrieving data from clipboard") );
270c23f7 638
66633398 639 /* return success */
b068c4e8 640 delete[] array;
de6185e2 641 return true;
b068c4e8 642 }
270c23f7 643
47cf53ef
VZ
644 wxLogTrace( TRACE_CLIPBOARD,
645 wxT("wxClipboard::GetData: format not found") );
270c23f7 646
b068c4e8
RR
647 /* return failure */
648 delete[] array;
de6185e2 649 return false;
b527aac5
RR
650}
651
ac57418f 652#endif
ac57418f 653 // wxUSE_CLIPBOARD