]>
Commit | Line | Data |
---|---|---|
c801d85f KB |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Name: dnd.cpp | |
3 | // Purpose: wxDropTarget class | |
4 | // Author: Robert Roebling | |
a81258be | 5 | // Id: $Id$ |
01111366 | 6 | // Copyright: (c) 1998 Robert Roebling |
65571936 | 7 | // Licence: wxWindows licence |
c801d85f KB |
8 | /////////////////////////////////////////////////////////////////////////////// |
9 | ||
14f355c2 | 10 | #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) |
510fc784 | 11 | #pragma implementation "dnd.h" |
c801d85f KB |
12 | #endif |
13 | ||
14f355c2 VS |
14 | // For compilers that support precompilation, includes "wx.h". |
15 | #include "wx/wxprec.h" | |
16 | ||
c801d85f | 17 | #include "wx/dnd.h" |
c0369005 CE |
18 | #include "wx/log.h" |
19 | ||
20 | ||
06cfab17 | 21 | #if wxUSE_DRAG_AND_DROP |
ac57418f | 22 | |
c801d85f KB |
23 | #include "wx/window.h" |
24 | #include "wx/app.h" | |
25 | #include "wx/gdicmn.h" | |
b527aac5 RR |
26 | #include "wx/intl.h" |
27 | #include "wx/utils.h" | |
c801d85f | 28 | |
9e691f46 VZ |
29 | #include "wx/gtk/private.h" |
30 | ||
071a2d78 | 31 | #include <gdk/gdkprivate.h> |
c801d85f | 32 | |
071a2d78 RR |
33 | #include <gtk/gtkdnd.h> |
34 | #include <gtk/gtkselection.h> | |
c801d85f | 35 | |
5549fa65 RR |
36 | //----------------------------------------------------------------------------- |
37 | // idle system | |
38 | //----------------------------------------------------------------------------- | |
39 | ||
40 | extern void wxapp_install_idle_handler(); | |
41 | extern bool g_isIdle; | |
42 | ||
b453e1b2 RR |
43 | //----------------------------------------------------------------------------- |
44 | // thread system | |
45 | //----------------------------------------------------------------------------- | |
46 | ||
47 | #if wxUSE_THREADS | |
b453e1b2 RR |
48 | #endif |
49 | ||
22d5903e RR |
50 | //---------------------------------------------------------------------------- |
51 | // global data | |
52 | //---------------------------------------------------------------------------- | |
c801d85f KB |
53 | |
54 | extern bool g_blockEventsOnDrag; | |
55 | ||
2245b2b2 VZ |
56 | // the flags used for the last DoDragDrop() |
57 | static long gs_flagsForDrag = 0; | |
58 | ||
b2dea2ab VZ |
59 | // the trace mask we use with wxLogTrace() - call |
60 | // wxLog::AddTraceMask(TRACE_DND) to enable the trace messages from here | |
61 | // (there are quite a few of them, so don't enable this by default) | |
62 | static const wxChar *TRACE_DND = _T("dnd"); | |
63 | ||
22d5903e RR |
64 | //---------------------------------------------------------------------------- |
65 | // standard icons | |
66 | //---------------------------------------------------------------------------- | |
67 | ||
13b22a67 | 68 | /* Copyright (c) Julian Smart */ |
90350682 | 69 | static const char * page_xpm[] = { |
13b22a67 JS |
70 | /* columns rows colors chars-per-pixel */ |
71 | "32 32 37 1", | |
72 | "5 c #7198D9", | |
73 | ", c #769CDA", | |
74 | "2 c #DCE6F6", | |
75 | "i c #FFFFFF", | |
76 | "e c #779DDB", | |
77 | ": c #9AB6E4", | |
78 | "9 c #EAF0FA", | |
79 | "- c #B1C7EB", | |
80 | "$ c #6992D7", | |
81 | "y c #F7F9FD", | |
82 | "= c #BED0EE", | |
83 | "q c #F0F5FC", | |
84 | "; c #A8C0E8", | |
85 | "@ c #366BC2", | |
86 | " c None", | |
87 | "u c #FDFEFF", | |
88 | "8 c #5987D3", | |
89 | "* c #C4D5F0", | |
90 | "7 c #7CA0DC", | |
91 | "O c #487BCE", | |
92 | "< c #6B94D7", | |
93 | "& c #CCDAF2", | |
94 | "> c #89A9DF", | |
95 | "3 c #5584D1", | |
96 | "w c #82A5DE", | |
97 | "1 c #3F74CB", | |
98 | "+ c #3A70CA", | |
99 | ". c #3569BF", | |
100 | "% c #D2DFF4", | |
101 | "# c #3366BB", | |
102 | "r c #F5F8FD", | |
103 | "0 c #FAFCFE", | |
104 | "4 c #DFE8F7", | |
105 | "X c #5E8AD4", | |
106 | "o c #5282D0", | |
107 | "t c #B8CCEC", | |
108 | "6 c #E5EDF9", | |
22d5903e | 109 | /* pixels */ |
13b22a67 JS |
110 | " ", |
111 | " ", | |
112 | " ", | |
113 | " ", | |
114 | " ", | |
115 | " .XXXooOO++@# ", | |
116 | " $%&*=-;::>,<1 ", | |
117 | " $2%&*=-;::><:3 ", | |
118 | " $42%&*=-;::<&:3 ", | |
119 | " 56477<<<<8<<9&:X ", | |
120 | " 59642%&*=-;<09&:5 ", | |
121 | " 5q9642%&*=-<<<<<# ", | |
122 | " 5qqw777<<<<<88:>+ ", | |
123 | " erqq9642%&*=t;::+ ", | |
124 | " eyrqq9642%&*=t;:O ", | |
125 | " eyywwww777<<<<t;O ", | |
126 | " e0yyrqq9642%&*=to ", | |
127 | " e00yyrqq9642%&*=o ", | |
128 | " eu0wwwwwww777<&*X ", | |
129 | " euu00yyrqq9642%&X ", | |
130 | " eiuu00yyrqq9642%X ", | |
131 | " eiiwwwwwwwwww742$ ", | |
132 | " eiiiuu00yyrqq964$ ", | |
133 | " eiiiiuu00yyrqq96$ ", | |
134 | " eiiiiiuu00yyrqq95 ", | |
135 | " eiiiiiiuu00yyrqq5 ", | |
136 | " eeeeeeeeeeeeee55e ", | |
137 | " ", | |
138 | " ", | |
139 | " ", | |
140 | " ", | |
141 | " " | |
142 | }; | |
f03fc89f VZ |
143 | |
144 | ||
2245b2b2 VZ |
145 | // ============================================================================ |
146 | // private functions | |
147 | // ============================================================================ | |
148 | ||
149 | // ---------------------------------------------------------------------------- | |
77ffb593 | 150 | // convert between GTK+ and wxWidgets DND constants |
2245b2b2 VZ |
151 | // ---------------------------------------------------------------------------- |
152 | ||
153 | static wxDragResult ConvertFromGTK(long action) | |
154 | { | |
155 | switch ( action ) | |
156 | { | |
157 | case GDK_ACTION_COPY: | |
158 | return wxDragCopy; | |
159 | ||
160 | case GDK_ACTION_LINK: | |
161 | return wxDragLink; | |
162 | ||
163 | case GDK_ACTION_MOVE: | |
164 | return wxDragMove; | |
165 | } | |
166 | ||
167 | return wxDragNone; | |
168 | } | |
4ba47b40 | 169 | |
33a5bc52 RR |
170 | // ---------------------------------------------------------------------------- |
171 | // "drag_leave" | |
172 | // ---------------------------------------------------------------------------- | |
173 | ||
865bb325 | 174 | extern "C" { |
33a5bc52 | 175 | static void target_drag_leave( GtkWidget *WXUNUSED(widget), |
f03fc89f VZ |
176 | GdkDragContext *context, |
177 | guint WXUNUSED(time), | |
178 | wxDropTarget *drop_target ) | |
33a5bc52 | 179 | { |
5549fa65 RR |
180 | if (g_isIdle) wxapp_install_idle_handler(); |
181 | ||
829e3e8d RR |
182 | /* inform the wxDropTarget about the current GdkDragContext. |
183 | this is only valid for the duration of this call */ | |
184 | drop_target->SetDragContext( context ); | |
f03fc89f | 185 | |
829e3e8d RR |
186 | /* we don't need return values. this event is just for |
187 | information */ | |
188 | drop_target->OnLeave(); | |
f03fc89f | 189 | |
829e3e8d RR |
190 | /* this has to be done because GDK has no "drag_enter" event */ |
191 | drop_target->m_firstMotion = TRUE; | |
f03fc89f | 192 | |
829e3e8d RR |
193 | /* after this, invalidate the drop_target's GdkDragContext */ |
194 | drop_target->SetDragContext( (GdkDragContext*) NULL ); | |
33a5bc52 | 195 | } |
865bb325 | 196 | } |
33a5bc52 RR |
197 | |
198 | // ---------------------------------------------------------------------------- | |
199 | // "drag_motion" | |
200 | // ---------------------------------------------------------------------------- | |
201 | ||
865bb325 | 202 | extern "C" { |
33a5bc52 | 203 | static gboolean target_drag_motion( GtkWidget *WXUNUSED(widget), |
f03fc89f VZ |
204 | GdkDragContext *context, |
205 | gint x, | |
206 | gint y, | |
207 | guint time, | |
208 | wxDropTarget *drop_target ) | |
33a5bc52 | 209 | { |
5549fa65 RR |
210 | if (g_isIdle) wxapp_install_idle_handler(); |
211 | ||
829e3e8d RR |
212 | /* Owen Taylor: "if the coordinates not in a drop zone, |
213 | return FALSE, otherwise call gtk_drag_status() and | |
214 | return TRUE" */ | |
f03fc89f | 215 | |
829e3e8d RR |
216 | /* inform the wxDropTarget about the current GdkDragContext. |
217 | this is only valid for the duration of this call */ | |
218 | drop_target->SetDragContext( context ); | |
f03fc89f | 219 | |
2245b2b2 VZ |
220 | // GTK+ always supposes that we want to copy the data by default while we |
221 | // might want to move it, so examine not only suggested_action - which is | |
222 | // only good if we don't have our own preferences - but also the actions | |
223 | // field | |
8ee9d618 | 224 | wxDragResult result; |
917ae499 RR |
225 | if (drop_target->GetDefaultAction() == wxDragNone) |
226 | { | |
227 | // use default action set by wxDropSource::DoDragDrop() | |
2245b2b2 VZ |
228 | if ( (gs_flagsForDrag & wxDrag_DefaultMove) == wxDrag_DefaultMove && |
229 | (context->actions & GDK_ACTION_MOVE ) ) | |
230 | { | |
231 | // move is requested by the program and allowed by GTK+ - do it, even | |
232 | // though suggested_action may be currently wxDragCopy | |
8ee9d618 | 233 | result = wxDragMove; |
2245b2b2 VZ |
234 | } |
235 | else // use whatever GTK+ says we should | |
236 | { | |
237 | result = ConvertFromGTK(context->suggested_action); | |
238 | ||
239 | if ( (result == wxDragMove) && !(gs_flagsForDrag & wxDrag_AllowMove) ) | |
240 | { | |
241 | // we're requested to move but we can't | |
242 | result = wxDragCopy; | |
243 | } | |
244 | } | |
917ae499 RR |
245 | } |
246 | else if (drop_target->GetDefaultAction() == wxDragMove && | |
247 | (context->actions & GDK_ACTION_MOVE)) | |
248 | { | |
249 | result = wxDragMove; | |
250 | } | |
251 | else | |
252 | { | |
253 | if (context->actions & GDK_ACTION_COPY) | |
254 | result = wxDragCopy; | |
255 | else if (context->actions & GDK_ACTION_MOVE) | |
256 | result = wxDragMove; | |
257 | else | |
258 | result = wxDragNone; | |
259 | } | |
8e00741d | 260 | |
829e3e8d | 261 | if (drop_target->m_firstMotion) |
d6086ea6 | 262 | { |
829e3e8d | 263 | /* the first "drag_motion" event substitutes a "drag_enter" event */ |
c9057ae1 | 264 | result = drop_target->OnEnter( x, y, result ); |
8e00741d RR |
265 | } |
266 | else | |
267 | { | |
268 | /* give program a chance to react (i.e. to say no by returning FALSE) */ | |
c9057ae1 | 269 | result = drop_target->OnDragOver( x, y, result ); |
d6086ea6 | 270 | } |
f03fc89f | 271 | |
8ee9d618 | 272 | bool ret = wxIsDragResultOk( result ); |
829e3e8d | 273 | if (ret) |
bd77da97 | 274 | { |
8ee9d618 | 275 | GdkDragAction action; |
917ae499 | 276 | if (result == wxDragCopy) |
8ee9d618 | 277 | action = GDK_ACTION_COPY; |
b184227d RD |
278 | else if (result == wxDragLink) |
279 | action = GDK_ACTION_LINK; | |
8ee9d618 VZ |
280 | else |
281 | action = GDK_ACTION_MOVE; | |
282 | ||
7b5d5699 | 283 | gdk_drag_status( context, action, time ); |
bd77da97 | 284 | } |
f03fc89f | 285 | |
829e3e8d RR |
286 | /* after this, invalidate the drop_target's GdkDragContext */ |
287 | drop_target->SetDragContext( (GdkDragContext*) NULL ); | |
f03fc89f | 288 | |
829e3e8d RR |
289 | /* this has to be done because GDK has no "drag_enter" event */ |
290 | drop_target->m_firstMotion = FALSE; | |
f03fc89f | 291 | |
829e3e8d | 292 | return ret; |
33a5bc52 | 293 | } |
865bb325 | 294 | } |
33a5bc52 RR |
295 | |
296 | // ---------------------------------------------------------------------------- | |
297 | // "drag_drop" | |
298 | // ---------------------------------------------------------------------------- | |
299 | ||
865bb325 | 300 | extern "C" { |
33a5bc52 | 301 | static gboolean target_drag_drop( GtkWidget *widget, |
f03fc89f VZ |
302 | GdkDragContext *context, |
303 | gint x, | |
304 | gint y, | |
305 | guint time, | |
306 | wxDropTarget *drop_target ) | |
33a5bc52 | 307 | { |
5549fa65 RR |
308 | if (g_isIdle) wxapp_install_idle_handler(); |
309 | ||
829e3e8d RR |
310 | /* Owen Taylor: "if the drop is not in a drop zone, |
311 | return FALSE, otherwise, if you aren't accepting | |
312 | the drop, call gtk_drag_finish() with success == FALSE | |
313 | otherwise call gtk_drag_data_get()" */ | |
4ba47b40 RR |
314 | |
315 | // printf( "drop.\n" ); | |
f03fc89f | 316 | |
829e3e8d RR |
317 | /* this seems to make a difference between not accepting |
318 | due to wrong target area and due to wrong format. let | |
319 | us hope that this is not required.. */ | |
f03fc89f | 320 | |
829e3e8d RR |
321 | /* inform the wxDropTarget about the current GdkDragContext. |
322 | this is only valid for the duration of this call */ | |
323 | drop_target->SetDragContext( context ); | |
f03fc89f | 324 | |
829e3e8d RR |
325 | /* inform the wxDropTarget about the current drag widget. |
326 | this is only valid for the duration of this call */ | |
327 | drop_target->SetDragWidget( widget ); | |
f03fc89f | 328 | |
829e3e8d RR |
329 | /* inform the wxDropTarget about the current drag time. |
330 | this is only valid for the duration of this call */ | |
331 | drop_target->SetDragTime( time ); | |
f03fc89f | 332 | |
bd77da97 RR |
333 | /* |
334 | wxDragResult result = wxDragMove; | |
335 | if (context->suggested_action == GDK_ACTION_COPY) result = wxDragCopy; | |
336 | */ | |
337 | ||
513abb88 RR |
338 | /* reset the block here as someone might very well |
339 | show a dialog as a reaction to a drop and this | |
340 | wouldn't work without events */ | |
341 | g_blockEventsOnDrag = FALSE; | |
b2dea2ab | 342 | |
829e3e8d | 343 | bool ret = drop_target->OnDrop( x, y ); |
f03fc89f | 344 | |
5af019af | 345 | if (!ret) |
829e3e8d | 346 | { |
b2dea2ab | 347 | wxLogTrace(TRACE_DND, wxT( "Drop target: OnDrop returned FALSE") ); |
8ee9d618 | 348 | |
829e3e8d RR |
349 | /* cancel the whole thing */ |
350 | gtk_drag_finish( context, | |
f03fc89f VZ |
351 | FALSE, /* no success */ |
352 | FALSE, /* don't delete data on dropping side */ | |
353 | time ); | |
829e3e8d | 354 | } |
8e00741d RR |
355 | else |
356 | { | |
b2dea2ab | 357 | wxLogTrace(TRACE_DND, wxT( "Drop target: OnDrop returned TRUE") ); |
8ee9d618 | 358 | |
8e00741d RR |
359 | #if wxUSE_THREADS |
360 | /* disable GUI threads */ | |
8e00741d RR |
361 | #endif |
362 | ||
363 | GdkAtom format = drop_target->GetMatchingPair(); | |
b72aa48c VZ |
364 | |
365 | // this does happen somehow, see bug 555111 | |
366 | wxCHECK_MSG( format, FALSE, _T("no matching GdkAtom for format?") ) | |
8ee9d618 | 367 | |
bd77da97 RR |
368 | /* |
369 | GdkDragAction action = GDK_ACTION_MOVE; | |
8ee9d618 VZ |
370 | if (result == wxDragCopy) action == GDK_ACTION_COPY; |
371 | context->action = action; | |
bd77da97 | 372 | */ |
8e00741d RR |
373 | /* this should trigger an "drag_data_received" event */ |
374 | gtk_drag_get_data( widget, | |
375 | context, | |
376 | format, | |
377 | time ); | |
378 | ||
379 | #if wxUSE_THREADS | |
380 | /* re-enable GUI threads */ | |
8e00741d RR |
381 | #endif |
382 | } | |
f03fc89f | 383 | |
829e3e8d RR |
384 | /* after this, invalidate the drop_target's GdkDragContext */ |
385 | drop_target->SetDragContext( (GdkDragContext*) NULL ); | |
f03fc89f | 386 | |
829e3e8d RR |
387 | /* after this, invalidate the drop_target's drag widget */ |
388 | drop_target->SetDragWidget( (GtkWidget*) NULL ); | |
f03fc89f | 389 | |
829e3e8d RR |
390 | /* this has to be done because GDK has no "drag_enter" event */ |
391 | drop_target->m_firstMotion = TRUE; | |
f03fc89f | 392 | |
829e3e8d | 393 | return ret; |
33a5bc52 | 394 | } |
865bb325 | 395 | } |
33a5bc52 RR |
396 | |
397 | // ---------------------------------------------------------------------------- | |
398 | // "drag_data_received" | |
399 | // ---------------------------------------------------------------------------- | |
400 | ||
865bb325 | 401 | extern "C" { |
33a5bc52 | 402 | static void target_drag_data_received( GtkWidget *WXUNUSED(widget), |
f03fc89f VZ |
403 | GdkDragContext *context, |
404 | gint x, | |
405 | gint y, | |
406 | GtkSelectionData *data, | |
407 | guint WXUNUSED(info), | |
408 | guint time, | |
409 | wxDropTarget *drop_target ) | |
33a5bc52 | 410 | { |
5549fa65 RR |
411 | if (g_isIdle) wxapp_install_idle_handler(); |
412 | ||
829e3e8d RR |
413 | /* Owen Taylor: "call gtk_drag_finish() with |
414 | success == TRUE" */ | |
415 | ||
829e3e8d | 416 | if ((data->length <= 0) || (data->format != 8)) |
33a5bc52 | 417 | { |
829e3e8d RR |
418 | /* negative data length and non 8-bit data format |
419 | qualifies for junk */ | |
420 | gtk_drag_finish (context, FALSE, FALSE, time); | |
f03fc89f | 421 | |
f03fc89f | 422 | return; |
829e3e8d | 423 | } |
f03fc89f | 424 | |
b2dea2ab | 425 | wxLogTrace(TRACE_DND, wxT( "Drop target: data received event") ); |
8ee9d618 | 426 | |
5af019af RR |
427 | /* inform the wxDropTarget about the current GtkSelectionData. |
428 | this is only valid for the duration of this call */ | |
429 | drop_target->SetDragData( data ); | |
f03fc89f | 430 | |
c7d94ca4 | 431 | wxDragResult result = ConvertFromGTK(context->action); |
8ee9d618 VZ |
432 | |
433 | if ( wxIsDragResultOk( drop_target->OnData( x, y, result ) ) ) | |
829e3e8d | 434 | { |
b2dea2ab | 435 | wxLogTrace(TRACE_DND, wxT( "Drop target: OnData returned TRUE") ); |
8ee9d618 | 436 | |
3103e8a9 | 437 | /* tell GTK that data transfer was successful */ |
ab8884ac | 438 | gtk_drag_finish( context, TRUE, FALSE, time ); |
33a5bc52 | 439 | } |
5af019af RR |
440 | else |
441 | { | |
b2dea2ab | 442 | wxLogTrace(TRACE_DND, wxT( "Drop target: OnData returned FALSE") ); |
8ee9d618 | 443 | |
3103e8a9 | 444 | /* tell GTK that data transfer was not successful */ |
5af019af RR |
445 | gtk_drag_finish( context, FALSE, FALSE, time ); |
446 | } | |
f03fc89f | 447 | |
5af019af RR |
448 | /* after this, invalidate the drop_target's drag data */ |
449 | drop_target->SetDragData( (GtkSelectionData*) NULL ); | |
33a5bc52 | 450 | } |
865bb325 | 451 | } |
33a5bc52 | 452 | |
4ba47b40 | 453 | //---------------------------------------------------------------------------- |
33a5bc52 | 454 | // wxDropTarget |
4ba47b40 | 455 | //---------------------------------------------------------------------------- |
33a5bc52 | 456 | |
8ee9d618 VZ |
457 | wxDropTarget::wxDropTarget( wxDataObject *data ) |
458 | : wxDropTargetBase( data ) | |
f5368809 | 459 | { |
829e3e8d RR |
460 | m_firstMotion = TRUE; |
461 | m_dragContext = (GdkDragContext*) NULL; | |
462 | m_dragWidget = (GtkWidget*) NULL; | |
5af019af | 463 | m_dragData = (GtkSelectionData*) NULL; |
829e3e8d | 464 | m_dragTime = 0; |
f5368809 RR |
465 | } |
466 | ||
c9057ae1 VZ |
467 | wxDragResult wxDropTarget::OnDragOver( wxCoord WXUNUSED(x), |
468 | wxCoord WXUNUSED(y), | |
469 | wxDragResult def ) | |
d6086ea6 | 470 | { |
8ee9d618 | 471 | // GetMatchingPair() checks for m_dataObject too, no need to do it here |
2edc8f5b VZ |
472 | |
473 | // disable the debug message from GetMatchingPair() - there are too many | |
474 | // of them otherwise | |
c4fda16b | 475 | #ifdef __WXDEBUG__ |
2edc8f5b VZ |
476 | wxLogNull noLog; |
477 | #endif // Debug | |
478 | ||
c9057ae1 | 479 | return (GetMatchingPair() != (GdkAtom) 0) ? def : wxDragNone; |
d6086ea6 RR |
480 | } |
481 | ||
c9057ae1 | 482 | bool wxDropTarget::OnDrop( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y) ) |
d6086ea6 | 483 | { |
b068c4e8 | 484 | if (!m_dataObject) |
a3e7d24d | 485 | return FALSE; |
8ee9d618 | 486 | |
8e00741d | 487 | return (GetMatchingPair() != (GdkAtom) 0); |
d6086ea6 RR |
488 | } |
489 | ||
8ee9d618 VZ |
490 | wxDragResult wxDropTarget::OnData( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), |
491 | wxDragResult def ) | |
5af019af | 492 | { |
b068c4e8 | 493 | if (!m_dataObject) |
11e1c70d | 494 | return wxDragNone; |
8ee9d618 | 495 | |
8e00741d | 496 | if (GetMatchingPair() == (GdkAtom) 0) |
11e1c70d | 497 | return wxDragNone; |
8ee9d618 VZ |
498 | |
499 | return GetData() ? def : wxDragNone; | |
5af019af RR |
500 | } |
501 | ||
8e00741d | 502 | GdkAtom wxDropTarget::GetMatchingPair() |
5af019af | 503 | { |
8ee9d618 | 504 | if (!m_dataObject) |
8e00741d | 505 | return (GdkAtom) 0; |
5af019af | 506 | |
8ee9d618 | 507 | if (!m_dragContext) |
8e00741d | 508 | return (GdkAtom) 0; |
f03fc89f | 509 | |
22d5903e RR |
510 | GList *child = m_dragContext->targets; |
511 | while (child) | |
512 | { | |
513 | GdkAtom formatAtom = (GdkAtom) GPOINTER_TO_INT(child->data); | |
2edc8f5b | 514 | wxDataFormat format( formatAtom ); |
f03fc89f | 515 | |
a3e7d24d | 516 | #ifdef __WXDEBUG__ |
b2dea2ab VZ |
517 | wxLogTrace(TRACE_DND, wxT("Drop target: drag has format: %s"), |
518 | format.GetId().c_str()); | |
2edc8f5b VZ |
519 | #endif // Debug |
520 | ||
b068c4e8 | 521 | if (m_dataObject->IsSupportedFormat( format )) |
2edc8f5b | 522 | return formatAtom; |
f03fc89f | 523 | |
22d5903e RR |
524 | child = child->next; |
525 | } | |
829e3e8d | 526 | |
8e00741d | 527 | return (GdkAtom) 0; |
d6086ea6 | 528 | } |
f03fc89f | 529 | |
8e00741d | 530 | bool wxDropTarget::GetData() |
d6086ea6 | 531 | { |
8ee9d618 | 532 | if (!m_dragData) |
8e00741d | 533 | return FALSE; |
f03fc89f | 534 | |
8ee9d618 | 535 | if (!m_dataObject) |
8e00741d | 536 | return FALSE; |
f03fc89f | 537 | |
8e00741d | 538 | wxDataFormat dragFormat( m_dragData->target ); |
8ee9d618 | 539 | |
b068c4e8 | 540 | if (!m_dataObject->IsSupportedFormat( dragFormat )) |
8e00741d | 541 | return FALSE; |
f03fc89f | 542 | |
97c79de2 RR |
543 | m_dataObject->SetData( dragFormat, (size_t)m_dragData->length, (const void*)m_dragData->data ); |
544 | ||
545 | return TRUE; | |
d6086ea6 | 546 | } |
f03fc89f | 547 | |
f5368809 RR |
548 | void wxDropTarget::UnregisterWidget( GtkWidget *widget ) |
549 | { | |
223d09f6 | 550 | wxCHECK_RET( widget != NULL, wxT("unregister widget is NULL") ); |
f03fc89f | 551 | |
829e3e8d | 552 | gtk_drag_dest_unset( widget ); |
f03fc89f | 553 | |
d6086ea6 | 554 | gtk_signal_disconnect_by_func( GTK_OBJECT(widget), |
f03fc89f | 555 | GTK_SIGNAL_FUNC(target_drag_leave), (gpointer) this ); |
33a5bc52 | 556 | |
d6086ea6 | 557 | gtk_signal_disconnect_by_func( GTK_OBJECT(widget), |
f03fc89f | 558 | GTK_SIGNAL_FUNC(target_drag_motion), (gpointer) this ); |
33a5bc52 | 559 | |
d6086ea6 | 560 | gtk_signal_disconnect_by_func( GTK_OBJECT(widget), |
f03fc89f | 561 | GTK_SIGNAL_FUNC(target_drag_drop), (gpointer) this ); |
33a5bc52 | 562 | |
d6086ea6 | 563 | gtk_signal_disconnect_by_func( GTK_OBJECT(widget), |
f03fc89f | 564 | GTK_SIGNAL_FUNC(target_drag_data_received), (gpointer) this ); |
f5368809 RR |
565 | } |
566 | ||
567 | void wxDropTarget::RegisterWidget( GtkWidget *widget ) | |
568 | { | |
223d09f6 | 569 | wxCHECK_RET( widget != NULL, wxT("register widget is NULL") ); |
f03fc89f | 570 | |
829e3e8d RR |
571 | /* gtk_drag_dest_set() determines what default behaviour we'd like |
572 | GTK to supply. we don't want to specify out targets (=formats) | |
573 | or actions in advance (i.e. not GTK_DEST_DEFAULT_MOTION and | |
574 | not GTK_DEST_DEFAULT_DROP). instead we react individually to | |
575 | "drag_motion" and "drag_drop" events. this makes it possible | |
f03fc89f | 576 | to allow dropping on only a small area. we should set |
829e3e8d RR |
577 | GTK_DEST_DEFAULT_HIGHLIGHT as this will switch on the nice |
578 | highlighting if dragging over standard controls, but this | |
579 | seems to be broken without the other two. */ | |
f03fc89f | 580 | |
d6086ea6 | 581 | gtk_drag_dest_set( widget, |
f03fc89f VZ |
582 | (GtkDestDefaults) 0, /* no default behaviour */ |
583 | (GtkTargetEntry*) NULL, /* we don't supply any formats here */ | |
584 | 0, /* number of targets = 0 */ | |
585 | (GdkDragAction) 0 ); /* we don't supply any actions here */ | |
586 | ||
d6086ea6 | 587 | gtk_signal_connect( GTK_OBJECT(widget), "drag_leave", |
f03fc89f | 588 | GTK_SIGNAL_FUNC(target_drag_leave), (gpointer) this ); |
33a5bc52 | 589 | |
d6086ea6 | 590 | gtk_signal_connect( GTK_OBJECT(widget), "drag_motion", |
f03fc89f | 591 | GTK_SIGNAL_FUNC(target_drag_motion), (gpointer) this ); |
33a5bc52 | 592 | |
d6086ea6 | 593 | gtk_signal_connect( GTK_OBJECT(widget), "drag_drop", |
f03fc89f | 594 | GTK_SIGNAL_FUNC(target_drag_drop), (gpointer) this ); |
33a5bc52 | 595 | |
d6086ea6 | 596 | gtk_signal_connect( GTK_OBJECT(widget), "drag_data_received", |
f03fc89f | 597 | GTK_SIGNAL_FUNC(target_drag_data_received), (gpointer) this ); |
f5368809 RR |
598 | } |
599 | ||
4ba47b40 RR |
600 | //---------------------------------------------------------------------------- |
601 | // "drag_data_get" | |
602 | //---------------------------------------------------------------------------- | |
603 | ||
865bb325 | 604 | extern "C" { |
f03fc89f | 605 | static void |
4ba47b40 | 606 | source_drag_data_get (GtkWidget *WXUNUSED(widget), |
b02da6b1 | 607 | GdkDragContext *WXUNUSED(context), |
f03fc89f VZ |
608 | GtkSelectionData *selection_data, |
609 | guint WXUNUSED(info), | |
610 | guint WXUNUSED(time), | |
611 | wxDropSource *drop_source ) | |
4ba47b40 | 612 | { |
5549fa65 RR |
613 | if (g_isIdle) wxapp_install_idle_handler(); |
614 | ||
97c79de2 | 615 | wxDataFormat format( selection_data->target ); |
8ee9d618 | 616 | |
b2dea2ab VZ |
617 | wxLogTrace(TRACE_DND, wxT("Drop source: format requested: %s"), |
618 | format.GetId().c_str()); | |
f6bcfd97 | 619 | |
1dd989e1 | 620 | drop_source->m_retValue = wxDragCancel; |
8ee9d618 | 621 | |
97c79de2 | 622 | wxDataObject *data = drop_source->GetDataObject(); |
f6bcfd97 | 623 | |
1dd989e1 | 624 | if (!data) |
97c79de2 | 625 | { |
b2dea2ab | 626 | wxLogTrace(TRACE_DND, wxT("Drop source: no data object") ); |
2edc8f5b | 627 | return; |
97c79de2 | 628 | } |
1dd989e1 | 629 | |
97c79de2 RR |
630 | if (!data->IsSupportedFormat(format)) |
631 | { | |
b2dea2ab | 632 | wxLogTrace(TRACE_DND, wxT("Drop source: unsupported format") ); |
2edc8f5b | 633 | return; |
97c79de2 | 634 | } |
f03fc89f | 635 | |
97c79de2 RR |
636 | if (data->GetDataSize(format) == 0) |
637 | { | |
b2dea2ab | 638 | wxLogTrace(TRACE_DND, wxT("Drop source: empty data") ); |
2edc8f5b | 639 | return; |
97c79de2 | 640 | } |
8ee9d618 | 641 | |
97c79de2 | 642 | size_t size = data->GetDataSize(format); |
f03fc89f | 643 | |
1dd989e1 | 644 | // printf( "data size: %d.\n", (int)data_size ); |
f03fc89f | 645 | |
1dd989e1 | 646 | guchar *d = new guchar[size]; |
8ee9d618 | 647 | |
97c79de2 | 648 | if (!data->GetDataHere( format, (void*)d )) |
1dd989e1 | 649 | { |
97c79de2 | 650 | delete[] d; |
2edc8f5b | 651 | return; |
1dd989e1 | 652 | } |
f03fc89f | 653 | |
b453e1b2 | 654 | #if wxUSE_THREADS |
1dd989e1 | 655 | /* disable GUI threads */ |
b453e1b2 | 656 | #endif |
8e193f38 | 657 | |
4ba47b40 | 658 | gtk_selection_data_set( selection_data, |
f03fc89f VZ |
659 | selection_data->target, |
660 | 8, // 8-bit | |
1dd989e1 RR |
661 | d, |
662 | size ); | |
f03fc89f | 663 | |
b453e1b2 | 664 | #if wxUSE_THREADS |
1dd989e1 | 665 | /* enable GUI threads */ |
b453e1b2 | 666 | #endif |
f03fc89f | 667 | |
97c79de2 | 668 | delete[] d; |
4ba47b40 | 669 | } |
865bb325 | 670 | } |
f03fc89f | 671 | |
4ba47b40 RR |
672 | //---------------------------------------------------------------------------- |
673 | // "drag_data_delete" | |
674 | //---------------------------------------------------------------------------- | |
675 | ||
865bb325 | 676 | extern "C" { |
9f39393d VZ |
677 | static void source_drag_data_delete( GtkWidget *WXUNUSED(widget), |
678 | GdkDragContext *context, | |
679 | wxDropSource *WXUNUSED(drop_source) ) | |
4ba47b40 | 680 | { |
f6bcfd97 | 681 | if (g_isIdle) |
13fb7b7a | 682 | wxapp_install_idle_handler(); |
33a5bc52 | 683 | |
13fb7b7a | 684 | // printf( "Drag source: drag_data_delete\n" ); |
4ba47b40 | 685 | } |
865bb325 | 686 | } |
f03fc89f | 687 | |
4ba47b40 RR |
688 | //---------------------------------------------------------------------------- |
689 | // "drag_begin" | |
690 | //---------------------------------------------------------------------------- | |
691 | ||
865bb325 | 692 | extern "C" { |
4ba47b40 | 693 | static void source_drag_begin( GtkWidget *WXUNUSED(widget), |
f03fc89f VZ |
694 | GdkDragContext *WXUNUSED(context), |
695 | wxDropSource *WXUNUSED(drop_source) ) | |
4ba47b40 | 696 | { |
f6bcfd97 | 697 | if (g_isIdle) |
13fb7b7a | 698 | wxapp_install_idle_handler(); |
5549fa65 | 699 | |
13fb7b7a | 700 | // printf( "Drag source: drag_begin.\n" ); |
4ba47b40 | 701 | } |
865bb325 | 702 | } |
f03fc89f | 703 | |
4ba47b40 RR |
704 | //---------------------------------------------------------------------------- |
705 | // "drag_end" | |
706 | //---------------------------------------------------------------------------- | |
707 | ||
865bb325 | 708 | extern "C" { |
4ba47b40 | 709 | static void source_drag_end( GtkWidget *WXUNUSED(widget), |
f03fc89f VZ |
710 | GdkDragContext *WXUNUSED(context), |
711 | wxDropSource *drop_source ) | |
4ba47b40 | 712 | { |
5549fa65 RR |
713 | if (g_isIdle) wxapp_install_idle_handler(); |
714 | ||
13fb7b7a | 715 | // printf( "Drag source: drag_end.\n" ); |
4ba47b40 RR |
716 | |
717 | drop_source->m_waiting = FALSE; | |
718 | } | |
865bb325 | 719 | } |
f03fc89f | 720 | |
7b5d5699 RR |
721 | //----------------------------------------------------------------------------- |
722 | // "configure_event" from m_iconWindow | |
723 | //----------------------------------------------------------------------------- | |
724 | ||
865bb325 | 725 | extern "C" { |
8ee9d618 | 726 | static gint |
7b5d5699 RR |
727 | gtk_dnd_window_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxDropSource *source ) |
728 | { | |
8ee9d618 | 729 | if (g_isIdle) |
7b5d5699 RR |
730 | wxapp_install_idle_handler(); |
731 | ||
2245b2b2 | 732 | source->GiveFeedback( ConvertFromGTK(source->m_dragContext->action) ); |
8ee9d618 | 733 | |
7b5d5699 RR |
734 | return 0; |
735 | } | |
865bb325 | 736 | } |
7b5d5699 | 737 | |
4ba47b40 RR |
738 | //--------------------------------------------------------------------------- |
739 | // wxDropSource | |
740 | //--------------------------------------------------------------------------- | |
22d5903e | 741 | |
f6bcfd97 BP |
742 | wxDropSource::wxDropSource(wxWindow *win, |
743 | const wxIcon &iconCopy, | |
744 | const wxIcon &iconMove, | |
745 | const wxIcon &iconNone) | |
22d5903e | 746 | { |
4ba47b40 | 747 | m_waiting = TRUE; |
f03fc89f | 748 | |
7b5d5699 | 749 | m_iconWindow = (GtkWidget*) NULL; |
8ee9d618 | 750 | |
22d5903e | 751 | m_window = win; |
a2053b27 RR |
752 | m_widget = win->m_widget; |
753 | if (win->m_wxwindow) m_widget = win->m_wxwindow; | |
f03fc89f | 754 | |
22d5903e RR |
755 | m_retValue = wxDragCancel; |
756 | ||
f6bcfd97 | 757 | SetIcons(iconCopy, iconMove, iconNone); |
22d5903e RR |
758 | } |
759 | ||
f6bcfd97 BP |
760 | wxDropSource::wxDropSource(wxDataObject& data, |
761 | wxWindow *win, | |
762 | const wxIcon &iconCopy, | |
763 | const wxIcon &iconMove, | |
764 | const wxIcon &iconNone) | |
22d5903e | 765 | { |
4ba47b40 | 766 | m_waiting = TRUE; |
8ee9d618 | 767 | |
b068c4e8 | 768 | SetData( data ); |
f03fc89f | 769 | |
7b5d5699 | 770 | m_iconWindow = (GtkWidget*) NULL; |
8ee9d618 | 771 | |
22d5903e | 772 | m_window = win; |
a2053b27 RR |
773 | m_widget = win->m_widget; |
774 | if (win->m_wxwindow) m_widget = win->m_wxwindow; | |
8ee9d618 | 775 | |
22d5903e | 776 | m_retValue = wxDragCancel; |
f03fc89f | 777 | |
f6bcfd97 BP |
778 | SetIcons(iconCopy, iconMove, iconNone); |
779 | } | |
780 | ||
781 | void wxDropSource::SetIcons(const wxIcon &iconCopy, | |
782 | const wxIcon &iconMove, | |
783 | const wxIcon &iconNone) | |
784 | { | |
785 | m_iconCopy = iconCopy; | |
786 | m_iconMove = iconMove; | |
787 | m_iconNone = iconNone; | |
788 | ||
789 | if ( !m_iconCopy.Ok() ) | |
790 | m_iconCopy = wxIcon(page_xpm); | |
791 | if ( !m_iconMove.Ok() ) | |
792 | m_iconMove = m_iconCopy; | |
793 | if ( !m_iconNone.Ok() ) | |
794 | m_iconNone = m_iconCopy; | |
22d5903e RR |
795 | } |
796 | ||
8e193f38 | 797 | wxDropSource::~wxDropSource() |
22d5903e | 798 | { |
22d5903e | 799 | } |
f03fc89f | 800 | |
f6bcfd97 | 801 | void wxDropSource::PrepareIcon( int action, GdkDragContext *context ) |
7b5d5699 | 802 | { |
f6bcfd97 BP |
803 | // get the right icon to display |
804 | wxIcon *icon = NULL; | |
805 | if ( action & GDK_ACTION_MOVE ) | |
806 | icon = &m_iconMove; | |
807 | else if ( action & GDK_ACTION_COPY ) | |
808 | icon = &m_iconCopy; | |
809 | else | |
810 | icon = &m_iconNone; | |
811 | ||
812 | GdkBitmap *mask; | |
813 | if ( icon->GetMask() ) | |
814 | mask = icon->GetMask()->GetBitmap(); | |
815 | else | |
816 | mask = (GdkBitmap *)NULL; | |
817 | ||
818 | GdkPixmap *pixmap = icon->GetPixmap(); | |
7b5d5699 RR |
819 | |
820 | gint width,height; | |
821 | gdk_window_get_size (pixmap, &width, &height); | |
822 | ||
823 | GdkColormap *colormap = gtk_widget_get_colormap( m_widget ); | |
9d084560 | 824 | #ifndef __WXGTK20__ |
7b5d5699 | 825 | gtk_widget_push_visual (gdk_colormap_get_visual (colormap)); |
9d084560 | 826 | #endif |
7b5d5699 RR |
827 | gtk_widget_push_colormap (colormap); |
828 | ||
829 | m_iconWindow = gtk_window_new (GTK_WINDOW_POPUP); | |
830 | gtk_widget_set_events (m_iconWindow, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); | |
831 | gtk_widget_set_app_paintable (GTK_WIDGET (m_iconWindow), TRUE); | |
832 | ||
9d084560 | 833 | #ifndef __WXGTK20__ |
7b5d5699 | 834 | gtk_widget_pop_visual (); |
9d084560 | 835 | #endif |
7b5d5699 RR |
836 | gtk_widget_pop_colormap (); |
837 | ||
838 | gtk_widget_set_usize (m_iconWindow, width, height); | |
839 | gtk_widget_realize (m_iconWindow); | |
840 | ||
841 | gtk_signal_connect( GTK_OBJECT(m_iconWindow), "configure_event", | |
842 | GTK_SIGNAL_FUNC(gtk_dnd_window_configure_callback), (gpointer)this ); | |
8ee9d618 | 843 | |
7b5d5699 | 844 | gdk_window_set_back_pixmap (m_iconWindow->window, pixmap, FALSE); |
8ee9d618 | 845 | |
7b5d5699 RR |
846 | if (mask) |
847 | gtk_widget_shape_combine_mask (m_iconWindow, mask, 0, 0); | |
848 | ||
f6bcfd97 | 849 | gtk_drag_set_icon_widget( context, m_iconWindow, 0, 0 ); |
7b5d5699 RR |
850 | } |
851 | ||
2245b2b2 | 852 | wxDragResult wxDropSource::DoDragDrop(int flags) |
22d5903e | 853 | { |
2245b2b2 VZ |
854 | wxCHECK_MSG( m_data && m_data->GetFormatCount(), wxDragNone, |
855 | wxT("Drop source: no data") ); | |
8ee9d618 | 856 | |
513abb88 RR |
857 | // still in drag |
858 | if (g_blockEventsOnDrag) | |
2245b2b2 | 859 | return wxDragNone; |
b2dea2ab | 860 | |
f6bcfd97 | 861 | // disabled for now |
513abb88 | 862 | g_blockEventsOnDrag = TRUE; |
f03fc89f | 863 | |
4ba47b40 | 864 | RegisterWindow(); |
f03fc89f | 865 | |
4ba47b40 | 866 | m_waiting = TRUE; |
22d5903e | 867 | |
4ba47b40 | 868 | GtkTargetList *target_list = gtk_target_list_new( (GtkTargetEntry*) NULL, 0 ); |
8ee9d618 | 869 | |
a3e7d24d | 870 | wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ]; |
b068c4e8 | 871 | m_data->GetAllFormats( array ); |
2245b2b2 VZ |
872 | size_t count = m_data->GetFormatCount(); |
873 | for (size_t i = 0; i < count; i++) | |
a3e7d24d RR |
874 | { |
875 | GdkAtom atom = array[i]; | |
b2dea2ab | 876 | wxLogTrace(TRACE_DND, wxT("Drop source: Supported atom %s"), gdk_atom_name( atom )); |
a3e7d24d RR |
877 | gtk_target_list_add( target_list, atom, 0, 0 ); |
878 | } | |
879 | delete[] array; | |
f03fc89f | 880 | |
4ba47b40 RR |
881 | GdkEventMotion event; |
882 | event.window = m_widget->window; | |
883 | int x = 0; | |
884 | int y = 0; | |
885 | GdkModifierType state; | |
886 | gdk_window_get_pointer( event.window, &x, &y, &state ); | |
887 | event.x = x; | |
888 | event.y = y; | |
889 | event.state = state; | |
b02da6b1 | 890 | event.time = (guint32)GDK_CURRENT_TIME; |
f03fc89f | 891 | |
4ba47b40 RR |
892 | /* GTK wants to know which button was pressed which caused the dragging */ |
893 | int button_number = 0; | |
894 | if (event.state & GDK_BUTTON1_MASK) button_number = 1; | |
895 | else if (event.state & GDK_BUTTON2_MASK) button_number = 2; | |
896 | else if (event.state & GDK_BUTTON3_MASK) button_number = 3; | |
897 | ||
b453e1b2 RR |
898 | #if wxUSE_THREADS |
899 | /* disable GUI threads */ | |
b453e1b2 | 900 | #endif |
8e193f38 | 901 | |
4ba47b40 RR |
902 | /* don't start dragging if no button is down */ |
903 | if (button_number) | |
22d5903e | 904 | { |
9f39393d | 905 | int action = GDK_ACTION_COPY; |
2245b2b2 | 906 | if ( flags & wxDrag_AllowMove ) |
9f39393d | 907 | action |= GDK_ACTION_MOVE; |
2245b2b2 VZ |
908 | |
909 | // VZ: as we already use g_blockEventsOnDrag it shouldn't be that bad | |
910 | // to use a global to pass the flags to the drop target but I'd | |
911 | // surely prefer a better way to do it | |
912 | gs_flagsForDrag = flags; | |
913 | ||
4ba47b40 | 914 | GdkDragContext *context = gtk_drag_begin( m_widget, |
f6bcfd97 | 915 | target_list, |
46c87a9a | 916 | (GdkDragAction)action, |
f6bcfd97 BP |
917 | button_number, /* number of mouse button which started drag */ |
918 | (GdkEvent*) &event ); | |
8ee9d618 VZ |
919 | |
920 | m_dragContext = context; | |
921 | ||
f6bcfd97 | 922 | PrepareIcon( action, context ); |
f03fc89f | 923 | |
2245b2b2 VZ |
924 | while (m_waiting) |
925 | gtk_main_iteration(); | |
f6bcfd97 | 926 | |
2245b2b2 VZ |
927 | m_retValue = ConvertFromGTK(context->action); |
928 | if ( m_retValue == wxDragNone ) | |
929 | m_retValue = wxDragCancel; | |
4ba47b40 | 930 | } |
22d5903e | 931 | |
b453e1b2 RR |
932 | #if wxUSE_THREADS |
933 | /* re-enable GUI threads */ | |
b453e1b2 | 934 | #endif |
8e193f38 | 935 | |
4ba47b40 | 936 | g_blockEventsOnDrag = FALSE; |
f03fc89f | 937 | |
4ba47b40 RR |
938 | UnregisterWindow(); |
939 | ||
940 | return m_retValue; | |
22d5903e RR |
941 | } |
942 | ||
4ba47b40 | 943 | void wxDropSource::RegisterWindow() |
22d5903e | 944 | { |
4ba47b40 | 945 | if (!m_widget) return; |
f6bcfd97 | 946 | |
4ba47b40 | 947 | gtk_signal_connect( GTK_OBJECT(m_widget), "drag_data_get", |
f03fc89f | 948 | GTK_SIGNAL_FUNC (source_drag_data_get), (gpointer) this); |
4ba47b40 | 949 | gtk_signal_connect (GTK_OBJECT(m_widget), "drag_data_delete", |
f03fc89f | 950 | GTK_SIGNAL_FUNC (source_drag_data_delete), (gpointer) this ); |
4ba47b40 | 951 | gtk_signal_connect (GTK_OBJECT(m_widget), "drag_begin", |
f03fc89f | 952 | GTK_SIGNAL_FUNC (source_drag_begin), (gpointer) this ); |
4ba47b40 | 953 | gtk_signal_connect (GTK_OBJECT(m_widget), "drag_end", |
f03fc89f | 954 | GTK_SIGNAL_FUNC (source_drag_end), (gpointer) this ); |
4ba47b40 | 955 | |
22d5903e RR |
956 | } |
957 | ||
4ba47b40 | 958 | void wxDropSource::UnregisterWindow() |
22d5903e RR |
959 | { |
960 | if (!m_widget) return; | |
f03fc89f | 961 | |
4ba47b40 | 962 | gtk_signal_disconnect_by_func( GTK_OBJECT(m_widget), |
f03fc89f | 963 | GTK_SIGNAL_FUNC(source_drag_data_get), (gpointer) this ); |
4ba47b40 | 964 | gtk_signal_disconnect_by_func( GTK_OBJECT(m_widget), |
f03fc89f | 965 | GTK_SIGNAL_FUNC(source_drag_data_delete), (gpointer) this ); |
4ba47b40 | 966 | gtk_signal_disconnect_by_func( GTK_OBJECT(m_widget), |
f03fc89f | 967 | GTK_SIGNAL_FUNC(source_drag_begin), (gpointer) this ); |
4ba47b40 | 968 | gtk_signal_disconnect_by_func( GTK_OBJECT(m_widget), |
f03fc89f | 969 | GTK_SIGNAL_FUNC(source_drag_end), (gpointer) this ); |
22d5903e RR |
970 | } |
971 | ||
ac57418f | 972 | #endif |
93c5dd39 | 973 | // wxUSE_DRAG_AND_DROP |