fdopen: don't rewind the file after creating the FILE* handle. Added
[wine] / dlls / x11drv / event.c
1 /*
2  * X11 event driver
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1999 Noel Borthwick
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23
24 #include <X11/Xatom.h>
25 #include <X11/keysym.h>
26
27 #include "ts_xlib.h"
28 #include <X11/Xresource.h>
29 #include <X11/Xutil.h>
30 #ifdef HAVE_LIBXXF86DGA2
31 #include <X11/extensions/xf86dga.h>
32 #endif
33
34 #include <assert.h>
35 #include <string.h>
36 #include "wine/winuser16.h"
37 #include "shlobj.h"  /* DROPFILES */
38
39 #include "clipboard.h"
40 #include "win.h"
41 #include "winpos.h"
42 #include "windef.h"
43 #include "winreg.h"
44 #include "x11drv.h"
45 #include "shellapi.h"
46 #include "wine/debug.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(event);
49
50 /* X context to associate a hwnd to an X window */
51 extern XContext winContext;
52
53 extern Atom wmProtocols;
54 extern Atom wmDeleteWindow;
55 extern Atom dndProtocol;
56 extern Atom dndSelection;
57
58 #define DndNotDnd       -1    /* OffiX drag&drop */
59 #define DndUnknown      0
60 #define DndRawData      1
61 #define DndFile         2
62 #define DndFiles        3
63 #define DndText         4
64 #define DndDir          5
65 #define DndLink         6
66 #define DndExe          7
67
68 #define DndEND          8
69
70 #define DndURL          128   /* KDE drag&drop */
71
72 static const char * const event_names[] =
73 {
74   "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
75   "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
76   "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
77   "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
78   "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
79   "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
80   "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
81   "ClientMessage", "MappingNotify"
82 };
83
84
85 static void EVENT_ProcessEvent( XEvent *event );
86
87   /* Event handlers */
88 static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
89 static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
90 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
91 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
92 static void EVENT_PropertyNotify( XPropertyEvent *event );
93 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
94
95 extern void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event );
96 extern void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event );
97 extern void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event );
98 extern void X11DRV_EnterNotify( HWND hwnd, XCrossingEvent *event );
99 extern void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event );
100 extern void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event );
101 extern void X11DRV_Expose( HWND hwnd, XExposeEvent *event );
102 extern void X11DRV_MapNotify( HWND hwnd, XMapEvent *event );
103 extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
104 extern void X11DRV_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
105 extern void X11DRV_MappingNotify( XMappingEvent *event );
106
107 #ifdef HAVE_LIBXXF86DGA2
108 static int DGAMotionEventType;
109 static int DGAButtonPressEventType;
110 static int DGAButtonReleaseEventType;
111 static int DGAKeyPressEventType;
112 static int DGAKeyReleaseEventType;
113
114 static BOOL DGAUsed = FALSE;
115 static HWND DGAhwnd = 0;
116
117 extern void X11DRV_DGAMotionEvent( HWND hwnd, XDGAMotionEvent *event );
118 extern void X11DRV_DGAButtonPressEvent( HWND hwnd, XDGAButtonEvent *event );
119 extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XDGAButtonEvent *event );
120 #endif
121
122 /* Static used for the current input method */
123 static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
124 static BOOL in_transition = FALSE; /* This is not used as for today */
125
126
127 /***********************************************************************
128  *           process_events
129  */
130 static int process_events( struct x11drv_thread_data *data )
131 {
132     XEvent event;
133     int count = 0;
134
135     wine_tsx11_lock();
136     while ( XPending( data->display ) )
137     {
138         XNextEvent( data->display, &event );
139         wine_tsx11_unlock();
140         EVENT_ProcessEvent( &event );
141         count++;
142         wine_tsx11_lock();
143     }
144     wine_tsx11_unlock();
145     return count;
146 }
147
148
149 /***********************************************************************
150  *           MsgWaitForMultipleObjectsEx   (X11DRV.@)
151  */
152 DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
153                                           DWORD timeout, DWORD mask, DWORD flags )
154 {
155     HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1];  /* FIXME! */
156     DWORD i, ret;
157     struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
158
159     if (!data || data->process_event_count)
160         return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
161                                          timeout, flags & MWMO_ALERTABLE );
162
163     for (i = 0; i < count; i++) new_handles[i] = handles[i];
164     new_handles[count] = data->display_fd;
165
166     wine_tsx11_lock();
167     XFlush( gdi_display );
168     XFlush( data->display );
169     wine_tsx11_unlock();
170
171     data->process_event_count++;
172     if (process_events( data )) ret = count;
173     else
174     {
175         ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
176                                         timeout, flags & MWMO_ALERTABLE );
177         if (ret == count) process_events( data );
178     }
179     data->process_event_count--;
180     return ret;
181 }
182
183
184 /***********************************************************************
185  *           EVENT_ProcessEvent
186  *
187  * Process an X event.
188  */
189 static void EVENT_ProcessEvent( XEvent *event )
190 {
191   HWND hWnd;
192   Display *display = event->xany.display;
193
194   TRACE( "called.\n" );
195
196   switch (event->type)
197   {
198     case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
199          FIXME("Got SelectionNotify - must not happen!\n");
200          /* fall through */
201
202       /* We get all these because of StructureNotifyMask.
203          This check is placed here to avoid getting error messages below,
204          as X might send some of these even for windows that have already
205          been deleted ... */
206     case CirculateNotify:
207     case CreateNotify:
208     case DestroyNotify:
209     case GravityNotify:
210     case ReparentNotify:
211       return;
212   }
213
214 #ifdef HAVE_LIBXXF86DGA2
215   if (DGAUsed) {
216     if (event->type == DGAMotionEventType) {
217       TRACE("DGAMotionEvent received.\n");
218       X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
219       return;
220     }
221     if (event->type == DGAButtonPressEventType) {
222       TRACE("DGAButtonPressEvent received.\n");
223       X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
224       return;
225     }
226     if (event->type == DGAButtonReleaseEventType) {
227       TRACE("DGAButtonReleaseEvent received.\n");
228       X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
229       return;
230     }
231     if ((event->type == DGAKeyPressEventType) ||
232         (event->type == DGAKeyReleaseEventType)) {
233       /* Fill a XKeyEvent to send to EVENT_Key */
234       XKeyEvent ke;
235       XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
236
237       TRACE("DGAKeyPress/ReleaseEvent received.\n");
238
239       if (evt->type == DGAKeyReleaseEventType)
240         ke.type = KeyRelease;
241       else
242         ke.type = KeyPress;
243       ke.serial = evt->serial;
244       ke.send_event = FALSE;
245       ke.display = evt->display;
246       ke.window = 0;
247       ke.root = 0;
248       ke.subwindow = 0;
249       ke.time = evt->time;
250       ke.x = -1;
251       ke.y = -1;
252       ke.x_root = -1;
253       ke.y_root = -1;
254       ke.state = evt->state;
255       ke.keycode = evt->keycode;
256       ke.same_screen = TRUE;
257       X11DRV_KeyEvent( 0, &ke );
258       return;
259     }
260   }
261 #endif
262
263   wine_tsx11_lock();
264   if (XFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
265       hWnd = 0;  /* Not for a registered window */
266   wine_tsx11_unlock();
267
268   if ( !hWnd && event->xany.window != root_window
269              && event->type != PropertyNotify
270              && event->type != MappingNotify)
271       WARN( "Got event %s for unknown Window %08lx\n",
272             event_names[event->type], event->xany.window );
273   else
274       TRACE("Got event %s for hwnd %p\n",
275             event_names[event->type], hWnd );
276
277   switch(event->type)
278     {
279     case KeyPress:
280     case KeyRelease:
281       /* FIXME: should generate a motion event if event point is different from current pos */
282       X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
283       break;
284
285     case ButtonPress:
286       X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
287       break;
288
289     case ButtonRelease:
290       X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
291       break;
292
293     case MotionNotify:
294       X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
295       break;
296
297     case EnterNotify:
298       X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
299       break;
300
301     case FocusIn:
302       EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
303       break;
304
305     case FocusOut:
306       EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
307       break;
308
309     case Expose:
310       X11DRV_Expose( hWnd, &event->xexpose );
311       break;
312
313     case ConfigureNotify:
314       if (!hWnd) return;
315       X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
316       break;
317
318     case SelectionRequest:
319       if (!hWnd) return;
320       EVENT_SelectionRequest( hWnd, (XSelectionRequestEvent *)event, FALSE );
321       break;
322
323     case SelectionClear:
324       if (!hWnd) return;
325       EVENT_SelectionClear( hWnd, (XSelectionClearEvent*) event );
326       break;
327
328     case PropertyNotify:
329       EVENT_PropertyNotify( (XPropertyEvent *)event );
330       break;
331
332     case ClientMessage:
333       if (!hWnd) return;
334       EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
335       break;
336
337     case NoExpose:
338       break;
339
340     case MapNotify:
341       X11DRV_MapNotify( hWnd, (XMapEvent *)event );
342       break;
343
344     case UnmapNotify:
345       X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
346       break;
347
348     case KeymapNotify:
349       X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
350       break;
351
352     case MappingNotify:
353       X11DRV_MappingNotify( (XMappingEvent *) event );
354       break;
355
356     default:
357       WARN("Unprocessed event %s for hwnd %p\n", event_names[event->type], hWnd );
358       break;
359     }
360     TRACE( "returns.\n" );
361 }
362
363
364 /*******************************************************************
365  *         can_activate_window
366  *
367  * Check if we can activate the specified window.
368  */
369 inline static BOOL can_activate_window( HWND hwnd )
370 {
371     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
372     if (!(style & WS_VISIBLE)) return FALSE;
373     if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
374     return !(style & WS_DISABLED);
375 }
376
377
378 /**********************************************************************
379  *              set_focus_error_handler
380  *
381  * Handler for X errors happening during XSetInputFocus call.
382  */
383 static int set_focus_error_handler( Display *display, XErrorEvent *event, void *arg )
384 {
385     return (event->error_code == BadMatch);
386 }
387
388
389 /**********************************************************************
390  *              set_focus
391  */
392 static void set_focus( HWND hwnd, Time time )
393 {
394     HWND focus;
395     Window win;
396
397     TRACE( "setting foreground window to %p\n", hwnd );
398     SetForegroundWindow( hwnd );
399
400     focus = GetFocus();
401     win = X11DRV_get_whole_window(focus);
402
403     if (win)
404     {
405         Display *display = thread_display();
406         TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
407         X11DRV_expect_error( display, set_focus_error_handler, NULL );
408         XSetInputFocus( display, win, RevertToParent, time );
409         if (X11DRV_check_error()) TRACE("got BadMatch, ignoring\n" );
410     }
411 }
412
413
414 /**********************************************************************
415  *              handle_wm_protocols_message
416  */
417 static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event )
418 {
419     Atom protocol = (Atom)event->data.l[0];
420
421     if (!protocol) return;
422
423     if (protocol == wmDeleteWindow)
424     {
425         /* Ignore the delete window request if the window has been disabled
426          * and we are in managed mode. This is to disallow applications from
427          * being closed by the window manager while in a modal state.
428          */
429         if (IsWindowEnabled(hwnd)) PostMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
430     }
431     else if (protocol == wmTakeFocus)
432     {
433         Time event_time = (Time)event->data.l[1];
434         HWND last_focus = x11drv_thread_data()->last_focus;
435
436         TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
437                hwnd, IsWindowEnabled(hwnd), GetFocus(), GetActiveWindow(),
438                GetForegroundWindow(), last_focus );
439
440         if (can_activate_window(hwnd))
441         {
442             /* simulate a mouse click on the caption to find out
443              * whether the window wants to be activated */
444             LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
445                                        (WPARAM)GetAncestor( hwnd, GA_ROOT ),
446                                        MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
447             if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
448             else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
449         }
450         else
451         {
452             hwnd = GetFocus();
453             if (!hwnd) hwnd = GetActiveWindow();
454             if (!hwnd) hwnd = last_focus;
455             if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
456         }
457     }
458 }
459
460
461 static const char * const focus_details[] =
462 {
463     "NotifyAncestor",
464     "NotifyVirtual",
465     "NotifyInferior",
466     "NotifyNonlinear",
467     "NotifyNonlinearVirtual",
468     "NotifyPointer",
469     "NotifyPointerRoot",
470     "NotifyDetailNone"
471 };
472
473 /**********************************************************************
474  *              EVENT_FocusIn
475  */
476 static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
477 {
478     if (!hwnd) return;
479
480     TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
481
482     if (wmTakeFocus) return;  /* ignore FocusIn if we are using take focus */
483     if (event->detail == NotifyPointer) return;
484
485     if (!can_activate_window(hwnd))
486     {
487         HWND hwnd = GetFocus();
488         if (!hwnd) hwnd = GetActiveWindow();
489         if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
490         if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
491     }
492     else SetForegroundWindow( hwnd );
493 }
494
495
496 /**********************************************************************
497  *              EVENT_FocusOut
498  *
499  * Note: only top-level windows get FocusOut events.
500  */
501 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
502 {
503     HWND hwnd_tmp;
504     Window focus_win;
505     int revert;
506
507     TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
508
509     if (event->detail == NotifyPointer) return;
510     x11drv_thread_data()->last_focus = hwnd;
511     if (hwnd != GetForegroundWindow()) return;
512     SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
513
514     /* don't reset the foreground window, if the window which is
515        getting the focus is a Wine window */
516
517     wine_tsx11_lock();
518     XGetInputFocus( thread_display(), &focus_win, &revert );
519     if (focus_win)
520     {
521         if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
522             focus_win = 0;
523     }
524     wine_tsx11_unlock();
525
526     if (!focus_win)
527     {
528         /* Abey : 6-Oct-99. Check again if the focus out window is the
529            Foreground window, because in most cases the messages sent
530            above must have already changed the foreground window, in which
531            case we don't have to change the foreground window to 0 */
532         if (hwnd == GetForegroundWindow())
533         {
534             TRACE( "lost focus, setting fg to 0\n" );
535             SetForegroundWindow( 0 );
536         }
537     }
538 }
539
540
541 /***********************************************************************
542  *           EVENT_SelectionRequest_TARGETS
543  *  Service a TARGETS selection request event
544  */
545 static Atom EVENT_SelectionRequest_TARGETS( Display *display, Window requestor,
546                                             Atom target, Atom rprop )
547 {
548     Atom xaTargets = TSXInternAtom(display, "TARGETS", False);
549     Atom* targets;
550     Atom prop;
551     UINT wFormat;
552     unsigned long cTargets;
553     BOOL bHavePixmap;
554     int xRc;
555
556     TRACE("Request for %s\n", TSXGetAtomName(display, target));
557
558     /*
559      * Count the number of items we wish to expose as selection targets.
560      * We include the TARGETS item, and a PIXMAP if we have CF_DIB or CF_BITMAP
561      */
562     cTargets = CountClipboardFormats() + 1;
563     if ( CLIPBOARD_IsPresent(CF_DIB) ||  CLIPBOARD_IsPresent(CF_BITMAP) )
564        cTargets++;
565
566     /* Allocate temp buffer */
567     targets = (Atom*)HeapAlloc( GetProcessHeap(), 0, cTargets * sizeof(Atom));
568     if(targets == NULL) return None;
569
570     /* Create TARGETS property list (First item in list is TARGETS itself) */
571
572     for ( targets[0] = xaTargets, cTargets = 1, wFormat = 0, bHavePixmap = FALSE;
573           (wFormat = EnumClipboardFormats( wFormat )); )
574     {
575         if ( (prop = X11DRV_CLIPBOARD_MapFormatToProperty(wFormat)) != None )
576         {
577             /* Scan through what we have so far to avoid duplicates */
578             int i;
579             BOOL bExists;
580             for (i = 0, bExists = FALSE; i < cTargets; i++)
581             {
582                 if (targets[i] == prop)
583                 {
584                     bExists = TRUE;
585                     break;
586                 }
587             }
588             if (!bExists)
589             {
590                 targets[cTargets++] = prop;
591
592                 /* Add PIXMAP prop for bitmaps additionally */
593                 if ( (wFormat == CF_DIB || wFormat == CF_BITMAP )
594                      && !bHavePixmap )
595                 {
596                     targets[cTargets++] = XA_PIXMAP;
597                     bHavePixmap = TRUE;
598                 }
599             }
600         }
601     }
602
603     if (TRACE_ON(event))
604     {
605         int i;
606         for ( i = 0; i < cTargets; i++)
607         {
608             if (targets[i])
609             {
610                 char *itemFmtName = TSXGetAtomName(display, targets[i]);
611                 TRACE("\tAtom# %d:  Type %s\n", i, itemFmtName);
612                 TSXFree(itemFmtName);
613             }
614         }
615     }
616
617     /* Update the X property */
618     TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
619
620     /* We may want to consider setting the type to xaTargets instead,
621      * in case some apps expect this instead of XA_ATOM */
622     xRc = TSXChangeProperty(display, requestor, rprop,
623                             XA_ATOM, 32, PropModeReplace,
624                             (unsigned char *)targets, cTargets);
625     TRACE("(Rc=%d)\n", xRc);
626
627     HeapFree( GetProcessHeap(), 0, targets );
628
629     return rprop;
630 }
631
632
633 /***********************************************************************
634  *           EVENT_SelectionRequest_STRING
635  *  Service a STRING selection request event
636  */
637 static Atom EVENT_SelectionRequest_STRING( Display *display, Window requestor,
638                                            Atom target, Atom rprop )
639 {
640     static UINT text_cp = (UINT)-1;
641     HANDLE hUnicodeText;
642     LPWSTR uni_text;
643     LPSTR  text;
644     int    size,i,j;
645     char* lpstr = 0;
646     char *itemFmtName;
647     int xRc;
648
649     if(text_cp == (UINT)-1)
650     {
651         HKEY hkey;
652         /* default value */
653         text_cp = CP_ACP;
654         if(!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\x11drv", &hkey))
655         {
656             char buf[20];
657             DWORD type, count = sizeof(buf);
658             if(!RegQueryValueExA(hkey, "TextCP", 0, &type, buf, &count))
659                 text_cp = atoi(buf);
660             RegCloseKey(hkey);
661           }
662     }
663
664     /*
665      * Map the requested X selection property type atom name to a
666      * windows clipboard format ID.
667      */
668     itemFmtName = TSXGetAtomName(display, target);
669     TRACE("Request for %s (wFormat=%x %s)\n",
670         itemFmtName, CF_UNICODETEXT, CLIPBOARD_GetFormatName(CF_UNICODETEXT, NULL, 0));
671     TSXFree(itemFmtName);
672
673     hUnicodeText = GetClipboardData(CF_UNICODETEXT);
674     if(!hUnicodeText)
675        return None;
676     uni_text = GlobalLock(hUnicodeText);
677     if(!uni_text)
678        return None;
679
680     size = WideCharToMultiByte(text_cp, 0, uni_text, -1, NULL, 0, NULL, NULL);
681     text = HeapAlloc(GetProcessHeap(), 0, size);
682     if (!text)
683        return None;
684     WideCharToMultiByte(text_cp, 0, uni_text, -1, text, size, NULL, NULL);
685
686     /* remove carriage returns */
687
688     lpstr = (char*)HeapAlloc( GetProcessHeap(), 0, size-- );
689     if(lpstr == NULL) return None;
690     for(i=0,j=0; i < size && text[i]; i++ )
691     {
692         if( text[i] == '\r' &&
693             (text[i+1] == '\n' || text[i+1] == '\0') ) continue;
694         lpstr[j++] = text[i];
695     }
696     lpstr[j]='\0';
697
698     /* Update the X property */
699     TRACE("\tUpdating property %s...\n", TSXGetAtomName(display, rprop));
700     xRc = TSXChangeProperty(display, requestor, rprop,
701                             XA_STRING, 8, PropModeReplace,
702                             lpstr, j);
703     TRACE("(Rc=%d)\n", xRc);
704
705     GlobalUnlock(hUnicodeText);
706     HeapFree(GetProcessHeap(), 0, text);
707     HeapFree( GetProcessHeap(), 0, lpstr );
708
709     return rprop;
710 }
711
712 /***********************************************************************
713  *           EVENT_SelectionRequest_PIXMAP
714  *  Service a PIXMAP selection request event
715  */
716 static Atom EVENT_SelectionRequest_PIXMAP( Display *display, Window requestor,
717                                            Atom target, Atom rprop )
718 {
719     HANDLE hClipData = 0;
720     Pixmap pixmap = 0;
721     UINT   wFormat;
722     char * itemFmtName;
723     int xRc;
724 #if(0)
725     XSetWindowAttributes win_attr;
726     XWindowAttributes win_attr_src;
727 #endif
728
729     /*
730      * Map the requested X selection property type atom name to a
731      * windows clipboard format ID.
732      */
733     itemFmtName = TSXGetAtomName(display, target);
734     wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
735     TRACE("Request for %s (wFormat=%x %s)\n",
736                   itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat, NULL, 0 ));
737     TSXFree(itemFmtName);
738
739     hClipData = GetClipboardData(wFormat);
740     if ( !hClipData )
741     {
742         TRACE("Could not retrieve a Pixmap compatible format from clipboard!\n");
743         rprop = None; /* Fail the request */
744         goto END;
745     }
746
747     if (wFormat == CF_DIB)
748     {
749         HWND hwnd = GetOpenClipboardWindow();
750         HDC hdc = GetDC(hwnd);
751
752         /* For convert from packed DIB to Pixmap */
753         pixmap = X11DRV_DIB_CreatePixmapFromDIB(hClipData, hdc);
754
755         ReleaseDC(hwnd, hdc);
756     }
757     else if (wFormat == CF_BITMAP)
758     {
759         HWND hwnd = GetOpenClipboardWindow();
760         HDC hdc = GetDC(hwnd);
761
762         pixmap = X11DRV_BITMAP_CreatePixmapFromBitmap(hClipData, hdc);
763
764         ReleaseDC(hwnd, hdc);
765     }
766     else
767     {
768         FIXME("%s to PIXMAP conversion not yet implemented!\n",
769                       CLIPBOARD_GetFormatName(wFormat, NULL, 0));
770         rprop = None;
771         goto END;
772     }
773
774     TRACE("\tUpdating property %s on Window %ld with %s %ld...\n",
775           TSXGetAtomName(display, rprop), (long)requestor,
776           TSXGetAtomName(display, target), pixmap);
777
778     /* Store the Pixmap handle in the property */
779     xRc = TSXChangeProperty(display, requestor, rprop, target,
780                             32, PropModeReplace,
781                             (unsigned char *)&pixmap, 1);
782     TRACE("(Rc=%d)\n", xRc);
783
784     /* Enable the code below if you want to handle destroying Pixmap resources
785      * in response to property notify events. Clients like XPaint don't
786      * appear to be duplicating Pixmaps so they don't like us deleting,
787      * the resource in response to the property being deleted.
788      */
789 #if(0)
790     /* Express interest in property notify events so that we can delete the
791      * pixmap when the client deletes the property atom.
792      */
793     xRc = TSXGetWindowAttributes(display, requestor, &win_attr_src);
794     TRACE("Turning on PropertyChangeEvent notifications from window %ld\n",
795           (long)requestor);
796     win_attr.event_mask = win_attr_src.your_event_mask | PropertyChangeMask;
797     TSXChangeWindowAttributes(display, requestor, CWEventMask, &win_attr);
798
799     /* Register the Pixmap we created with the request property Atom.
800      * When this property is destroyed we also destroy the Pixmap in
801      * response to the PropertyNotify event.
802      */
803     X11DRV_CLIPBOARD_RegisterPixmapResource( rprop, pixmap );
804 #endif
805
806 END:
807     return rprop;
808 }
809
810
811 /***********************************************************************
812  *           EVENT_SelectionRequest_WCF
813  *  Service a Wine Clipboard Format selection request event.
814  *  For <WCF>* data types we simply copy the data to X without conversion.
815  */
816 static Atom EVENT_SelectionRequest_WCF( Display *display, Window requestor,
817                                         Atom target, Atom rprop )
818 {
819     HANDLE hClipData = 0;
820     void*  lpClipData;
821     UINT   wFormat;
822     char * itemFmtName;
823     int cBytes;
824     int xRc;
825     int bemf;
826
827     /*
828      * Map the requested X selection property type atom name to a
829      * windows clipboard format ID.
830      */
831     itemFmtName = TSXGetAtomName(display, target);
832     wFormat = X11DRV_CLIPBOARD_MapPropertyToFormat(itemFmtName);
833     TRACE("Request for %s (wFormat=%x %s)\n",
834           itemFmtName, wFormat, CLIPBOARD_GetFormatName( wFormat, NULL, 0));
835     TSXFree(itemFmtName);
836
837     hClipData = GetClipboardData(wFormat);
838
839     bemf = wFormat == CF_METAFILEPICT || wFormat == CF_ENHMETAFILE;
840     if (bemf)
841         hClipData = X11DRV_CLIPBOARD_SerializeMetafile(wFormat, hClipData, sizeof(hClipData), TRUE);
842
843     if( hClipData && (lpClipData = GlobalLock(hClipData)) )
844     {
845         cBytes = GlobalSize(hClipData);
846
847         TRACE("\tUpdating property %s, %d bytes...\n",
848               TSXGetAtomName(display, rprop), cBytes);
849
850         xRc = TSXChangeProperty(display, requestor, rprop,
851                                 target, 8, PropModeReplace,
852                                 (unsigned char *)lpClipData, cBytes);
853         TRACE("(Rc=%d)\n", xRc);
854
855         GlobalUnlock(hClipData);
856     }
857     else
858     {
859         TRACE("\tCould not retrieve native format!\n");
860         rprop = None; /* Fail the request */
861     }
862
863     if (bemf) /* We must free serialized metafile data */
864         GlobalFree(hClipData);
865
866     return rprop;
867 }
868
869
870 /***********************************************************************
871  *           EVENT_SelectionRequest_MULTIPLE
872  *  Service a MULTIPLE selection request event
873  *  rprop contains a list of (target,property) atom pairs.
874  *  The first atom names a target and the second names a property.
875  *  The effect is as if we have received a sequence of SelectionRequest events
876  *  (one for each atom pair) except that:
877  *  1. We reply with a SelectionNotify only when all the requested conversions
878  *  have been performed.
879  *  2. If we fail to convert the target named by an atom in the MULTIPLE property,
880  *  we replace the atom in the property by None.
881  */
882 static Atom EVENT_SelectionRequest_MULTIPLE( HWND hWnd, XSelectionRequestEvent *pevent )
883 {
884     Display *display = pevent->display;
885     Atom           rprop;
886     Atom           atype=AnyPropertyType;
887     int            aformat;
888     unsigned long  remain;
889     Atom*          targetPropList=NULL;
890     unsigned long  cTargetPropList = 0;
891 /*  Atom           xAtomPair = TSXInternAtom(display, "ATOM_PAIR", False); */
892
893    /* If the specified property is None the requestor is an obsolete client.
894     * We support these by using the specified target atom as the reply property.
895     */
896     rprop = pevent->property;
897     if( rprop == None )
898         rprop = pevent->target;
899     if (!rprop)
900         goto END;
901
902     /* Read the MULTIPLE property contents. This should contain a list of
903      * (target,property) atom pairs.
904      */
905     if(TSXGetWindowProperty(display, pevent->requestor, rprop,
906                             0, 0x3FFF, False, AnyPropertyType, &atype,&aformat,
907                             &cTargetPropList, &remain,
908                             (unsigned char**)&targetPropList) != Success)
909         TRACE("\tCouldn't read MULTIPLE property\n");
910     else
911     {
912        TRACE("\tType %s,Format %d,nItems %ld, Remain %ld\n",
913              TSXGetAtomName(display, atype), aformat, cTargetPropList, remain);
914
915        /*
916         * Make sure we got what we expect.
917         * NOTE: According to the X-ICCCM Version 2.0 documentation the property sent
918         * in a MULTIPLE selection request should be of type ATOM_PAIR.
919         * However some X apps(such as XPaint) are not compliant with this and return
920         * a user defined atom in atype when XGetWindowProperty is called.
921         * The data *is* an atom pair but is not denoted as such.
922         */
923        if(aformat == 32 /* atype == xAtomPair */ )
924        {
925           int i;
926
927           /* Iterate through the ATOM_PAIR list and execute a SelectionRequest
928            * for each (target,property) pair */
929
930           for (i = 0; i < cTargetPropList; i+=2)
931           {
932               char *targetName = TSXGetAtomName(display, targetPropList[i]);
933               char *propName = TSXGetAtomName(display, targetPropList[i+1]);
934               XSelectionRequestEvent event;
935
936               TRACE("MULTIPLE(%d): Target='%s' Prop='%s'\n",
937                     i/2, targetName, propName);
938               TSXFree(targetName);
939               TSXFree(propName);
940
941               /* We must have a non "None" property to service a MULTIPLE target atom */
942               if ( !targetPropList[i+1] )
943               {
944                   TRACE("\tMULTIPLE(%d): Skipping target with empty property!\n", i);
945                   continue;
946               }
947
948               /* Set up an XSelectionRequestEvent for this (target,property) pair */
949               memcpy( &event, pevent, sizeof(XSelectionRequestEvent) );
950               event.target = targetPropList[i];
951               event.property = targetPropList[i+1];
952
953               /* Fire a SelectionRequest, informing the handler that we are processing
954                * a MULTIPLE selection request event.
955                */
956               EVENT_SelectionRequest( hWnd, &event, TRUE );
957           }
958        }
959
960        /* Free the list of targets/properties */
961        TSXFree(targetPropList);
962     }
963
964 END:
965     return rprop;
966 }
967
968
969 /***********************************************************************
970  *           EVENT_SelectionRequest
971  *  Process an event selection request event.
972  *  The bIsMultiple flag is used to signal when EVENT_SelectionRequest is called
973  *  recursively while servicing a "MULTIPLE" selection target.
974  *
975  *  Note: We only receive this event when WINE owns the X selection
976  */
977 static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple )
978 {
979     Display *display = event->display;
980   XSelectionEvent result;
981   Atom            rprop = None;
982   Window          request = event->requestor;
983   BOOL            couldOpen = FALSE;
984   Atom            xaClipboard = TSXInternAtom(display, "CLIPBOARD", False);
985   Atom            xaTargets = TSXInternAtom(display, "TARGETS", False);
986   Atom            xaMultiple = TSXInternAtom(display, "MULTIPLE", False);
987
988   /*
989    * We can only handle the selection request if :
990    * The selection is PRIMARY or CLIPBOARD, AND we can successfully open the clipboard.
991    * Don't do these checks or open the clipboard while recursively processing MULTIPLE,
992    * since this has been already done.
993    */
994   if ( !bIsMultiple )
995   {
996     if ( ( (event->selection != XA_PRIMARY) && (event->selection != xaClipboard) )
997         || !(couldOpen = OpenClipboard(hWnd)) )
998        goto END;
999   }
1000
1001   /* If the specified property is None the requestor is an obsolete client.
1002    * We support these by using the specified target atom as the reply property.
1003    */
1004   rprop = event->property;
1005   if( rprop == None )
1006       rprop = event->target;
1007
1008   if(event->target == xaTargets)  /*  Return a list of all supported targets */
1009   {
1010       /* TARGETS selection request */
1011       rprop = EVENT_SelectionRequest_TARGETS( display, request, event->target, rprop );
1012   }
1013   else if(event->target == xaMultiple)  /*  rprop contains a list of (target, property) atom pairs */
1014   {
1015       /* MULTIPLE selection request */
1016       rprop = EVENT_SelectionRequest_MULTIPLE( hWnd, event );
1017   }
1018   else if(event->target == XA_STRING)  /* treat CF_TEXT as Unix text */
1019   {
1020       /* XA_STRING selection request */
1021       rprop = EVENT_SelectionRequest_STRING( display, request, event->target, rprop );
1022   }
1023   else if(event->target == XA_PIXMAP)  /*  Convert DIB's to Pixmaps */
1024   {
1025       /* XA_PIXMAP selection request */
1026       rprop = EVENT_SelectionRequest_PIXMAP( display, request, event->target, rprop );
1027   }
1028   else if(event->target == XA_BITMAP)  /*  Convert DIB's to 1-bit Pixmaps */
1029   {
1030       /* XA_BITMAP selection request - TODO: create a monochrome Pixmap */
1031       rprop = EVENT_SelectionRequest_PIXMAP( display, request, XA_PIXMAP, rprop );
1032   }
1033   else if(X11DRV_CLIPBOARD_IsNativeProperty(event->target)) /* <WCF>* */
1034   {
1035       /* All <WCF> selection requests */
1036       rprop = EVENT_SelectionRequest_WCF( display, request, event->target, rprop );
1037   }
1038   else
1039       rprop = None;  /* Don't support this format */
1040
1041 END:
1042   /* close clipboard only if we opened before */
1043   if(couldOpen) CloseClipboard();
1044
1045   if( rprop == None)
1046       TRACE("\tRequest ignored\n");
1047
1048   /* reply to sender
1049    * SelectionNotify should be sent only at the end of a MULTIPLE request
1050    */
1051   if ( !bIsMultiple )
1052   {
1053     result.type = SelectionNotify;
1054     result.display = display;
1055     result.requestor = request;
1056     result.selection = event->selection;
1057     result.property = rprop;
1058     result.target = event->target;
1059     result.time = event->time;
1060     TRACE("Sending SelectionNotify event...\n");
1061     TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result);
1062   }
1063 }
1064
1065 /***********************************************************************
1066  *           EVENT_SelectionClear
1067  */
1068 static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event )
1069 {
1070   Atom xaClipboard = TSXInternAtom(event->display, "CLIPBOARD", False);
1071
1072   if (event->selection == XA_PRIMARY || event->selection == xaClipboard)
1073       X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd );
1074 }
1075
1076 /***********************************************************************
1077  *           EVENT_PropertyNotify
1078  *   We use this to release resources like Pixmaps when a selection
1079  *   client no longer needs them.
1080  */
1081 static void EVENT_PropertyNotify( XPropertyEvent *event )
1082 {
1083   /* Check if we have any resources to free */
1084   TRACE("Received PropertyNotify event: \n");
1085
1086   switch(event->state)
1087   {
1088     case PropertyDelete:
1089     {
1090       TRACE("\tPropertyDelete for atom %s on window %ld\n",
1091             TSXGetAtomName(event->display, event->atom), (long)event->window);
1092
1093       if (X11DRV_IsSelectionOwner())
1094           X11DRV_CLIPBOARD_FreeResources( event->atom );
1095       break;
1096     }
1097
1098     case PropertyNewValue:
1099     {
1100       TRACE("\tPropertyNewValue for atom %s on window %ld\n\n",
1101             TSXGetAtomName(event->display, event->atom), (long)event->window);
1102       break;
1103     }
1104
1105     default:
1106       break;
1107   }
1108 }
1109
1110 static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
1111 {
1112     RECT tempRect;
1113
1114     if (!IsWindowEnabled(hQueryWnd)) return 0;
1115     
1116     GetWindowRect(hQueryWnd, &tempRect);
1117
1118     if(!PtInRect(&tempRect, *lpPt)) return 0;
1119
1120     if (!IsIconic( hQueryWnd ))
1121     {
1122         GetClientRect( hQueryWnd, &tempRect );
1123         MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
1124
1125         if (PtInRect( &tempRect, *lpPt))
1126         {
1127             HWND *list = WIN_ListChildren( hQueryWnd );
1128             HWND bResult = 0;
1129
1130             if (list)
1131             {
1132                 int i;
1133                 
1134                 for (i = 0; list[i]; i++)
1135                 {
1136                     if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
1137                     {
1138                         GetWindowRect( list[i], &tempRect );
1139                         if (PtInRect( &tempRect, *lpPt )) break;
1140                     }
1141                 }
1142                 if (list[i])
1143                 {
1144                     if (IsWindowEnabled( list[i] ))
1145                         bResult = find_drop_window( list[i], lpPt );
1146                 }
1147                 HeapFree( GetProcessHeap(), 0, list );
1148             }
1149             if(bResult) return bResult;
1150         }
1151     }
1152
1153     if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
1154     
1155     ScreenToClient(hQueryWnd, lpPt);
1156
1157     return hQueryWnd;
1158 }
1159
1160 /**********************************************************************
1161  *           EVENT_DropFromOffix
1162  *
1163  * don't know if it still works (last Changlog is from 96/11/04)
1164  */
1165 static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
1166 {
1167     unsigned long       data_length;
1168     unsigned long       aux_long;
1169     unsigned char*      p_data = NULL;
1170     union {
1171         Atom    atom_aux;
1172         struct {
1173             int x;
1174             int y;
1175         }       pt_aux;
1176         int     i;
1177     }                   u;
1178     int                 x, y;
1179     BOOL                bAccept;
1180     Window              w_aux_root, w_aux_child;
1181     WND*                pWnd;
1182     HWND                hScope = hWnd;
1183
1184     pWnd = WIN_FindWndPtr(hWnd);
1185
1186     TSXQueryPointer( event->display, get_whole_window(pWnd), &w_aux_root, &w_aux_child,
1187                      &x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
1188                      (unsigned int*)&aux_long);
1189
1190     /* find out drop point and drop window */
1191     if( x < 0 || y < 0 ||
1192         x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
1193         y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
1194     {   
1195         bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; 
1196         x = 0;
1197         y = 0; 
1198     }
1199     else
1200     {
1201         POINT   pt = { x, y };
1202         HWND    hwndDrop = find_drop_window( hWnd, &pt );
1203         if (hwndDrop)
1204         {
1205             x = pt.x;
1206             y = pt.y;
1207             hScope = hwndDrop;
1208             bAccept = TRUE;
1209         }
1210         else
1211         {
1212             bAccept = FALSE;
1213         }
1214     }
1215     WIN_ReleaseWndPtr(pWnd);
1216
1217     if (!bAccept) return;
1218
1219     TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1220                           dndSelection, 0, 65535, FALSE,
1221                           AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
1222                           &data_length, &aux_long, &p_data);
1223
1224     if( !aux_long && p_data)  /* don't bother if > 64K */
1225     {
1226         signed char *p = (signed char*) p_data;
1227         char *p_drop;
1228
1229         aux_long = 0;
1230         while( *p )  /* calculate buffer size */
1231         {
1232             p_drop = p;
1233             if((u.i = *p) != -1 )
1234             {
1235                 INT len = GetShortPathNameA( p, NULL, 0 );
1236                 if (len) aux_long += len + 1;
1237                 else *p = -1;
1238             }
1239             p += strlen(p) + 1;
1240         }
1241         if( aux_long && aux_long < 65535 )
1242         {
1243             HDROP                 hDrop;
1244             DROPFILES *lpDrop;
1245
1246             aux_long += sizeof(DROPFILES) + 1;
1247             hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
1248             lpDrop = (DROPFILES*)GlobalLock( hDrop );
1249
1250             if( lpDrop )
1251             {
1252                 WND *pDropWnd = WIN_FindWndPtr( hScope );
1253                 lpDrop->pFiles = sizeof(DROPFILES);
1254                 lpDrop->pt.x = x;
1255                 lpDrop->pt.y = y;
1256                 lpDrop->fNC =
1257                     ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
1258                       y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
1259                       x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1260                       y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1261                 lpDrop->fWide = FALSE;
1262                 WIN_ReleaseWndPtr(pDropWnd);
1263                 p_drop = (char *)(lpDrop + 1);
1264                 p = p_data;
1265                 while(*p)
1266                 {
1267                     if( *p != -1 ) /* use only "good" entries */
1268                     {
1269                         GetShortPathNameA( p, p_drop, 65535 );
1270                         p_drop += strlen( p_drop ) + 1;
1271                     }
1272                     p += strlen(p) + 1;
1273                 }
1274                 *p_drop = '\0';
1275                 PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1276             }
1277         }
1278     }
1279     if( p_data ) TSXFree(p_data);
1280 }
1281
1282 /**********************************************************************
1283  *           EVENT_DropURLs
1284  *
1285  * drop items are separated by \n
1286  * each item is prefixed by its mime type
1287  *
1288  * event->data.l[3], event->data.l[4] contains drop x,y position
1289  */
1290 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
1291 {
1292   unsigned long data_length;
1293   unsigned long aux_long, drop_len = 0;
1294   unsigned char *p_data = NULL; /* property data */
1295   char          *p_drop = NULL;
1296   char          *p, *next;
1297   int           x, y;
1298   DROPFILES *lpDrop;
1299   HDROP hDrop;
1300   union {
1301     Atom        atom_aux;
1302     int         i;
1303     Window      w_aux;
1304   }             u; /* unused */
1305
1306   if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
1307
1308   TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1309                         dndSelection, 0, 65535, FALSE,
1310                         AnyPropertyType, &u.atom_aux, &u.i,
1311                         &data_length, &aux_long, &p_data);
1312   if (aux_long)
1313     WARN("property too large, truncated!\n");
1314   TRACE("urls=%s\n", p_data);
1315
1316   if( !aux_long && p_data) {    /* don't bother if > 64K */
1317     /* calculate length */
1318     p = p_data;
1319     next = strchr(p, '\n');
1320     while (p) {
1321       if (next) *next=0;
1322       if (strncmp(p,"file:",5) == 0 ) {
1323         INT len = GetShortPathNameA( p+5, NULL, 0 );
1324         if (len) drop_len += len + 1;
1325       }
1326       if (next) {
1327         *next = '\n';
1328         p = next + 1;
1329         next = strchr(p, '\n');
1330       } else {
1331         p = NULL;
1332       }
1333     }
1334
1335     if( drop_len && drop_len < 65535 ) {
1336       TSXQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
1337                        &x, &y, &u.i, &u.i, &u.i);
1338
1339       drop_len += sizeof(DROPFILES) + 1;
1340       hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
1341       lpDrop = (DROPFILES *) GlobalLock( hDrop );
1342
1343       if( lpDrop ) {
1344           WND *pDropWnd = WIN_FindWndPtr( hWnd );
1345           lpDrop->pFiles = sizeof(DROPFILES);
1346           lpDrop->pt.x = (INT)x;
1347           lpDrop->pt.y = (INT)y;
1348           lpDrop->fNC =
1349             ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
1350               y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
1351               x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
1352               y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
1353           lpDrop->fWide = FALSE;
1354           p_drop = (char*)(lpDrop + 1);
1355           WIN_ReleaseWndPtr(pDropWnd);
1356       }
1357
1358       /* create message content */
1359       if (p_drop) {
1360         p = p_data;
1361         next = strchr(p, '\n');
1362         while (p) {
1363           if (next) *next=0;
1364           if (strncmp(p,"file:",5) == 0 ) {
1365             INT len = GetShortPathNameA( p+5, p_drop, 65535 );
1366             if (len) {
1367               TRACE("drop file %s as %s\n", p+5, p_drop);
1368               p_drop += len+1;
1369             } else {
1370               WARN("can't convert file %s to dos name \n", p+5);
1371             }
1372           } else {
1373             WARN("unknown mime type %s\n", p);
1374           }
1375           if (next) {
1376             *next = '\n';
1377             p = next + 1;
1378             next = strchr(p, '\n');
1379           } else {
1380             p = NULL;
1381           }
1382           *p_drop = '\0';
1383         }
1384
1385         GlobalUnlock(hDrop);
1386         PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
1387       }
1388     }
1389     if( p_data ) TSXFree(p_data);
1390   }
1391 }
1392
1393 /**********************************************************************
1394  *           EVENT_ClientMessage
1395  */
1396 static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
1397 {
1398   if (event->message_type != None && event->format == 32) {
1399     if (event->message_type == wmProtocols)
1400         handle_wm_protocols_message( hWnd, event );
1401     else if (event->message_type == dndProtocol)
1402     {
1403         /* query window (drag&drop event contains only drag window) */
1404         Window root, child;
1405         int root_x, root_y, child_x, child_y;
1406         unsigned int u;
1407
1408         wine_tsx11_lock();
1409         XQueryPointer( event->display, root_window, &root, &child,
1410                        &root_x, &root_y, &child_x, &child_y, &u);
1411         if (XFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) hWnd = 0;
1412         wine_tsx11_unlock();
1413         if (!hWnd) return;
1414         if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles)
1415             EVENT_DropFromOffiX(hWnd, event);
1416         else if (event->data.l[0] == DndURL)
1417             EVENT_DropURLs(hWnd, event);
1418     }
1419     else {
1420 #if 0
1421       /* enable this if you want to see the message */
1422       unsigned char* p_data = NULL;
1423       union {
1424         unsigned long   l;
1425         int             i;
1426         Atom            atom;
1427       } u; /* unused */
1428       TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
1429                             dndSelection, 0, 65535, FALSE,
1430                             AnyPropertyType, &u.atom, &u.i,
1431                             &u.l, &u.l, &p_data);
1432       TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
1433             event->message_type, event->data.l[0], event->data.l[1],
1434             event->data.l[2], event->data.l[3], event->data.l[4],
1435             p_data);
1436 #endif
1437       TRACE("unrecognized ClientMessage\n" );
1438     }
1439   }
1440 }
1441
1442
1443 /**********************************************************************
1444  *              X11DRV_EVENT_SetInputMethod
1445  */
1446 INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
1447 {
1448   INPUT_TYPE prev = current_input_type;
1449
1450   /* Flag not used yet */
1451   in_transition = FALSE;
1452   current_input_type = type;
1453
1454   return prev;
1455 }
1456
1457 #ifdef HAVE_LIBXXF86DGA2
1458 /**********************************************************************
1459  *              X11DRV_EVENT_SetDGAStatus
1460  */
1461 void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
1462 {
1463   if (event_base < 0) {
1464     DGAUsed = FALSE;
1465     DGAhwnd = 0;
1466   } else {
1467     DGAUsed = TRUE;
1468     DGAhwnd = hwnd;
1469     DGAMotionEventType = event_base + MotionNotify;
1470     DGAButtonPressEventType = event_base + ButtonPress;
1471     DGAButtonReleaseEventType = event_base + ButtonRelease;
1472     DGAKeyPressEventType = event_base + KeyPress;
1473     DGAKeyReleaseEventType = event_base + KeyRelease;
1474   }
1475 }
1476 #endif