]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/dnd.cpp
Added new wxBitmapButton implementation
[wxWidgets.git] / src / gtk / dnd.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: dnd.cpp
3 // Purpose: wxDropTarget class
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "dnd.h"
12 #endif
13
14 #include "wx/dnd.h"
15 #include "wx/window.h"
16 #include "wx/app.h"
17 #include "wx/gdicmn.h"
18 #include <wx/intl.h>
19
20 #include "gdk/gdkprivate.h"
21
22 #include <X11/Xlib.h>
23
24 // ----------------------------------------------------------------------------
25 // global
26 // ----------------------------------------------------------------------------
27
28 extern bool g_blockEventsOnDrag;
29
30
31 #if (GTK_MINOR_VERSION == 1)
32 #if (GTK_MICRO_VERSION >= 3)
33 #define NEW_GTK_DND_CODE
34 #endif
35 #endif
36
37 #ifdef NEW_GTK_DND_CODE
38
39 wxDropTarget::wxDropTarget()
40 {
41 }
42
43 wxDropTarget::~wxDropTarget()
44 {
45 }
46
47 void wxDropTarget::UnregisterWidget( GtkWidget *widget )
48 {
49 if (!widget) return;
50
51 // TODO
52 }
53
54 void wxDropTarget::RegisterWidget( GtkWidget *widget )
55 {
56 if (!widget) return;
57
58 wxString formats;
59 int valid = 0;
60
61 for ( size_t i = 0; i < GetFormatCount(); i++ )
62 {
63 wxDataFormat df = GetFormat( i );
64 switch (df)
65 {
66 case wxDF_TEXT:
67 if (i > 0) formats += ";";
68 formats += "text/plain";
69 valid++;
70 break;
71 case wxDF_FILENAME:
72 if (i > 0) formats += ";";
73 formats += "file:ALL";
74 valid++;
75 break;
76 default:
77 break;
78 }
79 }
80
81 char *str = WXSTRINGCAST formats;
82
83 // TODO
84 }
85
86 // ----------------------------------------------------------------------------
87 // wxTextDropTarget
88 // ----------------------------------------------------------------------------
89
90 bool wxTextDropTarget::OnDrop( long x, long y, const void *data, size_t WXUNUSED(size) )
91 {
92 OnDropText( x, y, (const char*)data );
93 return TRUE;
94 }
95
96 bool wxTextDropTarget::OnDropText( long x, long y, const char *psz )
97 {
98 printf( "Got dropped text: %s.\n", psz );
99 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
100 return TRUE;
101 }
102
103 size_t wxTextDropTarget::GetFormatCount() const
104 {
105 return 1;
106 }
107
108 wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
109 {
110 return wxDF_TEXT;
111 }
112
113 // ----------------------------------------------------------------------------
114 // wxFileDropTarget
115 // ----------------------------------------------------------------------------
116
117 bool wxFileDropTarget::OnDropFiles( long x, long y, size_t nFiles, const char * const aszFiles[] )
118 {
119 printf( "Got %d dropped files.\n", (int)nFiles );
120 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
121 for (size_t i = 0; i < nFiles; i++)
122 {
123 printf( aszFiles[i] );
124 printf( "\n" );
125 }
126 return TRUE;
127 }
128
129 bool wxFileDropTarget::OnDrop(long x, long y, const void *data, size_t size )
130 {
131 size_t number = 0;
132 char *text = (char*) data;
133 for (size_t i = 0; i < size; i++)
134 if (text[i] == 0) number++;
135
136 if (number == 0) return TRUE;
137
138 char **files = new char*[number];
139
140 text = (char*) data;
141 for (size_t i = 0; i < number; i++)
142 {
143 files[i] = text;
144 int len = strlen( text );
145 text += len+1;
146 }
147
148 bool ret = OnDropFiles( x, y, 1, files );
149
150 free( files );
151
152 return ret;
153 }
154
155 size_t wxFileDropTarget::GetFormatCount() const
156 {
157 return 1;
158 }
159
160 wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
161 {
162 return wxDF_FILENAME;
163 }
164
165 //-------------------------------------------------------------------------
166 // wxDropSource
167 //-------------------------------------------------------------------------
168
169 wxDropSource::wxDropSource( wxWindow *win )
170 {
171 g_blockEventsOnDrag = TRUE;
172
173 m_window = win;
174 m_widget = win->m_widget;
175 if (win->m_wxwindow) m_widget = win->m_wxwindow;
176
177 m_data = (wxDataObject *) NULL;
178 m_retValue = wxDragCancel;
179
180 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
181 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
182 }
183
184 wxDropSource::wxDropSource( wxDataObject &data, wxWindow *win )
185 {
186 g_blockEventsOnDrag = TRUE;
187
188 m_window = win;
189 m_widget = win->m_widget;
190 if (win->m_wxwindow) m_widget = win->m_wxwindow;
191 m_retValue = wxDragCancel;
192
193 m_data = &data;
194
195 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
196 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
197 }
198
199 void wxDropSource::SetData( wxDataObject &data )
200 {
201 m_data = &data;
202 }
203
204 wxDropSource::~wxDropSource(void)
205 {
206 // if (m_data) delete m_data;
207
208 g_blockEventsOnDrag = FALSE;
209 }
210
211 wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
212 {
213 wxASSERT_MSG( m_data, "wxDragSource: no data" );
214
215 if (!m_data) return (wxDragResult) wxDragNone;
216 if (m_data->GetDataSize() == 0) return (wxDragResult) wxDragNone;
217
218 RegisterWindow();
219
220 // TODO
221
222 UnregisterWindow();
223
224 g_blockEventsOnDrag = FALSE;
225
226 return m_retValue;
227 }
228
229 void wxDropSource::RegisterWindow(void)
230 {
231 if (!m_data) return;
232
233 wxString formats;
234
235 wxDataFormat df = m_data->GetPreferredFormat();
236
237 switch (df)
238 {
239 case wxDF_TEXT:
240 formats += "text/plain";
241 break;
242 case wxDF_FILENAME:
243 formats += "file:ALL";
244 break;
245 default:
246 break;
247 }
248
249 char *str = WXSTRINGCAST formats;
250
251 // TODO
252 }
253
254 void wxDropSource::UnregisterWindow(void)
255 {
256 if (!m_widget) return;
257
258 // TODO
259 }
260
261 #else
262
263 // ----------------------------------------------------------------------------
264 // wxDropTarget
265 // ----------------------------------------------------------------------------
266
267 wxDropTarget::wxDropTarget()
268 {
269 }
270
271 wxDropTarget::~wxDropTarget()
272 {
273 }
274
275 void wxDropTarget::UnregisterWidget( GtkWidget *widget )
276 {
277 if (!widget) return;
278
279 gtk_widget_dnd_drop_set( widget, FALSE, (gchar **) NULL, 0, FALSE );
280 }
281
282 void wxDropTarget::RegisterWidget( GtkWidget *widget )
283 {
284 wxString formats;
285 int valid = 0;
286
287 for ( size_t i = 0; i < GetFormatCount(); i++ )
288 {
289 wxDataFormat df = GetFormat( i );
290 switch (df)
291 {
292 case wxDF_TEXT:
293 if (i > 0) formats += ";";
294 formats += "text/plain";
295 valid++;
296 break;
297 case wxDF_FILENAME:
298 if (i > 0) formats += ";";
299 formats += "file:ALL";
300 valid++;
301 break;
302 default:
303 break;
304 }
305 }
306
307 char *str = WXSTRINGCAST formats;
308
309 gtk_widget_dnd_drop_set( widget, TRUE, &str, valid, FALSE );
310 }
311
312 // ----------------------------------------------------------------------------
313 // wxTextDropTarget
314 // ----------------------------------------------------------------------------
315
316 bool wxTextDropTarget::OnDrop( long x, long y, const void *data, size_t WXUNUSED(size) )
317 {
318 OnDropText( x, y, (const char*)data );
319 return TRUE;
320 }
321
322 bool wxTextDropTarget::OnDropText( long x, long y, const char *psz )
323 {
324 printf( "Got dropped text: %s.\n", psz );
325 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
326 return TRUE;
327 }
328
329 size_t wxTextDropTarget::GetFormatCount() const
330 {
331 return 1;
332 }
333
334 wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
335 {
336 return wxDF_TEXT;
337 }
338
339 // ----------------------------------------------------------------------------
340 // wxFileDropTarget
341 // ----------------------------------------------------------------------------
342
343 bool wxFileDropTarget::OnDropFiles( long x, long y, size_t nFiles, const char * const aszFiles[] )
344 {
345 printf( "Got %d dropped files.\n", (int)nFiles );
346 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
347 for (size_t i = 0; i < nFiles; i++)
348 {
349 printf( aszFiles[i] );
350 printf( "\n" );
351 }
352 return TRUE;
353 }
354
355 bool wxFileDropTarget::OnDrop(long x, long y, const void *data, size_t size )
356 {
357 size_t number = 0;
358 char *text = (char*) data;
359 for (size_t i = 0; i < size; i++)
360 if (text[i] == 0) number++;
361
362 if (number == 0) return TRUE;
363
364 char **files = new char*[number];
365
366 text = (char*) data;
367 for (size_t i = 0; i < number; i++)
368 {
369 files[i] = text;
370 int len = strlen( text );
371 text += len+1;
372 }
373
374 bool ret = OnDropFiles( x, y, 1, files );
375
376 free( files );
377
378 return ret;
379 }
380
381 size_t wxFileDropTarget::GetFormatCount() const
382 {
383 return 1;
384 }
385
386 wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
387 {
388 return wxDF_FILENAME;
389 }
390
391 //-------------------------------------------------------------------------
392 // wxDropSource
393 //-------------------------------------------------------------------------
394
395 //-----------------------------------------------------------------------------
396 // drag request
397
398 void gtk_drag_callback( GtkWidget *widget, GdkEvent *event, wxDropSource *source )
399 {
400 printf( "Data requested for dropping.\n" );
401
402 wxDataObject *data = source->m_data;
403
404 size_t size = data->GetDataSize();
405 char *ptr = new char[size];
406 data->GetDataHere( ptr );
407
408 gtk_widget_dnd_data_set( widget, event, ptr, size );
409
410 delete ptr;
411
412 source->m_retValue = wxDragCopy;
413 }
414
415 wxDropSource::wxDropSource( wxWindow *win )
416 {
417 g_blockEventsOnDrag = TRUE;
418
419 m_window = win;
420 m_widget = win->m_widget;
421 if (win->m_wxwindow) m_widget = win->m_wxwindow;
422
423 m_data = (wxDataObject *) NULL;
424 m_retValue = wxDragCancel;
425
426 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
427 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
428 }
429
430 wxDropSource::wxDropSource( wxDataObject &data, wxWindow *win )
431 {
432 g_blockEventsOnDrag = TRUE;
433
434 m_window = win;
435 m_widget = win->m_widget;
436 if (win->m_wxwindow) m_widget = win->m_wxwindow;
437 m_retValue = wxDragCancel;
438
439 m_data = &data;
440
441 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
442 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
443 }
444
445 void wxDropSource::SetData( wxDataObject &data )
446 {
447 m_data = &data;
448 }
449
450 wxDropSource::~wxDropSource(void)
451 {
452 // if (m_data) delete m_data;
453
454 g_blockEventsOnDrag = FALSE;
455 }
456
457 wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
458 {
459 if (gdk_dnd.dnd_grabbed) return (wxDragResult) wxDragNone;
460 if (gdk_dnd.drag_really) return (wxDragResult) wxDragNone;
461
462 wxASSERT_MSG( m_data, "wxDragSource: no data" );
463
464 if (!m_data) return (wxDragResult) wxDragNone;
465 if (m_data->GetDataSize() == 0) return (wxDragResult) wxDragNone;
466
467 GdkWindowPrivate *wp = (GdkWindowPrivate*) m_widget->window;
468
469 RegisterWindow();
470
471 gdk_dnd.drag_perhaps = TRUE;
472
473 gdk_dnd.dnd_drag_start.x = 5;
474 gdk_dnd.dnd_drag_start.y = 5;
475 gdk_dnd.real_sw = wp;
476
477 if (gdk_dnd.drag_startwindows)
478 {
479 g_free( gdk_dnd.drag_startwindows );
480 gdk_dnd.drag_startwindows = (GdkWindow **) NULL;
481 }
482 gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
483
484 XWindowAttributes dnd_winattr;
485 XGetWindowAttributes( gdk_display, wp->xwindow, &dnd_winattr );
486 wp->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
487
488 gdk_dnd_drag_addwindow( m_widget->window );
489
490 GdkEventDragBegin ev;
491 ev.type = GDK_DRAG_BEGIN;
492 ev.window = m_widget->window;
493 ev.u.allflags = 0;
494 ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
495
496 gdk_event_put( (GdkEvent*)&ev );
497
498 XGrabPointer( gdk_display, wp->xwindow, False,
499 ButtonMotionMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
500 GrabModeAsync, GrabModeAsync, gdk_root_window, None, CurrentTime );
501
502 gdk_dnd_set_drag_cursors( m_defaultCursor.GetCursor(), m_goaheadCursor.GetCursor() );
503
504 gdk_dnd.dnd_grabbed = TRUE;
505 gdk_dnd.drag_really = 1;
506
507 int x = 0;
508 int y = 0;
509 gdk_window_get_pointer( m_widget->window, &x, &y, (GdkModifierType *) NULL );
510
511 gdk_dnd_display_drag_cursor( x, y, FALSE, TRUE );
512
513 while (gdk_dnd.drag_really || gdk_dnd.drag_perhaps) wxYield();
514
515 UnregisterWindow();
516
517 g_blockEventsOnDrag = FALSE;
518
519 return m_retValue;
520 }
521
522 void wxDropSource::RegisterWindow(void)
523 {
524 if (!m_data) return;
525
526 wxString formats;
527
528 wxDataFormat df = m_data->GetPreferredFormat();
529
530 switch (df)
531 {
532 case wxDF_TEXT:
533 formats += "text/plain";
534 break;
535 case wxDF_FILENAME:
536 formats += "file:ALL";
537 break;
538 default:
539 break;
540 }
541
542 char *str = WXSTRINGCAST formats;
543
544 gtk_widget_dnd_drag_set( m_widget, TRUE, &str, 1 );
545
546 gtk_signal_connect( GTK_OBJECT(m_widget), "drag_request_event",
547 GTK_SIGNAL_FUNC(gtk_drag_callback), (gpointer)this );
548 }
549
550 void wxDropSource::UnregisterWindow(void)
551 {
552 if (!m_widget) return;
553
554 gtk_widget_dnd_drag_set( m_widget, FALSE, (gchar **) NULL, 0 );
555
556 gtk_signal_disconnect_by_data( GTK_OBJECT(m_widget), (gpointer)this );
557 }
558
559 #endif
560 // NEW_GTK_DND_CODE
561