]>
Commit | Line | Data |
---|---|---|
c801d85f KB |
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 | { | |
e3e65dac RR |
49 | if (!widget) return; |
50 | ||
c801d85f KB |
51 | gtk_widget_dnd_drop_set( widget, FALSE, NULL, 0, FALSE ); |
52 | }; | |
53 | ||
e3e65dac RR |
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 | ||
c801d85f KB |
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 | ||
e3e65dac | 101 | size_t wxTextDropTarget::GetFormatCount() const |
c801d85f | 102 | { |
e3e65dac RR |
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 | } | |
c801d85f KB |
138 | |
139 | //------------------------------------------------------------------------- | |
e3e65dac | 140 | // wxDropSource |
c801d85f KB |
141 | //------------------------------------------------------------------------- |
142 | ||
143 | //----------------------------------------------------------------------------- | |
144 | // drag request | |
145 | ||
e3e65dac | 146 | void gtk_drag_callback( GtkWidget *widget, GdkEvent *event, wxDataObject *data ) |
c801d85f | 147 | { |
e3e65dac RR |
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 ); | |
c801d85f | 155 | |
e3e65dac | 156 | delete ptr; |
c801d85f KB |
157 | }; |
158 | ||
e3e65dac | 159 | wxDropSource::wxDropSource( wxWindow *win ) |
c801d85f KB |
160 | { |
161 | g_blockEventsOnDrag = TRUE; | |
e3e65dac | 162 | |
c801d85f KB |
163 | m_window = win; |
164 | m_widget = win->m_widget; | |
165 | if (win->m_wxwindow) m_widget = win->m_wxwindow; | |
c801d85f | 166 | |
e3e65dac RR |
167 | m_data = NULL; |
168 | ||
c801d85f KB |
169 | m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY ); |
170 | m_goaheadCursor = wxCursor( wxCURSOR_HAND ); | |
171 | }; | |
172 | ||
e3e65dac | 173 | wxDropSource::wxDropSource( wxDataObject &data, wxWindow *win ) |
c801d85f | 174 | { |
e3e65dac RR |
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 ); | |
c801d85f | 185 | }; |
e3e65dac RR |
186 | |
187 | void wxDropSource::SetData( wxDataObject &data ) | |
c801d85f | 188 | { |
e3e65dac | 189 | m_data = &data; |
c801d85f KB |
190 | }; |
191 | ||
e3e65dac | 192 | wxDropSource::~wxDropSource(void) |
c801d85f | 193 | { |
e3e65dac RR |
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; | |
c801d85f KB |
206 | |
207 | GdkWindowPrivate *wp = (GdkWindowPrivate*) m_widget->window; | |
208 | ||
209 | RegisterWindow(); | |
c801d85f KB |
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; | |
e3e65dac RR |
246 | |
247 | int x = 0; | |
248 | int y = 0; | |
249 | gdk_window_get_pointer( m_widget->window, &x, &y, NULL ); | |
250 | ||
c801d85f KB |
251 | gdk_dnd_display_drag_cursor( x, y, FALSE, TRUE ); |
252 | ||
253 | while (gdk_dnd.drag_really || gdk_dnd.drag_perhaps) wxYield(); | |
254 | ||
c801d85f | 255 | UnregisterWindow(); |
e3e65dac RR |
256 | |
257 | return Copy; | |
c801d85f KB |
258 | }; |
259 | ||
e3e65dac | 260 | void wxDropSource::RegisterWindow(void) |
c801d85f | 261 | { |
e3e65dac | 262 | if (!m_data) return; |
c801d85f | 263 | |
e3e65dac RR |
264 | wxString formats; |
265 | ||
266 | wxDataFormat df = m_data->GetPreferredFormat(); | |
c801d85f | 267 | |
e3e65dac RR |
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 | } | |
c801d85f | 279 | |
e3e65dac | 280 | char *str = WXSTRINGCAST formats; |
c801d85f | 281 | |
e3e65dac | 282 | gtk_widget_dnd_drag_set( m_widget, TRUE, &str, 1 ); |
c801d85f | 283 | |
e3e65dac RR |
284 | gtk_signal_connect( GTK_OBJECT(m_widget), "drag_request_event", |
285 | GTK_SIGNAL_FUNC(gtk_drag_callback), (gpointer)m_data ); | |
c801d85f KB |
286 | }; |
287 | ||
e3e65dac | 288 | void wxDropSource::UnregisterWindow(void) |
c801d85f KB |
289 | { |
290 | if (!m_widget) return; | |
291 | ||
e3e65dac RR |
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 ); | |
c801d85f | 295 | }; |