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