]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/dnd.cpp
Fixed bug in MDI
[wxWidgets.git] / src / gtk1 / dnd.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: dnd.cpp
3 // Purpose: wxDropTarget class
4 // Author: Robert Roebling
5 // Copyright: Robert Roebling
6 // Licence: wxWindows license
7 ///////////////////////////////////////////////////////////////////////////////
8
9 #ifdef __GNUG__
10 #pragma implementation "dnd.h"
11 #endif
12
13 #include "wx/dnd.h"
14 #include "wx/window.h"
15 #include "wx/app.h"
16 #include "wx/gdicmn.h"
17
18 #include "gdk/gdkprivate.h"
19
20 #include <X11/Xlib.h>
21
22 // ----------------------------------------------------------------------------
23 // global
24 // ----------------------------------------------------------------------------
25
26 extern bool g_blockEventsOnDrag;
27
28 // ----------------------------------------------------------------------------
29 // wxDropTarget
30 // ----------------------------------------------------------------------------
31
32 wxDropTarget::wxDropTarget()
33 {
34 };
35
36 wxDropTarget::~wxDropTarget()
37 {
38 };
39
40 void wxDropTarget::Drop( GdkEvent *event, int x, int y )
41 {
42 printf( "Drop data is of type %s.\n", event->dropdataavailable.data_type );
43
44 OnDrop( x, y, (char *)event->dropdataavailable.data);
45 };
46
47 void wxDropTarget::UnregisterWidget( GtkWidget *widget )
48 {
49 if (!widget) return;
50
51 gtk_widget_dnd_drop_set( widget, FALSE, NULL, 0, FALSE );
52 };
53
54 void wxDropTarget::RegisterWidget( GtkWidget *widget )
55 {
56 wxString formats;
57 int valid = 0;
58
59 for ( uint i = 0; i < GetFormatCount(); i++ )
60 {
61 wxDataFormat df = GetFormat( i );
62 switch (df)
63 {
64 case wxDF_TEXT:
65 if (i > 0) formats += ";";
66 formats += "text/plain";
67 valid++;
68 break;
69 case wxDF_FILENAME:
70 if (i > 0) formats += ";";
71 formats += "url:any";
72 valid++;
73 break;
74 default:
75 break;
76 };
77 }
78
79 char *str = WXSTRINGCAST formats;
80
81 gtk_widget_dnd_drop_set( widget, TRUE, &str, valid, FALSE );
82 };
83
84 // ----------------------------------------------------------------------------
85 // wxTextDropTarget
86 // ----------------------------------------------------------------------------
87
88 bool wxTextDropTarget::OnDrop( long x, long y, const void *pData )
89 {
90 OnDropText( x, y, (const char*)pData );
91 return TRUE;
92 };
93
94 bool wxTextDropTarget::OnDropText( long x, long y, const char *psz )
95 {
96 printf( "Got dropped text: %s.\n", psz );
97 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
98 return TRUE;
99 };
100
101 size_t wxTextDropTarget::GetFormatCount() const
102 {
103 return 1;
104 }
105
106 wxDataFormat wxTextDropTarget::GetFormat(size_t WXUNUSED(n)) const
107 {
108 return wxDF_TEXT;
109 }
110
111 // ----------------------------------------------------------------------------
112 // wxFileDropTarget
113 // ----------------------------------------------------------------------------
114
115 bool wxFileDropTarget::OnDropFiles( long x, long y, size_t nFiles, const char * const WXUNUSED(aszFiles)[] )
116 {
117 printf( "Got %d dropped files.\n", (int)nFiles );
118 printf( "At x: %d, y: %d.\n", (int)x, (int)y );
119 return TRUE;
120 }
121
122 bool wxFileDropTarget::OnDrop(long x, long y, const void *WXUNUSED(pData) )
123 {
124 char *str = "/this/is/a/path.txt";
125
126 return OnDropFiles(x, y, 1, &str );
127 }
128
129 size_t wxFileDropTarget::GetFormatCount() const
130 {
131 return 1;
132 }
133
134 wxDataFormat wxFileDropTarget::GetFormat(size_t WXUNUSED(n)) const
135 {
136 return wxDF_FILENAME;
137 }
138
139 //-------------------------------------------------------------------------
140 // wxDropSource
141 //-------------------------------------------------------------------------
142
143 //-----------------------------------------------------------------------------
144 // drag request
145
146 void gtk_drag_callback( GtkWidget *widget, GdkEvent *event, wxDataObject *data )
147 {
148 printf( "Data requested for dropping.\n" );
149
150 uint size = data->GetDataSize();
151 char *ptr = new char[size];
152 data->GetDataHere( ptr );
153
154 gtk_widget_dnd_data_set( widget, event, ptr, size );
155
156 delete ptr;
157 };
158
159 wxDropSource::wxDropSource( wxWindow *win )
160 {
161 g_blockEventsOnDrag = TRUE;
162
163 m_window = win;
164 m_widget = win->m_widget;
165 if (win->m_wxwindow) m_widget = win->m_wxwindow;
166
167 m_data = NULL;
168
169 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
170 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
171 };
172
173 wxDropSource::wxDropSource( wxDataObject &data, wxWindow *win )
174 {
175 g_blockEventsOnDrag = TRUE;
176
177 m_window = win;
178 m_widget = win->m_widget;
179 if (win->m_wxwindow) m_widget = win->m_wxwindow;
180
181 m_data = &data;
182
183 m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
184 m_goaheadCursor = wxCursor( wxCURSOR_HAND );
185 };
186
187 void wxDropSource::SetData( wxDataObject &data )
188 {
189 m_data = &data;
190 };
191
192 wxDropSource::~wxDropSource(void)
193 {
194 // if (m_data) delete m_data;
195
196 g_blockEventsOnDrag = FALSE;
197 };
198
199 wxDropSource::DragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
200 {
201 if (gdk_dnd.dnd_grabbed) return None;
202 if (gdk_dnd.drag_really) return None;
203
204 if (!m_data) return None;
205 if (m_data->GetDataSize() == 0) return None;
206
207 GdkWindowPrivate *wp = (GdkWindowPrivate*) m_widget->window;
208
209 RegisterWindow();
210
211 gdk_dnd.drag_perhaps = TRUE;
212
213 gdk_dnd.dnd_drag_start.x = 5;
214 gdk_dnd.dnd_drag_start.y = 5;
215 gdk_dnd.real_sw = wp;
216
217 if (gdk_dnd.drag_startwindows)
218 {
219 g_free( gdk_dnd.drag_startwindows );
220 gdk_dnd.drag_startwindows = NULL;
221 };
222 gdk_dnd.drag_numwindows = gdk_dnd.drag_really = 0;
223
224 XWindowAttributes dnd_winattr;
225 XGetWindowAttributes( gdk_display, wp->xwindow, &dnd_winattr );
226 wp->dnd_drag_savedeventmask = dnd_winattr.your_event_mask;
227
228 gdk_dnd_drag_addwindow( m_widget->window );
229
230 GdkEventDragBegin ev;
231 ev.type = GDK_DRAG_BEGIN;
232 ev.window = m_widget->window;
233 ev.u.allflags = 0;
234 ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
235
236 gdk_event_put( (GdkEvent*)&ev );
237
238 XGrabPointer( gdk_display, wp->xwindow, False,
239 ButtonMotionMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
240 GrabModeAsync, GrabModeAsync, gdk_root_window, None, CurrentTime );
241
242 gdk_dnd_set_drag_cursors( m_defaultCursor.GetCursor(), m_goaheadCursor.GetCursor() );
243
244 gdk_dnd.dnd_grabbed = TRUE;
245 gdk_dnd.drag_really = 1;
246
247 int x = 0;
248 int y = 0;
249 gdk_window_get_pointer( m_widget->window, &x, &y, NULL );
250
251 gdk_dnd_display_drag_cursor( x, y, FALSE, TRUE );
252
253 while (gdk_dnd.drag_really || gdk_dnd.drag_perhaps) wxYield();
254
255 UnregisterWindow();
256
257 return Copy;
258 };
259
260 void wxDropSource::RegisterWindow(void)
261 {
262 if (!m_data) return;
263
264 wxString formats;
265
266 wxDataFormat df = m_data->GetPreferredFormat();
267
268 switch (df)
269 {
270 case wxDF_TEXT:
271 formats += "text/plain";
272 break;
273 case wxDF_FILENAME:
274 formats += "url:any";
275 break;
276 default:
277 break;
278 }
279
280 char *str = WXSTRINGCAST formats;
281
282 gtk_widget_dnd_drag_set( m_widget, TRUE, &str, 1 );
283
284 gtk_signal_connect( GTK_OBJECT(m_widget), "drag_request_event",
285 GTK_SIGNAL_FUNC(gtk_drag_callback), (gpointer)m_data );
286 };
287
288 void wxDropSource::UnregisterWindow(void)
289 {
290 if (!m_widget) return;
291
292 gtk_widget_dnd_drag_set( m_widget, FALSE, NULL, 0 );
293
294 gtk_signal_disconnect_by_data( GTK_OBJECT(m_widget), (gpointer)m_data );
295 };